style(frontend): Prettier config + one-time repo-wide format pass
Prettier 3 (pinned), printWidth 100, double quotes — chosen to match the existing hand-formatting and minimise reflow. This commit is ONLY the mechanical format pass (`prettier --write`) plus the config/ignore/scripts, isolated so it never pollutes a feature diff. Verified behaviour-neutral: typecheck, eslint (0 errors), and vitest all green before and after. See .git-blame-ignore-revs — `git blame` skips this sha.
This commit is contained in:
+152
-74
@@ -237,7 +237,8 @@ function localizeDetail(d: any): string {
|
||||
if (d.reason === "max_jobs") return t("downloads.errors.quota.max_jobs", { limit: d.limit });
|
||||
return t("downloads.errors.quota.generic");
|
||||
}
|
||||
if (d?.code === "edit") return t(`downloads.errors.edit.${d.reason}`, t("downloads.errors.edit.generic"));
|
||||
if (d?.code === "edit")
|
||||
return t(`downloads.errors.edit.${d.reason}`, t("downloads.errors.edit.generic"));
|
||||
return t("errors.generic");
|
||||
}
|
||||
|
||||
@@ -789,7 +790,13 @@ export interface PlexItemDetail {
|
||||
markers: PlexMarker[];
|
||||
audio_streams: { ord: number; label: string; language?: string | null; default: boolean }[];
|
||||
// `text`=true → offered as a WebVTT <track>; image subs (PGS/VobSub) are text=false (hidden).
|
||||
subtitle_streams: { ord: number; label: string; language?: string | null; codec?: string; text: boolean }[];
|
||||
subtitle_streams: {
|
||||
ord: number;
|
||||
label: string;
|
||||
language?: string | null;
|
||||
codec?: string;
|
||||
text: boolean;
|
||||
}[];
|
||||
status: string;
|
||||
position_seconds: number;
|
||||
show_title?: string | null;
|
||||
@@ -992,13 +999,7 @@ interface DownloadAsset {
|
||||
expires_at: string | null;
|
||||
}
|
||||
|
||||
export type DownloadStatus =
|
||||
| "queued"
|
||||
| "running"
|
||||
| "paused"
|
||||
| "done"
|
||||
| "error"
|
||||
| "canceled";
|
||||
export type DownloadStatus = "queued" | "running" | "paused" | "done" | "error" | "canceled";
|
||||
|
||||
// Phase-2 editor recipe. A single `trim` (one output file) or a `segments` cut-list joined into
|
||||
// one file. `accurate` re-encodes for a frame-accurate cut (a crop always re-encodes).
|
||||
@@ -1101,8 +1102,7 @@ export const api = {
|
||||
return r && r.authenticated ? (r as Me) : null;
|
||||
},
|
||||
accounts: (): Promise<Account[]> => req("/api/me/accounts"),
|
||||
deleteAccount: (): Promise<{ deleted: boolean }> =>
|
||||
req("/api/me/account", { method: "DELETE" }),
|
||||
deleteAccount: (): Promise<{ deleted: boolean }> => req("/api/me/account", { method: "DELETE" }),
|
||||
switchAccount: (userId: number): Promise<{ ok: boolean; user_id: number }> =>
|
||||
req("/api/me/switch", { method: "POST", body: JSON.stringify({ user_id: userId }) }),
|
||||
// Signs the current tab's active account out of the browser wallet (per-tab aware via the
|
||||
@@ -1138,7 +1138,7 @@ export const api = {
|
||||
req(
|
||||
`/api/videos/${id}/state`,
|
||||
{ method: "POST", body: JSON.stringify({ status }) },
|
||||
{ idempotent: true }
|
||||
{ idempotent: true },
|
||||
),
|
||||
clearState: (id: string) =>
|
||||
req(`/api/videos/${id}/state`, { method: "DELETE" }, { idempotent: true }),
|
||||
@@ -1152,7 +1152,7 @@ export const api = {
|
||||
duration_seconds: Math.floor(durationSeconds),
|
||||
}),
|
||||
},
|
||||
{ idempotent: true }
|
||||
{ idempotent: true },
|
||||
),
|
||||
// Fire-and-forget YT progress save that survives page unload (F5/close/navigate).
|
||||
saveProgressBeacon: (id: string, positionSeconds: number, durationSeconds: number): void =>
|
||||
@@ -1172,22 +1172,18 @@ export const api = {
|
||||
channels: (): Promise<ManagedChannel[]> => req("/api/channels"),
|
||||
updateChannel: (
|
||||
id: string,
|
||||
patch: { priority?: number; hidden?: boolean; deep_requested?: boolean }
|
||||
patch: { priority?: number; hidden?: boolean; deep_requested?: boolean },
|
||||
) => req(`/api/channels/${id}`, { method: "PATCH", body: JSON.stringify(patch) }),
|
||||
resetChannelBackfill: (id: string) =>
|
||||
req(`/api/channels/${id}/reset-backfill`, { method: "POST" }),
|
||||
deepAll: (on = true) =>
|
||||
req(`/api/sync/deep-all?on=${on}`, { method: "POST" }),
|
||||
deepAll: (on = true) => req(`/api/sync/deep-all?on=${on}`, { method: "POST" }),
|
||||
attachChannelTag: (id: string, tagId: number) =>
|
||||
req(`/api/channels/${id}/tags`, { method: "POST", body: JSON.stringify({ tag_id: tagId }) }),
|
||||
detachChannelTag: (id: string, tagId: number) =>
|
||||
req(`/api/channels/${id}/tags/${tagId}`, { method: "DELETE" }),
|
||||
unsubscribeChannel: (id: string) =>
|
||||
req(`/api/channels/${id}/subscription`, { method: "DELETE" }),
|
||||
discoveredChannels: (): Promise<DiscoveredChannel[]> =>
|
||||
req("/api/channels/discovery"),
|
||||
subscribeChannel: (id: string) =>
|
||||
req(`/api/channels/${id}/subscribe`, { method: "POST" }),
|
||||
unsubscribeChannel: (id: string) => req(`/api/channels/${id}/subscription`, { method: "DELETE" }),
|
||||
discoveredChannels: (): Promise<DiscoveredChannel[]> => req("/api/channels/discovery"),
|
||||
subscribeChannel: (id: string) => req(`/api/channels/${id}/subscribe`, { method: "POST" }),
|
||||
syncSubscriptions: () => req("/api/sync/subscriptions", { method: "POST" }),
|
||||
// --- channel page (About detail + ephemeral exploration of un-subscribed channels) ---
|
||||
channelDetail: (id: string): Promise<ChannelDetail> => req(`/api/channels/${id}`),
|
||||
@@ -1201,12 +1197,13 @@ export const api = {
|
||||
return req(
|
||||
`/api/channels/${id}/explore${qs ? `?${qs}` : ""}`,
|
||||
{ method: "POST" },
|
||||
{ quiet: true }
|
||||
{ quiet: true },
|
||||
);
|
||||
},
|
||||
// --- per-user channel blocklist (excluded from live search + feed/explore) ---
|
||||
blockedChannels: (): Promise<{ id: string; title: string | null; handle: string | null; thumbnail_url: string | null }[]> =>
|
||||
req("/api/channels/blocked/list"),
|
||||
blockedChannels: (): Promise<
|
||||
{ id: string; title: string | null; handle: string | null; thumbnail_url: string | null }[]
|
||||
> => req("/api/channels/blocked/list"),
|
||||
blockChannel: (id: string) => req(`/api/channels/${id}/block`, { method: "POST" }),
|
||||
unblockChannel: (id: string) => req(`/api/channels/${id}/block`, { method: "DELETE" }),
|
||||
// Admin: reclaim all un-kept discovery content (search results + explored channels) now.
|
||||
@@ -1247,8 +1244,7 @@ export const api = {
|
||||
req("/api/playlists/sync-youtube", { method: "POST" }),
|
||||
revertPlaylist: (id: number): Promise<{ items: number }> =>
|
||||
req(`/api/playlists/${id}/revert-youtube`, { method: "POST" }),
|
||||
playlistPushPlan: (id: number): Promise<PushPlan> =>
|
||||
req(`/api/playlists/${id}/push-plan`),
|
||||
playlistPushPlan: (id: number): Promise<PushPlan> => req(`/api/playlists/${id}/push-plan`),
|
||||
pushPlaylist: (id: number): Promise<PushResult> =>
|
||||
req(`/api/playlists/${id}/push`, { method: "POST" }),
|
||||
|
||||
@@ -1307,18 +1303,35 @@ export const api = {
|
||||
return req(`/api/plex/collections${qs ? `?${qs}` : ""}`);
|
||||
},
|
||||
// --- Collection editing (admin only; writes back to Plex) ---
|
||||
plexCreateCollection: (library: string, title: string, item_rating_key: string): Promise<PlexCollection> =>
|
||||
req(`/api/plex/collections`, { method: "POST", body: JSON.stringify({ library, title, item_rating_key }) }),
|
||||
plexCreateCollection: (
|
||||
library: string,
|
||||
title: string,
|
||||
item_rating_key: string,
|
||||
): Promise<PlexCollection> =>
|
||||
req(`/api/plex/collections`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ library, title, item_rating_key }),
|
||||
}),
|
||||
plexCollectionAddItem: (rk: string, itemRk: string): Promise<PlexCollection> =>
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}/items/${encodeURIComponent(itemRk)}`, { method: "POST" }),
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}/items/${encodeURIComponent(itemRk)}`, {
|
||||
method: "POST",
|
||||
}),
|
||||
plexCollectionRemoveItem: (rk: string, itemRk: string): Promise<PlexCollection> =>
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}/items/${encodeURIComponent(itemRk)}`, { method: "DELETE" }),
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}/items/${encodeURIComponent(itemRk)}`, {
|
||||
method: "DELETE",
|
||||
}),
|
||||
plexRenameCollection: (rk: string, title: string): Promise<PlexCollection> =>
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}`, { method: "PATCH", body: JSON.stringify({ title }) }),
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ title }),
|
||||
}),
|
||||
plexDeleteCollection: (rk: string): Promise<{ deleted: string }> =>
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}`, { method: "DELETE" }),
|
||||
plexSetCollectionEditable: (rk: string, editable: boolean): Promise<PlexCollection> =>
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}/editable`, { method: "POST", body: JSON.stringify({ editable }) }),
|
||||
req(`/api/plex/collections/${encodeURIComponent(rk)}/editable`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ editable }),
|
||||
}),
|
||||
// --- Playlists (Siftlode-native, per-user, ordered) ---
|
||||
// `contains`=single rating_key → per-playlist has_item; `containsGroup`=a set of rating_keys (a whole
|
||||
// season/show) → per-playlist group_in + a top-level group_size (for the bulk add-to-playlist dialog).
|
||||
@@ -1334,39 +1347,76 @@ export const api = {
|
||||
},
|
||||
plexPlaylist: (id: number): Promise<PlexPlaylistDetail> => req(`/api/plex/playlists/${id}`),
|
||||
plexCreatePlaylist: (title: string, item_rating_key?: string): Promise<PlexPlaylist> =>
|
||||
req(`/api/plex/playlists`, { method: "POST", body: JSON.stringify({ title, item_rating_key }) }),
|
||||
plexPlaylistAddBulk: (id: number, itemRks: string[]): Promise<{ added: number; item_count: number }> =>
|
||||
req(`/api/plex/playlists/${id}/items/bulk`, { method: "POST", body: JSON.stringify({ item_rating_keys: itemRks }) }),
|
||||
plexPlaylistRemoveBulk: (id: number, itemRks: string[]): Promise<{ removed: number; item_count: number }> =>
|
||||
req(`/api/plex/playlists/${id}/items/remove-bulk`, { method: "POST", body: JSON.stringify({ item_rating_keys: itemRks }) }),
|
||||
req(`/api/plex/playlists`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ title, item_rating_key }),
|
||||
}),
|
||||
plexPlaylistAddBulk: (
|
||||
id: number,
|
||||
itemRks: string[],
|
||||
): Promise<{ added: number; item_count: number }> =>
|
||||
req(`/api/plex/playlists/${id}/items/bulk`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ item_rating_keys: itemRks }),
|
||||
}),
|
||||
plexPlaylistRemoveBulk: (
|
||||
id: number,
|
||||
itemRks: string[],
|
||||
): Promise<{ removed: number; item_count: number }> =>
|
||||
req(`/api/plex/playlists/${id}/items/remove-bulk`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ item_rating_keys: itemRks }),
|
||||
}),
|
||||
plexRenamePlaylist: (id: number, title: string): Promise<PlexPlaylist> =>
|
||||
req(`/api/plex/playlists/${id}`, { method: "PATCH", body: JSON.stringify({ title }) }),
|
||||
plexDeletePlaylist: (id: number): Promise<{ deleted: number }> =>
|
||||
req(`/api/plex/playlists/${id}`, { method: "DELETE" }),
|
||||
plexPlaylistAddItem: (id: number, itemRk: string): Promise<{ ok: boolean }> =>
|
||||
req(`/api/plex/playlists/${id}/items`, { method: "POST", body: JSON.stringify({ item_rating_key: itemRk }) }),
|
||||
req(`/api/plex/playlists/${id}/items`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ item_rating_key: itemRk }),
|
||||
}),
|
||||
plexPlaylistRemoveItem: (id: number, itemRk: string): Promise<{ ok: boolean }> =>
|
||||
req(`/api/plex/playlists/${id}/items/${encodeURIComponent(itemRk)}`, { method: "DELETE" }),
|
||||
plexReorderPlaylist: (id: number, itemRks: string[]): Promise<{ ok: boolean }> =>
|
||||
req(`/api/plex/playlists/${id}/order`, { method: "PUT", body: JSON.stringify({ item_rating_keys: itemRks }) }),
|
||||
req(`/api/plex/playlists/${id}/order`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({ item_rating_keys: itemRks }),
|
||||
}),
|
||||
plexShow: (id: string): Promise<PlexShowDetail> =>
|
||||
req(`/api/plex/show/${encodeURIComponent(id)}`),
|
||||
// Mark a whole show / season watched or unwatched (all its episodes) for the current user.
|
||||
plexShowState: (rk: string, watched: boolean): Promise<{ changed: number; watched: boolean }> =>
|
||||
req(`/api/plex/show/${encodeURIComponent(rk)}/state`, { method: "POST", body: JSON.stringify({ watched }) }),
|
||||
req(`/api/plex/show/${encodeURIComponent(rk)}/state`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ watched }),
|
||||
}),
|
||||
plexSeasonState: (rk: string, watched: boolean): Promise<{ changed: number; watched: boolean }> =>
|
||||
req(`/api/plex/season/${encodeURIComponent(rk)}/state`, { method: "POST", body: JSON.stringify({ watched }) }),
|
||||
req(`/api/plex/season/${encodeURIComponent(rk)}/state`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ watched }),
|
||||
}),
|
||||
plexItem: (id: string): Promise<PlexItemDetail> =>
|
||||
req(`/api/plex/item/${encodeURIComponent(id)}`),
|
||||
// Cards for the actor filter-chips currently applied: name + cached headshot + in-scope film/show count.
|
||||
plexPeopleCards: (names: string[], scope: string): Promise<{ people: PlexPersonCard[] }> =>
|
||||
req(`/api/plex/people/cards?scope=${encodeURIComponent(scope)}&names=${encodeURIComponent(names.join(","))}`),
|
||||
plexSession: (id: string, start = 0, audio?: number | null, aoff = 0, multi = false): Promise<PlexPlaySession> => {
|
||||
req(
|
||||
`/api/plex/people/cards?scope=${encodeURIComponent(scope)}&names=${encodeURIComponent(names.join(","))}`,
|
||||
),
|
||||
plexSession: (
|
||||
id: string,
|
||||
start = 0,
|
||||
audio?: number | null,
|
||||
aoff = 0,
|
||||
multi = false,
|
||||
): Promise<PlexPlaySession> => {
|
||||
const p = new URLSearchParams({ start: String(Math.max(0, Math.floor(start))) });
|
||||
if (audio != null) p.set("audio", String(audio));
|
||||
if (aoff) p.set("aoff", String(aoff));
|
||||
if (multi) p.set("multi", "1"); // ≥2 audio tracks → multi-rendition HLS (client-side audio switch)
|
||||
return req(`/api/plex/stream/${encodeURIComponent(id)}/session?${p.toString()}`, { method: "POST" });
|
||||
return req(`/api/plex/stream/${encodeURIComponent(id)}/session?${p.toString()}`, {
|
||||
method: "POST",
|
||||
});
|
||||
},
|
||||
// WebVTT URL for a text subtitle track (used directly as a <track src>). Same-origin → cookie-authed.
|
||||
// `offset` = the session's real media start (0 for direct-play); the backend shifts the absolute
|
||||
@@ -1408,7 +1458,9 @@ export const api = {
|
||||
}),
|
||||
// Two-way Plex watch-sync (Phase A: owner link + one-time "Plex is master" import).
|
||||
plexWatchLink: (): Promise<PlexWatchLink> => req("/api/plex/watch/link"),
|
||||
plexWatchSetLink: (enabled: boolean): Promise<PlexWatchLink & { import: PlexWatchImport | null }> =>
|
||||
plexWatchSetLink: (
|
||||
enabled: boolean,
|
||||
): Promise<PlexWatchLink & { import: PlexWatchImport | null }> =>
|
||||
req("/api/plex/watch/link", { method: "POST", body: JSON.stringify({ enabled }) }),
|
||||
plexWatchImport: (): Promise<PlexWatchLink & { import: PlexWatchImport }> =>
|
||||
req("/api/plex/watch/import", { method: "POST" }),
|
||||
@@ -1428,7 +1480,10 @@ export const api = {
|
||||
adminDeleteUser: (id: number): Promise<{ deleted: number }> =>
|
||||
req(`/api/admin/users/${id}`, { method: "DELETE" }),
|
||||
schedulerStatus: (): Promise<SchedulerStatus> => req("/api/admin/scheduler"),
|
||||
updateSchedulerJob: (jobId: string, intervalMinutes: number): Promise<{ id: string; interval_minutes: number }> =>
|
||||
updateSchedulerJob: (
|
||||
jobId: string,
|
||||
intervalMinutes: number,
|
||||
): Promise<{ id: string; interval_minutes: number }> =>
|
||||
req(`/api/admin/scheduler/jobs/${jobId}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ interval_minutes: intervalMinutes }),
|
||||
@@ -1455,22 +1510,50 @@ export const api = {
|
||||
setupInfo: (token: string): Promise<{ secrets_manageable: boolean }> =>
|
||||
req("/api/setup/info", { headers: setupHeaders(token) }, { quiet: true }),
|
||||
setupAdmin: (token: string, email: string, password: string): Promise<{ ok: boolean }> =>
|
||||
req("/api/setup/admin", { method: "POST", headers: setupHeaders(token), body: JSON.stringify({ email, password }) }, { quiet: true }),
|
||||
req(
|
||||
"/api/setup/admin",
|
||||
{ method: "POST", headers: setupHeaders(token), body: JSON.stringify({ email, password }) },
|
||||
{ quiet: true },
|
||||
),
|
||||
setupConfig: (token: string, values: Record<string, unknown>): Promise<{ saved: string[] }> =>
|
||||
req("/api/setup/config", { method: "POST", headers: setupHeaders(token), body: JSON.stringify(values) }, { quiet: true }),
|
||||
req(
|
||||
"/api/setup/config",
|
||||
{ method: "POST", headers: setupHeaders(token), body: JSON.stringify(values) },
|
||||
{ quiet: true },
|
||||
),
|
||||
setupTestEmail: (token: string, to: string): Promise<{ ok: boolean }> =>
|
||||
req("/api/setup/test-email", { method: "POST", headers: setupHeaders(token), body: JSON.stringify({ to }) }, { quiet: true }),
|
||||
req(
|
||||
"/api/setup/test-email",
|
||||
{ method: "POST", headers: setupHeaders(token), body: JSON.stringify({ to }) },
|
||||
{ quiet: true },
|
||||
),
|
||||
setupFinish: (token: string): Promise<{ ok: boolean }> =>
|
||||
req("/api/setup/finish", { method: "POST", headers: setupHeaders(token) }, { quiet: true }),
|
||||
// --- auth: email + password (errors handled inline via quiet) ---
|
||||
register: (email: string, password: string): Promise<{ status: string }> =>
|
||||
req("/auth/register", { method: "POST", body: JSON.stringify({ email, password }) }, { quiet: true }),
|
||||
req(
|
||||
"/auth/register",
|
||||
{ method: "POST", body: JSON.stringify({ email, password }) },
|
||||
{ quiet: true },
|
||||
),
|
||||
passwordLogin: (email: string, password: string): Promise<{ ok: boolean }> =>
|
||||
req("/auth/password-login", { method: "POST", body: JSON.stringify({ email, password }) }, { quiet: true }),
|
||||
req(
|
||||
"/auth/password-login",
|
||||
{ method: "POST", body: JSON.stringify({ email, password }) },
|
||||
{ quiet: true },
|
||||
),
|
||||
requestPasswordReset: (email: string): Promise<{ status: string }> =>
|
||||
req("/auth/password-reset/request", { method: "POST", body: JSON.stringify({ email }) }, { quiet: true }),
|
||||
req(
|
||||
"/auth/password-reset/request",
|
||||
{ method: "POST", body: JSON.stringify({ email }) },
|
||||
{ quiet: true },
|
||||
),
|
||||
confirmPasswordReset: (token: string, password: string): Promise<{ ok: boolean }> =>
|
||||
req("/auth/password-reset/confirm", { method: "POST", body: JSON.stringify({ token, password }) }, { quiet: true }),
|
||||
req(
|
||||
"/auth/password-reset/confirm",
|
||||
{ method: "POST", body: JSON.stringify({ token, password }) },
|
||||
{ quiet: true },
|
||||
),
|
||||
// Confirm an email-verification token the SPA read from the URL fragment (SB3).
|
||||
verifyEmail: (token: string): Promise<{ ok: boolean }> =>
|
||||
req("/auth/verify", { method: "POST", body: JSON.stringify({ token }) }, { quiet: true }),
|
||||
@@ -1481,7 +1564,7 @@ export const api = {
|
||||
req(
|
||||
"/auth/set-password",
|
||||
{ method: "POST", body: JSON.stringify({ password, current_password: currentPassword }) },
|
||||
{ quiet: true }
|
||||
{ quiet: true },
|
||||
),
|
||||
// --- onboarding / admin ---
|
||||
requestAccess: (email: string): Promise<{ status: string }> =>
|
||||
@@ -1490,18 +1573,15 @@ export const api = {
|
||||
// sign-in. Returns whether a session was established.
|
||||
demoLogin: (email: string): Promise<{ authenticated: boolean }> =>
|
||||
req("/auth/demo", { method: "POST", body: JSON.stringify({ email }) }),
|
||||
adminDemoWhitelist: (): Promise<DemoWhitelistEntry[]> =>
|
||||
req("/api/admin/demo/whitelist"),
|
||||
adminDemoWhitelist: (): Promise<DemoWhitelistEntry[]> => req("/api/admin/demo/whitelist"),
|
||||
addDemoWhitelist: (email: string): Promise<DemoWhitelistEntry> =>
|
||||
req("/api/admin/demo/whitelist", { method: "POST", body: JSON.stringify({ email }) }),
|
||||
removeDemoWhitelist: (id: number) =>
|
||||
req(`/api/admin/demo/whitelist/${id}`, { method: "DELETE" }),
|
||||
removeDemoWhitelist: (id: number) => req(`/api/admin/demo/whitelist/${id}`, { method: "DELETE" }),
|
||||
resetDemo: (): Promise<{ reset: boolean; playlists_seeded: number }> =>
|
||||
req("/api/admin/demo/reset", { method: "POST" }),
|
||||
adminInvites: (status?: string): Promise<Invite[]> =>
|
||||
req(`/api/admin/invites${status ? `?status=${status}` : ""}`),
|
||||
approveInvite: (id: number) =>
|
||||
req(`/api/admin/invites/${id}/approve`, { method: "POST" }),
|
||||
approveInvite: (id: number) => req(`/api/admin/invites/${id}/approve`, { method: "POST" }),
|
||||
denyInvite: (id: number) => req(`/api/admin/invites/${id}/deny`, { method: "POST" }),
|
||||
addInvite: (email: string) =>
|
||||
req("/api/admin/invites", { method: "POST", body: JSON.stringify({ email }) }),
|
||||
@@ -1511,10 +1591,8 @@ export const api = {
|
||||
req(`/api/me/notifications?include_dismissed=${includeDismissed}`),
|
||||
notificationUnreadCount: (): Promise<{ count: number }> =>
|
||||
req("/api/me/notifications/unread_count"),
|
||||
markNotificationRead: (id: number) =>
|
||||
req(`/api/me/notifications/${id}/read`, { method: "POST" }),
|
||||
markAllNotificationsRead: () =>
|
||||
req("/api/me/notifications/read_all", { method: "POST" }),
|
||||
markNotificationRead: (id: number) => req(`/api/me/notifications/${id}/read`, { method: "POST" }),
|
||||
markAllNotificationsRead: () => req("/api/me/notifications/read_all", { method: "POST" }),
|
||||
dismissNotification: (id: number) =>
|
||||
req(`/api/me/notifications/${id}/dismiss`, { method: "POST" }),
|
||||
clearNotifications: () => req("/api/me/notifications/clear", { method: "POST" }),
|
||||
@@ -1563,19 +1641,17 @@ export const api = {
|
||||
req("/api/downloads/profiles", { method: "POST", body: JSON.stringify(p) }),
|
||||
updateDownloadProfile: (
|
||||
id: number,
|
||||
patch: { name?: string; spec?: DownloadSpec }
|
||||
patch: { name?: string; spec?: DownloadSpec },
|
||||
): Promise<DownloadProfile> =>
|
||||
req(`/api/downloads/profiles/${id}`, { method: "PATCH", body: JSON.stringify(patch) }),
|
||||
deleteDownloadProfile: (id: number) =>
|
||||
req(`/api/downloads/profiles/${id}`, { method: "DELETE" }),
|
||||
deleteDownloadProfile: (id: number) => req(`/api/downloads/profiles/${id}`, { method: "DELETE" }),
|
||||
|
||||
enqueueDownload: (body: {
|
||||
source: string;
|
||||
profile_id?: number;
|
||||
spec?: DownloadSpec;
|
||||
display_name?: string;
|
||||
}): Promise<DownloadJob> =>
|
||||
req("/api/downloads", { method: "POST", body: JSON.stringify(body) }),
|
||||
}): Promise<DownloadJob> => req("/api/downloads", { method: "POST", body: JSON.stringify(body) }),
|
||||
enqueueEdit: (body: {
|
||||
source_job_id: number;
|
||||
edit_spec: EditSpec;
|
||||
@@ -1606,7 +1682,7 @@ export const api = {
|
||||
display_uploader?: string;
|
||||
display_uploader_url?: string;
|
||||
extra_links?: string[];
|
||||
}
|
||||
},
|
||||
): Promise<DownloadJob> =>
|
||||
req(`/api/downloads/${id}`, { method: "PATCH", body: JSON.stringify(meta) }),
|
||||
shareDownload: (id: number, email: string): Promise<{ shared_with: string }> =>
|
||||
@@ -1619,12 +1695,12 @@ export const api = {
|
||||
downloadLinks: (jobId: number): Promise<ShareLink[]> => req(`/api/downloads/${jobId}/links`),
|
||||
createDownloadLink: (
|
||||
jobId: number,
|
||||
body: { allow_download?: boolean; expires_days?: number | null; password?: string }
|
||||
body: { allow_download?: boolean; expires_days?: number | null; password?: string },
|
||||
): Promise<ShareLink> =>
|
||||
req(`/api/downloads/${jobId}/links`, { method: "POST", body: JSON.stringify(body) }),
|
||||
updateDownloadLink: (
|
||||
linkId: number,
|
||||
patch: { allow_download?: boolean; expires_days?: number | null; password?: string }
|
||||
patch: { allow_download?: boolean; expires_days?: number | null; password?: string },
|
||||
): Promise<ShareLink> =>
|
||||
req(`/api/downloads/links/${linkId}`, { method: "PATCH", body: JSON.stringify(patch) }),
|
||||
revokeDownloadLink: (linkId: number): Promise<{ deleted: number }> =>
|
||||
@@ -1651,7 +1727,9 @@ export const api = {
|
||||
req(`/api/admin/downloads/quota/${userId}`),
|
||||
adminSetDownloadQuota: (
|
||||
userId: number,
|
||||
patch: Partial<Pick<AdminDownloadQuota, "max_bytes" | "max_concurrent" | "max_jobs" | "unlimited">>
|
||||
patch: Partial<
|
||||
Pick<AdminDownloadQuota, "max_bytes" | "max_concurrent" | "max_jobs" | "unlimited">
|
||||
>,
|
||||
): Promise<AdminDownloadQuota> =>
|
||||
req(`/api/admin/downloads/quota/${userId}`, { method: "PUT", body: JSON.stringify(patch) }),
|
||||
adminResetDownloadQuota: (userId: number): Promise<AdminDownloadQuota> =>
|
||||
|
||||
Reference in New Issue
Block a user