Commit Graph
2495 Commits
Author SHA1 Message Date
vicrodh c6f05346d7 feat(backend): add remove and get custom artist image commands 2026-02-23 02:21:42 -06:00
vicrodh 6b8955e2d3 feat(backend): resize and thumbnail custom artist images 2026-02-23 02:19:08 -06:00
vicrodh 118656ee18 feat(ui): click album artwork to view full size 2026-02-23 02:17:42 -06:00
vicrodh b8f8ca4e3d feat(ui): click artist image to view full size 2026-02-23 02:16:45 -06:00
vicrodh a5da6e4755 feat(ui): add ImageLightbox component 2026-02-23 02:15:35 -06:00
vicrodh 985e673b72 feat(favorites): add genre filter to tracks tab with independent persistence 2026-02-23 02:02:31 -06:00
vicrodh faa4dd969c fix(ui): move results count to nav bar, left of filter/sort controls 2026-02-23 01:58:00 -06:00
vicrodh dc6646efbd fix(ui): prevent alpha-index from expanding to fill flex space in artist browse view 2026-02-23 01:56:17 -06:00
vicrodh 61b73147ca fix(ui): reduce results-count reserved width, fix dropdown menus clipped by nav bar 2026-02-23 01:53:17 -06:00
vicrodh 44d0794d4d fix(ui): move results count to header row right of search with reserved width 2026-02-23 01:50:29 -06:00
vicrodh 4b5649a464 fix(ui): move toolbar controls into nav bar right-aligned for all tabs 2026-02-23 01:48:07 -06:00
vicrodh 30e1e0d0d4 fix(ui): always show close button on expanded search input 2026-02-23 01:44:54 -06:00
vicrodh 627c7d403e fix(ui): move search to header row, right-aligned inline with title 2026-02-23 01:44:20 -06:00
vicrodh 1293ae7aa7 fix(ui): match play button size to secondary in favorites tracks header 2026-02-23 01:41:46 -06:00
vicrodh 79f4bea41b fix(ui): favorites header layout - title and actions inline on same row
Remove header-content wrapper so h1 and action buttons are direct
flex children of .header, placing them inline on the same row.
Remove orphaned CSS and margin-top from header-actions.
2026-02-23 01:41:04 -06:00
vicrodh 8955d90c3a refactor(favorites): remove custom icon, keep only tab order settings
Strip the customizable icon from the Favorites header (now always a
Heart icon) and remove icon/background customization sections from the
edit modal. The modal now only handles tab order reordering. Removed
dead code: resolveCustomIconSrc, customIconSrc, unused lucide imports
(Star, Folder, Library, Heart), convertFileSrc import, header-icon CSS.
2026-02-23 01:35:41 -06:00
vicrodh 4ce765d7f8 fix(immersive): add drag handle button to window controls
Add a Move icon button inside the expandable window controls group
in ImmersiveHeader. On mousedown it calls window.startDragging() to
let the user reposition the window. Cursor shows grab/grabbing.
Only available when the controls are expanded (hover), so collapsed
state has no drag zone as intended.
2026-02-23 01:03:46 -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 3d2a4cbe97 fix(deep-link): robust qobuzapp:// handler across all packages
- Auto-detect installed .desktop filename (com.blitzfc.qbz.desktop,
  qbz.desktop, qbz-nix.desktop) instead of hardcoding
- Run update-desktop-database after register/deregister so xdg-open
  and browsers pick up the MIME association immediately
- Fix v2_check_qobuzapp_handler to match all known desktop filenames
- Align StartupWMClass to com.blitzfc.qbz across all packaging formats
- Add StartupNotify=true to Arch/AUR/Snap desktop files

Fixes browser URI handler not working for .deb users (Discussion #44)
2026-02-23 00:38:10 -06:00
vicrodh 7a5fe2f5ce fix(ui): keybindings settings modal z-index and 2-column layout
KeybindingsSettings (Customize Shortcuts) had z-index 1000, behind
NowPlayingBar (2001). Bumped to 3000 per ADR-003. Also widened to
660px and added 2-column grid layout with responsive fallback.

This was the actual broken modal — KeyboardShortcutsModal was already
fixed but KeybindingsSettings was missed.
2026-02-22 22:28:07 -06:00
vicrodh abc7a1a2a3 fix(ui): right-click context menu on all card components
- AlbumCard: right-click opens AlbumMenu at click position
- FavoritePlaylistCard: right-click opens menu at click position
- QobuzPlaylistCard: add right-click context menu with click positioning
- SearchPlaylistCard: add right-click context menu with click positioning
- All card menus now use floatingMenuStore for mutual exclusion
- Menu positioning uses click coordinates instead of trigger button
2026-02-22 20:17:40 -06:00
vicrodh 0ee8b9db0e feat(settings): make sync audio on startup opt-in
The reload_settings() call at bootstrap is now gated behind a new
sync_audio_on_startup setting (default OFF). Most users don't need
it; it exists for edge cases where Player::new() holds stale settings
(e.g., after Flatpak updates changing DB schema).

Adds toggle in Settings > Audio with i18n for all 4 locales.
2026-02-22 19:54:12 -06:00
vicrodh 0dea116c69 fix(audio): move reload_settings from per-play to once at bootstrap
reload_settings() was running before every v2_play_track call, which
is excessive and can overwrite correct in-memory audio settings with
stale DB values (especially in Flatpak where DB sync timing differs).

Moved to runtime_bootstrap Step 6, after session activation when
per-user stores are ready. v2_reinit_audio_device still reloads on
explicit device changes.
2026-02-22 19:48:32 -06:00
vicrodh 33e8d34bef fix(i18n): add missing diacritics in es, fr, de locales 2026-02-22 18:45:14 -06:00
vicrodh e811afe27e feat(ui): add right-click context menu to album and playlist cards 2026-02-22 18:13:11 -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 d7213e06a4 fix(runtime): wait for CoreBridge init before bootstrap auth 2026-02-22 17:59:22 -06:00
vicrodh 2e51c2e1f2 fix(ui): favorites albums and artists height overflow behind player 2026-02-22 17:58:58 -06:00
vicrodh 37cca5dccf fix(ui): render sanitized HTML in playlist descriptions 2026-02-22 17:58:41 -06:00
vicrodh 66d25b773b fix(ui): keybindings modal z-index and 2-column layout 2026-02-22 17:57:46 -06:00
vicrodh 02bfc7ba91 fix(ui): suppress WebKit default context menu globally 2026-02-22 17:57:05 -06:00
vicrodh 221a66c675 fix(audio): reload settings before first play to prevent 48kHz lock
On first play after app start, the audio thread held stale settings from
Player::new() — if the user had configured PipeWire/ALSA backend, the
thread might not use the correct backend/device, defaulting to 48kHz.

Now v2_play_track reloads settings from the DB before every play_data()
call, matching what v2_reinit_audio_device already does. This is why
re-selecting the device fixed the issue: it called reload_settings first.

Also extracts convert_to_qbz_audio_settings() helper to deduplicate the
settings conversion between v2_play_track and v2_reinit_audio_device.

Fixes #69
2026-02-21 08:54:57 -06:00
vicrodh 06c6b3457b feat(radio): add track radio submenu to playlist and favorites views
Thread onCreateQbzRadio/onCreateQobuzRadio through TrackRow,
VirtualizedTrackList, PlaylistDetailView, and FavoritesView so
track context menus in playlists and favorites show the radio
submenu with QBZ Radio and Qobuz Radio options.
2026-02-21 07:34:58 -06:00
vicrodh 209cacb569 feat(mixes): add FavQ and TopQ to Your Mixes section
FavQ shuffles up to 50 tracks from the user's Qobuz favorites.
TopQ seeds the Qobuz suggest API from the user's most-played playlists.
Both have same-day cache, refresh button, red/blue gradient artwork,
and a "qbz" badge (vs "qobuz" on DailyQ/WeeklyQ).
2026-02-20 22:45:55 -06:00
vicrodh f4113a9622 feat(ui): add right-click context menu to track rows
Add context menu support (right-click) to the inline track rows in
ArtistDetailView and LabelView popular tracks sections. Right-clicking
a track opens the TrackMenu at the cursor position with all available
actions. Also wires up TrackRow component with contextMenuPosition
prop for the same functionality in reusable track rows.
2026-02-20 22:12:35 -06:00
vicrodh 2dcaa76027 feat(radio): add Qobuz artist/track radio with submenu selection
Add /radio/artist and /radio/track Qobuz API endpoints alongside the
existing /radio/album. TrackMenu now shows a radio submenu with QBZ
Radio (RadioPoolBuilder) and Qobuz Radio options when both are
available. Artist header radio button opens a dropdown to choose
between the two engines.

Backend: get_radio_artist(), get_radio_track() in client.rs,
v2_create_qobuz_artist_radio and v2_create_qobuz_track_radio commands.
Frontend: TrackMenu radio submenu with mutual exclusion against
share/download submenus, ArtistDetailView dropdown, LabelView support.
i18n keys added to all four locale files.
2026-02-20 22:10:44 -06:00
vicrodh f8a56d7f4b fix(radio): fetch full track data for album radio
The /radio/album endpoint returns partial track objects without the
performer field, causing all tracks to show as "Unknown Artist".
Extract track IDs from the response and fetch each via get_track()
to get complete data, matching the pattern used by artist/track radio.
2026-02-20 21:38:56 -06:00
vicrodh 557414ce4e feat(radio): add album radio button to UI
Add Radio button to album detail header (next to favorite button)
that calls v2_create_album_radio, populates the queue with Qobuz
API recommended tracks, and starts playback of the first track.

Add i18n keys for album radio in all 4 locale files (en/es/de/fr).
2026-02-20 21:35:15 -06:00
vicrodh d47f89c6b2 feat(radio): add RadioResponse model, API method, and v2_create_album_radio command
Add /radio/album Qobuz API endpoint support:
- RadioResponse struct in models.rs with lenient deserialization
- get_radio_album() client method
- v2_create_album_radio command that calls the API directly (no
  RadioPoolBuilder/RadioDb), filters blacklisted artists, populates
  queue, and sets Radio playback context
- Register command in lib.rs invoke handler
2026-02-20 21:32:23 -06:00
vicrodh 06c0e9735c fix(session): use struct return type and proactive saves
Two fixes for session not persisting:

1. Changed v2_get_all_queue_tracks to return a struct instead of a
   tuple — Tauri IPC serialization of tuples is unreliable.

2. Added proactive session saves instead of relying on async
   beforeunload (which races with window close):
   - Debounced full save on track change (2s after new track starts)
   - Debounced full save on pause
   - Reduced periodic save from 60s to 15s during playback
   - Close handler remains as best-effort backup
2026-02-20 20:43:35 -06:00
vicrodh aa1aa32f7a fix(session): save full queue with all tracks and metadata
The save was broken in two ways:
1. Only current_track + upcoming (capped at 20) were saved, dropping
   all history tracks. Queue was reconstructed incomplete on restore.
2. Track metadata (hires, bit_depth, sample_rate, source, etc.) was
   not being persisted, only the basic 6 fields.

Add v2_get_all_queue_tracks command that returns the full uncapped
track list with correct current_index. Use it in saveSessionBeforeClose
instead of the capped v2_get_queue_state. Map all metadata fields.
2026-02-20 20:33:39 -06:00
vicrodh 5a0d4c50a1 feat(session): re-enable session restore and add startup page setting
Re-enable queue/track restore on startup (visual only, paused at 0:00).
Update saveSessionBeforeClose to persist current view with context IDs.
Add "Startup page" dropdown in Settings > Appearance (Home / Where you
left off) that controls whether the last view is restored on launch.
i18n keys added to all 4 locale files.
2026-02-20 20:02:26 -06:00
vicrodh 07d5d95cea feat(session): extend frontend service and add restoreView helpers
Update PersistedSession interface with last_view fields. Add lastView,
viewContextId, viewContextType params to saveSessionState(). Add
restoreView(), setRestoredPlaylistId(), setRestoredLocalAlbumId() to
navigationStore for session restore without triggering data fetches.
2026-02-20 19:58:54 -06:00
vicrodh cda07f97c5 feat(session): extend schema with last_view columns and V2 params
Add last_view, view_context_id, view_context_type to player_state
table via migration. Update PersistedSession struct, save/load/clear,
and v2_save_session_state with 3 new optional parameters.
2026-02-20 19:58:17 -06:00
vicrodh 6a04f13174 fix(keybindings): resolve 4 keyboard shortcut bugs (#95)
- Strip Shift modifier for symbol keys in eventToShortcut() so ? maps correctly
- Remove duplicate Space handler in ImmersivePlayer that caused double-fire
- Add bindingsVersion dependency to KeybindingsSettings for instant visual updates
- Add missing uiOpenLink i18n key and use getActionLabel() fallback in modal
- Add full keybindings translations to de.json and fr.json
2026-02-20 19:33:40 -06:00
vicrodh cd57d37e7a feat(settings): add font family selector in Appearance
- Add 4 bundled fonts: Montserrat, Noto Sans, Source Sans 3, plus
  existing LINE Seed JP (default) and System fallback
- Font selector dropdown in Settings > Appearance, after Language
- Persisted in localStorage, applied on app bootstrap via data-font
  attribute on <html> which overrides --font-sans CSS variable
- @font-face declarations for variable font files in static/fonts/
- i18n key "fontFamily" added to all 4 locales
2026-02-20 18:13:57 -06:00
vicrodh e82940810b feat(immersive): make window draggable and rename to Immersive Mode
- Add persistent drag region (32px strip) at top of immersive overlay
  that remains active even when the header auto-hides after 4 seconds
- Add app-region: drag CSS to ImmersiveHeader's left spacer for proper
  drag support when header is visible
- Add app-region: no-drag to tabs and window controls to keep them
  clickable
- Double-click on drag strip toggles maximize
- Rename "Full Screen" to "Immersive Mode" in all 4 locales (en/es/de/fr)
2026-02-20 18:03:41 -06:00