From 2b8f6f861106eee6d95e97a15760b5c906b33b80 Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sat, 27 Jun 2026 23:58:22 -0700 Subject: [PATCH] Release 2.8.0: version bump + docker-publish tag + What's New / version modal + PR description - web_server: _SOULSYNC_BASE_VERSION 2.7.9 -> 2.8.0 - docker-publish.yml: default version_tag -> 2.8.0 - pr_description.md: rewritten for 2.8.0 (preview-clip cleanup, unverified-queue self-heal #934, album-completeness split albums #936, clear-completed, youtube cookies, #937, discography speed, wishlist art, dashboard perf #935, bounded memory #802) - helper.js: WHATS_NEW carries the 2.8.0 block + folded "Earlier versions" summary; VERSION_MODAL_SECTIONS leads with 2.8.0 highlights, rolls 2.7.9 into an aggregator --- .github/workflows/docker-publish.yml | 4 +- pr_description.md | 55 ++++++++--------- web_server.py | 2 +- webui/static/helper.js | 92 ++++++++++++++++------------ 4 files changed, 80 insertions(+), 73 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 91daceac..8b1d29d3 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -9,9 +9,9 @@ on: workflow_dispatch: inputs: version_tag: - description: 'Version tag (e.g. 2.7.9)' + description: 'Version tag (e.g. 2.8.0)' required: true - default: '2.7.9' + default: '2.8.0' jobs: build-and-push: diff --git a/pr_description.md b/pr_description.md index c2e865ac..19659f76 100644 --- a/pr_description.md +++ b/pr_description.md @@ -1,49 +1,44 @@ -# soulsync 2.7.9 — `dev` → `main` +# soulsync 2.8.0 — `dev` → `main` -a big one. the headline is the new **best-quality download system + a real quality profile**, plus a much smarter **Discover** page, a new **Wing It Pool**, a redesigned **Auto-Sync** board, and a pile of reported fixes (multi-disc albums, playlist sync labels, the import-vs-quarantine race). +mostly a quality + reliability release. the headline is a big cleanup of the **Unverified review queue** (it stops inflating and self-heals), a new **Preview Clip Cleanup** tool, smarter **Album Completeness** for split/fragmented albums, and a real pass on **dashboard performance** (especially Firefox/Zen). plus a pile of reported fixes. --- ## what's new -### best-quality downloads + a real quality profile -downloads are now driven by a **ranked-target quality profile** instead of a fixed preference. you order the formats you want (drag to reorder — FLAC 24/192 down to mp3, every format controllable, with "all lossless / all lossy" group shortcuts), and: -- **best-quality search mode** pools candidates across *every* source per query and grabs the highest-quality copy that meets your profile — not just the first/fastest match. priority mode is still there, now with an opt-in **"rank-based download order"** toggle if you want quality-first ordering there too. -- each streaming source's download tier is derived from the one global profile, so you set it once. -- AAC is an opt-in tier; old per-source Hi-Res preferences migrate into the profile automatically. +### Preview Clip Cleanup (new Tools job) +the HiFi source sometimes hands back a ~30-second **preview clip** instead of the full song, and it lands looking like a normal track. the new job scans your short tracks, checks how long each one *should* be from its metadata source, and flags the previews. approve a finding and it deletes the clip, drops it from the library, and re-wishlists the full version. each finding has a **▶ Play** button + a file-length-vs-real-length readout so you can confirm it's busted before approving. conservative by design — genuine short tracks and anything it can't verify are left alone. -### quarantine, cleaned up + safer -- the quarantine view is **consolidated into the Downloads page** as a filter (no separate place to check), with real audio quality shown on the rows and approve/retry handled inline. -- **AcoustID fail-closed mode** (opt-in): only import tracks that actually verify, so a wrong file never lands in your library. -- **silence + truncated-download guards** catch mostly-silent preview files and downloads that are shorter than their container claims, before they import. -- a **library quality check** runs as a repair job and can flag files that are upgradeable to your preferred quality. +### the Unverified queue stops inflating + self-heals (#934) +big one for anyone who saw thousands of "unverified" rows. the AcoustID scan was creating a fresh history row every run and leaving already-verified files stuck as "unverified" (a frozen import-time path that stopped matching once the file moved). now: +- scans no longer duplicate rows and heal on the spot, and +- a one-time **reconcile** on startup clears the existing backlog from your library's truth — no re-scan needed, including human-verified files a scan skips, and +- a **🧹 Clean orphaned** button removes dead rows whose file is genuinely gone (with a safety gate that refuses to run if your library looks offline). +the Unverified review rows also got the nicer Quarantine-style cards (artwork, inline details). *(thanks @nick2000713 for #938.)* -### Discover got a lot smarter -- **"Based On Your Listening"** — a new artist row, ranked from who you actually *play* the most (consensus + recency weighted), with a "because you listen to X, Y" reason on each card. -- **"Your Listening Mix"** — a playable track playlist built from those artists' top tracks. works on **any** metadata source (falls back to Deezer's public API), not just Spotify. -- **Fresh Tape** actually fills now — it was starving down to 5–10 tracks because future-dated albums ate the candidate budget. -- the **SoulSync Discovery** tab on the Sync page now lists *every* playlist kind (incl. the Listening Mix) so you can mirror + auto-sync them. +### Album Completeness handles split albums (#936, #929, #931) +a physical album split across multiple library rows used to show every fragment as falsely "incomplete." it now groups the validated fragments into one logical album and emits a single correct finding — grouping by a shared id **and** validating at the track level, so unrelated rows never get fused. also recognizes MusicBrainz as a readable album source. *(thanks @ragnarlotus.)* -### Wing It Pool -a new button next to **Discovery Pool** on the Mirrored Playlists tab. Wing It auto-matches tracks it couldn't match to metadata on a best-effort guess — those were invisible until now. the Wing It Pool opens to a two-card view (**guesses to review** + **resolved**) so you can verify or re-match what it guessed. - -### Auto-Sync Manager redesign -the scheduling board no longer scrolls sideways through a wall of columns. intervals (hourly) and days (weekly) are now **horizontal lanes** — empty ones collapse, busy ones grow, and the scroll position holds when you add a playlist. +### Clear Completed is back on the Downloads page +since completed downloads now persist across restart, the **Clear Completed** button had gone missing for them. it's back — it clears the live list *and* the persisted history so the page actually empties and stays empty (your files are untouched). --- ## fixes -- **multi-disc albums showed disc-2 tracks as "missing" / under disc 1 (#927)** — the library scan never read the disc number, so every track was stored as disc 1. it now captures the real disc from Jellyfin/Plex/Navidrome at scan time. *(re-scan your library once to backfill existing tracks.)* -- **playlists always said "Never Synced" (#925)** — auto-synced/mirrored playlists were only checked against the direct-sync status, never their auto-sync status. fixed (thanks @ramonskie). -- **tracks imported while quarantined / shown "completed" (#928)** — a race let both the browser poll and the download monitor post-process the same finished download. an atomic claim now ensures exactly one path handles it (thanks @nick2000713). -- **library card badges hijacked the click** — clicking the watchlist eye or a source badge on an artist card also opened the artist detail page (and the badge's own link). badges now do only their own thing. +- **pasted YouTube cookies threw `unsupported browser: "custom"` (Docker)** — the client passed the "Paste cookies.txt" mode through as a browser name instead of using the cookies file. now it loads the pasted `cookies.txt` correctly — the only auth path that works on a headless/Docker box. *(thanks HellRa1SeR.)* +- **longer remasters quarantined as "truncated" (#937)** — the duration check was symmetric, so a remaster running a few seconds *longer* than the metadata got rejected like a truncated download. it's asymmetric now: short files stay strict, longer versions get room. *(thanks @diegocade1.)* +- **"Add to Wishlist" from an artist discography was painfully slow** — ~15–30s *per track* on a large library, because the per-track library-ownership check fell through to a full-table fuzzy scan. it now matches in-memory against the artist's tracks once — effectively instant. +- **wishlist art was blank for re-downloads / preview re-fetches** — library-sourced items stored a relative media-server path that doesn't render in a browser. they're normalized on read now, so album + artist art show up (fixes already-saved items too). +- **watchlist didn't record automatic scans (#933)** + **watchlist fused different editions of an album as one.** +- **manual search:** a pasted Qobuz/Tidal track now floats to the top of results (#932). +- **Popular Picks came up empty on Deezer** — a popularity-threshold scale mismatch. --- -## under the hood -- music automations page no longer shows video-app automations (they live in the shared engine DB). -- quality-settings tile tidied up — collapsible ⓘ help instead of walls of text, proper reset button, dropped the redundant per-source "quality is global" notes. -- download clients don't crash on init when the download path can't be created. +## performance + UI + +- **dashboard GPU usage, especially on Firefox/Zen (#935)** — frosted-glass blur, cursor-glow blobs, and the worker-orb animation were repainting every frame. trimmed the worst offenders, made the orb loop hold a steady framerate on Firefox instead of dropping to ~1fps, and set **Background Particles OFF by default**. the dashboard system-memory tile now also shows SoulSync's own RAM. +- **bounded memory growth (#802)** — browsing every page used to climb RSS into the GBs (plexapi's XML trees deferring GC) and could lock the app up. a lightweight sweeper now collects + hands memory back to the OS as it grows, so it sawtooths and settles instead of climbing. --- diff --git a/web_server.py b/web_server.py index a9b69d1b..7edda4bb 100644 --- a/web_server.py +++ b/web_server.py @@ -40,7 +40,7 @@ logger = setup_logging(_log_level, _log_path) # App version — single source of truth for backup metadata, system-info, update check, etc. # Semver: MAJOR.MINOR.PATCH. Bump at each dev→main release. -_SOULSYNC_BASE_VERSION = "2.7.9" +_SOULSYNC_BASE_VERSION = "2.8.0" def _build_version_string(): """Append short commit hash to version when available (e.g. 2.35+abc1234).""" diff --git a/webui/static/helper.js b/webui/static/helper.js index ddcac5cd..168b98c0 100644 --- a/webui/static/helper.js +++ b/webui/static/helper.js @@ -3404,19 +3404,20 @@ function closeHelperSearch() { const WHATS_NEW = { // Convention: keep only the CURRENT release here, plus a single brief // "Earlier versions" summary entry. Don't accumulate old per-version blocks. - '2.7.9': [ - { date: 'June 2026 — 2.7.9 release' }, - { title: 'Best-quality downloads + a real quality profile', desc: 'downloads now follow a ranked-target quality profile — drag to order every format (FLAC 24/192 → mp3, with "all lossless / all lossy" shortcuts). best-quality search mode pools candidates across EVERY source per query and grabs the highest-quality copy that meets your profile; priority mode gains an opt-in "rank-based download order" toggle. each streaming source\'s tier comes from the one profile, AAC is an opt-in tier, and old per-source Hi-Res prefs migrate in automatically.', page: 'settings' }, - { title: 'Quarantine cleaned up + safer imports', desc: 'the quarantine view is folded into the Downloads page as a filter (real audio quality on the rows, inline approve/retry). opt-in AcoustID fail-closed mode only imports tracks that actually verify; silence + truncated-download guards catch preview/short files before they import; a library quality check runs as a repair job and flags upgradeable files.', page: 'downloads' }, - { title: 'Discover — Based On Your Listening + Listening Mix', desc: 'a new artist row ranked from who you actually PLAY the most (consensus + recency weighted, with a "because you listen to X" reason), plus "Your Listening Mix" — a playable track playlist of those artists\' top tracks that works on ANY metadata source (Deezer public fallback). the SoulSync Discovery sync tab now lists every playlist kind so you can mirror + auto-sync them.', page: 'discover' }, - { title: 'Fresh Tape fills properly now', desc: 'it was starving down to 5–10 tracks because future-dated/announced albums sorted to the top and ate the candidate budget before being skipped. released albums now fill it.', page: 'discover' }, - { title: 'Wing It Pool', desc: 'a new button next to Discovery Pool on the Mirrored Playlists tab. Wing It auto-matches tracks it couldn\'t match to metadata on a best-effort guess — previously invisible. the Wing It Pool shows a two-card view (guesses to review + resolved) so you can verify or re-match them.', page: 'sync' }, - { title: 'Auto-Sync Manager redesign', desc: 'the scheduling board no longer scrolls sideways through a wall of columns — intervals (hourly) and days (weekly) are now horizontal lanes; empty ones collapse, busy ones grow, and the scroll holds when you drop a playlist in.', page: 'sync' }, - { title: 'Multi-disc albums fixed (#927)', desc: 'the scan never read the disc number, so every track stored as disc 1 — disc-2+ tracks showed as "missing" or under disc 1. it now captures the real disc from Jellyfin/Plex/Navidrome at scan time. re-scan once to backfill existing tracks.', page: 'library' }, - { title: 'Playlists always said "Never Synced" (#925)', desc: 'auto-synced/mirrored playlists were only checked against the direct-sync status, never their auto-sync status, so they read "Never Synced" even when synced. fixed (thanks @ramonskie).', page: 'sync' }, - { title: 'Tracks imported while quarantined (#928)', desc: 'a race let both the browser poll and the download monitor post-process the same finished download — imported despite quarantine, or "completed" while quarantined. an atomic claim now ensures exactly one path handles it (thanks @nick2000713).', page: 'downloads' }, - { title: 'Library card badges hijacked the click', desc: 'clicking the watchlist eye or a source badge on an artist card also opened the artist detail page (and the badge\'s own link). badges now do only their own thing — only the card opens detail.', page: 'library' }, - { title: 'Earlier versions', desc: '2.7.8 added Align Playlists (fix the order on the server) + re-add-to-wishlist from sync history, plus the #922 Spotify-Free label and #918 iTunes-cache fixes. 2.7.7 was a fix sweep; 2.7.6 listenbrainz/youtube export; 2.7.3 the Quality Upgrade Finder; 2.7.0 made multi-user real.' }, + '2.8.0': [ + { date: 'June 2026 — 2.8.0 release' }, + { title: 'Preview Clip Cleanup (new Tools job)', desc: 'the HiFi source sometimes returns a ~30s preview clip instead of the full song, landing as a normal track. the new job scans your short tracks, checks how long each should be from its metadata source, and flags the previews. approve a finding and it deletes the clip, drops it from the library, and re-wishlists the full version. each finding has a ▶ Play button + a file-length-vs-real-length readout so you can confirm before approving.', page: 'downloads' }, + { title: 'Unverified queue stops inflating + self-heals (#934)', desc: 'the AcoustID scan was creating a fresh history row every run and leaving already-verified files stuck "unverified". now scans don\'t duplicate rows, a one-time reconcile on startup clears the existing backlog from your library truth (no re-scan), and a 🧹 Clean orphaned button removes dead rows whose file is gone. unverified review rows also got the Quarantine-style cards. (thanks @nick2000713 for #938.)', page: 'downloads' }, + { title: 'Album Completeness handles split albums (#936)', desc: 'an album split across multiple library rows used to show every fragment as falsely "incomplete". it now groups the validated fragments into one logical album and emits one correct finding — grouping by shared id AND validating at the track level, so unrelated rows never fuse. also recognizes MusicBrainz as a readable source. (thanks @ragnarlotus.)', page: 'library' }, + { title: 'Clear Completed is back on Downloads', desc: 'completed downloads now persist across restart, which had hidden the Clear Completed button for them. it\'s back, and clears the live list AND the persisted history so the page actually empties and stays empty (your files are untouched).', page: 'downloads' }, + { title: 'Pasted YouTube cookies fixed (#Docker)', desc: 'pasting cookies threw `unsupported browser: "custom"` — the client passed the "Paste cookies.txt" mode through as a browser name instead of loading the file. now it uses the pasted cookies.txt, the only auth path that works on a headless/Docker box. (thanks HellRa1SeR.)', page: 'settings' }, + { title: 'Longer remasters no longer quarantined (#937)', desc: 'the duration check was symmetric, so a remaster running a few seconds LONGER than the metadata got rejected like a truncated download. it\'s asymmetric now — short files stay strict, longer versions get room. (thanks @diegocade1.)', page: 'downloads' }, + { title: '"Add to Wishlist" from a discography is instant now', desc: 'it was ~15–30s PER TRACK on a large library — the per-track ownership check fell through to a full-table fuzzy scan. it now matches in-memory against the artist\'s tracks once.', page: 'library' }, + { title: 'Wishlist art renders for re-downloads', desc: 'library-sourced wishlist items (re-downloads, preview re-fetches) stored a relative media-server path that doesn\'t render in a browser. they\'re normalized on read now, so album + artist art show up — fixes already-saved items too.', page: 'downloads' }, + { title: 'More fixes', desc: 'watchlist now records automatic scans (#933) and no longer fuses different editions of an album; a pasted Qobuz/Tidal track floats to the top of manual search (#932); Popular Picks no longer comes up empty on Deezer.', page: 'search' }, + { title: 'Dashboard performance, esp. Firefox/Zen (#935)', desc: 'frosted-glass blur, cursor-glow blobs and the worker-orb animation were repainting every frame. trimmed the worst offenders, kept the orb framerate steady on Firefox (was dropping to ~1fps), and set Background Particles OFF by default. the system-memory tile now also shows SoulSync\'s own RAM.', page: 'dashboard' }, + { title: 'Bounded memory growth (#802)', desc: 'browsing every page used to climb RSS into the GBs (plexapi XML trees deferring garbage collection) and could lock the app up. a lightweight sweeper now collects + hands memory back to the OS as it grows, so it sawtooths and settles instead of climbing.', page: 'dashboard' }, + { title: 'Earlier versions', desc: '2.7.9 brought best-quality downloads + a ranked quality profile, the quarantine-into-Downloads consolidation, Discover "Based On Your Listening" + Listening Mix, the Wing It Pool, the Auto-Sync redesign, and the multi-disc fix (#927). 2.7.8 added Align Playlists; 2.7.3 the Quality Upgrade Finder; 2.7.0 made multi-user real.' }, ], }; @@ -3447,48 +3448,59 @@ const WHATS_NEW = { // usage_note?: 'optional hint shown at the bottom' } const VERSION_MODAL_SECTIONS = [ { - title: "Best-quality downloads + a real quality profile", - description: "the headline — downloads now follow a ranked-target quality profile instead of a fixed preference.", + title: "The Unverified queue, finally under control", + description: "the headline cleanup — review-queue rows stop piling up and the existing backlog clears itself.", features: [ - "drag to order the formats you want (FLAC 24/192 → mp3, every format controllable, with \"all lossless / all lossy\" group shortcuts)", - "best-quality search mode pools candidates across EVERY source per query and grabs the highest-quality copy that meets your profile — not just the first/fastest match", - "priority mode keeps its behavior, with an opt-in \"rank-based download order\" toggle; each streaming source's tier comes from the one profile; AAC is an opt-in tier, and old per-source Hi-Res prefs migrate in", - "quarantine folded into the Downloads page (real quality on the rows, inline approve/retry), opt-in AcoustID fail-closed mode, and silence/truncation guards that catch preview + short files before import", + "#934 — the AcoustID scan was creating a fresh history row every run and leaving already-verified files stuck \"unverified\" (a frozen import-time path that stopped matching once the file moved)", + "scans no longer duplicate rows + heal on the spot; a one-time reconcile on startup clears the existing backlog from your library's truth — no re-scan, including human-verified files a scan skips", + "a 🧹 Clean orphaned button removes dead rows whose file is genuinely gone, with a safety gate that refuses to run if your library looks offline", + "Unverified review rows got the nicer Quarantine-style cards (artwork + inline details). thanks @nick2000713 for #938", ], }, { - title: "Discover, a lot smarter", - description: "Discover now learns from what you actually play.", + title: "Preview Clip Cleanup (new Tools job)", + description: "find the ~30s preview clips the HiFi source sometimes hands back instead of the full song.", features: [ - "\"Based On Your Listening\" — a new artist row ranked by who you play the most (consensus + recency weighted), with a \"because you listen to X, Y\" reason on each card", - "\"Your Listening Mix\" — a playable track playlist from those artists' top tracks; works on ANY metadata source (falls back to Deezer's public API), not just Spotify", - "Fresh Tape fills properly now — it was starving to 5–10 tracks because future-dated albums ate the candidate budget; and the SoulSync Discovery sync tab lists every playlist kind so you can mirror + auto-sync them", + "scans your short tracks, checks how long each should be from its metadata source, and flags the previews — conservative, so genuine short tracks and anything it can't verify are left alone", + "approve a finding and it deletes the clip, drops it from the library, and re-wishlists the full version", + "each finding has a ▶ Play button + a file-length-vs-real-length readout so you can confirm it's busted before approving", ], }, { - title: "Wing It Pool", - description: "a place to review the tracks Wing It guessed at — they used to be invisible.", + title: "Album Completeness handles split albums", + description: "a physical album split across multiple library rows no longer reports false \"incomplete\".", features: [ - "a new button next to Discovery Pool on the Mirrored Playlists tab; Wing It auto-matches tracks it couldn't match to metadata on a best-effort guess", - "opens to a two-card view — guesses to review + resolved — so you can verify or re-match what it guessed (re-match reuses the same fix flow as Discovery Pool)", - ], - }, - { - title: "Auto-Sync Manager redesign", - description: "the scheduling board no longer scrolls sideways through a wall of columns.", - features: [ - "intervals (hourly) and days (weekly) are now horizontal lanes — empty ones collapse to thin strips, busy ones grow", - "the scroll position holds when you drop a playlist in (it used to snap back to the start every time)", + "#936 — fragments are grouped into one logical album and emit a single correct finding, instead of each row looking incomplete on its own", + "safe by design: it groups by a shared id AND validates at the track level, so a stale id can never fuse two unrelated albums; also recognizes MusicBrainz as a readable album source. thanks @ragnarlotus", ], }, { title: "Recent fixes", description: "reported bugs squashed this cycle.", features: [ - "#927 — multi-disc albums showed disc-2 tracks as \"missing\" or under disc 1; the scan never read the disc number. it now captures the real disc from Jellyfin/Plex/Navidrome at scan time (re-scan once to backfill existing tracks)", - "#925 — auto-synced/mirrored playlists always read \"Never Synced\" because only the direct-sync status was checked, never the auto-sync one (thanks @ramonskie)", - "#928 — a race let both the browser poll and the download monitor post-process the same finished download, so a track could import while quarantined; an atomic claim fixes it (thanks @nick2000713)", - "library artist-card badges (the watchlist eye + source links) no longer hijack the click into the artist detail page — they do only their own thing", + "pasted YouTube cookies threw `unsupported browser: \"custom\"` on Docker — now it loads the pasted cookies.txt (the only auth path on a headless box). thanks HellRa1SeR", + "#937 — a remaster running a few seconds LONGER than the metadata got quarantined like a truncated download; the duration check is asymmetric now. thanks @diegocade1", + "\"Add to Wishlist\" from a discography went from ~15–30s PER TRACK to instant (the ownership check was doing a full-table fuzzy scan per track)", + "wishlist art now renders for re-downloads/preview re-fetches (relative media-server paths are normalized on read); Clear Completed is back on the Downloads page and clears the persisted history too", + "watchlist records automatic scans (#933) + stops fusing different editions; pasted Qobuz/Tidal floats to the top of manual search (#932); Popular Picks no longer empty on Deezer", + ], + }, + { + title: "Performance — dashboard + memory", + description: "lower idle cost and no more runaway RAM.", + features: [ + "#935 — frosted-glass blur, cursor-glow blobs and the worker-orb animation were repainting every frame, hammering the GPU (worst on Firefox/Zen). trimmed them, kept the orb framerate steady on Firefox, and set Background Particles OFF by default", + "#802 — browsing every page used to climb RSS into the GBs (plexapi XML trees deferring GC) and could lock up; a lightweight sweeper now collects + returns memory to the OS as it grows, so it settles instead of climbing", + "the dashboard system-memory tile now also shows SoulSync's own RAM", + ], + }, + { + title: "Earlier in 2.7.9", + description: "2.7.9 was a big features release.", + features: [ + "best-quality downloads + a ranked-target quality profile (drag to order every format; pools candidates across every source and grabs the best copy that meets your profile)", + "quarantine folded into the Downloads page; Discover \"Based On Your Listening\" + a playable \"Your Listening Mix\"; the Wing It Pool; the horizontal-lane Auto-Sync redesign", + "#927 — multi-disc albums no longer show disc-2 tracks as \"missing\" (the scan now reads the real disc number; re-scan once to backfill)", ], }, {