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

feat(server,frontend): playlist quality selector + per-video overrides + sync UI

routes.rs:
- CaptureBody gains per_item_quality (HashMap<String,String>, serde(default))
  and sync (bool, serde(default)); both validated before use
  - per_item_quality values validated against same quality predicate as top-level
    quality field ("best"|"audio"|"NNNp") so bad per-video values are rejected
    at the API boundary rather than silently falling through to quality_format
- capture_handler threads body.per_item_quality + body.sync into CaptureConfig
  (replaces hardcoded empty stubs); rearchive_handler keeps empty defaults
- New POST /api/archives/:id/captures/probe-playlist: calls
  probe_playlist_qualities via spawn_blocking; 400 for non-playlist locator,
  502 on yt-dlp failure, returns PlaylistProbeResult as JSON

api.js:
- probePlaylist(archiveId, locator): POST probe-playlist endpoint
- submitCapture: forwards per_item_quality (non-empty) and sync:true from
  extraExtensions param added to submitBgJob

CaptureDialog.jsx:
- isPlaylistSource(): detects yt:/youtube: playlist/@/channel, ytm:playlist/,
  YouTube/YTM HTTP(S) URLs with list= param or channel pathnames
- makeItem(): 6 new playlist state fields
- applyPlaylistQuality(): conflict logic — videos that can reach selected
  quality get it set; videos that can't and have no prior selection are left
  null (conflict); videos with a prior selection keep it when quality is raised
- hasConflict(): any playlistItems entry with quality===null
- updateLocator(): isPlaylistSource branch with 800ms debounce→probePlaylist;
  existing isVideoSource path unchanged
- Archive button disabled when anyConflict or any probe in flight
- Per-video expand list with individual quality selects, conflict badges,
  sync toggle (appears after probe completes)

styles.css: playlist expansion, conflict, sync toggle CSS
This commit is contained in:
TheGeneralist 2026-07-20 22:46:30 +02:00
parent 096c98a678
commit 7499deeab0
Signed by: thegeneralist01
SSH key fingerprint: SHA256:pp9qddbCNmVNoSjevdvQvM5z0DHN7LTa8qBMbcMq/R4
8 changed files with 447 additions and 87 deletions

View file

@ -2866,3 +2866,77 @@ body.has-audio-bar { padding-bottom: 56px; }
font-size: 0.85em;
opacity: 0.55;
}
/* ── Playlist quality expansion ──────────────────────────── */
.capture-playlist-toggle {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 0.75rem;
color: var(--muted);
background: none;
border: none;
cursor: pointer;
padding: 2px 6px;
}
.capture-playlist-toggle:hover { color: var(--text); }
.capture-conflict-badge {
font-size: 0.7rem;
color: #c07000;
background: #fff3cd;
border: 1px solid #e0a000;
border-radius: 4px;
padding: 1px 6px;
margin-left: 6px;
}
.capture-playlist-items {
border-top: 1px solid var(--line-soft);
padding: 4px 0;
max-height: 300px;
overflow-y: auto;
}
.capture-playlist-item {
display: flex;
align-items: center;
gap: 8px;
padding: 4px 12px;
font-size: 0.8rem;
}
.capture-playlist-item--conflict {
background: #fff8f0;
}
.capture-playlist-item-title {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text);
}
.capture-item-quality {
font-size: 0.75rem;
padding: 2px 4px;
border: 1px solid var(--line);
border-radius: 4px;
background: var(--bg);
color: var(--text);
}
.capture-playlist-conflict-badge {
font-size: 0.7rem;
color: #c07000;
white-space: nowrap;
}
.capture-sync-row {
display: flex;
align-items: center;
gap: 6px;
padding: 6px 12px;
font-size: 0.78rem;
color: var(--muted);
border-top: 1px solid var(--line-soft);
cursor: pointer;
}
.capture-sync-row input[type=checkbox] { cursor: pointer; }