Commit Graph
512 Commits
Author SHA1 Message Date
vicrodh 72700a9ee7 feat: center tab bar, tab navigation history, persist last tab
- 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
2026-03-10 01:29:23 -06:00
vicrodh da225499ef fix: pass known MBID from scene discovery to artist detail view
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.
2026-03-09 16:21:19 -06:00
vicrodh 277ac7a391 feat: rewrite scene discovery view to match Favorites Artists UX
- 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
2026-03-09 15:04:33 -06:00
vicrodh 0f1595eba5 feat: add ArtistsByLocationView and wire scene discovery navigation
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.
2026-03-09 12:18:02 -06:00
vicrodh d2430fa19f fix: migrate localStorage to user-scoped storage in views
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.
2026-03-09 11:22:34 -06:00
vicrodh fd3586cf70 refactor: replace setTimeout with tick() for DOM scroll query
handleViewArtistDiscography now uses await tick() instead of
setTimeout(100ms) to wait for the DOM update before scrolling
to the discography section.
2026-03-09 11:05:50 -06:00
vicrodh 620dc10a3a perf: batch queue-next calls into single IPC
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.
2026-03-09 11:02:18 -06:00
vicrodh 9f709efdc6 fix: artist network sidebar UX and equalizer paused state
- 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
2026-03-08 22:40:29 -06:00
vicrodh 7cec1101d1 fix: make currentNavItemId reactive with $state()
Without $state(), Svelte 5 doesn't track changes to currentNavItemId,
so the scroll reset $effect never re-fires on same-view item changes.
2026-03-08 10:17:45 -06:00
vicrodh 3c783973b1 fix: reset scroll to top on forward navigation between same-view items
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.
2026-03-08 10:12:02 -06:00
vicrodh 150d80dfac feat: granular navigation history with per-item scroll position
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.
2026-03-08 10:05:45 -06:00
vicrodh 6baae44327 fix: map epSingle type and re-categorize items from download/other groups (#149)
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.
2026-03-07 23:03:20 -06:00
vicrodh 765287817b fix: backfill EPs & Singles when artist/page omits them (#149)
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.
2026-03-07 22:20:49 -06:00
vicrodh cffbce9faa fix: faster session restore and remember playback position
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).
2026-03-07 22:01:18 -06:00
vicrodh 9c841365f8 Revert "feat(theme): add System (Dark / Light) theme and rename System to Match Colors"
This reverts commit 82e358208a.
2026-03-06 12:46:32 -06:00
vicrodh 82e358208a feat(theme): add System (Dark / Light) theme and rename System to Match Colors
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
2026-03-06 11:27:14 -06:00
vicrodh 5b9f5a75c2 feat(ui): add explicit content badge across entire app
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.
2026-03-06 08:48:51 -06:00
vicrodh 18b7bcaf31 ui: increase custom titlebar height by 4px (36 -> 40)
Search input in titlebar also grows 4px (24 -> 28) for better
readability. Layout calculations updated in page, sidebar, and store.
2026-03-04 09:02:06 -06:00
vicrodh 00675de6b8 feat(snap): add snap sandbox detection and welcome modal wiring
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.
2026-03-02 11:10:50 -06:00
vicrodh 47f80149d5 feat(playlists): add custom artwork and folder sidebar visibility controls
cx
2026-03-01 22:09:43 -06:00
vicrodh 55a1ef25e6 fix(ui): polish mini/immersive layout and queue favorite behavior
cx
2026-03-01 18:56:23 -06:00
vicrodh 7753d2520e fix: multi-select add to playlist sends all tracks in one call
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.
2026-03-01 16:19:12 -06:00
vicrodh 976e5226b4 feat: add miniplayer keyboard shortcuts and fix X button behavior
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.
2026-03-01 14:04:18 -06:00
vicrodh d6852500bf fix(miniplayer): refine queue artwork overlays and inline controls
cx
2026-02-26 02:22:52 -06:00
vicrodh e0cfc5d92b feat(miniplayer): add default surface setting and queue row play controls
cx
2026-02-26 02:14:09 -06:00
vicrodh 339f2b8106 fix(miniplayer): restore next/prev playback and remanent shuffle
cx
2026-02-26 02:03:15 -06:00
vicrodh 9302ffe5e6 fix(miniplayer): sync window theme with global app settings
cx
2026-02-26 01:58:37 -06:00
vicrodh 1ba6fe13d5 refactor(miniplayer): tighten compact spacing and simplify play button
cx
2026-02-26 01:54:11 -06:00
vicrodh d6b0e0f5ea feat(miniplayer): refine micro surface layout and controls
cx
2026-02-26 01:45:59 -06:00
vicrodh 99c8ae1ed3 feat(miniplayer): rebuild surfaces window with compact overlay polish
cx
2026-02-26 00:54:13 -06:00
vicrodh af83cec692 feat(ui): subtle rounded corners and shadow when window is floating
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.
2026-02-25 20:20:59 -06:00
vicrodh 736753585e feat(titlebar): add window controls customization store and i18n keys 2026-02-25 20:00:15 -06:00
vicrodh 867abb5f51 feat(search): hide SearchView input when search is in titlebar
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.
2026-02-25 17:56:11 -06:00
vicrodh bff518e638 feat(search): add toggleable search bar in titlebar
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)
2026-02-25 17:53:13 -06:00
vicrodh cc21491079 fix(search): search shortcut works with collapsed sidebar
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
2026-02-25 16:55:55 -06:00
vicrodh 5ad2357aca security: sanitize console.log statements that leak sensitive data
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.
2026-02-24 12:20:25 -06:00
vicrodh 52e5054172 fix: purchases and verbose log toggles not persisting across restart
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
2026-02-24 10:57:02 -06:00
vicrodh 114b120fd4 feat: propagate custom album covers across all views
Resolve custom album covers in AlbumCard (covers 30+ usages
automatically), NowPlayingBar, and ImmersivePlayer.
2026-02-24 10:11:01 -06:00
vicrodh 877c3e4a0c feat(store): add customAlbumCoverStore with init/clear lifecycle
Frontend store for custom album covers. Initialized on login,
cleared on logout. Same pattern as customArtistImageStore.

cc
2026-02-24 10:00:24 -06:00
vicrodh 8fe8d39b53 feat(keybindings): add sidebar shortcut, rebrand Focus to Immersive
- Add ui.sidebar action (Shift+S) to toggle sidebar (fixes #125)
- Change ui.focusMode default to Shift+I, ui.queue to Shift+Q
- Rename "Focus Mode" to "Immersive" in all user-facing labels
- Update all 4 locale files (en, es, de, fr)
- KeybindingsSettings modal: 820px width, 3-column layout
- ShortcutInput: compact sizing (32px height, smaller fonts)

cc
2026-02-24 09:41:13 -06:00
vicrodh 7f17d53879 feat(app): initialize custom artist image store on login
Load all custom artist image overrides on login and clear
them on logout, alongside existing blacklist store init.
2026-02-23 08:55:25 -06:00
vicrodh d2f846c541 fix(ui): disable playback controls when nothing to play
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
2026-02-23 00:56:39 -06:00
vicrodh d5203d498a feat(favorites): add random album and artist buttons 2026-02-22 18:12:20 -06:00
vicrodh 6229fa8400 feat(ui): add loading spinner to radio buttons 2026-02-22 18:09:07 -06:00
vicrodh 6c1979b7ea fix(session): persist empty queue state on clear 2026-02-22 18:05:18 -06:00
vicrodh 643bb20c2e feat(settings): add opt-in session persistence toggle 2026-02-22 18:05:02 -06:00
vicrodh 02bfc7ba91 fix(ui): suppress WebKit default context menu globally 2026-02-22 17:57:05 -06:00
vicrodh 155897a5b1 fix: improve connect-time queue push reliability
- 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
2026-02-22 14:02:18 -06:00
vicrodh 8f2fd7cf1a fix: resolve queue_item_id from track_id, fix loadQconnectQueue, push queue on connect
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.
2026-02-22 14:01:42 -06:00
vicrodh db0360f4e0 fix(qconnect): sync full queue to remote when starting album or playlist
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.
2026-02-22 13:00:19 -06:00