feat(pinchflat): Media Profiles — named download presets per Library source
A MediaProfile bundles { kind, quality, options, outputTemplate, extraArgs }
that a Source points at via Source.profileId, overriding the global defaults
field-by-field for that source's downloads.
Backend mirrors CommandTemplate: profiles.ts (createJsonStore, PROFILES_MAX,
isProfileLike + sanitize), CRUD IPC (profiles:list/save/remove) + preload +
useProfiles store; Source.profileId + sources:set-profile. Pure resolution
in @shared/profileResolve.ts (profile → global, per field; unit-tested).
Applied in the sources-store enqueueItems; a per-download collectionOutput-
Template override threads to buildArgs so a profile's outputTemplate wins.
UI: ProfileManager (mirrors TemplateManager) in a new Settings → Advanced →
Media profiles card, plus a per-source Profile picker in the Library source
detail. Both live-verified in the preview; 354 tests pass.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import {
|
||||
type CookiesStatus,
|
||||
type CookiesLoginResult,
|
||||
type CommandTemplate,
|
||||
type MediaProfile,
|
||||
type CommandPreviewResult,
|
||||
type ErrorLogEntry,
|
||||
type BackupExportResult,
|
||||
@@ -126,6 +127,14 @@ const api = {
|
||||
removeTemplate: (id: string): Promise<CommandTemplate[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.templatesRemove, id),
|
||||
|
||||
listProfiles: (): Promise<MediaProfile[]> => ipcRenderer.invoke(IpcChannels.profilesList),
|
||||
|
||||
saveProfile: (profile: MediaProfile): Promise<MediaProfile[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.profilesSave, profile),
|
||||
|
||||
removeProfile: (id: string): Promise<MediaProfile[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.profilesRemove, id),
|
||||
|
||||
/** Build the exact yt-dlp command line for the given form state, without running it. */
|
||||
previewCommand: (opts: StartDownloadOptions): Promise<CommandPreviewResult> =>
|
||||
ipcRenderer.invoke(IpcChannels.commandPreview, opts),
|
||||
@@ -214,6 +223,10 @@ const api = {
|
||||
setSourceWatched: (id: string, watched: boolean): Promise<Source[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourceSetWatched, id, watched),
|
||||
|
||||
/** Point a source at a MediaProfile, or clear it (profileId = null). */
|
||||
setSourceProfile: (id: string, profileId: string | null): Promise<Source[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourceSetProfile, id, profileId),
|
||||
|
||||
/** Re-index all watched sources; resolves with the videos found new. Named to
|
||||
* match the main function `syncWatchedSources` (L92). */
|
||||
syncWatchedSources: (): Promise<SyncResult> => ipcRenderer.invoke(IpcChannels.sourcesSync),
|
||||
|
||||
Reference in New Issue
Block a user