github Nezreka/SoulSync 2.6.0
Version 2.6.0

6 hours ago

Release 2.6.0

Merging devmain 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 with tidal-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,
    new core/discovery/qobuz.py worker, 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.py covering
    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,
    see core/auto_import_worker.py:1316) but each card now shows a
    via Deezer badge 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.png 404 loop on Import / Discover cards. The
    onerror handler pointed at a non-existent asset; now uses the
    shipped placeholder-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_VERSION2.6.0 in web_server.py
  • WHATS_NEW split: Qobuz + Import-fallback entries promoted into a
    new 2.6.0 block; old 2.5.9 Release Stability Pass modal section
    rolled down to a generic Earlier in v2.5 aggregator
  • .github/workflows/docker-publish.yml manual version_tag default
    bumped to 2.6.0
  • Semver classification: MINOR (new feature, no breaking changes)

Don't miss a new SoulSync release

NewReleases is sending notifications on new releases.