Download manager: cancel/retry/queue controls + dedup off-switch

Download management UI (web + desktop):
- Cancel a running job (SIGKILL, marked "cancelled" so it isn't auto-retried
  and shows a distinct state rather than a misleading error class)
- Cancel a still-queued job before it starts
- Manually retry a failed/cancelled job (fresh auto-retry budget)
- Live speed · ETA · % on running jobs, parsed from the yt-dlp progress line
- Expandable full per-job log fetched on demand
New endpoints: POST /api/jobs/:idx/{cancel,retry}, GET /api/jobs/:idx/log,
DELETE /api/queued/:idx.

Perceptual-dedup off-switch:
- backup.dedup_enabled (default true) hard-disables the "similar content"
  scan in both UIs; the web scan endpoint returns {disabled:true} and the
  desktop scan no-ops with a note. Wired through all five settings touchpoints.

Docs: README seeking note + ROADMAP recently-shipped updates for the prior
seekable-playback / federation / auto-tagging work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-06-15 16:35:05 -07:00
parent c3ff9121f6
commit 9ed62935f5
7 changed files with 305 additions and 33 deletions

View file

@ -160,10 +160,16 @@ pub struct BackupSection {
/// live in [`crate::download_options::DownloadOptions`].
#[serde(default)]
pub fetch_comments: bool,
/// Whether the perceptual "similar content" dedup scan is available. On by
/// default; set to `false` to hard-disable fingerprinting in both UIs (the
/// scan button no-ops / the web scan endpoint returns 409). Useful on
/// low-powered machines where the ffmpeg keyframe pass is unwanted.
#[serde(default = "default_true")]
pub dedup_enabled: bool,
}
fn default_max_concurrent() -> usize { 3 }
fn default_true() -> bool { true }
pub fn default_true() -> bool { true }
fn default_sponsorblock_mode() -> String { "mark".to_string() }
/// `[player]` table — external player and browser cookie source.
@ -300,6 +306,7 @@ impl Config {
youtube_player_clients: String::new(),
sponsorblock_mode: default_sponsorblock_mode(),
fetch_comments: false,
dedup_enabled: true,
},
player: PlayerSection::default(),
ui: UiSection::default(),