Commit Graph
2516 Commits
Author SHA1 Message Date
vicrodh 415a9d93f3 fix: hide cover art on unavailable albums so overlay text is readable 2026-02-17 18:58:08 -06:00
vicrodh 42915197e3 feat: add downloaded purchases registry in SQLite backend with V2 commands
- downloaded_purchases table in library DB (permanent, per-user)
- V2 commands: mark_downloaded, remove_downloaded, get_downloaded_track_ids
- Frontend enriches purchase data with download status from backend
- Grid overlay for unavailable albums centered on artwork
- Quality filter expanded: All / Hi-Res / CD / Lossy (radio group)
- Album download status derived from track-level registry
2026-02-17 18:57:24 -06:00
vicrodh eb6830430e feat: move unavailable banner to artwork overlay, add hide-downloaded filter with persistence 2026-02-17 18:44:56 -06:00
vicrodh 3cabd95ff4 refactor: use portal file picker instead of mock text input for download folder 2026-02-17 18:36:34 -06:00
vicrodh c14754d4ef refactor: reuse existing UI patterns in purchases views
- Toolbar: FavoritesView pattern (control-btn, dropdown-menu, dropdown-item)
- Albums: grid/list toggle, group by (Off/A-Z/Artist), sort with direction
- Filter panel: LocalLibraryView pattern (checkbox for hide unavailable, Hi-Res)
- Tracks: group by (Off/Artist/Album/Name A-Z)
- Format selector: standard Dropdown component instead of custom pill
- Download All: global action-btn-circle instead of custom button
- Quality in track rows: plain text (12/192) instead of QualityBadge images
- QualityBadge compact only in album header and list mode
- Add filter.availability and filter.hideUnavailable i18n keys (4 locales)
2026-02-17 18:31:21 -06:00
vicrodh c7752cc1c1 style: polish purchases views to match app design language
Rewrite PurchasesView and PurchaseAlbumDetailView to match existing
views (FavoritesView, AlbumDetailView). Consistent header, sticky nav,
expandable search, scrollbar, table headers, track rows, and spacing.
2026-02-17 18:06:49 -06:00
vicrodh 58101a27f5 fix: add generic type parameters to invoke calls in purchases service 2026-02-17 17:56:03 -06:00
vicrodh 0599493a5a feat: add purchases i18n keys to all 4 locales
Keys added to en.json, es.json, de.json, fr.json:
- nav.purchases
- settings.appearance.showPurchases/showPurchasesDesc
- purchases.* section with tabs, search, filters, sorts,
  download actions, progress, formats, and empty states
2026-02-17 17:54:37 -06:00
vicrodh d57a27ad45 feat: wire purchases views into navigation, sidebar, and settings
- Add 'purchases' and 'purchase-album' to ViewType
- Add conditional ShoppingBag nav item in Sidebar (between Favorites and Playlists)
- Wire PurchasesView and PurchaseAlbumDetailView in +page.svelte
- Add Show Purchases toggle in Settings > Appearance
- Toggle persisted via purchasesStore, hidden by default
2026-02-17 17:52:05 -06:00
vicrodh 86593749ec feat: add PurchasesView and PurchaseAlbumDetailView components
PurchasesView: albums grid and tracks list with search, filter
(all/hires), sort (date/artist/album/quality), and download buttons.

PurchaseAlbumDetailView: album header, format picker, folder picker
(mock mode text input), per-track download buttons, progress bar,
multi-disc grouping, and post-download Add to Library button.
2026-02-17 17:49:26 -06:00
vicrodh eecaa624a8 feat: add purchase types, service layer, and store
- PurchaseResponse, PurchasedAlbum, PurchasedTrack, progress types
- Service layer with mock/real toggle via VITE_MOCK_PURCHASES env var
- purchasesStore for show/hide toggle persistence via userStorage
2026-02-17 17:46:12 -06:00
vicrodh 1d39d37a29 feat: add FastAPI mock server for purchase downloads
Lightweight mock API serving Qobuz-shaped purchase data with CORS
enabled for localhost:1420. Includes 8 albums (varied genres, one
multi-disc, one with downloadable:false), 5 individual tracks,
format options, search, and simulated download progress via SSE.
2026-02-17 17:45:24 -06:00
vicrodh ceaf299558 feat(immersive): add spectral ribbon and fix home blacklist filtering
- add Spectral Ribbon analyzer/render path and immersive panel
- tune ribbon density/interpolation and bars edge-bin rendering
- apply artist blacklist filtering to discover index home containers
- include supporting i18n/settings/player wiring changes

cx
2026-02-17 17:28:32 -06:00
vicrodh e00d58949a fix: remove downloadStateVersion from each-block keys to stop flicker
The global downloadStateVersion counter was embedded in {#each} key
expressions, causing Svelte to destroy and recreate all DOM nodes
whenever the counter incremented during downloads. Track IDs alone
are stable and unique keys; download status reactivity is already
handled by props passed to TrackRow.

Also skip redundant notifyListeners() calls in setOfflineCacheState
when status and progress haven't actually changed, preventing
unnecessary downloadStateVersion++ cascades.
2026-02-17 11:38:36 -06:00
vicrodh 7b8e2d56ac feat(local-library): add Plex source filter and one-shot session sync
Add dedicated Plex source filter in albums view, header sync button when Plex is configured, and one-time auto-sync per session when Plex cache is empty.

cx
2026-02-17 11:38:24 -06:00
vicrodh 7e0c54c9f8 fix(playlists): restore suggestions and duplicate-check commands in v2
cx
2026-02-17 11:22:27 -06:00
vicrodh 76cf401a3a perf: separate library DB connection for download post-processing
Add a second LibraryDatabase connection to OfflineCacheState dedicated
to download post-processing writes. SQLite WAL mode natively handles
concurrent reads (UI via main connection) and writes (downloads via
this separate connection), eliminating app-level mutex contention that
caused progressive UI lag during bulk downloads.

Init after library.init_at() in both activate_session and
activate_offline_session. Teardown before main offline_cache teardown.
2026-02-17 11:02:02 -06:00
vicrodh 644571f82a perf: add batch offline cache command to replace sequential IPC loops
Add v2_cache_tracks_batch_for_offline command that inserts all tracks
in a single SQLite transaction and spawns download tasks in one IPC
call. Extract spawn_track_cache_download helper shared by both single
and batch commands.

Replace sequential for-of loops with batch calls in PlaylistDetailView
and +page.svelte (downloadAlbumById, handleDownloadAlbum,
handleReDownloadAlbum, reDownloadAlbumById). Single-track handlers
remain unchanged.

Reduces 75 IPC round-trips to 1 for bulk downloads.
2026-02-17 10:59:02 -06:00
vicrodh 343bfff357 perf: add 200ms time throttle to download progress events
Add a minimum 200ms interval between progress emissions per track,
on top of the existing 2% change filter. Always emits at 100%.
Limits events to max 5/sec/track, reducing IPC pressure during
concurrent downloads.
2026-02-17 10:55:09 -06:00
vicrodh 086f7f62e4 perf: rAF debounce for offline cache listener notifications
Coalesce all offline cache state notifications within a single
animation frame (~16ms) into one notification cycle. This caps
UI re-renders from hundreds/sec down to max 60/sec during bulk
downloads, preventing progressive UI lag from event storms.
2026-02-17 10:54:10 -06:00
vicrodh bc8300ea62 fix: add WAL mode to api_cache and favorites_preferences SQLite connections
These two databases were missing PRAGMA journal_mode=WAL and
PRAGMA synchronous=NORMAL, which could cause UI lag from lock
contention during concurrent reads/writes.
2026-02-17 10:22:33 -06:00
vicrodh cfd033e2bd fix(artist): lower jump-nav z-index from 40000 to 50 2026-02-17 09:55:49 -06:00
vicrodh 4c765617d5 fix(immersive): increase gap between reactive artwork and track info 2026-02-17 09:52:19 -06:00
vicrodh 86e3424c79 fix(immersive): track info inline with player, artwork right of text
Shrink player bar min-width 700→670px. Move track info block to
bottom: 24px (same level as player). Album art now sits to the right
of the text block (title/album/artist/badge). The info block is part
of the panel so it stays visible when player controls auto-hide.
2026-02-17 09:36:48 -06:00
vicrodh 39b2ccaa8b fix(immersive): 4-row track info + album art thumbnail on all viz panels
All 4 canvas panels (Oscilloscope, Energy, Pulse, X/Y) now share:
- Bottom-left: 72px album art thumbnail with rounded corners
- Bottom-right: 4 rows (title, album, artist, compact badge), right-aligned,
  max-width 400px for longer text
- Energy: removed 85% height constraint, rings use full canvas
2026-02-17 09:23:17 -06:00
vicrodh 4f7bc88155 fix(immersive): oscilloscope track info as 4 separate rows with wider max-width 2026-02-17 09:17:19 -06:00
vicrodh be9166d6d2 refactor(immersive): visualizer dropdown, compact track info, aggressive reactivity
Convert 6 visualizer tabs into a single dropdown menu in the header.
Remove album art and full quality badge from Oscilloscope, Energy,
Transient Pulse, and Lissajous panels. Replace with bottom-right
compact track info (title, artist/album, text-only quality badge).
Dramatically increase AlbumReactive sensitivity for heavy music
(faster attack/decay, 3x scale/glow multipliers).
2026-02-17 08:46:48 -06:00
vicrodh d4bc1fe677 fix(immersive): improve visualizer panels per feedback
Energy Bands + Oscilloscope:
- Constrain drawing area to 85% of screen height, vertically centered

Oscilloscope:
- Change from bottom-left info to centered artwork layout (like Bars)

Transient Pulse:
- Lower backend threshold 0.15 -> 0.04, cooldown 6 -> 3 frames
- Use raw (un-smoothed) bass-weighted RMS for sharper detection
- Add frontend-side supplementary beat detection from energy data

Album Reactive:
- Fix glow layer centering (was anchored to top-left, now inset: 0)
- Double scale effect (0.04 -> 0.08) and glow spread (40 -> 80)
- Fast attack / medium decay smoothing for visible reactivity
2026-02-17 08:22:56 -06:00
vicrodh 6c4eaef9a5 feat(immersive): add 4 new visualizer tabs
Backend:
- Emit viz:energy with 5-band RMS (sub-bass, bass, mids, presence, air)
- Emit viz:transient with attack detection (threshold + cooldown)

Frontend panels:
- EnergyBandsPanel: concentric glowing rings around centered artwork
- LissajousPanel: stereo X/Y phase plot with trail (watermark layout)
- TransientPulsePanel: expanding rings from center on beat detection
- AlbumReactivePanel: album art with breathing scale/glow from energy

All panels extract colors from album art, throttle at 30fps, and follow
the existing visualizer lifecycle (enable/disable backend on mount).

Focus tabs now: Coverflow, Static, Bars, Scope, Energy, X/Y, Pulse,
Reactive, Lyrics, Queue (keys 1-0).
2026-02-17 07:53:49 -06:00
vicrodh 5c11469c87 feat(immersive): add stereo oscilloscope visualizer tab
New OscilloscopePanel renders dual L/R waveforms from viz:waveform
event data. ALBUM_SECONDARY layout with small artwork bottom-left.
Colors extracted from album art with green tint (L) and blue tint (R).
Registered as focus tab with AudioWaveform icon and keyboard shortcut 4.
Renumbered focus tab shortcuts (1-6) to match new tab order.
2026-02-17 03:42:09 -06:00
vicrodh 3b94acd95e feat(visualizer): emit stereo waveform data for oscilloscope
Add viz:waveform event emission alongside existing viz:data FFT output.
De-interleaves L/R channels from the raw sample buffer and downsamples
to 256 points per channel (512 floats = 2048 bytes). Pre-allocates the
waveform buffer outside the hot loop to avoid per-frame allocations.
2026-02-17 03:40:13 -06:00
vicrodh 06d0a9e471 fix(wizard): use pipewire stream.rules instead of pulse.rules for per-app config
The wizard step 6 was writing per-app bit-perfect rules to
pipewire-pulse.conf.d/pulse.rules, but QBZ uses pipewire-alsa (via
rodio/cpal), so those rules were never applied.

Changed to pipewire.conf.d/stream.rules which applies to ALL PipeWire
clients regardless of API (ALSA, PulseAudio, JACK). Also updated the
step indicator from "Pulse" to "Apps" in all 4 locale files.

Fixes #53 (wizard bug)
2026-02-17 02:42:17 -06:00
vicrodh 4ff8f65de0 fix(ui): correct Go button contrast in LinkResolverModal
Use --accent-primary instead of nonexistent --accent variable,
and #fff for button text to ensure visibility on all themes.
2026-02-17 02:15:29 -06:00
vicrodh 2ff17faaee fix(album): load album credits modal via v2_get_album
cx
2026-02-17 02:14:15 -06:00
vicrodh d2c9d88e4a feat(ui): add qobuzapp handler toggle in settings
Integrations section now shows a toggle to register/deregister QBZ as
the default handler for qobuzapp:// links. Checks current status on
mount, calls v2_register/v2_deregister commands on toggle.
2026-02-17 00:31:03 -06:00
vicrodh 107c222c7e feat(ui): add Ctrl+L keybinding for link resolver
New ui.openLink action in keybindingsStore (Ctrl+L default).
Registered in +page.svelte to open the link resolver modal.
2026-02-17 00:29:42 -06:00
vicrodh 55c5ea4013 feat(ui): wire link resolver into main page
Import LinkResolverModal, add handleResolvedLink() that dispatches to
handleAlbumClick/handleArtistClick/selectPlaylist. Listen for
link:resolved event from OS scheme handler. Render modal in template.
2026-02-17 00:29:15 -06:00
vicrodh 448c658996 feat(ui): add LinkResolverModal component
Svelte 5 modal with input field for pasting Qobuz URLs. Calls
v2_resolve_qobuz_link and forwards the resolved link to the parent.
Enter key submits, error displayed inline.
2026-02-17 00:27:51 -06:00
vicrodh 590b652649 feat(i18n): add link resolver translation keys
Added to all 4 locales (en, es, de, fr):
- settings.integrations.qobuzLinkHandler* keys for settings toggle
- linkResolver.* keys for the modal (title, placeholder, go, resolving, invalidLink)
2026-02-17 00:27:24 -06:00
vicrodh f583092a76 chore(packaging): add qobuzapp scheme to desktop files
All 6 .desktop files now declare x-scheme-handler/qobuzapp in their
MimeType line, enabling OS-level link capture for qobuzapp:// URLs.
2026-02-17 00:25:09 -06:00
vicrodh d286aec9ef feat(core): forward scheme links from single-instance and launch args
Single-instance plugin now inspects args for qobuzapp:// or
play.qobuz.com URLs and emits link:resolved event. Launch args
are also checked on first startup with a 1.5s delay for frontend
readiness.
2026-02-17 00:24:49 -06:00
vicrodh 261d420540 feat(v2): add qobuzapp handler registration commands
v2_check_qobuzapp_handler, v2_register_qobuzapp_handler,
v2_deregister_qobuzapp_handler — use xdg-mime for scheme handler
registration and mimeapps.list editing for deregistration.
2026-02-17 00:24:02 -06:00
vicrodh 9006e64fa2 feat(v2): add v2_resolve_qobuz_link command
Thin Tauri command that calls qbz_qobuz::resolve_link(). Pure parsing,
no State params, no auth required. Registered in invoke_handler.
2026-02-17 00:23:16 -06:00
vicrodh 985f634817 feat(qobuz): add link resolver module with tests
Pure-Rust URL parser for qobuzapp:// and https://play.qobuz.com/ links.
Resolves to typed ResolvedLink enum (OpenAlbum, OpenTrack, OpenArtist,
OpenPlaylist). 24 unit tests covering happy paths and edge cases.
2026-02-17 00:22:26 -06:00
vicrodh 36a708d501 feat(ui): add artwork column in playlist tracks
cx
2026-02-16 23:02:45 -06:00
vicrodh 0c66a14249 fix(player): stabilize seek interaction and remove misleading secondary bar refs #75
cx
2026-02-16 22:48:39 -06:00
vicrodh 39bbbdc230 fix(playback): reduce mpris desync and stale playback event lag refs #85
cx
2026-02-16 21:36:07 -06:00
vicrodh 3ea67f0cdc fix(ui): keep sidebar menus above playlist overlays refs #78
cx
2026-02-16 21:28:47 -06:00
vicrodh 243c212c62 chore(playback): validate long-track auto-advance fix refs #80
cx
2026-02-16 20:52:43 -06:00
vicrodh c3696f02d4 fix(playback): harden auto-advance for long-track edge cases
cx
2026-02-16 20:08:34 -06:00