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.
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.
- 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.
Include downloadStateVersion in the each loop key to force re-render
when offline cache state changes, fixing tracks showing gray icons
even when cached.
- 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
- 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.