Release 2.6.0
Merging dev → main to cut the 2.6.0 release.
25 commits since 2.5.9. Headline is Qobuz playlist sync; Soulseek
album-bundle downloads and the stats-page React migration land too.
Headline features
Qobuz playlist sync (#677)
Qobuz joins Tidal and Deezer as a first-class playlist sync source.
- New Qobuz tab on the Sync page (between Deezer and Deezer Link).
- Lists your Qobuz user playlists plus a virtual Favorite Tracks
card (same trick Tidal uses withtidal-favorites). - Click any card → discovery → sync / download — same multi-step
pipeline as Tidal / Deezer. - Reuses the Qobuz auth token already configured for downloads — no
extra connection flow. - Backend: 13 new
/api/qobuz/*endpoints mirroring Tidal one-for-one,
newcore/discovery/qobuz.pyworker, four new methods on
core/qobuz_client.py(get_user_playlists,get_playlist,
get_user_favorite_tracks,get_user_favorite_tracks_count). - Tests: 12 unit tests in
tests/test_qobuz_playlists.pycovering
pagination, normalization, virtual-favorites routing, and
artist-name fallback chain. - Scope discipline: did not refactor the per-service transformers
shared with Tidal / Deezer / Spotify-public / YouTube / Mirrored.
That cleanup is its own follow-up PR; this one adds the 6th copy of
a proven pattern instead.
Soulseek album bundle downloads
Single-source album downloads on Soulseek now route through the same
album-bundle staging flow that torrent / usenet use — picks the best
release once, watches live progress, imports matching tracks from
staged files. Hybrid mode unchanged.
Stats page React migration (#590 from @kettui)
The Stats page is the next big surface to ride on the Vite / TanStack
React shell. Lots of internal cleanup commits ship as part of this —
legacy stats-automations.js shrinks ~660 lines, shell-route smoke
coverage generalises, recharts cell deprecation cleaned up.
Media player: playable tracks across modals + lyrics
Modals across the app now render play buttons that route through the
shared media player. Lyrics panel ships on the now-playing modal
(LRClib + local sidecar .lrc / .txt files, synced highlighting).
Notable fixes
- #681
Surface metadata source on Import album results— Import
album search silently fell back to the next source when the
configured primary returned 0. Fallback behaviour stays (intentional,
seecore/auto_import_worker.py:1316) but each card now shows a
via Deezerbadge when the served source differs from your primary,
and a banner above the grid spells it out when every result came
from the fallback. - #682
Fix missing album placeholder asset path— endless
/static/placeholder.png404 loop on Import / Discover cards. The
onerrorhandler pointed at a non-existent asset; now uses the
shippedplaceholder-album.png. Regression test added. Fix admin PIN after profile switches— admin PIN entry stayed
locked after switching profiles.Fix Picard albumartist orphan false positives— orphan detector
was flagging Picard-tagged albums that used a different albumartist
spelling than the per-track artist.Fix Usenet settings reload without restart— settings saved on
the Indexers & Downloaders tab now hot-reload without a process
restart.fix(webui): make sidebar nav SPA links(#679 from @kettui) — fixes
full-page reloads when clicking the React-routed sidebar entries.
Version bump
_SOULSYNC_BASE_VERSION→2.6.0inweb_server.pyWHATS_NEWsplit: Qobuz + Import-fallback entries promoted into a
new2.6.0block; old2.5.9 Release Stability Passmodal section
rolled down to a genericEarlier in v2.5aggregator.github/workflows/docker-publish.ymlmanualversion_tagdefault
bumped to2.6.0- Semver classification: MINOR (new feature, no breaking changes)