1
Fork 0
mirror of https://github.com/thegeneralist01/archivr synced 2026-07-22 03:05:32 +02:00

fix(frontend): block playlist submission unless probe is done

Previous guard only blocked while playlistProbeState==='probing'.
Two remaining bypass paths:
- idle: 800ms debounce not yet fired after URL typed
- error: probe failed — no per-video quality data available

Change anyProbing and handleArchive guard to:
  isPlaylistSource(locator) && playlistProbeState !== 'done'

This means idle/probing/error all block submission for playlist items.
error is intentionally blocking — without quality data the per-video
requirement can't be satisfied; user must retry or remove the URL.
This commit is contained in:
TheGeneralist 2026-07-20 22:57:34 +02:00
parent dcdfa78073
commit 1cc5f73ae1
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
3 changed files with 16 additions and 10 deletions

View file

@ -392,7 +392,8 @@ export default function CaptureDialog({ open, archiveId, onClose, onCaptured, on
const toSubmit = items.filter(it => it.locator.trim())
if (toSubmit.length === 0) return
if (toSubmit.some(it => hasConflict(it))) return
if (toSubmit.some(it => it.playlistProbeState === 'probing' || it.probeState === 'probing')) return
if (toSubmit.some(it => it.probeState === 'probing' ||
(isPlaylistSource(it.locator) && it.playlistProbeState !== 'done'))) return
const batchId = toSubmit.length > 1
? (crypto.randomUUID?.() ?? `batch-${Date.now()}`)
: null
@ -517,7 +518,12 @@ export default function CaptureDialog({ open, archiveId, onClose, onCaptured, on
const pendingCount = items.filter(it => it.locator.trim()).length
const anyConflict = items.some(it => hasConflict(it))
const anyProbing = items.some(it => it.playlistProbeState === 'probing' || it.probeState === 'probing')
const anyProbing = items.some(it =>
it.probeState === 'probing' ||
// For playlist sources block unless probe completed successfully:
// idle = debounce not yet fired; probing = in flight; error = no quality data.
(isPlaylistSource(it.locator) && it.playlistProbeState !== 'done')
)
return (
<dialog ref={dialogRef} className="capture-dialog">