Commit Graph
100 Commits
Author SHA1 Message Date
vicrodh 154b39b6a8 refactor(ui): compact filter and sort buttons, two-column filter panel in LocalLibrary 2026-01-29 21:30:06 -06:00
vicrodh 16adbd4682 refactor(ui): move alpha-index inline in LocalLibrary albums and tracks tabs 2026-01-29 21:22:52 -06:00
vicrodh fcde0a90b3 refactor(ui): redesign Favorites header layout with inline alpha-index 2026-01-29 21:14:36 -06:00
vicrodh 0ca6d923a2 fix(ui): compact Favorites header, move alpha-index to horizontal position 2026-01-29 20:30:04 -06:00
vicrodh 6935aeb552 fix(ui): vertically center action buttons in Favorites 2026-01-29 20:18:07 -06:00
vicrodh c0fdfbc6a6 fix(ui): fix double scrollbar in Favorites tracks tab, replace Play All with circle buttons 2026-01-29 20:15:51 -06:00
vicrodh a401327ab3 fix(ui): remove unwanted fixed track-list-header from FavoritesView 2026-01-29 20:10:10 -06:00
vicrodh fae962d59b feat(ui): add ViewTransition to LocalLibraryView and all tabs
- Outer view slides down on initial mount (200ms, 12px)
- Each tab content (albums, artists, tracks) slides up on tab change
- Uses {#key activeTab} to re-trigger transition on tab switch
- Simple transition without spinner fadeout logic
2026-01-29 20:07:39 -06:00
vicrodh f910b222d3 fix(ui): add slide-down transition to spinner on tab change in FavoritesView
When switching tabs, the loading spinner now animates with slide-down
transition (200ms, 12px) using {#key activeTab} to re-trigger on tab change.
This completes the animation flow: spinner slides down -> fadeout -> content slides up
2026-01-29 20:02:08 -06:00
vicrodh df17f859e0 feat(ui): add ViewTransition to PlaylistDetail and PlaylistManager views
- PlaylistDetailView: outer slide-down (200ms), spinner fadeout, content slide-up
- PlaylistManagerView: outer slide-down (200ms), spinner fadeout, content slide-up
- Matches the FavoritesView transition pattern
2026-01-29 19:58:06 -06:00
vicrodh 4ce7694290 fix(ui): add initial slide-down transition to FavoritesView
Wrap entire FavoritesView in ViewTransition with direction="down" so the
initial view (header + spinner) slides down on first load.

Complete flow:
0. Initial view appears with slide-down transition (200ms, 12px)
1. Loading spinner shows while syncing
2. When sync completes, spinner fades out (200ms)
3. Content appears with slide-up transition (200ms, 12px)
2026-01-29 19:54:39 -06:00
vicrodh b5a437d0d0 feat(ui): add ViewTransition to Album and Favorites views
- Add ViewTransition wrapper to AlbumDetailView (200ms, 12px slide up)
- Add ViewTransition to FavoritesView content sections (tracks, albums, artists, playlists)
- Add spinner fadeout animation (200ms) before content transition in FavoritesView
- Both loading spinner and playlists loading spinner now fade out smoothly
2026-01-29 19:50:46 -06:00
vicrodh 4c606e029e feat(favorites): implement local SQLite persistence for favorites
This ensures favorites sync properly across all views (album detail,
continue listening, etc.) by using local persistence as the source
of truth for UI, with API calls for actual operations.

Backend (Rust):
- Add favorites_cache.rs module with SQLite tables:
  - favorite_tracks (track_id INTEGER PRIMARY KEY)
  - favorite_albums (album_id TEXT PRIMARY KEY)
  - favorite_artists (artist_id INTEGER PRIMARY KEY)
- Add Tauri commands for cache operations:
  - get_cached_favorite_* - read from local cache
  - cache_favorite_* / uncache_favorite_* - add/remove single items
  - sync_cached_favorite_* - bulk sync from API data
  - clear_favorites_cache - for logout

Frontend:
- Rewrite favoritesStore.ts to use persistence:
  - loadFavorites(): Load from cache first, then sync from API
  - toggleFavorite(): API call first → update cache on success
  - No optimistic updates - UI shows loading state until confirmed
- Rewrite albumFavoritesStore.ts with same pattern
- Create artistFavoritesStore.ts for artist favorites
- Update +page.svelte to load all favorites on login
- Update FavoritesView to sync cache when loading from API

Sync strategy:
- On login: Fetch from Qobuz API → sync to local cache
- On toggle: API call → on success → update local cache → notify UI
- FavoritesView reads from API and syncs local cache
- All other views read from local cache (instant UI)
2026-01-29 19:42:04 -06:00
vicrodh defd2f0fe1 fix(favorites): ensure favorites sync with Qobuz API and show loading state
Issues fixed:
- playbackService was bypassing the favorites store, causing UI desync
- Album favorites weren't loaded on login (only track favorites were)
- No visual feedback while favorite API call was in progress

Changes:
- Add toggling state tracking to favoritesStore and albumFavoritesStore
- Add isTrackToggling() and isAlbumToggling() exports
- Prevent double-toggle while API call is in progress
- Update TrackRow and AlbumCard to show pulse animation while toggling
- Update playbackService to use store's toggle (centralized API calls)
- Load both track and album favorites on login
2026-01-29 19:24:13 -06:00
vicrodh 4858faa696 fix(ui): adjust UserCard icon sizes
- Increase settings gear icon from 14px to 18px
- Increase QBZ logo from 28px to 30px
- Remove border-radius from logo (was clipping the icon)
2026-01-29 19:12:19 -06:00
vicrodh 8db47aaee0 fix(ui): remove flicker-causing effect and add view transition to Settings
- Remove problematic $effect that ran loadPlaybackPreferences() on every
  render, causing a state update loop and visual flicker
- The function is already called in onMount, so the duplicate was redundant
- Add ViewTransition wrapper for consistent subtle animation (200ms fade+slide)
2026-01-29 19:09:01 -06:00
vicrodh 65ffabbf1d feat(ui): navigate to search on 3rd char + add subtle view transition
- Only navigate to search page after 3 characters typed
- Sync still happens immediately from 1st character
- Remove auto-navigate on focus (let user type first)
- Add ViewTransition component for reusable subtle animations
- Apply 200ms fade+slide transition to SearchView

cc
2026-01-29 19:04:29 -06:00
vicrodh a13f153a63 feat(ui): convert sidebar search button to synced input field
- Replace search button with actual text input in sidebar
- Add X button to clear search when text is present
- Sync sidebar input 1:1 with SearchView input (bidirectional)
- Typing in sidebar navigates to search page and triggers search
- Clearing sidebar input resets search page to standby state
- Add subscribeSearchQuery and setSearchQuery to searchState store

cc
2026-01-29 18:52:06 -06:00
vicrodh 6a756a7aeb fix(ui): use fixed positioning to eliminate scroll flash
Redesigned dropdown architecture:
- Menu uses position:fixed instead of absolute
- Menu rendered outside dropdown container (sibling, not child)
- Position calculated in pixels before menu opens
- Completely removes menu from document flow

This eliminates the momentary scroll flash that occurred when
dropdowns opened and temporarily expanded the page.

cc
2026-01-29 17:34:47 -06:00
vicrodh 669e9dbf4a fix(ui): use dynamic item height for compact mode dropdowns
Account for 36px items in compact mode vs 40px in normal mode when
calculating menu max-height and options container height.

cc
2026-01-29 17:03:25 -06:00
vicrodh 5421bb9eb1 fix(ui): rewrite Dropdown with smart positioning and search
- Add search input when options > 5
- Implement smart positioning to dodge viewport edges
- Fixed height showing 4 items when searchable
- Add scroll snap for clean item display
- Recalculate position on scroll/resize

cc
2026-01-29 16:57:04 -06:00
vicrodh fb0ab88b51 fix: refresh theme palettes and names
cx
2026-01-29 16:33:45 -06:00
vicrodh 21b1950857 feat: add Mira theme and reorder list
cx
2026-01-29 13:57:23 -06:00
vicrodh 0056d74824 chore: update theme slugs
cx
2026-01-29 13:54:10 -06:00
vicrodh 7f9a580a8c feat: rename new theme labels
cx
2026-01-29 13:30:32 -06:00
vicrodh 56c61499d9 fix: move track header outside virtualized container
- Header now outside .track-sections.virtualized (like LocalLibraryView)
- Use calc() height for virtualized section to give explicit dimensions
- Removes complex flex/absolute positioning that was breaking layout
2026-01-29 12:05:46 -06:00
vicrodh c1e6bd1a92 fix: virtualized track list height using absolute positioning 2026-01-29 12:03:21 -06:00
vicrodh 3163a893c6 fix: track list layout in Favorites Tracks view
- Fix virtualized container not showing tracks
- Remove conflicting height: 100% properties
- Add overflow: hidden to prevent extra scrollbar
- Add flex-shrink: 0 to header to prevent compression
2026-01-29 11:58:47 -06:00
vicrodh cd84f15ee2 feat: add Album column and header to Favorites Tracks view
- Add track list header with columns: #, Title, Album, Duration,
  Quality, Favorite icon, Download icon
- Album column is hidden when grouping by album (redundant)
- Add getTrackAlbum and showAlbum props to VirtualizedTrackList
- Style matches PlaylistDetailView for consistency
2026-01-29 11:51:53 -06:00
vicrodh 19d84326b8 fix: enable resume for streaming tracks
Previously, streaming tracks could not be resumed after pause timeout
because current_audio_data was never set for streaming playback.

Changes:
- Store BufferedMediaSource in current_streaming_source for streaming tracks
- On resume, check if streaming source has complete data and use it
- Clear streaming source on Stop and when switching to non-streaming play
- Log buffered bytes when streaming not complete yet

This allows users to pause streaming tracks and resume them after the
download completes, instead of getting "no audio data available" error.
2026-01-29 11:23:58 -06:00
vicrodh 873895709a fix: dropdown positioning in Favorites view
- Add z-index: 1000 to dropdown-container to appear above sidebar
- Change dropdown alignment from right: 0 to left: 0 for natural
  left-to-right opening
- Affects all tabs: Albums, Tracks, Artists
2026-01-29 10:21:56 -06:00
vicrodh 7269642464 fix: dropdown z-index and volume persistence
- Fix Favorites Albums group dropdown appearing behind sidebar
  (z-index 10 -> 100)
- Persist volume level to localStorage between sessions
- Allow changing volume when nothing is playing (volume
  applies when playback starts)
2026-01-29 10:12:34 -06:00
vicrodh af55c9a0fa chore: update android icons in static folder (UserCard, AboutModal) 2026-01-29 08:57:03 -06:00
vicrodh 56faddf2dc chore: update app logo to v3
New logo design with vinyl/gear motif, replacing old GPT-generated logo.
Updated all icon sizes for Tauri, Windows Store, favicon, and static assets.
2026-01-29 01:22:05 -06:00
vicrodh e570caa115 fix(playlist): increase sort dropdown min-width to 200px 2026-01-28 23:02:16 -06:00
vicrodh a75addbb42 fix(playlist): increase sort dropdown min-width to 180px 2026-01-28 23:01:21 -06:00
vicrodh 84f8b5f8c9 fix(playlist): align sort dropdown caret to right edge 2026-01-28 23:00:35 -06:00
vicrodh 9e44dad677 fix(playlist): prevent text wrapping in sort dropdown 2026-01-28 22:59:44 -06:00
vicrodh f0fa6a1e26 fix(suggestions): prevent layout jump during animations with fixed height 2026-01-28 22:56:30 -06:00
vicrodh 48cdb2750f chore(suggestions): remove debug artist count text 2026-01-28 21:36:13 -06:00
vicrodh f1b0b85119 feat(suggestions): smooth animations for add/dismiss tracks
- Add fade/slide transitions when tracks are added or dismissed
- Show success state (checkmark + green highlight) before fade out
- Add track to local state without page reload
- Update sidebar counts via callbacks
- Disable buttons during adding animation
2026-01-28 21:28:26 -06:00
vicrodh 95fcb4ed4e feat(suggestions): adaptive artist selection and duplicate filtering
- Add extractAdaptiveArtists() for dynamic seed artist count based on playlist size
- Mix 60% top artists (coherence) + 40% random (discovery) for variety
- Filter duplicates by title+artist, not just track ID
- Catches same song from compilations, live albums, remasters, etc.
- Deduplicate within suggestion pool itself
2026-01-28 21:14:32 -06:00
vicrodh 591b194b25 Fix quality badges to match TrackRow simple text style
- Fix qobuzAdapters to use formatQuality for track quality (was showing Hi-Res)
- Update QualityBadge compact mode to simple text style:
  - font-size: 12px
  - color: #666666 (uniform gray)
  - width: 80px (fixed)
  - No background, border, or special hires styling
2026-01-28 19:42:53 -06:00
vicrodh c0e9a94f98 Refactor quality badges to use QualityBadge component with compact mode
- Add compact prop to QualityBadge for inline usage in track lists
- Compact mode shows simple text (24bit/96kHz or CD Quality)
- Use golden gradient for hires badges in compact mode
- Update ArtistDetailView to use QualityBadge compact
- Update FavoritesView to use QualityBadge compact
- Update SearchView to use QualityBadge compact
- Remove duplicate CSS and getQualityLabel functions
- LocalLibrary views keep custom format showing codec (FLAC 24/96)
2026-01-28 19:28:43 -06:00
vicrodh af74ee8cb8 Fix SearchView track-quality badge styling to match other components 2026-01-28 19:16:49 -06:00
vicrodh aa224d7167 Standardize quality badges and fix header favorite button
- Use golden gradient (#fbbf24 to #b8860b) with dark text for hires badges
- Increase min-width to 90px for consistent sizing across all badges
- Rename track-row favorite button to avoid CSS conflict with header button
- Header favorite button now properly circular like radio and network buttons
2026-01-28 19:14:52 -06:00
vicrodh eef89f904c Fix quality badge and favorite button styling in ArtistDetailView
- Use correct quality badge colors (alpha variables, orange gradient for hires)
- Fix favorite button to match TrackRow component styling (opacity-based)
2026-01-28 19:04:14 -06:00
vicrodh 0354917221 Add search re-focus, quality badges in artist view, fix favorites quality label
1. Search: Re-clicking Search button in sidebar scrolls to top and focuses input
   - Added triggerSearchFocus mechanism in searchState store
   - SearchView subscribes to focus trigger for scroll + focus

2. ArtistDetailView: Added quality badge and favorite button to Popular Tracks
   - Added getQualityLabel function with bit depth/sample rate
   - Added quality-badge element with hires styling
   - Added favorite button in track actions

3. FavoritesView: Fixed getAlbumQualityLabel to show detailed format
   - Now shows "24bit/96kHz" instead of generic "Hi-Res"
2026-01-28 18:45:21 -06:00
vicrodh 5b380ba7da Fix sticky header gap and scrollbar layout shift
- Change overflow-y to scroll to always reserve scrollbar space
- Fix sticky header top position to -24px to eliminate gap with window edge
- Add proper padding-top compensation when scrolled
2026-01-28 18:31:04 -06:00
vicrodh fe2bc4b726 Add sticky header and scrollbar-gutter to SearchView
- Add scrollbar-gutter: stable to prevent layout shift when content scrolls
- Create sticky header that activates on scroll with:
  - Compact search input (bottom border only, muted accent, smaller height)
  - Tabs and filters remain visible
  - Title hidden when scrolled to save space
  - Box-shadow for visual separation
2026-01-28 18:19:14 -06:00
vicrodh b21979180e style(dropdown): set fixed width 170px for trigger and menu
- Trigger width: fixed 170px (was min-width: 160px, width: 100%)
- Menu min-width: 170px (matches trigger)
- Wide variant: 280px fixed width
2026-01-28 17:22:46 -06:00
vicrodh a2dc496cc1 style(dropdown): improve dropdown menu styling for consistency
- Increased menu min-width to 200px with width: max-content
  to prevent word wrap on options
- Added padding: 4px 0 to menu (matches context menus)
- Changed box-shadow to match context menu (0 8px 24px)
- Reduced option padding to 10px 16px (was 12px 16px)
- Changed font-size to 13px (was 14px) to match context menus
- Added color transition on hover to match context menus
- Removed overflow/text-overflow from options (no wrap needed)
2026-01-28 17:16:31 -06:00
vicrodh d68799da25 perf(library): optimize artist list and albums grid scrolling
- Added smooth scroll CSS optimizations to artist list:
  - webkit-overflow-scrolling: touch
  - scroll-behavior: smooth
  - overscroll-behavior: contain
  - will-change: scroll-position
  - contain: strict
- Added contain: layout style to artist cards for better rendering
- Added same optimizations to albums grid
- Memory: selectedArtistAlbums is a derived value that auto-updates
  when switching artists, old arrays are garbage collected
- Note: VirtualizedArtistList exists for future use with large libraries
2026-01-28 13:19:03 -06:00
vicrodh 5944099943 fix(library): allow clicking Various Artists card in artist list
- Removed early return that blocked Various Artists clicks
  (album header already protected via HTML condition)
- Added special case in selectedArtistAlbums: when user selects
  "Various Artists", show all albums with that artist name
2026-01-28 13:13:45 -06:00
vicrodh e97a2ed86f fix(library): load artists before navigating from album view
When clicking artist link from album view, ensure artists are loaded
before switching to artists tab. This fixes empty page on first visit.
2026-01-28 13:10:11 -06:00
vicrodh 2ad92a5854 fix(library): improve artists view layout to fill available space
- Remove background from artist column, integrate with main background
- Add vertical border line separating artist list from albums view
- Wrap artists tab content in flex container for proper height
- Artist list now fills full available height (no gaps at top/bottom)
- Adjusted padding and margins for better visual integration
2026-01-28 13:05:23 -06:00
vicrodh 28ab39a905 fix(library): fix artist view height and scroll timing
- Adjusted artist two-column layout height to account for NowPlayingBar
  (was calc(100vh - 320px), now calc(100vh - 424px))
- Added 100ms delay before scrolling to artist card to ensure content
  is fully rendered after tab switch
2026-01-28 12:59:27 -06:00
vicrodh 72c42c289a feat(library): make artist links navigable in local library album view
- Artist name in album header now clickable (except for Various Artists)
- Clicking artist navigates to Artists tab, scrolls to artist card,
  and shows their albums
- Track artist links (when different from album artist) work the same
- Added IDs to artist cards for scroll targeting
- Navigation history updated so back button returns to album view
2026-01-28 12:52:12 -06:00
vicrodh b1bc4091e0 fix(settings): improve artwork cache display and button style
- Handle undefined/null values in cache stats with nullish coalescing
- Show "No cached artwork" when both counts are 0
- Use outlined style for Clear All button (consistent with others)
- Simplified description text
2026-01-28 12:12:59 -06:00
vicrodh 685efcfd76 fix(cast): update play button status and add disconnect handoff
1. Play button fix: After resuming on cast device, update playerStore.isPlaying
   so the UI shows the correct playing state immediately.

2. Disconnect handoff: When disconnecting from Chromecast/DLNA while playing:
   - Captures current track and position from cast state
   - Shows confirm dialog asking if user wants to continue locally
   - If yes, starts local playback and seeks to saved position
   - If no, just resets player state

This provides seamless transitions in both directions:
- Local → Cast: auto-resumes with position
- Cast → Local: asks user, then resumes with position
2026-01-28 12:09:38 -06:00
vicrodh d52ebeac20 fix(cast): stop local playback before establishing cast connection
When user connects to a Chromecast/DLNA device while local playback is
active, the local stream was conflicting with the cast stream.

Now connectToDevice():
1. Captures current track info and position
2. Stops local playback completely
3. Establishes the cast connection
4. Automatically resumes the track on the cast device
5. Seeks to the saved position (if > 5 seconds)

This provides seamless handoff from local to cast playback.
2026-01-28 11:41:37 -06:00
vicrodh 03eae06cd3 feat(settings): add artwork cache clear and clear all caches buttons
- Added artwork thumbnails cache stats and clear button
- Shows legacy artwork files count if old cache exists
- Added "Clear All Caches" button that clears all cached data at once
- Danger button styling for destructive action
2026-01-28 11:28:42 -06:00
vicrodh 7ed3dac7f5 fix(library): reduce artwork cache bloat with thumbnails
- metadata.rs now creates 500px thumbnails instead of copying full images
- Added cache management commands: library_get_cache_stats,
  library_clear_artwork_cache, library_clear_thumbnails_cache
- Thumbnails stored in ~/.local/share/qbz/thumbnails/ (was ~/.cache/qbz/artwork)
- Reduces cache size from GB to MB for large libraries
2026-01-28 11:24:19 -06:00
vicrodh a6fc264903 fix(playback): persist streaming quality setting
Quality was hardcoded to UltraHiRes in backend. Now:
- Frontend passes quality from localStorage to play_track command
- Backend parses quality string to Quality enum
- All prefetch and stream URL calls use the user's preferred quality
2026-01-28 11:24:11 -06:00
vicrodh 700dc07014 fix(library): improve artist consolidation and album matching
- Add all_artists field to LocalAlbum for accurate artist matching
- Consolidate duplicate artists with case differences (e.g., "Alice in Chains" / "Alice In Chains")
- Fix album count calculation to avoid double-counting
- Show Various Artists albums under contributing artists
- Handle multi-artist names (e.g., "A, B, C") with union matching
- Add cleanup missing files feature in settings maintenance section
- Improve settings UI with side-by-side Maintenance/Danger Zone layout
- Add status indicator during cleanup operations
2026-01-28 08:13:07 -06:00
vicrodh 8bf85a1c8a debug(library): add more logging to find similar artist albums 2026-01-28 03:04:12 -06:00
vicrodh 7327a3d060 fix(library): improve Qobuz badge display and add artist debug logging
- Remove background/border from Qobuz badge, show icon at full 24px
- Keep background only for local badge (HardDrive icon)
- Add console logging when selecting artist to debug mismatch:
  - Shows selected artist name (original and normalized)
  - Shows which albums match
  - Shows artist data from the artists array
2026-01-28 02:59:26 -06:00
vicrodh d559832ffe feat(library): add source filters and fix Qobuz badge icon
- Add Local and Offline cache filters to the filter panel
- Icons: HardDrive for local, Qobuz logo for offline cache
- Remove CSS filter from Qobuz badge icon (display as-is with proper size)
2026-01-28 02:54:05 -06:00
vicrodh 685606be5d fix(library): fix artist view alpha index scroll and multi-artist albums
- Fix alphabetical index scroll to work within the artist list container
- Add scroll reference binding to artist-list-scroll
- Fix group header ID (was duplicating prefix)
- Include multi-artist albums when selecting an artist:
  - Exact match on album artist
  - Partial match (artist name appears in album artist string)
  - Split by common separators (,&feat.ft.featuring, etc.)
2026-01-28 02:49:26 -06:00
vicrodh bd47c175ea feat(library): redesign artist view with two-column layout
- Move alphabetical index from vertical (right) to horizontal (top)
- Replace full-width grid with two-column layout:
  - Left: Single-column artist list with compact cards and scroll
  - Right: Selected artist's albums in a grid
- Hide group dropdown and view mode toggle (kept in code for future use)
- Click artist to select and show their albums (instead of navigating to Qobuz)
- Defaults to alphabetical grouping and grid view
2026-01-28 02:43:23 -06:00
vicrodh e8f0c96ccc feat(library): add source badge to album cards in Local Library
Albums now show a small badge indicating their source:
- HardDrive icon for local files (source='user')
- Qobuz logo for offline cached content (source='qobuz_download')

Badge appears in bottom-right corner of album artwork.
2026-01-28 02:40:00 -06:00
vicrodh e025882a9f fix(favorites): add type=button to favorite toggle and remove debug logs 2026-01-28 01:56:23 -06:00
vicrodh c87788f0f8 fix(flatpak): add version to metainfo.xml
Flatpak uses the <releases> section in metainfo.xml to display the
application version. Added a placeholder release entry and updated
the workflow to inject the actual version and date during build.
2026-01-27 20:54:45 -06:00
vicrodh efb305fe09 debug(favorites): add logging to track favorite toggle issue
Also adds type="button" to favorite button for consistency with other buttons.
2026-01-27 19:44:59 -06:00
vicrodh a483c766ab fix(offline): clean up empty folders when removing cached tracks
When deleting a cached track (individually, via clear all, or via LRU
eviction), the audio file was deleted but cover.jpg remained orphaned.

Now the system removes the entire album folder if no audio files remain,
and recursively removes the artist folder if it also becomes empty.
2026-01-27 19:36:15 -06:00
vicrodh 655aaf4c88 fix(home): properly show offline cache status in Continue Listening
- Add getTrackOfflineCacheStatus prop to HomeView
- Pass downloadStatus and downloadProgress to TrackRow
- Use reactive cache status function that depends on downloadStateVersion

Tracks in Continue Listening now correctly show their cached state.
2026-01-27 19:24:23 -06:00
vicrodh 79a667fb50 fix(home): reactively update offline cache state in Continue Listening
Include downloadStateVersion in the each loop key to force re-render
when offline cache state changes, fixing tracks showing gray icons
even when cached.
2026-01-27 19:15:57 -06:00
vicrodh 4b975869df fix(offline): correct event names for cache completion
Frontend was listening for wrong event names:
- offline:cached → offline:caching_completed
- offline:cache_failed → offline:caching_failed

Also added "Open cache folder" button to Settings.
2026-01-27 19:01:08 -06:00
vicrodh 900df9307a refactor(suggestions): move preview to album art overlay
Move play button from action buttons to album art hover overlay,
matching the pattern used in ArtistDetailView popular tracks.
2026-01-27 17:56:31 -06:00
vicrodh 79e37cbf7a fix(suggestions): only show for owned playlists
Suggestions are for curating your own playlists, not for
playlists you're just browsing from other users.
2026-01-27 17:53:56 -06:00
vicrodh b4fe6c87b5 feat(suggestions): add track preview and clean up UI
- Add preview (play) button to suggested tracks
- Remove pagination info for cleaner UX ("Showing X of Y")
- Remove "Load more" links (auto-loads when cycling)
- Add onPreviewTrack callback to play suggested tracks
- Convert SuggestedTrack to DisplayTrack for playback
2026-01-27 17:47:04 -06:00
vicrodh fab1ff3003 fix(suggestions): wrap artist_id in Some for Option type 2026-01-27 17:13:03 -06:00
vicrodh 79c68d292e feat(suggestions): improve vector store and add cache management
- Add get_all_related_artists for direct relationship lookup
- Add get_related_artists helper method
- Add clear_all method to vector store for cache management
- Add clear_vector_store Tauri command
- Add Artist Vectors cache section to Settings view
- Use artist_info tuples (mbid, name) for better track searching
2026-01-27 16:54:11 -06:00
vicrodh 9a89074b5f feat(suggestions): add interactive navigation and track info modal
- Add artist_id field to SuggestedTrack for navigation
- Make artist names clickable to navigate to artist view
- Make album names clickable to navigate to album view
- Add TrackInfo button (info icon) to view track credits
- Integrate TrackInfoModal component with suggestions
- Update PlaylistDetailView to pass navigation callbacks
2026-01-27 16:53:56 -06:00
vicrodh 54315c2e4e fix(suggestions): fix deadlock in build_vector
The build_vector function was calling build_from_musicbrainz and
build_from_qobuz while holding the store lock. These functions also
try to acquire the store lock, causing a deadlock.

Fixed by saving the vectors from the first call and reusing them
for storage, instead of calling the functions again.
2026-01-27 14:42:10 -06:00
vicrodh 7e76fd6925 debug: add info-level logging to build_from_musicbrainz 2026-01-27 14:22:40 -06:00
vicrodh d90edc4feb debug(suggestions): add more logging to find deadlock 2026-01-27 13:40:17 -06:00
vicrodh 5f13617ae7 debug(suggestions): add logging to vector building
Added info-level logs to track:
- ensure_vector start/success/failure
- build_from_musicbrainz cache hit/API fetch
2026-01-27 13:35:18 -06:00
vicrodh 12d3c6b654 style: remove emojis from log messages 2026-01-27 13:26:57 -06:00
vicrodh b551df71c0 perf(suggestions): limit to top 5 artists and reduce rate limiting
Major optimizations:
- Extract only top 5 artists by track frequency instead of all artists
- Use faster rate limiter (200ms) when using MusicBrainz proxy
- Remove skip_vector_build since we now have manageable artist count

Expected load time: ~5-8 seconds for first load with 5 artists
vs previous: 50+ seconds with 50 artists
2026-01-27 13:20:16 -06:00
vicrodh 7506d69e53 fix(suggestions): hide section entirely when no suggestions available
Instead of showing 'No suggestions available' message, the entire
suggestions section is now hidden when there are no results.
Better UX - less frustrating for users.
2026-01-27 12:47:36 -06:00
vicrodh a49cdf483a perf(suggestions): skip MusicBrainz API calls when skip_vector_build=true
When skip_vector_build is enabled, also skip network calls for MBID
resolution of uncached artists. This prevents rate limiting (429) errors
that were causing 55+ second delays on initial load.

Tradeoff: First load with empty cache may have no results, but
subsequent loads will be instant using cached data.
2026-01-27 12:31:51 -06:00
vicrodh ff9e11db5c perf(suggestions): add skip_vector_build option for faster initial load
- Add skip_vector_build config option to SuggestionConfig
- When true, skips ensure_vector calls (which can be very slow)
- Uses only cached/existing vectors for similarity search
- Frontend now uses skip_vector_build=true for initial load

- Add timestamped logging helper in frontend component
2026-01-27 12:23:05 -06:00
vicrodh ba5ca133f4 fix(suggestions): simplify effect to prevent re-render issues
Replace cleanup-based effect with simpler lastLoadedPlaylistId tracking.
Avoids setting state in cleanup function which could cause render issues.
2026-01-27 12:18:03 -06:00
vicrodh 541c93f06d fix(suggestions): fix config deserialization and effect loop
- Add #[serde(default)] to SuggestionConfig to allow partial config
  from frontend (fixes "missing field max_artists" error)

- Fix effect loop in PlaylistSuggestions.svelte:
  - Add loadingInitiated flag to prevent re-triggering
  - Add cleanup effect when playlistId changes
  - Prevent concurrent loading attempts
2026-01-27 12:07:08 -06:00
vicrodh 1560cd4e3d debug(suggestions): add detailed timing logs for debugging
Frontend logging:
- Log when effect triggers with artist count
- Log when backend call starts/finishes with timing
- Log result details (tracks, artists counts)

Backend logging (playlist_suggestions.rs):
- Log MBID resolution with cache hits/misses/failures
- Log config values
- Log engine call timing

Engine logging (suggestions.rs):
- Step 1: ensure_vector timing per artist
- Step 2: playlist vector computation
- Step 3: find_nearest timing
- Step 4: track search timing per artist
- Early exit when pool size reached
2026-01-27 12:02:31 -06:00
vicrodh e9a5dfcb80 perf(suggestions): optimize loading with backend MBID resolution
- Move MBID resolution from frontend to backend
  - Eliminates multiple sequential IPC calls
  - Uses MusicBrainz cache for faster resolution
  - Logs resolution progress for debugging

- Implement progressive loading in UI
  - Initial load: 18 tracks (3 pages)
  - "Load more" expands to 60 tracks on demand
  - Better feedback during loading states

- Fix refresh button styling
  - Remove background while spinning
  - Update title based on available actions

- Add "Load more" link in pagination area
2026-01-27 11:58:54 -06:00
vicrodh f0aa539849 feat(ui): add playlist suggestions component and service
- Create PlaylistSuggestions.svelte component with:
  - Pool management (60 tracks, show 6 at a time)
  - Pagination/rotation on refresh
  - Loading, empty, and error states
  - Add (+) and dismiss (-) track actions
  - Album art display
  - Reason tooltip support (dev mode)

- Create playlistSuggestionsService.ts with:
  - MBID resolution from artist names (batched)
  - TypeScript types for SuggestedTrack, SuggestionResult
  - localStorage helpers for dismissed tracks
  - Qobuz album art URL generation

- Integrate into PlaylistDetailView:
  - Show suggestions at bottom of playlist track list
  - Extract unique artists from playlist for suggestions
  - Add track to playlist via add_tracks_to_playlist command
  - Hide when searching
2026-01-27 11:48:48 -06:00
vicrodh cadb346e32 feat(suggestions): add vector-based playlist suggestions engine
- Add suggestions.rs with SuggestionsEngine for generating suggestions
- Add SuggestionConfig with configurable parameters
- Add SuggestedTrack and SuggestionResult types
- Integrate with MusicBrainz relationships and Qobuz track search
- Add Tauri commands: get_playlist_suggestions_v2, get_vector_store_stats
- Add cleanup_vector_store command for maintenance
- Add Serialize to StoreStats for IPC
- Register ArtistVectorStoreState in app initialization
- 23 tests passing
2026-01-27 11:38:56 -06:00
vicrodh f3dcb6ebf2 feat(vectors): add vector builder with MB and Qobuz sources
- Add weights.rs with configurable RelationshipWeights
- Add builder.rs with ArtistVectorBuilder for constructing vectors
- Integrate MusicBrainz relationships (members, groups, collaborators)
- Integrate Qobuz similar artists API
- Add ensure_vector() with TTL for lazy building
- Add resolve_qobuz_to_mbid() for ID resolution via name search
- 21 tests passing (sparse_vector, store, weights, builder)
2026-01-27 11:30:06 -06:00