chore: bump version to 2.0.0
QBZ 2.0 "Rebuild". Workspace, Tauri manifests, npm manifests and the Flatpak metainfo all move to 2.0.0; TAG_DETAILS for the release notes. snapcraft.yaml uses version: git and needs no bump. cc
This commit is contained in:
10 files changed
+473
-35
No files matched your search
@@ -0,0 +1,364 @@
|
||||
# QBZ 2.0.0 — Technical Changelog (v1.2.15 → v2.0.0)
|
||||
|
||||
824 commits on `slint-mvp` (2026-05-18 → 2026-07-03). This release replaces the
|
||||
Tauri 2.0/WebView (SvelteKit) frontend with a native Slint UI running in the
|
||||
same process as the Rust core — no web engine, no IPC bridge. Nearly every
|
||||
feature below was rebuilt from scratch against the new shell; the sections
|
||||
group work by area rather than by commit date.
|
||||
|
||||
---
|
||||
|
||||
## 1. Architecture
|
||||
|
||||
- **Frontend rewrite**: the SvelteKit/WebView frontend is replaced by a native
|
||||
Slint UI (`qbz-ui` library crate + `qbz` binary crate). Single Rust process,
|
||||
no embedded browser, no Tauri IPC — the UI calls into the core crates
|
||||
directly (`f1748383`, `c8ef2a1b`).
|
||||
- **`qbzd` removed**: the dormant standalone TUI/daemon crate was dropped from
|
||||
the workspace; it pinned an old `unicode-width` that blocked the Slint
|
||||
upgrade past 1.14 (`eddfaed4`).
|
||||
- **Frontend-agnostic core crates extracted from `src-tauri`** (ADR-005/006 —
|
||||
no legacy dependency, no `tauri::State` in core logic), so the same code
|
||||
runs headless (Slint, future TUI/CLI):
|
||||
- `qbz-credentials` — keyring + AES-256-GCM encrypted token store (`aa64f3fa`).
|
||||
- `qbz-radio` — smart-radio builder/db/engine (`4a9cbdeb`).
|
||||
- `qbz-offline-cache` — offline download pipeline, metadata/migration,
|
||||
`CacheEvent` sink, purge logic (`d6e9345f`…`c8158bf4`).
|
||||
- `qbz-plex` — Plex integration, ~1700 lines moved out of Tauri (`2fe7008e`).
|
||||
- `qbz-mixtape` — Mixtapes/Collections backend (`5458f3aa`).
|
||||
- `qbz-lyrics` — synced-lyrics provider chain and cache (`46c15f50`).
|
||||
- `qbz-theme` — theme/token registry with WCAG/APCA contrast math (`ff5536a0`).
|
||||
- `qbz-i18n` — pure-Rust gettext bundling (`f92c95ee`).
|
||||
- `qbz-reco` — recommendation/taste-vector engine (`65de9849`).
|
||||
- `qbz-dsd` — DSD demux/decode/output engine (landing in the 2.0.0 tag).
|
||||
- `qbz-dac-wizard`, `qbz-text-utils`, `qbz-slint-common` — further splits off
|
||||
`qbz-ui` for build parallelism (`7678bceb`, `6f9ad466`, `d1437c70`).
|
||||
- **In-process communication model**: state that used to cross the Tauri IPC
|
||||
boundary (`tauri::State`, `invoke`/event channels) is now shared directly
|
||||
between the Slint controller layer and `QbzCore`/`qbz-app` — no serialization
|
||||
boundary between UI and playback/session state.
|
||||
- **Qobuz Connect cross-frontend seam**: a 16-method `QconnectRendererEngine`
|
||||
trait is implemented once by each frontend (`CoreBridge` for Tauri,
|
||||
`SlintRendererEngine` for Slint) so renderer orchestration (echo-seek
|
||||
rejection, cursor align, queue materialize) lives in `qconnect-app` a single
|
||||
time instead of being re-derived per shell (`e5e8d4a8`, `e8ac6185`, `88e72c3e`).
|
||||
- **CMAF streaming, playback caches, and the offline-tier resolver** moved into
|
||||
the frontend-agnostic `qbz-player`/`qbz-core`, so both frontends share one
|
||||
playback path (`29b6c205`, `d0a4a329`, `506ba5ef`).
|
||||
|
||||
## 2. UI shell & views
|
||||
|
||||
- Three-state sidebar (open/mini/closed), right-flyout section nav, live theme
|
||||
switching, Discovery-style segmented tab bar, browser-like back/forward
|
||||
navigation history (`682719ca`, `12ed5a7c`).
|
||||
- **Custom title bar**: frameless window with drawn controls, drag-to-move,
|
||||
double-click-to-maximize, edge resize (Linux opt-in, macOS overlay default
|
||||
on), plus an opt-in compact icon-only header nav (`a7f538b3`).
|
||||
- **Theming**: 24 standard themes transcribed 1:1 from the old `app.css` into
|
||||
a Rust registry, alpha polarity resolved per-theme rather than by a flat
|
||||
light/dark flag, plus 6 redesigned high-contrast accessibility themes with
|
||||
WCAG/APCA contrast tests and a broad `Theme.is-high-contrast` tokenization
|
||||
pass across sliders, tabs, toasts, badges and focus rings (`40bd77f7`,
|
||||
`48eefa3c`, `ff5536a0`).
|
||||
- **NowPlayingBar**: rebuilt with four selectable layouts — New, Classic,
|
||||
Small ("Mode C", 42px compact row with floating art-hover preview), and
|
||||
Large ("Mode B") — plus a borderless **miniplayer** window with 5 surfaces
|
||||
(micro/compact/artwork/queue/lyrics), mirror-driven state, no extra poll
|
||||
loop (`da7758b9`, `1ad0d7c1`, `8fa03a8c`, `9d6b3533`, `c974b8a9`).
|
||||
- **System tray, MPRIS/SMTC media controls, and notifications**: Linux tray via
|
||||
`ksni` (Wayland-safe hide/show, since winit's `set_visible` is a no-op on
|
||||
Wayland), macOS/Windows tray icon (later hand-rolled objc2 menu for correct
|
||||
icon sizing), MPRIS on Linux and SMTC/MediaRemote on Windows/macOS with
|
||||
content-sniffed album art, now-playing system notifications (`8a78c225`,
|
||||
`a91d629c`, `7a7e5f82`, `d08c5f65`).
|
||||
- **UI scale presets** (XS/S/Default/L/XL via a settings-driven scale factor)
|
||||
shipped for interface density (`b7549790`).
|
||||
|
||||
## 3. Playback & audio engine
|
||||
|
||||
- **CMAF streaming** ported into `qbz-player`: `play_track` fetches the init
|
||||
segment first, derives sample rate/bit depth, then background-fetches and
|
||||
decrypts subsequent segments, falling back to the legacy path on setup
|
||||
failure (`29b6c205`, `74ab627c`, `655a90f4`).
|
||||
- **Gapless + prefetch**: L1+L2 instant-replay cache and gapless-prefetch
|
||||
helpers wired into the Slint playback controller (`7b84fa9a`, `3a6aae19`).
|
||||
- **Device routing (issue #263)**: a three-tier fix stops the PipeWire global
|
||||
clock `force-rate` write from firing while a device lock is held, fixes a
|
||||
`clock.force-rate` leak on stop, resumes a suspended sink after exclusive
|
||||
access ends, and finally routes locked output to the actually-selected sink
|
||||
via `PIPEWIRE_NODE` instead of silently following the system default
|
||||
(`d19312fe`, `b139392b`, `64fb77ad`, `d2c4aaf9`).
|
||||
- **New JACK backend**: lock-free SPSC ring buffer, allocation-free RT process
|
||||
callback, feeder thread resampling to the JACK graph rate, auto-connect to
|
||||
physical ports — offered as an opt-in backend, explicitly not bit-perfect
|
||||
(single fixed graph rate) (`fbc03f41`, `68bc9bd6`).
|
||||
- **PulseAudio works out of the box** alongside the existing ALSA/PipeWire
|
||||
backends, with output-device list dedup, a searchable device selector, and
|
||||
Flatpak `--device=all` for direct `/dev/snd` access (`c75a0af5`, `bdb9cada`,
|
||||
`f98d92d8`).
|
||||
- **Bit-perfect** playback preserved throughout the rewrite: format-first
|
||||
quality badges, per-device bit-perfect-capable marking, and a HiFi Wizard
|
||||
self-test with bit-perfect read-back (see section 12).
|
||||
|
||||
## 4. DSD support (landing in the 2.0.0 tag)
|
||||
|
||||
New `qbz-dsd` crate with in-house DSF/DFF demuxers. Three playback modes are
|
||||
selectable in Settings (ALSA backend):
|
||||
|
||||
- **Convert** — dsd2pcm (Gesemann-derived 6x256 LUT engine) with halfband
|
||||
decimation down to 88.2 kHz/24-bit PCM. Works on any output device.
|
||||
- **DoP** — DSD-over-PCM packing (0x05/0xFA markers over an S32 carrier) via
|
||||
direct ALSA hardware access, with gapless DSD playback and a pause mode that
|
||||
keeps the DAC locked using DSD silence bytes.
|
||||
- **Native** — raw DSD_U32_BE/LE output for DACs and kernels that support it,
|
||||
covering DSD64/128/256.
|
||||
|
||||
Also included: ID3 tag and artwork extraction for DSF/DFF, library-scanner
|
||||
recognition of `.dsf`/`.dff` with DSD64/128/256 quality badges, 5.1 SACD rips
|
||||
played back via ITU BS.775 stereo downmix in Convert mode, and a local-FLAC
|
||||
gapless bug fixed along the way. This work lands just ahead of the 2.0.0 tag
|
||||
and is uncommitted at the time of writing.
|
||||
|
||||
## 5. Search
|
||||
|
||||
- **"Intelligent Search"**: a frontend-agnostic `SearchService` in `qbz-app`
|
||||
with a result cache (Capa A) and interaction-based ranking (Capa B), a live
|
||||
header dropdown with skeleton loading, stale-while-revalidate, 220ms
|
||||
debounce, keyboard nav, per-section caps, and an opt-out setting (`22fb4162`).
|
||||
- **Search "cortinilla"** — a glass search overlay for Albums/Artists/
|
||||
Playlists that swaps playback without leaving Immersive mode, with a
|
||||
configurable action (replace queue / play next / add to queue), later
|
||||
extended to Local Library, Plex, and per-source artwork (`22fb4162`,
|
||||
`b1ac402c`).
|
||||
- Hardening: the dropdown no longer resurrects on navigation, auto-closes
|
||||
after 4.5s idle, and a typing guard was extended across remaining text
|
||||
inputs so hotkeys don't fire while typing (`12b1b312`, `31436325`,
|
||||
`c65bd9c2`).
|
||||
|
||||
## 6. Offline mode & Local Library
|
||||
|
||||
- **Offline mode**: a new frontend-agnostic `qbz_app::offline_mode` state
|
||||
machine (Online / RealOffline session-scoped / InducedOffline persisted)
|
||||
backed by a layered connectivity actor (default-route signal, audio-liveness
|
||||
window, vendor-diverse probes, hysteresis, captive-portal/suspend-resume
|
||||
handling), with all Qobuz HTTP traffic routed through a single offline gate
|
||||
(`edae9d24`, `ba702bc3`). Slint wiring covers offline session entry, a
|
||||
recovery banner, tri-state Settings, offline artwork policy, disk-first
|
||||
cached favorites, first-class local/offline-only playlists, and QConnect
|
||||
offline gating.
|
||||
- **Local Library** (new feature area, folder-based/self-managed music):
|
||||
server-paginated Albums/Tracks tabs with local+offline playback and
|
||||
source-aware auto-advance, Folders tab (flat then flat+tree), Artists tab as
|
||||
a two-column master/detail browser, folder management in Settings, and a
|
||||
library scan engine with progress (`835a6cad`, `56b3ca79`, `df351ec6`,
|
||||
`aa7c320b`).
|
||||
- **Tag editing**: a full tag editor built on `lofty` (sidecar-default,
|
||||
opt-in write-to-file), a manual-edit modal, and remote metadata lookup
|
||||
against MusicBrainz + Discogs (`7e0d970f`, `4e79386d`, `3c2f46b7`).
|
||||
- **Plex integration** ported end to end: credential store, Settings auth/PIN,
|
||||
albums/artists/tracks in Local Library, progressive/fast-play streaming,
|
||||
source-aware artwork everywhere (now-playing bar, queue, MPRIS),
|
||||
server-transcoded thumbnails, and same-title album disambiguation into
|
||||
selectable versions (`f7619a92`, `a45840d1`, `06b2bea9`, `334ddf31`).
|
||||
- **Offline cache manager**: a Settings view for remove/redownload, covers,
|
||||
sort, and a failed-only filter, plus per-row offline buttons on every track
|
||||
row and whole-playlist caching (`3e0a718e`, `a7f2283c`).
|
||||
- **Scrobbling**: Last.fm and ListenBrainz scrobblers wired to the player and
|
||||
Settings (`952846b6`).
|
||||
|
||||
## 7. Qobuz Connect
|
||||
|
||||
- **Hardening** (merged `f3d37dac`): unified cast-eligibility checks, strict
|
||||
source parsing (unknown sources blocked, not allowed through), mixed-queue
|
||||
guards with a Rust-side per-track origin backstop, a 12s renderer-liveness
|
||||
watchdog, half-open WebSocket detection via keepalive pong-timeout,
|
||||
idle-retry/startup-backoff recovery, takeover arbitration on `SESSION_STATE`,
|
||||
and full resync (state + queue) on reconnect (`f3686c19`, `434c2218`,
|
||||
`a05e8abc`, `7628c284`, `ed1d7aee`, `6c48266a`).
|
||||
- **Cross-frontend extraction**: session/liveness logic, `device_uuid`
|
||||
persistence, and diagnostics relocated to shared crates; the
|
||||
`QconnectRendererEngine` trait now carries renderer orchestration once for
|
||||
both frontends (see Architecture) (`f100cf4d`, `e5e8d4a8`).
|
||||
- **Slint port**: renderer + controller integration, device picker with
|
||||
cast-aware now-playing state, peer-renderer playback reflected on the
|
||||
now-playing bar, peer volume with a 50% safety clamp, bit-perfect volume
|
||||
lock/force-100 parity, per-device-type icons, and takeback resume at the
|
||||
handed-off position (`44876d01`, `0d7ac793`, `9bb5e6db`, `8e1bf18f`).
|
||||
|
||||
## 8. Discovery & recommendations
|
||||
|
||||
- **`qbz-reco`** (new crate, ADR-006): `SparseVector` math, relationship
|
||||
weights, a 3-table SQLite `ArtistVectorStore`, and a direct-weight-ranking
|
||||
suggestions engine, trained from per-user play events (favorite-add,
|
||||
playlist-add) to back DailyQ/WeeklyQ mixes, a Rediscover row, and reordered
|
||||
"For You" favorites (`65de9849`, `4828e54c`).
|
||||
- **External recommendations**: a Last.fm + ListenBrainz → Qobuz resolution
|
||||
engine wired as a 4th Discover tab, redesigned artist/album-centric with
|
||||
common/recent split and a 48h results cache, plus a Last.fm similar-albums
|
||||
carousel on AlbumView (`408b3c83`, `124d97e7`).
|
||||
- **Playlist "Suggested Songs"** shipped, and a Discover section configurator
|
||||
lets users reorder/toggle Home/For You sections (`2e1d8e43`, `2a37f2ad`).
|
||||
|
||||
## 9. Lyrics
|
||||
|
||||
- New `qbz-track-lyrics` Qobuz endpoint with verified wire DTOs, feeding a
|
||||
headless `qbz-lyrics` engine: Qobuz-first provider chain, LRCLIB (search +
|
||||
scorer) fallback, then lyrics.ovh; LRC parser/emitter preserving word-level
|
||||
wsync, a per-user SQLite cache (WAL, additive migration), offline
|
||||
cache-only mode, in-flight dedupe, and 55 unit tests (`46c15f50`, `d1203937`).
|
||||
- Slint UI: static rendering evolved into a full sync engine with karaoke
|
||||
fill and auto-center scroll, plus a controls flyout for prefs and cache
|
||||
settings (`5a4dbd87`, `5f9fd5bd`, `eea336fd`).
|
||||
|
||||
## 10. Content blocking
|
||||
|
||||
- **Artist blacklist**: headless service extracted from `src-tauri`, applied
|
||||
across search, track rows (greyout/inert), albums/playlists/favorites/
|
||||
suggest rows, all play/queue builders, and a dedicated Blacklist Manager
|
||||
view (`ef93c864`, `836dd249`).
|
||||
- **Album blacklist**: a parallel String-keyed `album_blacklist` table
|
||||
alongside the artist table, sharing the same enabled flag, enforced across
|
||||
the same consumers with a Manager "Albums" tab (`3fbb166b`, `c85ad5f6`,
|
||||
`66889af4`).
|
||||
|
||||
## 11. Immersive mode & visualizers
|
||||
|
||||
- Full-screen "Immersive" now-playing experience (new epic, not present in
|
||||
Tauri): reusable atmosphere generation (art-derived blur/vignette), a
|
||||
zero-IPC 30fps visualizer feed (`VizFrame`/`VizSink`) lifted off
|
||||
`tauri::AppHandle` into `qbz-audio` (`3adb5172`).
|
||||
- Visual modes: Album Reactive, Static, Coverflow (2D fan), Spectrum
|
||||
Visualizer (~2240 to ~28 gradient bars for performance) (`92052a3c`,
|
||||
`c067d237`, `03dfd661`).
|
||||
- **wgpu fragment-shader underlay**: renderer swapped femtovg(GL) to
|
||||
femtovg-wgpu, with a WGSL plasma shader driven by the visualizer feed, then
|
||||
extended to Tunnel and Aurora "milkdrop" scenes plus a scene picker; macOS
|
||||
stays on the Skia renderer since femtovg-wgpu pegs CPU on Metal
|
||||
(`e46e8554`, `653a449d`, `fb0aa619`). Later scenes added: Wave Bed, Spectral
|
||||
Ribbon, Line Bed (`226c2118`); shader scenes hide automatically on
|
||||
non-wgpu renderer tiers (`a050e639`).
|
||||
- Focus/split layouts: lyrics panel, queue/history panel, track-info panel,
|
||||
and a live-query suggestions panel (`77068e3b`…`e6f9c3b4`).
|
||||
|
||||
## 12. HiFi Wizard revamp
|
||||
|
||||
Built headless-first: native `pw-dump` device enumeration with `pactl`
|
||||
fallback, DAC negotiated-rate probing via `/proc/asound`, audio-stack health
|
||||
and distro/init-system detection (systemd/antiX/Artix/NixOS), and
|
||||
Flatpak/Snap sandbox-aware host detection (`381eafdf`, `f08943ad`, `93da676f`).
|
||||
Slint UI: a 6-step guided modal (check → select DACs → test → review/apply →
|
||||
done) with a self-service playback test and bit-perfect read-back (`9bb392c2`,
|
||||
`9c5febda`, `f87f2986`).
|
||||
|
||||
## 13. Internationalization
|
||||
|
||||
- New pure-Rust `qbz-i18n` crate: gettext `.po` catalogs bundled at compile
|
||||
time (no gettext C dependency), plural rules, and a `t`/`tn`/`t_args`/`tf`
|
||||
API (`f92c95ee`).
|
||||
- Full extraction and seeding pipeline from the old Tauri JSON strings across
|
||||
every module (local library, MyQBZ, discover/home/search, artist/album/
|
||||
label, playback/offline, integrations/DAC wizard) (`f14c5130`…`e167936c`).
|
||||
- Live language switching without restart, locale-aware dates, and dynamic
|
||||
msgid registration via `mark()` (`69d85f19`, `8243f2a8`).
|
||||
- Seven bundled locales at full coverage: English, Spanish, German, French,
|
||||
Portuguese, Russian, Japanese — the last two (`be487dca`) plus a macOS CJK
|
||||
font-fallback fix (vendored `i-slint-common`, `fa3ee1e4`) so Japanese kanji
|
||||
render correctly on Mac builds.
|
||||
|
||||
## 14. Performance
|
||||
|
||||
- **Renderer tier auto-detect** (wgpu → GL → software) with a Settings
|
||||
override and auto-revert if a tier misbehaves (`fe111c3f`).
|
||||
- **Artwork memory bounding**: decoded-artwork memory capped and covers
|
||||
decoded at display size instead of full resolution (`f37b6b6a`).
|
||||
- **Leak/idle fixes**: shader-underlay GPU leak and idle 30Hz wakeups fixed,
|
||||
palette computation moved off the UI thread, idle now-playing pushes
|
||||
skipped, immersive atmosphere animation stopped while paused (`dbe818c7`,
|
||||
`d7716d7c`, `e71f0ded`).
|
||||
- **Viewport windowing** (phase 1) applied to the Local Library albums grid;
|
||||
virtualized `ListView`s (instead of `Flickable` + `for`) applied to
|
||||
Favorites Tracks and Playlist track lists for 2000+ item lists
|
||||
(`23b572e5`, `85223b03`, `4465a367`).
|
||||
- **Reduced motion** on GL/software renderer tiers (`d9b82e7b`).
|
||||
|
||||
## 15. macOS
|
||||
|
||||
- Stable native build with a dedicated dev build/run script (`85518699`).
|
||||
- CJK font fallback fix so Japanese/Chinese/Korean text renders correctly
|
||||
(vendored `i-slint-common`, `fa3ee1e4`).
|
||||
- macOS Dock policy handling for the tray icon, then a hand-rolled objc2
|
||||
tray menu for correct icon sizing/click routing (`a91d629c`, `b9434a50`).
|
||||
- Overlay title bar as the macOS default, distinct from the Linux
|
||||
frameless mode (`a7f538b3`).
|
||||
- Renderer forced to Skia on macOS since femtovg-wgpu pegs CPU under Metal
|
||||
(`fb0aa619`).
|
||||
- Contributor work from Afonso on macOS-specific fixes throughout the range.
|
||||
|
||||
## 16. Build, CI & packaging
|
||||
|
||||
- **Crate split for build memory**: `qbz-slint` split into a `qbz-ui` library
|
||||
crate (owns the full `.slint` tree + bundled translations) and a `qbz`
|
||||
binary crate reclaiming the `qbz` binary name from the retired Tauri app —
|
||||
halves the ~20GB single-crate `rustc` peak into two independently cacheable
|
||||
units, with further extractions (`qbz-dac-wizard`, `qbz-text-utils`,
|
||||
`qbz-slint-common`) (`c8ef2a1b`, `7678bceb`).
|
||||
- **aarch64 Linux** build script added (native ARM runner + x86-64 cross
|
||||
path); documents the ~30GB `qbz_ui` RAM wall that rules out 8GB Macs and
|
||||
4GB Raspberry Pis for native builds (`b89ee385`, `5fdbdb3a`).
|
||||
- **CI rewrite**: GitHub Actions build for `qbz-slint` on Linux stood up and
|
||||
hardened (runner disk exhaustion fixed, swap sized for the ~30GB peak,
|
||||
mupdf-sys system libs added), then moved to a self-hosted runner for real
|
||||
artifact builds (`5806b0c0`…`b9eb3005`).
|
||||
- All-hosted Snap pipeline added; deb/rpm packaging metadata added for the
|
||||
Slint `qbz` binary; release workflows rewritten and channel packagers
|
||||
repointed at the Slint binary; release profile now strips symbols
|
||||
(`77a476c8`, `9c37e456`, `1b933299`, `6e6153b2`).
|
||||
- Linux binary kept compatible with glibc older than 2.43 (`cafd521b`).
|
||||
- Faster local dev builds via the mold linker and a memory-aware
|
||||
`slint-run.sh` to dodge the OOM wall (`ec4b10fc`, `14e800ea`).
|
||||
|
||||
## 17. Other new features
|
||||
|
||||
- **Purchases** ("My Purchases", 13-slice epic): wire models, HTTP + CDN
|
||||
fetch, pagination, download state machine, list/detail views with format
|
||||
and quality pickers, Settings toggle (default off) (`aceaf9b0`…`9fbfcb55`).
|
||||
- **Awards pages** ported (landing, album listing, follow) (`9ccfbd38`).
|
||||
- **Playlist importer** ported (Open Playlist Importer) (`3689a5fd`).
|
||||
- **Keyboard multi-select** ported and extended to Mix/Label/Local Library
|
||||
Albums, with a three-column shortcuts cheatsheet and matching customize
|
||||
editor (`53e1e8cd`, `1a9c1327`).
|
||||
- **Chromecast/DLNA casting**: a shared external-stream resolver
|
||||
(CMAF-first, UltraHiRes-first), `qbz-cast` crate, picker modal, and
|
||||
offline-gate routing (`fdf2fec3`, `3e1101ff`).
|
||||
- **Discord Rich Presence** (opt-in) ported from Tauri (`ef38e7a0`).
|
||||
- **Session persistence** across restarts: startup page, window geometry,
|
||||
and playback state (`dd32f573`).
|
||||
|
||||
## Fixes
|
||||
|
||||
- Output-device routing/locking bugs from issue #263 (see Playback section).
|
||||
- Local-FLAC gapless playback fixed (landed alongside the DSD work).
|
||||
- Half-open QConnect WebSocket sessions now detected via keepalive
|
||||
pong-timeout instead of hanging indefinitely (`7628c284`).
|
||||
- Startup now restores the exact last view, not just the top-level tab
|
||||
(`e44aa07a`).
|
||||
- Album credit fixed to read the album-level composer field instead of
|
||||
per-track (`0ddcad40`); missing pagination fields in album responses are
|
||||
now tolerated instead of erroring (`9e2a1d12`).
|
||||
- Single-click bug on button primitives (a `FocusScope` ate the first press)
|
||||
fixed app-wide (`88f1967d`); single-click album context menus (`8c182875`).
|
||||
- Secret-vault open moved off the async pool to avoid a zbus panic
|
||||
(`40414991`).
|
||||
- Artist follow heart made a real working toggle, reflected across every
|
||||
card surface (`d906e556`).
|
||||
- Qobuz playlist Follow/Copy state fixed across surfaces, with owner-aware
|
||||
remove (delete vs. unfollow) (`bf4ffbd6`, `de32c168`).
|
||||
- `/radio/*` deserialization repaired and every radio entry point rewired
|
||||
(`6520c007`).
|
||||
- rustls `CryptoProvider` installed at startup for Qobuz Connect (`90705471`).
|
||||
- Don't cache empty ListenBrainz results, which previously made Weekly
|
||||
mixes vanish (`1e78884e`).
|
||||
|
||||
---
|
||||
|
||||
Full changelog: https://github.com/vicrodh/qbz/compare/v1.2.15...v2.0.0
|
||||
Reference in new issue
Block a user