- 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
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.
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
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.
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.
- 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
- 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
- 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
- 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)
- Use top/bottom positioning instead of calculated height
- top: 32px (below title bar), bottom: 104px (above player)
- Add adjustment for when title bar is hidden (top: 0)
- Sidebar now always fits within visible content area
- Make "Adding n tracks" inline with "Choose playlist" label
- Add min-height 400px for addTrack mode modal
- Fix dropdown being clipped by modal: overflow visible + z-index 10001
- Dropdown can now extend outside modal boundaries
PlaylistModal changes:
- Replace native select with custom searchable dropdown
- Show max 8 playlists at a time with scroll indicator
- Add search/autocomplete functionality
- Support keyboard navigation (arrows, enter, escape)
Button contrast fix:
- Add --btn-primary-text CSS variable per theme
- Use dark text on light accent colors (Warm, Nord, Dracula, etc.)
- Use light text on dark accent colors (Adwaita, default)
- Add FlatpakWelcomeModal component shown once for Flatpak users
- Add persistence for Flatpak welcome shown state (updates.db)
- Implement sequential modal priority: Flatpak > What's new > Update available
- Add Flatpak section to Settings navigation (only when running in Flatpak)
- Clean up duplicate Flatpak section and invalid style block in SettingsView
- Add copyable command styling for Flatpak section
- Add floatingMenuStore.ts with global menu state management
- Only one floating menu can be open at a time across the entire app
- Standardize inactivity timeout to 2 seconds for all menus
Updated components:
- TrackMenu: integrate with global store, reduce timeout from 5s to 2s
- AlbumMenu: integrate with global store, add inactivity timeout
- Sidebar: integrate dropdown, context menu, and folder popover
- PlaylistManagerView: integrate filter and sort dropdowns
- Dropdown.svelte: integrate generic dropdown component
The global store ensures that opening any menu (context menu,
dropdown, popover) automatically closes all other open menus.
- Fix playing indicator to consider isPlaybackActive (not just activeTrackId)
- Track now shows as playing only when actually playing, not when paused
- Change reorder controls from vertical to horizontal layout
- Homologate UI with PlaylistManagerView (buttons beside drag handle)
cc
- Add checkbox selection for tracks in custom order mode
- Add batch controls bar with Select All, Clear, Move Up/Down
- Implement moveSelectedUp/Down to move multiple tracks as group
- Refactor PlaylistManagerView to use savePlaylistOrder helper
- Add CSS styles for batch controls and checkboxes
cc
- Add ChevronUp/ChevronDown buttons alongside drag handle in custom mode
- Implement movePlaylistUp/movePlaylistDown functions
- Extract savePlaylistOrder helper for code reuse
- Support both grid and list view layouts
- Add CSS styles for reorder controls
cc
- Add custom order state management in PlaylistDetailView
- Load custom order when entering custom sort mode
- Initialize custom order from current tracks if not exists
- Add move up/down buttons for track reordering
- Update sorting logic to use customOrderMap
- Add CSS styles for reorder controls
cc
- Extend DisplayTrack interface with label, addedIndex, customPosition fields
- Add PlaylistTrack.album.label type for record label data
- Add three new sort options: Added Recently, Label, Custom Order
- Implement sorting logic for new options
- Label sorting places tracks without label (local) at the end
- Added Recently uses original index as proxy for date added
cc
- Add showGenre prop (default true) to AlbumCard
- Make genre prop optional
- Hide genre and favorite button in LocalLibrary albums
- VirtualizedAlbumList passes showGenre={false}, showFavorite={false}
- Add spacer to keep Play button centered when favorite is hidden
Backend:
- Emit 'library:tag_write_progress' events with current/total count
- Progress updates as each file is written
Frontend:
- Listen for progress events during direct write mode
- Save button shows "Writing X of Y..." dynamically
- Cleanup listener on completion or error
- Show spinner-inline animation on Save button while saving
- Different text: "Writing tags..." for direct mode, "Saving..." for sidecar
- Provides visual feedback during potentially slow file operations