Commit Graph
100 Commits
Author SHA1 Message Date
vicrodh bf56eefd7a chore(deps): bump cpal 0.17.1 -> 0.17.3 and alsa 0.10 -> 0.11
cpal 0.17.3 requires alsa 0.11, which in turn pulls alsa-sys 0.4. The
`links = "alsa"` constraint permits only one alsa-sys in the dependency
graph, so qbz-audio's direct alsa stack is raised in lockstep:
alsa 0.10 -> 0.11 and alsa-sys 0.3 -> 0.4. Both workspace lockfiles
(crates/ and src-tauri/) are updated to cpal 0.17.3 / alsa 0.11.0 /
alsa-sys 0.4.0.

No source changes required: alsa_direct.rs uses only the stable
high-level alsa API (pcm, HwParams, Format, Direction, ValueOr, mixer),
and the snd_lib_error_set_handler FFI in alsa_error_handler.rs is
unchanged in alsa-sys 0.4. Both workspaces pass cargo check.

cc
2026-05-23 22:25:26 -06:00
vicrodh bec71d58d5 chore(deps-dev): bump vite from 8.0.13 to 8.0.14
cc
2026-05-23 18:08:06 -06:00
vicrodh e9b021e7e5 chore(deps-dev): bump vitest to 4.1.7
cc
2026-05-23 17:17:55 -06:00
vicrodh a4a281221a chore(deps): bump @kawarp/core to 1.2.0
cc
2026-05-23 17:17:44 -06:00
vicrodh 81d3751cb9 chore(deps-dev): bump vite to 8.0.13
cc
2026-05-23 17:17:40 -06:00
vicrodh cb8421accc chore(deps-dev): bump @tauri-apps/cli to 2.11.2
cc
2026-05-23 17:17:32 -06:00
vicrodh b1c946de6c chore(deps-dev): bump @sveltejs/kit from 2.59.1 to 2.60.1
cc
2026-05-23 17:17:21 -06:00
vicrodh 97dd405bcf chore(deps): bump open from 5.3.4 to 5.3.5
cc
2026-05-23 14:04:48 -06:00
vicrodh 9b2c6743e6 chore(deps): bump tauri-build from 2.6.1 to 2.6.2
cc
2026-05-23 14:03:10 -06:00
vicrodh d5f9d0b83c chore(deps): bump tokio from 1.52.2 to 1.52.3
cc
2026-05-23 14:01:17 -06:00
vicrodh d5d2e93744 chore(deps): bump ashpd from 0.13.10 to 0.13.11
cc
2026-05-23 13:59:34 -06:00
vicrodh 9e505a9fa4 chore(deps): bump tower-http from 0.6.8 to 0.6.11
cc
2026-05-23 13:58:00 -06:00
vicrodh a8ee939dab Merge bugfix/internal/post-1.2.13: post-1.2.13 bugfixes
Fixes #467 (long-session offline death), #468 (favorite on see-all), #466
(PipeWire backend hidden without pactl), #452 (remix version on initial play
from favorites), #449 (sample-rate sync regression on PipeWire), and #453
(macOS queue drag — pending Mac confirmation). Includes the recovered adaptive
prefetch throttle that #467's offline-liveness signal builds on.

cc
2026-05-23 12:05:05 -06:00
vicrodh e437e620a1 fix(queue): restore drag-and-drop reordering on macOS (#453)
c1c151ee added `-webkit-user-select: none` to <body>; on macOS WKWebView this
also blocks dragstart on the draggable .queue-track rows (WebKit couples
selectability with draggability), so queue reordering and its blue insertion
line silently broke. Marking the rows as `-webkit-user-drag: element` restores
drag initiation. WebKitGTK (Linux) is unaffected. Needs confirmation on a Mac.

cc
2026-05-23 12:04:29 -06:00
vicrodh ee4c889c55 fix(player): rebuild output stream on sample-rate change for all backends (#449)
The stream-recreate decision only forced a rebuild on a decoded-format change
for bit-perfect backends (DAC passthrough, ALSA Direct, CoreAudio exclusive).
The default/PipeWire path relied on Stop dropping the stream to get a fresh one
at the new rate; once that drop was deferred to avoid a track-change click
(e93fcaec), the PipeWire node stayed locked to the first track's rate for all
subsequent tracks — a regression vs 1.2.10. Make any decoded-format change
rebuild the stream on every backend; same-rate tracks still reuse it, so the
click fix is preserved.

Verified on hardware via pw-top: PipeWire without passthrough now switches rate
per track; PipeWire with passthrough and ALSA Direct unchanged (no regression).

cc
2026-05-23 08:35:38 -06:00
vicrodh d075902380 fix(favorites): carry remix/edition version on initial click-to-play from the favorites tracks view (#452)
The favorites queue builder forwarded the track version, so skipping/seeking to
a track showed its remix subtitle, but buildDisplayTrack (used for the initial
click-to-play via onTrackPlay) dropped it — so the now-playing bar, queue,
MPRIS and Last.fm lost the version on first play. Add version to the
DisplayTrack interface and buildDisplayTrack.

cc
2026-05-22 23:16:53 -06:00
vicrodh 3a09ce7fe7 fix(audio): detect PipeWire via runtime socket so the backend is not hidden without pactl (#466)
is_pipewire_available() shelled out to `pactl info`, which lives in
pulseaudio-utils and is absent on PipeWire-only systems — hiding the PipeWire
backend even though PipeWire was running. Detect via the
$XDG_RUNTIME_DIR/pipewire-0 socket first (no extra package required), with
pw-cli and pactl as fallbacks.

cc
2026-05-22 23:16:53 -06:00
vicrodh f5de06aeef fix(discovery): wire favorite button on browse/see-all pages (#468)
The heart overlay on AlbumCardLite always renders and calls onFavorite, but
VirtualizedFavoritesAlbumGrid never forwarded onFavorite/isFavorite, so the
button was dead on every discover see-all page. Thread both through the grid
and wire DiscoverBrowseView to the shared albumFavoritesStore (same pattern as
the collapsed DiscoveryView). Fixes favoriting across all six browse pages.

cc
2026-05-22 21:46:34 -06:00
vicrodh 50384d3d3c fix(player): never skip the gapless target offline + bound the skip cascade (#467)
The offline-skip recursion walked the entire remaining queue synchronously,
desyncing the logical queue from the still-playing engine. Fixes:

- The gapless-transition target is the track the engine is already playing;
  never run the availability-skip branch for it.
- isTrackAvailable now counts the in-memory/disk cache (new v2_is_track_cached
  command), not just downloaded copies.
- Cap consecutive offline skips and play-failure auto-skips at 5 in both
  +page.svelte and playbackService.ts.

cc
2026-05-22 21:46:34 -06:00
vicrodh bdaee1af1a fix(qobuz): retry transient fetch failures with backoff instead of skipping (#467)
A single transient 5xx / timeout / reset on the next track's file/url or a CMAF
segment used to be terminal and skipped the track. Add a retry wrapper (3
attempts, exponential backoff + jitter) around get_file_url, the init segment,
and per-segment fetches. Retry only transient errors (network/timeout, 5xx, 429
honoring Retry-After); a real 404 is classified as TrackUnavailable and
propagates immediately to the bounded skip path.

cc
2026-05-22 21:46:33 -06:00
vicrodh 133e90f752 fix(offline): hysteresis + cheap probe + streaming liveness override (#467)
Long sessions died when a single transient blip flipped the app to offline and
the queue then skipped every cached-but-not-downloaded track. Harden the
detector:

- Consecutive-failure hysteresis: declare offline only after 2 failed polls,
  not a single blip.
- Replace the HEAD https://1.1.1.1 probe with a concurrent race of cheap
  generate_204 endpoints, so a saturated link (long Hi-Res tracks) no longer
  times the probe out.
- Positive liveness override: if a segment downloaded within the last 45s we
  are online by definition, regardless of the probe.

cc
2026-05-22 21:46:33 -06:00
vicrodh e4fa90c1b2 feat(prefetch): adaptive throttle based on observed bandwidth + underrun signal
Recovered from 63ecc324 (authored on the native-port branch, never merged to
pre-release). Backend-only, no Slint. Scales the prefetch cap down on slow
links and during audio underruns, and exposes the per-segment download signal
the offline detector reuses as a positive liveness override (#467).

cc
2026-05-22 21:46:07 -06:00
vicrodh 4b66775688 Merge refactor/internal/shared-cache-credentials: share image cache and credentials via crates
cc
2026-05-18 14:11:14 -06:00
vicrodh 3477edfb76 refactor: share the image cache and credential store via crates
Extracts two self-contained, framework-agnostic modules out of
src-tauri so they can be reused by other clients without duplicating
logic:

- ImageCacheService / ImageCacheStats move into the qbz-cache crate
  (LRU disk cache, MD5-keyed, SQLite index).
- The credential store (keyring + AES-256-GCM encrypted file for Qobuz
  credentials and the OAuth token) moves into a new qbz-credentials
  crate.

src-tauri/image_cache.rs and src-tauri/credentials/mod.rs become thin
re-exports, keeping their Tauri managed-state wrappers. The Tauri app
is behavior-identical; both modules were already self-contained (no
Tauri and no crate:: references).

cc
2026-05-18 14:11:05 -06:00
vicrodh 196fa796f5 Merge refactor/qbz-app-session-activation: minimal session activation
cc
2026-05-18 09:35:55 -06:00
vicrodh 7ef6300a22 refactor(qbz-app): add minimal session activation to AppRuntime
Task 2 of the Slint POC readiness audit. AppRuntime now performs
framework-agnostic per-user session activation: activate, activate_at,
activate_offline, deactivate, plus is_session_active, active_user_id,
and a with_session_store accessor.

This is the minimal version per the 2026-05-18 audit correction. It
opens only the session store and does the portable scaffolding (user
paths, directories, last_user_id marker, runtime state machine). It
does not touch Tauri's session_lifecycle, does not initialize the
src-tauri-side per-user stores, and does not run the flat-to-user
migration. The shipping app keeps identical behavior; this is additive.

activate_at takes explicit directories and is the testable core;
activate resolves real per-user paths through UserDataPaths.

cc
2026-05-18 09:26:22 -06:00
vicrodh f979c52307 Merge refactor/qbz-app-shell-facade: shell facade skeleton
cc
2026-05-18 08:29:01 -06:00
vicrodh a213b37807 refactor(qbz-app): add AppRuntime shell facade skeleton
Adds a framework-agnostic composition root for non-Tauri UI shells
(Slint, TUI, headless) as Task 1 of the Slint POC readiness audit
(session-20-slint-poc-readiness-audit).

AppRuntime<A> owns an Arc<QbzCore<A>> plus the runtime state machine,
built with the same recipe as the Tauri CoreBridge but with no Tauri
dependency. Scope is composition and accessors only; per-user store
ownership and session activation are deferred to Task 2.

qbz-app now depends on qbz-core, qbz-player, qbz-audio, and qbz-models.
The Tauri app does not consume this module; it is purely additive.

cc
2026-05-18 07:28:19 -06:00
vicrodh d4ea8b01a7 Merge refactor/qbz-app-playback-context: playback context foundation 2026-05-17 20:14:54 -06:00
vicrodh 1052ff25b3 refactor(tauri): use qbz-app playback context
cx
2026-05-17 19:42:53 -06:00
vicrodh f79c550889 refactor(qbz-app): add playback context
cx
2026-05-17 19:39:14 -06:00
vicrodh 2ed2a30a2c Merge refactor/qbz-app-session-store: session store foundation 2026-05-17 19:30:34 -06:00
vicrodh 8b850999f9 refactor(tauri): use qbz-app session store
cx
2026-05-17 19:19:47 -06:00
vicrodh 4ba96fe59a refactor(qbz-app): add session store foundation
cx
2026-05-17 19:16:13 -06:00
vicrodh ba7cf05b6f chore: bump Nix flake hashes for v1.2.13
Update srcHash and npmHash to point at the v1.2.13 tag. qbzVersion was
already bumped during the release version bump.

cc
2026-05-17 16:38:27 -06:00
vicrodh d647268af8 fix: play individual tracks from expanded Mixtape items
Clicking a track inside an expanded Mixtape/Collection item now plays
it. Qobuz albums and playlists build the queue directly; Plex and
local-library albums delegate to the backend collection-item resolver,
then jump the queue cursor to the clicked track.

cc
2026-05-17 13:15:32 -06:00
vicrodh 3a22cbdbd5 fix: show playlist tracks and version in expanded Mixtape items
Expanded playlist items showed "No results found"; fetch their tracks
via v2_get_playlist. Also carry the remix/edition version field so
titles render consistently.

cc
2026-05-17 13:15:32 -06:00
vicrodh 6cb9284968 fix: pass remix/edition version metadata from playlists (#443)
Carry the track version field through PlaylistDetailView so remix and
edition subtitles reach the now-playing bar and queue views.

cc
2026-05-17 13:15:32 -06:00
vicrodh d9d6caae55 feat: include playback preferences in diagnostics snapshot
Add playback/audio/graphics settings to the diagnostics snapshot via
v2_get_playback_preferences. No sensitive data (no username or paths);
gated by the existing diagnostics opt-in toggle.

cc
2026-05-17 13:15:32 -06:00
vicrodh 74d75f3fbf fix: persist session durably to survive reboot (#440)
Switch the session store SQLite connection from synchronous=NORMAL to
synchronous=FULL. With WAL + NORMAL the last writes can sit unsynced in
the WAL and be lost on a hard reboot / power loss, dropping the restored
session.

cc
2026-05-17 13:15:32 -06:00
vicrodh 813892d605 Merge pre-release: 1.2.13 (400+ stars)
cc
2026-05-16 19:28:22 -06:00
vicrodh 3dac920187 fix(cast): suspend Qobuz Connect while casting (#439)
Qobuz Connect renderer mode and casting are mutually exclusive output modes. While qbz is registered as a QConnect renderer, the Qobuz cloud drives playback through the renderer-command path, which bypasses the cast path entirely — the cast device receives no LOAD and stays silent.

connectToDevice() now checks QConnect status and, if it is on, suspends it (v2_qconnect_disconnect) before connecting the cast device. When the cast ends, disconnect() restores QConnect only if it was on beforehand; a failed cast connection restores it too. Applies to Chromecast and DLNA alike.

Fixes #439.

cc
2026-05-16 18:59:34 -06:00
vicrodh 59990fdc35 docs(release): add 1.2.13 release notes and full changelog
TAG_DETAILS.md is the curated, user-facing release summary rendered by the website and the in-app About modal. CHANGELOG_FULL.md is the complete commit list for v1.2.12..v1.2.13, restoring the two-file release-docs layout last used at 1.2.5.

cc
2026-05-16 14:40:09 -06:00
vicrodh c747c72e9d chore(release): bump version to 1.2.13 "400+ stars"
Version bumped across Cargo.toml, tauri.conf.json, package.json, snapcraft.yaml (version + source-tag), flake.nix, and the lockfiles. metainfo.xml gains a 1.2.13 release entry, the About modal codename becomes "400+ stars", and the README contributors list adds @Vudgekek and @DoubleGate.

cc
2026-05-16 14:40:09 -06:00
vicrodh bfcd769055 fix(cast): heartbeat the Chromecast every 5s to keep the connection alive
Google Cast closes a control connection that goes roughly 10 seconds without a heartbeat PING. QBZ pinged every 25 seconds, so any cast connection left idle between connect and load — for example while the track downloads, or across a delayed second play attempt — was dropped by the receiver. The next LOAD then failed with EPIPE (broken pipe): the device chimed on connect but never played audio, and the heartbeat thread logged repeating broken-pipe warnings.

Pinging every 5s is the cadence the Cast protocol expects and keeps the connection alive through those idle gaps.

Fixes #439.

cc
2026-05-16 14:38:29 -06:00
vicrodh bf734546d1 Merge bugfix/pre-1.2.13: graphics recommendation cleanup, faster track resume
cc
2026-05-16 13:53:24 -06:00
vicrodh 3abb7f66cb fix(playback): gate within-track resume on cache, drop slow seek path
Session resume of a Qobuz track no longer forces the streaming start-position path, which buffered the CMAF stream sequentially from byte 0 up to the saved offset (up to ~30s wait, with no buffering indication).

v2_play_track is now always called without a start position. The track resumes at the saved offset only on a cache hit (format_id === null), where the audio is a full in-memory buffer and Seek lands like a local file. On a cache miss it starts from 0:00 instead of blocking on a sequential buffer fill.

No backend or audio-engine change; the start_position_secs streaming path is now unused.

cc
2026-05-16 13:53:17 -06:00
vicrodh 3d29cf1384 fix(graphics): make recommendation advisory-only, GPU-aware DMA-BUF help
The graphics recommendation banner no longer writes settings: the Apply button and the v2_apply_graphics_recommendation command are removed, so the banner only detects and explains. The user applies the change with the real toggles, matching the HiFi Wizard's advisory model. write_recommendation stays for the qbz --autoconfig-graphics CLI.

The Force DMA-BUF help text is now GPU-aware: the instability warning only shows on NVIDIA-only systems; non-NVIDIA and hybrid hosts are told it is safe to enable. On hybrid hosts the rendering GPU dropdown marks the integrated GPU as recommended.

cc
2026-05-16 12:22:41 -06:00
vicrodh 29b766ae24 fix(graphics): recommend CPU for NVIDIA-only, allow DMA-BUF on hybrid
NVIDIA-only systems no longer get a hardware-acceleration recommendation that visibly stutters under WebKitGTK. The three NVIDIA-only branches (Wayland+GNOME, Wayland, X11) collapse into one CPU-rendering profile, since XWayland does not rescue the stutter either.

NVIDIA + iGPU hybrid now allows DMA-BUF: WebKit composites on the stable iGPU stack, so the instability that affects NVIDIA-only systems does not apply. The recommendation also tells the user to pick the iGPU explicitly in the rendering GPU selector instead of Auto.

cc
2026-05-16 12:22:41 -06:00
vicrodh 420fd4d286 Merge refactor/qbz-app-boot-watchdog: boot watchdog
cx
2026-05-16 09:37:18 -06:00
vicrodh 1a5dbe07bb refactor(qbz-app): extract boot watchdog decision
cx
2026-05-16 09:04:34 -06:00
vicrodh fbf3a5a17c Merge refactor/qbz-app-graphics-autoconfig: graphics autoconfig
cx
2026-05-16 08:57:21 -06:00
vicrodh 3c963cdaf3 refactor(qbz-app): extract graphics autoconfig
cx
2026-05-16 08:50:06 -06:00
vicrodh f457401dd9 Merge refactor/qbz-app-graphics-detection: graphics detection 2026-05-16 00:49:21 -06:00
vicrodh dceeacb57e refactor(tauri): use qbz-app graphics detection
cx
2026-05-16 00:47:11 -06:00
vicrodh 2fc9270c89 refactor(qbz-app): add graphics detection
cx
2026-05-16 00:44:16 -06:00
vicrodh 2beb83cbb6 Merge refactor/qbz-app-user-data-paths: user data paths 2026-05-16 00:29:17 -06:00
vicrodh b65feee511 refactor(tauri): use qbz-app user data paths
cx
2026-05-16 00:24:03 -06:00
vicrodh a497d61b75 refactor(qbz-app): add user data paths
cx
2026-05-16 00:20:21 -06:00
vicrodh e4ec5cd318 Merge refactor/qbz-app-developer-settings: developer settings store 2026-05-15 23:25:22 -06:00
vicrodh be500956ff refactor(qbz-app): add developer settings store
cx
2026-05-15 23:25:06 -06:00
vicrodh 1fe0ac3568 Merge refactor/qbz-audio-settings-foundation: audio settings store 2026-05-15 23:19:10 -06:00
vicrodh 87e426ab5d refactor(tauri): use qbz-audio settings
cx
2026-05-15 19:51:13 -06:00
vicrodh f85df353ca refactor(qbz-audio): align audio settings store
cx
2026-05-15 19:42:17 -06:00
vicrodh c4a0a52ab4 Merge refactor/qbz-app-graphics-settings: graphics settings store 2026-05-15 19:22:23 -06:00
vicrodh 441bcc5f0e refactor(tauri): use qbz-app graphics settings
cx
2026-05-15 18:53:24 -06:00
vicrodh bcdbc69913 refactor(qbz-app): add graphics settings store
cx
2026-05-15 18:52:15 -06:00
vicrodh 88432500d1 Merge refactor/qbz-app-image-cache-settings: image cache settings store
cx
2026-05-15 18:24:14 -06:00
vicrodh 4d1feec75d refactor(tauri): use qbz-app image cache settings
cx
2026-05-15 18:20:56 -06:00
vicrodh f8f8bb88d6 refactor(qbz-app): add image cache settings store
cx
2026-05-15 18:18:36 -06:00
vicrodh 62cd6ae130 Merge refactor/qbz-app-download-settings: download settings store
cx
2026-05-15 17:54:54 -06:00
vicrodh 10b0e259f4 refactor(tauri): use qbz-app download settings
cx
2026-05-15 17:50:59 -06:00
vicrodh 26012e98c9 refactor(qbz-app): add download settings store
cx
2026-05-15 17:48:14 -06:00
vicrodh 74ce1c3201 Merge refactor/qbz-app-remote-control-settings: remote control settings store
cx
2026-05-15 14:23:27 -06:00
vicrodh faca837658 chore(tauri): update qbz-app lock dependencies
cx
2026-05-15 14:21:17 -06:00
vicrodh f527186ca7 refactor(tauri): use qbz-app remote control settings
cx
2026-05-15 14:20:35 -06:00
vicrodh 2e43831800 refactor(qbz-app): add remote control settings store
cx
2026-05-15 14:17:35 -06:00
vicrodh ebe03193c2 Merge refactor/qbz-app-ui-preferences-foundation: qbz-app UI preference stores
cx
2026-05-15 00:41:12 -06:00
vicrodh 7f8e3533cb Merge bugfix/pre-1.2.13: release watch filter, album tooltip, copyable settings text 2026-05-15 00:36:00 -06:00
vicrodh 0b83c5a01e fix(css): keep pre, code, kbd, samp selectable globally
After the app-wide `user-select: none` on body, content the user
legitimately needs to copy stopped being selectable: HiFi Wizard
commands and paths, snap/flatpak/Pulse/PipeWire setup blocks in
Settings, graphics recovery commands, environment-variable hints, log
viewers, keyboard shortcut chips.

The HTML5 elements that wrap literal text — `pre`, `code`, `kbd`, `samp`
— are already the right escape hatch and every wizard/settings/logs
block in the codebase uses them. Adding a single rule alongside the
existing form-input exception restores selection everywhere it matters
without scattering `.selectable` classes through the views.

cc
2026-05-15 00:35:53 -06:00
vicrodh 29e70de58f feat(discovery-v2): tooltip with full album title on AlbumCardLite
The compact 220x220 cards in Discovery V2 truncate long album titles in
the metadata row. With the marquee scroll removed there was no way to
read the full title without opening the album detail.

Pipe the title and artist through a native `title` attribute on the
text-stack wrapper; the global SystemTooltip already mounted in the
layout intercepts that and renders the custom tooltip with adaptive
positioning. Shows the full "Title — Artist" string regardless of
truncation, no extra component, no per-card hover state.

cc
2026-05-15 00:35:45 -06:00
vicrodh 3903086f36 fix(release-watch): drop upcoming and non-streamable albums
`/favorite/getNewReleases` includes albums whose stream availability is
still in the future, so they appear in the Release Watch grid even
though `get_album` 404s as soon as the user clicks them. Same shape for
regional restrictions and label takedowns surfaced via `streamable=false`.

Add `release_date_stream` and `streamable` to the Album struct (both
optional with serde defaults so existing call sites stay happy) and
filter the response inside `v2_get_release_watch` after the artist
blacklist pass: skip any album marked `streamable=false` or whose
`release_date_stream` is strictly greater than today (UTC). The total
count gets adjusted alongside so pagination math stays consistent.

cc
2026-05-15 00:35:38 -06:00
vicrodh 04d5b45134 docs(qbz-app): keep app comments frontend agnostic
cx
2026-05-15 00:12:22 -06:00
vicrodh 2d7639c637 refactor(tauri): use qbz-app ui preference stores
cx
2026-05-15 00:10:57 -06:00
vicrodh d1082317f5 refactor(qbz-app): add ui preference stores
cx
2026-05-15 00:04:36 -06:00
vicrodh 2b7b2312ea Merge bugfix/pre-1.2.13: offline-tolerant CoreBridge + Continue Listening hydration 2026-05-14 23:35:34 -06:00
vicrodh db39072488 fix(discovery-v2): hydrate Continue Listening tracks with full metadata and context
The TrackRowLite click handler was constructing a DisplayTrack with only
the fields shown on the row (id, title, artist, album, albumArt), masked
by an `as DisplayTrack` cast. duration, durationSeconds, hires, bitDepth,
samplingRate and isrc never reached the player, so the NowPlayingBar
showed no time and the seekbar was unusable. The legacy HomeView path
(home:continue_listening) also wired setPlaybackContext +
replacePlaybackQueue before the play call; the discovery-v2 rewrite
dropped both, which left a stale context label and a stale queue after
clicking a track from the section.

Backend already returns the full TrackDisplayMeta (duration_seconds,
hires, bit_depth, sampling_rate, isrc); the wire and the display types
just weren't carrying it. Extend RecoTrackDisplayMeta and
DiscoveryTrackCard with those fields, propagate them in
fetchHomeResolved, and rebuild the click handler to set the
home:continue_listening context and replace the queue with the full
section before emitting onTrackPlay with a complete DisplayTrack.

cc
2026-05-14 23:35:21 -06:00
vicrodh a40b1b6c48 fix(core): make QbzCore::init tolerant to offline startup
Bundle token extraction requires the network. When the host is fully
offline at startup, the failure used to propagate out of CoreBridge::new
and leave the bridge as None, which made every queue/playback V2 command
panic at `bridge.get().expect("CoreBridge not initialized")`.

QbzCore::init() now treats bundle extraction as best-effort: on failure
the core still finishes initialization, the queue manager and player stay
usable for local/offline playback, and API methods return
CoreError::NotInitialized cleanly instead of crashing the runtime. Adds
is_api_initialized and try_init_api so callers can rebuild the API
client lazily once the network returns.

cc
2026-05-14 23:24:33 -06:00
vicrodh 7f38dbcc6f refactor(tauri): use qbz-app preference stores
cx
2026-05-14 19:49:11 -06:00
vicrodh 61d5715a22 refactor(qbz-app): add preference stores
cx
2026-05-14 19:48:54 -06:00
vicrodh d48a1019d2 chore(deps): bump svelte to 5.55.7
cx
2026-05-14 18:23:07 -06:00
vicrodh 917b2a8be8 fix(ui): avoid t shadow in mixtape detail
cx
2026-05-14 18:22:46 -06:00
vicrodh dac1b3a762 refactor(tauri): use qbz-app settings stores
cx
2026-05-14 17:08:57 -06:00
vicrodh 800447d33c refactor(qbz-app): add settings stores
cx
2026-05-14 17:08:45 -06:00
vicrodh dc74db6401 test(qbz-app): cover runtime state transitions 2026-05-14 11:54:16 -06:00
vicrodh 0877f4a5a2 refactor(tauri): use qbz-app runtime types 2026-05-14 11:52:43 -06:00
vicrodh d16ef003a5 refactor(qbz-app): move runtime core 2026-05-14 11:45:59 -06:00
vicrodh 4f008cd219 refactor(qbz-app): scaffold app crate 2026-05-14 11:40:19 -06:00
vicrodh 1bb8d53dd0 feat(graphics): NVIDIA Wayland compat toggle + watchdog fallback to CPU
Two-pronged improvement to the graphics safety net for users hitting
the NVIDIA + Wayland + WebKit GBM issue:

1) New opt-in toggle 'NVIDIA Wayland compatibility (experimental)' in
   Settings > Graphics. When ON:
   - Sets __NV_DISABLE_EXPLICIT_SYNC=1 to bypass libnvidia-egl-gbm's
     buggy implicit-sync paths that produce "Failed to create GBM
     buffer of size NxN: Invalid argument" on driver 550+.
   - Lifts the defensive compositing-mode shutdown that QBZ applies
     to NVIDIA-only Wayland sessions — the user is signaling the real
     fix is now in place, so the safety net is no longer needed.
   - Persisted in graphics_settings.db column nvidia_compat_mode (new,
     default off). Migrated via ALTER TABLE so existing installs don't
     pick up a behaviour change.

2) Reset-graphics CLI affordance, surfaced only when the toggle is on:
   inline copyable input + Copy button rendering `qbz --reset-graphics`
   (or `flatpak run com.blitzfc.qbz --reset-graphics` based on detected
   install method). Works around the global select-disable elsewhere
   in SettingsView via user-select: all + onclick={e.select()} + the
   explicit button. The boot watchdog still auto-reverts on crash, but
   this is the manual escape hatch when the user wants to recover
   without waiting for the watchdog to fire.

3) Watchdog recovery now lands in full CPU mode after ANY revert.
   The single-knob revert (hw_accel / dmabuf / preferred_gpu) still
   narrows the cause for the UI banner, but the safest post-crash
   state is full CPU mode (HW accel off + DMA-BUF off + preferred_gpu
   reset to auto). A partial revert can still hit the next crash if
   the failure was stack-wide (driver bug, missing extension); going
   all-the-way-CPU guarantees the user always reaches a paintable
   window after a recovery — they can selectively re-enable from the
   Settings banner.

4) preferred_gpu='software' now implies hardware_acceleration=off at
   env-var application time. Forcing Mesa llvmpipe while keeping
   WebKit GPU compositing on would just round-trip software pixels
   through a "GPU" path that has no GPU — nonsensical configuration
   that the watchdog had to clean up after. Now it's prevented at
   source.

i18n keys (en/es/de/fr/pt): settings.graphics.nvidiaCompatMode,
nvidiaCompatModeDesc, resetCmdTitle, resetCmdDesc;
actions.copiedToClipboard.

cc
2026-05-14 09:18:56 -06:00
vicrodh db45051c45 chore(security): patch file-type 16.5.4 ASF infinite-loop (GHSA, alert 56)
GitHub Security advisory for file-type < 21.3.1: malformed ASF input
with a zero-size sub-header triggers an infinite loop in the ASF parser
(medium severity). Our exposure is transitive — node-vibrant → jimp →
file-type — and only reached when extracting palette colors from album
artwork. Trusted Qobuz CDN + user-local library limit the practical
attack surface to near zero, but the alert is real and easy to close.

The upstream fix is a 6-line position-advance guard in core.js
(commit 319abf87). Cleanly backports to our 16.5.4 with identical
semantics. Applied via patch-package so the change survives every
`npm install` and is visible in the repo.

Direct upgrade to 21.3.1 wasn't viable: file-type went ESM-only at
17.0.0, and our jimp 0.22.x chain still uses CommonJS `require()` —
an override would have broken vibrant at runtime. Patch-package is
the right tool when upstream's only fix lives behind a breaking
module-system change.

Added `postinstall: patch-package` to package.json so the patch
applies automatically on fresh installs.

cc
2026-05-14 09:18:02 -06:00