- Center button group in content area, independent of greeting
- Increase tab button size (padding 7px 16px, font 13px)
- Each tab is an independent history entry (back/forward works)
- Persist last used tab in localStorage across restarts
- Context navigation returns to correct home tab (forYou/editorPicks)
- Rename sidebar Home to Discover in all 4 locales
When navigating from scene discovery to artist detail, pass the
MBID we already have from MusicBrainz instead of resolving by
name. Fixes wrong metadata for homonymous artists (e.g. The
Warning MX vs The Warning US).
Also improve Qobuz validation to request 5 results and pick
the best match by albums_count for name collisions.
- Country flag header from circle-flags CDN
- Client-side search filtering
- A-Z grouping toggle
- Grid/sidepanel view toggle with album browser
- Back button matching FavoritesView style
- Proper margins and layout matching existing views
- Scene label shows country name only
- Pass countryCode through location context for flag display
Create the artists-by-location view that displays scene discovery
results using VirtualizedFavoritesArtistGrid. Wire onLocationClick
from ArtistDetailView through +page.svelte to navigate to the new view.
ArtistDetailView sort preferences and PlaylistDetailView copied
playlists now use getUserItem/setUserItem for per-user scoping.
Added migrateLocalStorageV2 to handle qbz_ prefixed keys that
the original migration missed (only covered qbz- prefix). Runs
once per user independently from v1 migration.
Replace per-track loops in queueAlbumNextById,
queuePlaylistNextById, and handleAddAlbumToQueueNext with a
single addTracksToQueueNext() call that sends all tracks in one
invoke to v2_add_tracks_to_queue_next. Backend already reverses
order internally.
- Sidebar opens by default with localStorage persistence
- Simplified header: "Artist Network" title + PanelRightClose icon
- Hide RELATIONSHIPS section when no data (no empty placeholder)
- Restore sidebar after queue/lyrics panel closes
- Clean up sidebar state on artist view destroy
- TrackRow: show track number instead of frozen bars when paused
When navigating from album(1) to album(2), the view type stays 'album'
so the scroll reset effect didn't trigger. Now tracks currentNavItemId
changes too, and explicitly scrolls to top for forward navigation while
preserving scroll restore on back/forward.
Navigation history now tracks itemId per entry (album, artist, playlist,
label, musician, purchase-album) so back/forward restores the exact page.
Scroll positions are saved per view+itemId key and restored on back/forward.
The Qobuz artist/page API returns release groups with type "epSingle"
(not "ep" or "single"), and groups like "download" and "other" contain
mixed items (singles, albums) that should be re-categorized by each
item's individual release_type field.
The Qobuz artist/page endpoint sometimes excludes the EP/single
release group from its response. When this happens, fetch them
explicitly via get_releases_grid as a non-blocking backfill.
Move session restore to run immediately after playback preferences
load, before network-heavy initializations (favorites, offline
status, recommendation scores). This eliminates the multi-second
"No track playing" gap on slow storage.
Also restore the saved playback position visually and on first play
(seek to saved position, no auto-play).
Add a new "System (Dark / Light)" theme option that toggles between
Dark and Light themes based on OS prefers-color-scheme, with a live
matchMedia listener for instant switching. Rename old "System" (auto
palette generation) to "Match Colors" for clarity.
Applies to main window, miniplayer, and bootstrap.
Closes#148
Display parental_warning badge (E icon) next to track titles in all
views: TrackRow, QueuePanel, NowPlayingBar, ImmersivePlayer with all
13 visualizer panels, MiniPlayer surfaces, and AlbumDetailView.
Propagate parental_warning field through the full data chain from
Rust backend (qbz-models, queue, commands_v2, session_store, API
server) to frontend stores, adapters, and UI components. Badge uses
CSS mask technique with explicit.svg for theme compatibility.
Detect when QBZ runs inside a Snap sandbox (via SNAP env var) and show
a one-time welcome modal with required plug connection commands. Adds a
Snap Sandbox section in Settings with copyable commands, mirroring the
existing Flatpak pattern.
Backend: snap.rs module, DB table snap_welcome_shown, V2 commands.
Frontend: updatesService, +page.svelte modal queue, SettingsView section.
The broken views called onTrackAddToPlaylist in a loop (once per
selected track), causing each call to overwrite the previous track
IDs in the playlist modal. Only the last track survived. Now all 6
views collect IDs first and call onBulkAddToPlaylist once with the
full array.
Views fixed: ArtistDetailView, AlbumDetailView, LabelView,
FavoritesView, WeeklySuggestView, PlaylistDetailView.
Add Shift+M toggle shortcut for mini player mode (main and mini window).
Add 1-5 number keys for surface switching (micro/compact/artwork/queue/lyrics)
in mini player context. Add playback shortcuts (Space, Ctrl+Arrow) to mini
player window. Fix X button to close app (or hide to tray) instead of
duplicating the Expand button behavior. Closes#134.
Detect maximized state via Tauri window API. When the window is not
maximized (floating), apply 8px border-radius and a soft box-shadow.
Body/html backgrounds set to transparent so corners show through
the Tauri transparent window.
When the titlebar search is active, the search input inside SearchView
is redundant. Hide it so only the tabs and results remain. The query
still syncs from the titlebar via the shared searchState store.
Search input can now live in the titlebar instead of the sidebar,
controlled by a new toggle in Settings > Appearance. When the custom
titlebar is hidden or system titlebar is active, search stays in the
sidebar regardless of the toggle.
- New searchBarLocationStore with localStorage persistence
- TitleBar accepts search props and exposes focusSearch()
- Sidebar hides its search container when titlebar search is active
- Ctrl+F focuses the active search input in both modes
- Titlebar height increased from 32px to 36px to fit the search field
- Translations added to all 4 locale files (en, es, de, fr)
Expand the sidebar automatically when Ctrl+F is pressed while it's
collapsed. Also replace setTimeout with Svelte's tick() in focusSearch
to properly wait for DOM updates before focusing the input.
Closes#124
cc
Login responses were serialized as full objects (user_id, subscription,
tokens). Track play logs dumped the entire QobuzTrack/Track object which
may include signed CDN URLs. Now only log the minimum needed for
debugging (success booleans, track id + title).
This likely caused the 0x0.st 451 rejection when users tried to upload
their console logs for bug reports.
Both stores read getUserItem() at module load time when the userId is
still null, so they hit the unscoped localStorage key. After login,
writes go to the user-scoped key (qbz.{userId}.key) which is never
read back on the next restart.
Add rehydrate functions that re-read from localStorage after
setStorageUserId() + migrateLocalStorage() have run, matching the
existing resyncPersistedVolume() pattern.
Closes#113
Grey out shuffle, previous, play/pause, next, repeat, add-to-playlist,
and favorite buttons when no track is loaded and queue is empty.
Volume/mute controls remain always active.
Closes#103
- Use parseInt(item.id) as fallback when trackId is not set on QueueTrack
- Add 2s delay after TransportConnected to let QConnect session setup
complete before pushing local queue
Three fixes for QConnect seekbar and queue sync:
1. Position reports now include currentTrackId from frontend. Backend
looks up queue_item_id by matching track_id against QConnect queue
state when renderer sync state has no cached value. This resolves
the root cause of seekbar showing position 0 on controllers.
2. loadQconnectQueue changed from fire-and-forget (void) to proper
error handling with logging at every step. Added logging before
isQconnectConnected check to diagnose silent failures.
3. When TransportConnected event fires while QBZ is already playing,
automatically push the local queue to QConnect server so controllers
immediately see the correct tracks.
When playing an album or playlist from QBZ, the local queue was
replaced but the QConnect remote queue was never updated, causing
controllers to show a stale queue.
Add loadQconnectQueue() function that sends queue_load_tracks to the
remote with all track IDs. Wire it into playAlbumById() and
playPlaylistById() so the remote queue updates when a new
album/playlist starts playing locally.