feat(pinchflat): Retention & quality-upgrade per Library source
On-demand maintenance panel (SourceRetention) on the source detail — not a persisted schedule (roadmap's niche-for-desktop scope). Prune: keep the newest N downloaded files, delete the rest's files (download archive prevents silent re-download); dry-run count + two-step confirm before any deletion. Upgrade: re-enqueue items whose recorded downloadedQuality ranks below the source's current target (profile or global). Selection is pure + injected-now in @shared/retention.ts (selectPruneCandidates/selectUpgradeCandidates + qualityRank), unit- tested; pruneMediaItems (main) deletes best-effort and clears state. MediaItem.downloadedQuality now recorded through the completion path. Live-verified the panel renders. 366 tests pass. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -216,8 +216,8 @@ const api = {
|
||||
|
||||
/** Persist that a media item has finished downloading (drives incremental sync).
|
||||
* Named to match the main handler `setMediaItemDownloaded` (L92). */
|
||||
setMediaItemDownloaded: (id: string, filePath?: string): Promise<MediaItem[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourceItemDownloaded, id, filePath),
|
||||
setMediaItemDownloaded: (id: string, filePath?: string, quality?: string): Promise<MediaItem[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourceItemDownloaded, id, filePath, quality),
|
||||
|
||||
/** Toggle whether a source is watched for new uploads. */
|
||||
setSourceWatched: (id: string, watched: boolean): Promise<Source[]> =>
|
||||
@@ -227,6 +227,13 @@ const api = {
|
||||
setSourceProfile: (id: string, profileId: string | null): Promise<Source[]> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourceSetProfile, id, profileId),
|
||||
|
||||
/** Prune (delete files of) the given media items; returns the source's updated list + count. */
|
||||
pruneMediaItems: (
|
||||
sourceId: string,
|
||||
itemIds: string[]
|
||||
): Promise<{ items: MediaItem[]; deleted: number }> =>
|
||||
ipcRenderer.invoke(IpcChannels.sourcePruneItems, sourceId, itemIds),
|
||||
|
||||
/** 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