diff --git a/PLAN-download-quality-flags.md b/PLAN-download-quality-flags.md new file mode 100644 index 00000000..f68ccb89 --- /dev/null +++ b/PLAN-download-quality-flags.md @@ -0,0 +1,123 @@ +# Plan: Download Quality Flags Refactor + +## Background + +The current `force_download_all` flag is misleadingly named. It does NOT lower +quality requirements or "force download any quality". It only skips the library +ownership check so every track is treated as missing and re-downloaded regardless +of whether the user already owns it. + +This causes two distinct problems: + +1. The name implies quality-related behavior that doesn't exist. +2. The discover sync tab currently sends `force_download_all: true`, which means + every discover playlist sync re-downloads tracks the user already owns. + +Additionally, users have expressed a real need for a per-batch quality override: +their main library should stay strict (FLAC preferred, high bitrate) while +rotating/ephemeral playlists (discover) should grab whatever is available for +quantity over quality. + +Per-client fallback settings already exist (Soulseek quality profile +`fallback_enabled`, Deezer/Tidal/Qobuz `allow_fallback` chains) but they are +global all-or-nothing flags. There is no way today to say "relax quality just +for this one batch". + +## Goals + +1. Rename `force_download_all` to reflect what it actually does (skip ownership + check / re-download owned). +2. Stop discover sync from blindly re-downloading owned tracks. +3. Add a new per-batch "Any Quality" flag that bypasses quality filtering for + that specific batch only, without touching the user's global quality + settings. + +## Non-Goals + +- No changes to the global per-client quality/fallback settings. +- No changes to the matching engine scoring. +- No changes to album consistency / MusicBrainz preflight logic. + +## Phase 0 (this PR): UI framework only + +Scope is tiny and safe to ship immediately. + +- Replace the "Force DL" toggle in the Sync page Discover tab with an "Any + Quality" toggle. +- Leave the new toggle permanently disabled / greyed out for now. +- Tooltip on the toggle reads something like "Coming soon: download any + available quality for this batch". +- Remove the `force_download_all: true` body payload from the discover sync + path. Discover playlists will now always run ownership analysis. +- No backend changes in this phase. + +Files touched: +- `webui/static/discover.js` - replace toggle HTML, remove `forceDownload` + plumbing from `syncDiscoverPlaylistFromTab` / `_doSyncDiscoverPlaylist`. + +## Phase 1: Rename `force_download_all` + +Rename to `skip_ownership_check` (backend) and surface in the UI as +"Re-download Owned" (or equivalent). + +- Backend: add new key `skip_ownership_check` everywhere the flag is used. + Accept both keys on inbound API payloads for one release (back-compat). +- Frontend: rename the Wishlist / Downloads modal toggles, keep the same + default behavior (wishlists still skip the library check by default). +- Update `helper.js` tooltip description to match the new name and behavior. + +Files touched: +- `web_server.py` (lines ~15663, 24858, 25858, 26065, 29051, 29057, 29062, + 29104, 29135, 33556, 33596) +- `webui/static/downloads.js` (lines ~195, 598, 2152, 2155, 2195, 2436) +- `webui/static/wishlist-tools.js` (line ~6347) +- `webui/static/helper.js` (lines ~663) + +## Phase 2: Implement "Any Quality" per-batch override + +Introduce a new batch flag `any_quality` that, when set, bypasses quality +filtering for that batch only. + +Backend behavior: +- Add `any_quality` to the batch dict alongside `skip_ownership_check`. +- For Soulseek: when `any_quality` is true, skip the call to + `soulseek_client.filter_results_by_quality_preference()` and pass ranked + candidates through unchanged. +- For Deezer / Tidal / Qobuz: when `any_quality` is true, temporarily force + the candidate selection path to treat `allow_fallback=True` AND start from + the lowest quality tier so downloads succeed fastest. +- The flag is per-batch only. Global quality profile / `allow_fallback` + settings remain untouched. + +Frontend behavior: +- Enable the "Any Quality" toggle added in Phase 0. +- Remove the "Coming soon" tooltip, replace with a real description. +- Wire the toggle into the discover sync POST body as `any_quality: true`. +- Consider exposing the same toggle on the Wishlist / Downloads modal. + +Files touched: +- `web_server.py` - batch creation + candidate selection path +- `core/soulseek_client.py` - accept override in filter call +- `core/deezer_download_client.py`, `core/tidal_download_client.py`, + `core/qobuz_client.py` - accept per-request quality override +- `webui/static/discover.js` - enable toggle, send flag +- `webui/static/downloads.js` - add matching toggle on manual download + modals + +## Risks / Open Questions + +- Soulseek quality profile bypass: is it safe to pass all density-filtered + candidates through without the priority filter? Likely yes, since the + matching engine already ranks by confidence and peer quality. +- Streaming clients with strict API quality params (Tidal HiRes vs Lossless + entitlement, Qobuz subscription tiers): forcing lowest tier should be safe + for all users regardless of subscription. +- Back-compat on the renamed flag: keep the old `force_download_all` key + accepted for at least one release cycle to avoid breaking any third-party + callers or stale browser sessions. + +## Rollout + +- Phase 0 ships with this PR (UI framework + discover fix). +- Phase 1 and Phase 2 can ship as separate PRs on dev. +- No migrations required; all flags are request-scoped and batch-scoped. diff --git a/webui/static/discover.js b/webui/static/discover.js index 85fc68b9..64e35d9a 100644 --- a/webui/static/discover.js +++ b/webui/static/discover.js @@ -9123,10 +9123,10 @@ function renderDiscoverSyncCard(playlist, container, sourceLabel) { -
- -