Commit Graph
561 Commits
Author SHA1 Message Date
vicrodh 1e7475e308 Fix sample rate decimal precision for bit-perfect playback (CRITICAL)
Problem:
- sample_rate stored as INTEGER in DB and u32 in Rust
- Fractional rates (44.1, 88.2, 176.4 kHz) stored as 44100, 88200, 176400 Hz
- Integer division (44100 / 1000 = 44) lost decimals
- DAC badge showed "resampling 44 → 44.1 kHz" false positive
- Breaks bit-perfect guarantee - user requirement: "no es negociable"

Root Cause:
- DB schema: sample_rate INTEGER (44100 Hz)
- Frontend: Math.round(44100 / 1000) = 44 kHz (lost .1)
- Badge: Compared 44 kHz vs 44.1 kHz → false resampling warning

Solution:
1. Changed LocalTrack.sample_rate from u32 to f64 (models.rs)
2. Changed AudioProperties.sample_rate from u32 to f64 (models.rs)
3. Changed DB schema from INTEGER to REAL (database.rs)
4. Added migration to convert existing data (database.rs)
5. Updated metadata extraction to cast to f64 (metadata.rs)
6. Fixed frontend to use float division without rounding (+page.svelte)

Migration:
- Checks if sample_rate is INTEGER
- Creates temp table with REAL, copies data, drops old, renames
- Preserves all data and indexes
- Runs automatically on app start

Result:
- 44100 Hz stored as 44100.0
- Division: 44100.0 / 1000.0 = 44.1 kHz (exact)
- Badge: 44.1 kHz = 44.1 kHz → no resampling (correct)
- Bit-perfect guarantee restored

Files modified:
- src-tauri/src/library/models.rs - Changed sample_rate to f64 in structs
- src-tauri/src/library/metadata.rs - Cast sample_rate to f64
- src-tauri/src/library/database.rs - Changed schema to REAL + migration
- src/routes/+page.svelte - Fixed division to preserve decimals
2026-01-19 19:49:34 -06:00
vicrodh 61fa05da93 Fix critical shuffle queue bug, Local Library context, and sample rate crash
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
2026-01-19 19:13:07 -06:00
vicrodh 3d8c049226 Fix Qobuz album shuffle to start with random track and add debug logs
- 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')"
2026-01-19 19:02:46 -06:00
vicrodh 7d9071442f fix(layout): keep NowPlayingBar out of app-body
cx
2026-01-19 14:51:14 -06:00
vicrodh 0701892ed5 fix(local): clear context and seed queue
cx
2026-01-19 13:10:42 -06:00
vicrodh 1fae9b7d9f fix(ui): wire active state in lists
cx
2026-01-19 13:02:43 -06:00
vicrodh c59ab226b9 fix(playback): honor autoplay and seed queues
cx
2026-01-19 12:46:28 -06:00
vicrodh 7c4fb6d483 fix(favorites): show active track and icon
cx
2026-01-19 12:42:27 -06:00
vicrodh 05780f2b13 refactor(theme): centralize global theme styles
cx
2026-01-19 11:43:14 -06:00
vicrodh 395fd165d4 feat(player): add volume sliders to FocusMode and MiniPlayer
cx
2026-01-19 11:26:08 -06:00
vicrodh 318e3d795a feat(context): scroll to active track on context navigation
cx
2026-01-19 11:19:52 -06:00
vicrodh 7831b07c30 feat(favorites): make tabs history-aware views and normalize order
cx
2026-01-19 11:11:03 -06:00
vicrodh ffb16656e7 feat(phase4.7): implement history-aware favorites tab navigation
- 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
2026-01-18 15:52:31 -06:00
vicrodh d39180bd6c feat(ui): show playing status in search and artist tracks
cx
2026-01-18 05:46:57 -06:00
vicrodh 12067d7a61 fix(phase3): context navigation and autoplay persistence
- Fixed context navigation using correct property names (.type, .id)
- Simplified autoplay setting from radio buttons to toggle switch
- Fixed tooltip using native title attribute (like QualityBadge)
- Removed custom tooltip CSS and hover state
- Updated translations (en/es) for clearer autoplay behavior description

cp
2026-01-18 04:53:43 -06:00
vicrodh 92f1644601 fix(context): add custom tooltip and pass onClick callback
- 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
2026-01-18 04:34:42 -06:00
vicrodh 584650fee1 feat(phase37): implement clickable context tooltip navigation
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
2026-01-18 03:47:11 -06:00
vicrodh fe80896fd2 feat(phase35): add helper for context creation with DisplayTrack
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
2026-01-18 03:21:21 -06:00
vicrodh 7907b695f8 feat(ui): complete stack icon repositioning (all 4 players)
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
2026-01-18 03:16:38 -06:00
vicrodh 17cd6f0ae2 fix(logic): context creation should NOT depend on autoplay setting
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
2026-01-18 03:09:57 -06:00
vicrodh f69a7ab461 fix(ui): fix settings layout and add detailed logging
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
2026-01-18 01:53:21 -06:00
vicrodh f2891c2071 fix(wiring): move context logic to parent (+page.svelte)
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
2026-01-18 01:39:01 -06:00
vicrodh 9d4a269d36 feat(init): initialize playback context and preferences stores
- 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
2026-01-18 00:58:26 -06:00
vicrodh cf5be434e3 feat(ui): add stack icon to all 4 players
- 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
2026-01-18 00:39:25 -06:00
vicrodh 26116d0670 Wire up onPlaylistSelect prop in FavoritesView 2026-01-16 14:40:07 -06:00
vicrodh 94d7d78a22 Fix buffering UX when transitioning from local to Qobuz tracks
- 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
2026-01-16 07:58:13 -06:00
vicrodh aeb13b9ffc Connect playlist count callback for single source of truth
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.
2026-01-16 07:19:34 -06:00
vicrodh 9366388041 Fix local tracks not being added to queue from playlists
- 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
2026-01-16 06:51:59 -06:00
vicrodh 825534621a Add login timeout mechanism and fix premature API calls
- 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
2026-01-16 06:49:03 -06:00
vicrodh 3297257a24 Fix tooltip updates and change Song to Track terminology
- 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
2026-01-16 06:39:08 -06:00
vicrodh 3915abd3bb fix(playlists): add local tracks to playlists correctly
- 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
2026-01-16 06:03:09 -06:00
vicrodh 6f3bcfe1cb Add offline mode track handling for playlists and queue
- 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)
2026-01-16 03:01:15 -06:00
vicrodh 51ca294d8e Fix offline detection on app startup
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.
2026-01-16 00:11:15 -06:00
vicrodh 6e0d7486b0 feat(offline): add offline mode link to login screen
- 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)
2026-01-15 22:59:30 -06:00
vicrodh b7c1af6123 feat(offline): add view access restrictions for offline mode
- 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
2026-01-15 22:19:17 -06:00
vicrodh 031cc3e081 fix(ui): improve queue toggle, theme sensitivity
- 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
2026-01-15 11:25:41 -06:00
vicrodh d0a30c7175 fix(local-library): remove non-existent AddToPlaylistModal import
- 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
2026-01-15 09:43:40 -06:00
vicrodh 0b439bff14 fix(ui): use existing PlaylistModal for now playing add to playlist
- Remove duplicate AddToPlaylistModal component
- Reuse PlaylistModal component that TrackRow already uses
- Consolidate playlist management UI patterns

cp
2026-01-15 09:32:42 -06:00
vicrodh e281932340 feat(artist): increase album and track limits
- 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
2026-01-15 08:25:03 -06:00
vicrodh bba12f2832 feat(ui): improve home settings layout and add playlist modal to now playing
- 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
2026-01-15 08:22:16 -06:00
vicrodh 7952bbb7d6 feat(downloads): add album download status to grid overlays (partial)
- 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
2026-01-15 00:23:58 -06:00
vicrodh c30c16145e feat(downloads): add smart download menu for fully downloaded albums
- 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
2026-01-15 00:07:54 -06:00
vicrodh 25d0a13d6b fix(library): integrate navigation history for back/forward support
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
2026-01-14 08:14:13 -06:00
vicrodh 2d5ababba4 feat(ui): add album card actions and fixed-speed tickers 2026-01-14 01:03:14 -06:00
vicrodh b57889a910 feat(library): link local artists to Qobuz 2026-01-14 00:11:42 -06:00
vicrodh 4c6bfe3fbc revert(session): remove restore prefetch flow 2026-01-13 17:42:55 -06:00
vicrodh e1de9235cf fix: keep sidebar above content 2026-01-13 17:11:01 -06:00
vicrodh a86dc5bcba fix: restore playback buffering and mpris controls 2026-01-13 15:06:49 -06:00
vicrodh 84e19c0a02 fix(library): use tauri file src for local artwork 2026-01-13 10:31:31 -06:00
vicrodh 3e8fe0771a perf: add adaptive polling and fix lyrics interval leak
- 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
2026-01-12 20:38:48 -06:00