Fix M17: statusByUrl picks highest-priority status for duplicate URLs

LibraryView mapped url -> status by last-write, so when a URL had multiple
queue entries ("Download anyway"), the row reflected whichever item was
iterated last. Added a STATUS_PRIORITY ranking (completed > downloading >
queued > saved > paused > error > canceled) and keep the highest-priority
status per URL, so a row shows the most meaningful state of that video.

typecheck + 242 tests + eslint green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-30 15:37:52 -04:00
parent c55e131fb0
commit af6c4d3c67
2 changed files with 21 additions and 2 deletions
+1 -1
View File
@@ -272,7 +272,7 @@ token system + shared primitives (UI/SIMP — high value, larger effort) · i18n
fallback is dependency-free (no Fluent/theme provider — the crash may have come from that tree), logs via
`componentDidCatch`, shows the error message, and offers a Reload button (`window.location.reload()`;
persisted data lives in main, so nothing is lost).*
- [ ] **M17 — `statusByUrl` collapses duplicate URLs.** LibraryView maps URL→status into one
- [x] **M17 — `statusByUrl` collapses duplicate URLs.** LibraryView maps URL→status into one
`Map`; with "Download anyway" duplicates, a row can reflect the wrong item's state.
- [ ] **M18 — Audio "quality" presets hard-code MP3.** `QUALITY_OPTIONS.audio` labels ("Best
(MP3)", "320 kbps") are shown even when `downloadOptions.audioFormat` is opus/flac/wav, so the
+20 -1
View File
@@ -59,6 +59,19 @@ type LibRow =
/** Above this many flattened rows, the item list switches to a virtualized panel. */
const VIRTUALIZE_AT = 100
// When a URL appears more than once in the queue ("Download anyway" duplicates),
// the library row should reflect the most meaningful state: a finished copy wins,
// then anything in flight, then terminal failures (M17).
const STATUS_PRIORITY: Record<DownloadStatus, number> = {
completed: 6,
downloading: 5,
queued: 4,
saved: 3,
paused: 2,
error: 1,
canceled: 0
}
const useStyles = makeStyles({
root: { display: 'flex', flexDirection: 'column', gap: '18px' },
sub: { color: tokens.colorNeutralForeground3 },
@@ -308,7 +321,13 @@ export function LibraryView(): React.JSX.Element {
// Live per-URL queue status so a video row reflects its real download state.
const statusByUrl = useMemo(() => {
const m = new Map<string, DownloadStatus>()
for (const d of downloadItems) m.set(d.url, d.status)
for (const d of downloadItems) {
const prev = m.get(d.url)
// Keep the highest-priority status when a URL has duplicate queue entries.
if (prev === undefined || STATUS_PRIORITY[d.status] > STATUS_PRIORITY[prev]) {
m.set(d.url, d.status)
}
}
return m
}, [downloadItems])