1. QUEUE SHUFFLE FIX (CRITICAL):
- When shuffle enabled and set_queue called, starting track was placed randomly in shuffle_order
- This caused queue UI to show only tracks AFTER that random position
- Example: 11 tracks, start at index 5, but index 5 was at position 7 in shuffle → only 3 tracks visible
- FIX: When shuffle enabled, swap starting track to position 0 in shuffle_order
- Now all tracks appear in queue UI as expected
2. LOCAL LIBRARY CONTEXT FIX:
- handleLocalTrackPlay was clearing context immediately after LocalLibraryView set it
- FIX: Removed clearPlaybackContext() call - LocalLibraryView handles context correctly
- Context icon should now display for Local Library playback
3. SAMPLE RATE CRASH FIX:
- show_track_notification expected u32 but received f64 (44.1, 88.2, etc.)
- Error: "invalid type: floating point 44.1, expected u32"
- FIX: Changed sample_rate parameter from u32 to f64 in notification command and format_quality
- Bonus: Format shows "44.1" for fractional rates, "48" for whole numbers
Files modified:
- src-tauri/src/queue/mod.rs - Fixed set_queue to move start_index to front of shuffle_order
- src/routes/+page.svelte - Removed clearPlaybackContext from handleLocalTrackPlay
- src-tauri/src/commands/notification.rs - Changed sample_rate to f64 with proper formatting
- Modified handleShuffleAlbum to pick random starting track (same fix as Local Library)
- Added comprehensive debug logs to handleAlbumTrackPlay to diagnose queue issues
- Fixed favoritesStore crash when response.tracks is undefined (defensive checks)
Fixes:
- Qobuz album shuffle no longer always starts with first track
- App no longer crashes on startup with "undefined is not an object (evaluating 'response.tracks.items')"
- Extended navigationStore with FavoritesTab state tracking
- Added setFavoritesTab() to push tab changes to history
- Modified navigateTo() to support favorites sub-navigation
- Wired handleTabChange() to call setFavoritesTab()
- Synced activeTab with navigation store via currentTab prop
- Back button now returns to correct Favorites tab
cp
- Implemented custom tooltip for StackIcon (similar to AudioOutputBadges)
- Shows 'Playing from', context name, and 'Click to navigate' hint
- Added onContextClick={handleContextNavigation} to ExpandedPlayer
- Fixed onClick prop not being passed, enabling navigation
cp
StackIcon Component:
- Now accepts onClick prop
- Changed from div to button element
- Added arrow (→) that appears on hover
- Tooltip text changed to "Click to go to: {source}"
- Visual feedback: hover background + active scale
Navigation Logic (+page.svelte):
- Added handleContextNavigation function
- Switch based on context_type:
- album → handleAlbumClick
- playlist → navigate + set selectedPlaylistId
- artist_top → handleArtistClick
- favorites → navigate to favorites
- home_list → navigate to home
- search → navigate to search
- Import getCurrentContext from playbackContextStore
UI Integration:
- ExpandedPlayer: Added onContextClick prop, passed to StackIcon
- FocusMode: Added onContextClick prop, passed to StackIcon
- Both receive handleContextNavigation callback
Phase 3.7 COMPLETE ✅
cp
Added createContextAndPlayDisplayTrack helper that:
- Creates playback context with provided type/id/label/tracks
- Calls handleDisplayTrackPlay to start playback
- Will be used by Playlist, Artist, Favorites, Home views
Next: Implement context creation in each view component internally
(following AlbumDetailView pattern but keeping logic in views)
cp
Stack icon now appears in artist/album area across all players:
- FocusMode: icon before artist (size 12px)
- MiniPlayer: icon at start of artist-album row (size 12px)
- Consistent sizing: 12px (compact players), 16px (expanded player)
- Visual hierarchy: Title → [icon] Artist · Album
All 4 players updated and consistent.
cp
CRITICAL LOGIC FIX:
The autoplay setting was misunderstood. Corrected behavior:
BEFORE (wrong):
- Setting controls whether context is created
- 'continue' = create context
- 'track_only' = clear context
AFTER (correct):
- Context is ALWAYS created when playing from a source (album/playlist)
- Stack icon ALWAYS appears
- Setting only affects what happens at END of track:
- 'continue' = play next track in context
- 'track_only' = stop after current track
Why this makes sense:
- You're playing from an album = that's the context
- Stack icon shows the origin (informative)
- Setting controls continuation behavior (not context existence)
Also:
- Added logging to handleAutoplayModeChange
- Will investigate why setting doesn't persist
cp
UI Fix:
- Add :has(.radio-group) rule to allow flexible height
- Set align-items: flex-start for radio group rows
- Prevents radio buttons from being squashed
Logging Enhancement:
- Log autoplay_mode preference value
- Log track index and total tracks
- Log when no album tracks found
- Will help diagnose why context isn't being created
cp
CRITICAL FIX: Context was being cleared instead of created.
Root cause:
- AlbumDetailView had internal handlers but used parent's onTrackPlay
- Parent's handleAlbumTrackPlay had no context logic
- Result: context always cleared (default behavior)
Solution:
- Moved context creation logic to handleAlbumTrackPlay in +page.svelte
- Checks autoplay_mode preference
- Creates context if 'continue', clears if 'track_only'
- Removed duplicate logic from AlbumDetailView (was never executed)
Now when clicking a track:
1. handleAlbumTrackPlay checks preference
2. Creates/clears context accordingly
3. Stack icon should appear/disappear correctly
Test with default setting ('continue'):
- Click any track → should see context creation logs
- Stack icon should appear immediately
cp
- Call initPlaybackContextStore() on app mount
- Call initPlaybackPreferences() on app mount
- Load backend state into frontend stores
- Phase 3 backend + UI complete
- Wiring for track actions pending (will be done per-page)
cp
- Create StackIcon component with reactive context subscription
- Display Layers icon before track title when context exists
- Show tooltip with origin info on hover
- Add to: NowPlayingBar, ExpandedPlayer, FocusMode, MiniPlayer
- Icon hidden when no playback context (single track)
- Responsive sizing per player (14px-18px)
cp
- Stop playback immediately when starting a Qobuz track to prevent
previous track from continuing during download
- Show buffering toast while downloading Qobuz audio
- Skip buffering UI for local tracks since they load instantly
- Add is_local field to QueueTrack for prefetch optimization
- Update prefetch to skip local tracks (no network needed)
- Update all queue track builders to include is_local flag
Wire onPlaylistCountUpdate from PlaylistDetailView to Sidebar's
updatePlaylistCounts method in +page.svelte. This ensures the
sidebar displays accurate track counts from the database instead
of calculated values that could drift out of sync.
- Update handlePlayAll to include both Qobuz and local tracks
- Update handlePlayAllNext and handlePlayAllLater similarly
- Add onSetLocalQueue prop to mark local tracks in queue store
- Connect prop to handleSetLocalQueue in +page.svelte
- Add 60-second timeout to login initialization in LoginView
- Show retry/offline options when login times out
- Move loadFavorites() to handleLoginSuccess to prevent API calls
before authentication is complete
- Prevents errors when auto-login is slow or stuck
- Update onPlaylistUpdated callback to also refresh local track counts
- Change all Song/Songs references to Track/Tracks in Sidebar tooltips
- Ensure tooltip cache is properly invalidated when tracks are modified
- PlaylistModal now uses playlist_add_local_track command for local tracks
instead of the Qobuz-only add_tracks_to_playlist command
- Added isLocalTracks prop to PlaylistModal and wired it through uiStore
- Updated LocalLibraryView to pass isLocal=true when adding tracks to playlists
- Added HardDrive icon indicator next to quality badge for local tracks in TrackRow
cc
- Add batch check command for track local status in Rust
- Show unavailable tracks with grayed-out visual state in PlaylistDetailView
- Disable interactions for unavailable tracks (click, menu, play)
- Add WifiOff indicator for unavailable tracks
- Update QueuePanel to show unavailable track styling
- Implement auto-skip for unavailable tracks during playback
- Add offline mode sync to queue store
- Add offline-specific filter states to PlaylistManager:
- Available Offline
- Partially Available
- Not Available Offline (view-only)
- Disable edit/drag for unavailable playlists in PlaylistManager
- Add i18n strings for offline states (en/es)
Refresh offline status after successful login to prevent false offline
detection. Previously, the offline status was checked during bootstrap
before auto_login completed, causing 'NotLoggedIn' reason even though
the user would be logged in moments later.
- Add "Start in offline mode" link below login form
- Enable offline mode without authentication
- Navigate directly to local library when starting offline
- Add i18n strings for offline start link (en/es)
- Create OfflinePlaceholder component with reason-specific messaging
- Add i18n strings for offline mode (en/es)
- Subscribe to offlineStore in +page.svelte
- Show OfflinePlaceholder for home, search, favorites views when offline
- Provide quick navigation to local library from placeholder
cc
- Queue button in NowPlayingBar now acts as toggle (open/close)
- Queue sidebar uses theme-aware background instead of glassmorphic effect
- Dropdown hover and selected states now use CSS variables for theme support
- Fixes contrast issues in Light and Warm themes
cp
- Remove broken AddToPlaylistModal component import
- Use existing PlaylistModal infrastructure from parent component
- Pass onTrackAddToPlaylist callback from +page.svelte to LocalLibraryView
- Follow existing pattern used in AlbumDetailView and other views
cp
- Increase initial artist albums fetch from 500 to 1000
- Increase load more albums batch from 50 to 200
- Increase top tracks display from 5 to 20
- Prefer full biography content over summary
- Increase bio truncate threshold from 500 to 800 characters
cp
- Move item limits inline with section toggles in home settings modal
- Remove separate limits section for cleaner, more compact layout
- Add add-to-playlist functionality to now playing bar Plus button
- Wire up AddToPlaylistModal to current playing track
cp
- Add backend command to check if album is fully downloaded
- Add frontend functions to check album download status
- Pass download handlers to HomeView
- Update HomeView AlbumCards with download status props
cp
- Add submenu to album download option when album is fully downloaded
- New options: Open containing folder and Re-download album
- Backend command to open album folder in file manager
- Helper function to check if album is fully downloaded
- Works in both AlbumCard overlay and AlbumDetailView menus
cp
Mouse back/forward buttons now work in local library view.
Changes:
- Add 'library-album' ViewType to navigation store
- Add selectLocalAlbum(), clearLocalAlbum(), getSelectedLocalAlbumId()
- LocalLibraryView subscribes to navigation state changes
- Album clicks use selectLocalAlbum() for proper history tracking
- Back button uses navGoBack() to navigate properly
- Tab changes navigate back to 'library' when viewing album
- +page.svelte shows LocalLibraryView for both 'library' and 'library-album'
cc
- Playback state polling: 1000ms when paused, 250ms when playing
- Audio thread timeout: 500ms when idle, 100ms when playing
- Lyrics interval: self-check to auto-stop when conditions not met
- Add cleanup return to lyrics in +page.svelte
- Add build-and-run.sh and monitor-resources.sh scripts
- Add OPTIMIZATION_PLAN.md documentation