Commit Graph
1805 Commits
Author SHA1 Message Date
vicrodh 736753585e feat(titlebar): add window controls customization store and i18n keys 2026-02-25 20:00:15 -06:00
vicrodh 76cdfc73b2 fix(titlebar): reduce circular large button gap to 15px 2026-02-25 20:00:10 -06:00
vicrodh 44bb1dc6f9 feat(titlebar): scale window control button gap by size
Circular: 6px (small) -> 12px (normal) -> 18px (large)
Square: 4px (small) -> 8px (normal) -> 12px (large)
Rectangular stays flush (no gap) at all sizes.
2026-02-25 19:57:40 -06:00
vicrodh 56b4d467e3 fix(listenbrainz): fix error display, persistence, and build warning
- Remove unused ListenBrainzResponse struct (build warning)
- Fix error display showing [object Object] instead of actual message
- Persist credentials to legacy SQLite cache on connect/disconnect
  so they survive app restarts
2026-02-25 19:13:15 -06:00
vicrodh dce0b5c900 feat(settings): convert to tab-based navigation
Replace scroll-based section navigation with tab-based rendering where
only one section is visible at a time. Merge Offline Mode into Downloads
tab. Move Remote Control into Developer tab. Uncollapse previously
collapsed sections (Downloads, Storage, Developer). Add Developer to
nav tabs.
2026-02-25 18:59:40 -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 7babed1e63 chore: remove test file 2026-02-25 17:22:20 -06:00
vicrodh 3f5170e3bd test: should pass 2026-02-25 17:22:17 -06:00
vicrodh a68594f348 fix(adr-001): replace t variable names in store callbacks
Rename t -> item/track in .map()/.filter() callbacks in
favoritesStore.ts and queueStore.ts to comply with ADR-001
and prevent intermittent PostCSS extraction failures.

cc
2026-02-25 17:18:07 -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 4e2be5d77e fix(search): use v2_search_playlists command for playlist search
Playlist search tab was invoking legacy 'search_playlists' command
which no longer exists. Updated both initial search and load-more
to use 'v2_search_playlists', matching the other search tabs.

Closes #129

cc
2026-02-25 16:49:22 -06:00
vicrodh c72a168bf6 fix: clear progress bar and add-to-library button after adding
After clicking Add to Local Library, the in-memory download state is
cleared so the progress bar and button disappear. Also triggers a
background scan of the added folder so the library indexes the new
files without requiring a manual refresh.
2026-02-24 15:12:06 -06:00
vicrodh 6067eb280b feat: format-aware download status in album detail view
Download checkmarks now only show for the currently selected format.
In-memory store tracks formatId per album download, and the album
detail view checks track.downloaded_format_ids from backend against
the selected format dropdown. Switching quality hides checkmarks
from a different format's downloads.
2026-02-24 15:09:16 -06:00
vicrodh 4435674210 fix: persist download checkmarks across restarts, keep track numbers
Album detail view now checks track.downloaded (from SQLite) in
addition to in-memory session status, so checkmarks survive restart.
Track numbers are no longer replaced by checkmarks -- the number
column always shows the track number (spinner only while downloading),
and the download column handles all status indicators.
2026-02-24 14:42:53 -06:00
vicrodh f31dd8755c feat: allow re-downloading purchased tracks
Green checkmark on downloaded tracks now shows a download icon on
hover, allowing users to re-download in a different format or
location. Applied to both the Purchases track list and album detail.
2026-02-24 14:31:17 -06:00
vicrodh 43d8f90153 feat: add quality/format selector for individual track downloads
When downloading a single track from the Purchases tab, if multiple
formats are available a popup lets the user choose before the folder
picker opens. Single-format tracks proceed directly as before.
2026-02-24 14:30:27 -06:00
vicrodh 328dd39dc2 fix: download path order now Artist/Album/Quality/track
Quality folder was being prepended to the destination path by the
frontend, resulting in Quality/Artist/Album/track. Now quality_dir
is passed as a separate parameter through the full stack and inserted
between album and filename by the backend path builder.
2026-02-24 14:28:26 -06:00
vicrodh f8a0b4089b fix: purchases tab counters showing zero on initial load
The metadata call used getPurchaseIds(1, 0) without a type filter.
With limit=1 the Qobuz API returns only the first type's total,
leaving the other at 0. Now fetches totals per type separately in
parallel so both counters are correct from mount.

Closes #112
2026-02-24 13:27:24 -06:00
vicrodh e9c0238e3c fix: clean up CoverflowPanel animation timeout on unmount 2026-02-24 13:14:20 -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 2917abb81c fix: track menu not closing on click outside
The click-outside logic used `el && !el.contains(target)` which
short-circuits to falsy when submenu refs are null (not rendered),
preventing the menu from ever closing. Changed to `!el || !el.contains()`
so a null ref correctly counts as "outside". Also added missing
radioSubmenuEl to the check.

Closes #120
2026-02-24 10:40:03 -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 5f1d5a24ce feat(ui): add album cover context menu in AlbumDetailView
Right-click on album artwork shows context menu with:
- Add/Change/Remove custom album cover
- Open in browser
- Save as...

Also adds v2_save_image_url_to_file backend command.

cc
2026-02-24 10:06:02 -06:00
vicrodh cac07b92d7 feat(i18n): add album cover context menu translations
Keys for add/change/remove custom cover, open in browser,
save as, and toast messages. All 4 locales (en, es, de, fr).

cc
2026-02-24 10:01:34 -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 03507c0a49 fix(keybindings): restore original queue shortcut to q
Closes #125

cc
2026-02-24 09:51: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 00c47694b3 Merge branch 'pre-release' 2026-02-23 17:16:03 -06:00
vicrodh 67ef1d5918 fix: apply GDK_DPI_SCALE on all backends, not just XWayland
GDK_DPI_SCALE is a float multiplier that works on X11, XWayland, and
native Wayland. Previously it was only applied when force_x11 was
enabled, leaving native Wayland users with no way to compensate for
their DE scale factor from within the app.

- Move GDK_DPI_SCALE application out of the force_x11 block in main.rs
- Show the DPI Scale setting in the UI for all backends (not gated
  behind the Force X11 toggle)
- GDK_SCALE remains XWayland-only (integer, not useful on Wayland)
- Setting is already persistent in graphics_settings.db
2026-02-23 17:10:41 -06:00
vicrodh 835fd19934 feat(oauth): persist session token for automatic re-auth on restart
- Save user_auth_token after successful OAuth login
- On bootstrap, restore session via saved token if no email/password creds
- If token is expired, clear it so user sees login screen normally
- Clear OAuth token on v2_clear_saved_credentials (logout)
- Add login_with_token() to api client (reuses OAuth /user/login step)

Also rename t->translateStore in NowPlayingBar.svelte (ADR-001 fix from Codex)
and improve clean-dev-runtime.sh to kill all stale processes and ports
2026-02-23 15:30:43 -06:00
vicrodh 35ac015bb7 feat(login): add OAuth browser login button and fix ToS persistence race condition 2026-02-23 14:45:34 -06:00
vicrodh 1c3cff46a3 fix(login): await ToS persistence before backend login call
The subscribe handler in qobuzLegalStore persists acceptance fire-and-
forget. If the user checks the box and immediately clicks Login, the
async write can lose the race against require_tos_accepted() which reads
the DB synchronously. Force a synchronous persist in handleLogin() so the
backend gate always sees the correct value.
2026-02-23 14:13:00 -06:00
vicrodh 84709b4adc fix(navigation): expire scroll positions after 1 hour 2026-02-23 12:14:04 -06:00
vicrodh 69b60b1bd9 fix(navigation): scope scroll position by item ID to prevent bleed between different albums/artists
Previously all albums shared one scroll position key ('album'), so
opening any album would restore the scroll from the last album visited.
Now keyed as 'album:id', 'artist:id', 'playlist:id' so each item
tracks its own position independently. Back navigates to exact scroll,
fresh opens start at 0.
2026-02-23 12:09:40 -06:00
vicrodh 6b6dd54944 fix(multi-select): move BulkActionBar to bottom position, add LabelView multi-select
- Revert placement='top' to default bottom sticky across all views
- Content area already has padding-bottom: 100px in all views so no
  track is ever hidden behind the bar
- AlbumDetailView/ArtistDetailView/WeeklySuggestView: bar now after tracks
- DynamicSuggestView/FavQView/TopQView: bar now after tracks (new views)
- LabelView: complete multi-select implementation with checkbox rows,
  Select toggle button, and BulkActionBar after popular tracks list
2026-02-23 12:05:14 -06:00
vicrodh e2beba23f2 feat(multi-select): Phase 3 - AlbumDetailView, ArtistDetailView, WeeklySuggestView
AlbumDetailView:
- Select toggle button alongside AlbumMenu in action bar
- TrackRow selectable/selected/onToggleSelect props wired
- BulkActionBar with play next/later, add to playlist, add to favorites
- buildAlbumQueueTracks helper (album artwork and artist from album props)

ArtistDetailView (Popular Tracks section):
- Select button in section-header-actions alongside Play All
- Checkbox injected before track-number in custom track-row div
- click/keydown/contextmenu handlers respect multiSelectMode
- multi-selected highlight CSS
- BulkActionBar with add to favorites using toggleTrackFavorite

WeeklySuggestView:
- Select toggle button in track-controls (next to search)
- TrackRow selectable/selected/onToggleSelect props wired
- BulkActionBar with play next/later, add to playlist
- Reuses existing buildQueueTracks helper
2026-02-23 11:31:58 -06:00
vicrodh 127841a18b feat(multi-select): Phase 2 - PlaylistDetailView + BulkActionBar fixes
- Add multi-select mode to PlaylistDetailView (independent of custom order mode):
  Select toggle button in track-controls toolbar, multiSelectedKeys state,
  checkboxes per row, multi-selected highlight, BulkActionBar with play
  next/later, add to playlist, and bulk remove from playlist
- Bulk remove handles local tracks (one-by-one), Qobuz tracks with
  playlistTrackId, and fallback trackId in a single invocation each
- Add onRemoveFavorites prop to BulkActionBar (HeartOff icon, danger style)
- Fix FavoritesView: replace Add to Favorites with Remove from Favorites
  (tracks are already in favorites, remove makes sense there)
2026-02-23 11:13:09 -06:00
vicrodh b1a7ce51c7 feat(multi-select): Phase 1 - FavoritesView track multi-select
- Add BulkActionBar component (sticky-bottom bar with queue split button,
  add to playlist, add to favorites, clear selection)
- Add selectable/selected/onToggleSelect props to TrackRow with checkbox UI
- Add .selected highlight and .track-checkbox CSS to TrackRow
- Extend VirtualizedTrackList with selectable/selectedIds/onToggleSelect props
- Wire FavoritesView tracks tab: Select toggle button in toolbar,
  selectedTrackIds state, BulkActionBar with bulk queue/favorites/playlist handlers
- Add actions.select and actions.cancelSelection i18n keys to all 4 locales
2026-02-23 11:07:30 -06:00
vicrodh f53af39185 feat(favorites): show album artwork in track rows, add release codename
- Favorite tracks now display album art between track number and title,
  matching the layout used in PlaylistDetailView (showArtwork=true)
- VirtualizedTrackList gains showArtwork and getArtworkUrl props
- AboutModal: add release codename 'La marrano de engorda' (1.1.15)
- README: remove stale KWin native title bar manual workaround section
2026-02-23 10:25:36 -06:00
vicrodh e843cb736f fix(svelte): remove hidden t shadow and harden checker
cx
2026-02-23 10:09:41 -06:00
vicrodh c761ff1fd7 feat(settings): add 85% and 95% UI scale options
Add finer granularity below 100% for users who prefer slightly
smaller UI without jumping from 90% to 100%.
2026-02-23 08:55:25 -06:00
vicrodh cd1a56cde6 feat(ui): sync custom image store from detail and library views
After setting/removing custom artist images in ArtistDetailView
or LocalLibraryView, update the global store so all views
reflect the change immediately. Also fix LocalLibraryView to use
the resized thumbnail path from the backend result instead of
the original unresized file path.
2026-02-23 08:55:25 -06:00
vicrodh 40060497db feat(ui): resolve custom artist images in LabelView
Insert custom image check at top of getArtistImageUrl() before
all other fallback sources. Artists on label pages show custom
images when set.
2026-02-23 08:55:25 -06:00
vicrodh c1a67c61d5 feat(ui): resolve custom artist images in FavoritesView
Add withCustomImages() helper that overrides artist image objects
before passing to groupArtists(). All 3 call sites (alpha index,
sidepanel, virtualized grid) get custom image overrides.
2026-02-23 08:55:25 -06:00
vicrodh aac411d82f feat(ui): resolve custom artist images in HomeView
Wrap toArtistCard() image resolution with custom image store
lookup. Featured artists on home page show custom images.
2026-02-23 08:55:25 -06:00
vicrodh c4c467eecd feat(ui): resolve custom artist images in SearchView
Wrap getArtistImage() to check custom image store before
falling back to Qobuz default. All 3 call sites (most popular,
search results, virtual grid) get the override automatically.
2026-02-23 08:55:25 -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 6b54db1073 feat(store): create customArtistImageStore
Centralized store for resolving custom artist image overrides
globally. Loaded on login, exposes resolveArtistImage() with
normalized name matching (handles diacritics, case differences).
2026-02-23 08:55:25 -06:00