Commit Graph
239 Commits
Author SHA1 Message Date
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 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 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
vicrodh 73d2bd114a feat(ui): show now-playing indicator in album and playlist rows 2026-01-12 15:56:08 -06:00
vicrodh 7a142b8d3e fix(ui): refresh sidebar playlist visibility 2026-01-12 15:39:08 -06:00
vicrodh 1b6c895f62 fix(cast): route playback controls to cast devices 2026-01-12 14:14:32 -06:00
vicrodh 21582315cc feat: wire save queue as playlist, disable AirPlay backend
- Add handleSaveQueueAsPlaylist() to collect queue track IDs
- Wire QueuePanel "Save as Playlist" button to open playlist modal
- Comment out AirPlay commands in lib.rs (RAOP not implemented)
- Comment out AirPlay state initialization
- Move documentation files to qbz-nix-docs/ directory

AirPlay research concluded no viable Rust RAOP library exists.
Feature deferred until custom implementation or library emerges.
See qbz-nix-docs/AIRPLAY_IMPLEMENTATION_STATUS.md for details.
2026-01-12 11:00:02 -06:00
vicrodh 1ac6d15551 Implement Chromecast frontend and DLNA AVTransport casting
Frontend:
- Add castStore for managing cast state (connect, disconnect, play, pause, etc)
- Update CastPicker to use castStore, show connected device banner with disconnect
- Wire isCastConnected to NowPlayingBar and ExpandedPlayer for visual indicator
- Modify playbackService to cast when connected instead of local playback

DLNA Backend:
- Implement full AVTransport SOAP client with:
  - SetAVTransportURI with DIDL-Lite metadata
  - Play, Pause, Stop, Seek actions
  - RenderingControl SetVolume
- Add dlna_play_track command that fetches stream, downloads audio, and serves via media server
- Share media server between Chromecast and DLNA
2026-01-12 10:11:09 -06:00
vicrodh e4483b4afa fix(session): fetch track details on restore for album/artist links
- Fetch full track info from Qobuz API when restoring session
- Populate albumId and artistId for working album/artist links
- Show correct quality badge (bitDepth/sampleRate) instead of placeholder
- Fallback to cached data if API call fails
2026-01-12 09:16:16 -06:00
vicrodh e93144e5ef feat(toast): buffering toast with shimmer effect, persistent until loaded
- Add 'buffering' toast type that doesn't auto-hide
- Add shimmer animation to "Buffering" text
- Add spinning loader icon for buffering state
- Toast shows "Buffering... [track name]" format
- Dismiss buffering toast when track loads or on error
- Remove callback pattern, use toastStore directly in services

fix(artwork): show empty placeholder when no artwork available

- NowPlayingBar shows empty placeholder instead of Play icon
- Miniplayer shows empty placeholder instead of Play icon
- Prevents showing incorrect CD placeholder on session restore
2026-01-12 09:06:58 -06:00
vicrodh 6d41741f76 feat: Redesign MiniPlayer to replace main window temporarily
- MiniPlayer now resizes the main window instead of creating a separate floating window
- Cider-inspired UI with large album art, track info, full playback controls
- Progress bar with current/remaining time display
- Shuffle, repeat, volume controls integrated
- Pin/restore buttons to control always-on-top and return to main view
- Fixed tray icon to use transparent PNG from static/icons
2026-01-12 07:28:14 -06:00
vicrodh 79b030f8ee feat: add MiniPlayer floating window
- Create miniplayerService.ts for window management
- Add /miniplayer route with compact player UI
- Sync playback state from main window via events
- MiniPlayer features:
  - Draggable window (decorations disabled)
  - Always-on-top toggle (pin button)
  - Album art, track title, artist
  - Play/Pause, Next, Previous controls
  - Progress bar
  - Close button (hides window)
- Add PictureInPicture2 button to NowPlayingBar
- State synced via emitTo('miniplayer', ...) events
2026-01-12 02:26:29 -06:00
vicrodh 06fa565d84 feat: add system tray icon with playback controls
- Add tray-icon feature to Tauri dependencies
- Create tray.rs module with full tray implementation
- Tray menu: Play/Pause, Next, Previous, Show/Hide, Quit
- Left-click toggles window visibility
- Double-click always shows and focuses window
- Right-click shows context menu
- Frontend listens for tray:play_pause, tray:next, tray:previous events
- Tray icon uses app default icon with "QBZ - Music Player" tooltip
2026-01-12 02:07:51 -06:00
vicrodh fb0bd2b9cd fix: reliable session persistence during playback
- Enable debouncedSavePosition() during playback state updates
  (saves position every 5 seconds while playing)
- Flush position save immediately when pausing
- Add periodic full session save every 30 seconds during playback
- Persist volume changes to session immediately
- Persist shuffle/repeat mode changes to session immediately

This fixes the race condition where async saves in beforeunload
wouldn't complete before app close. Now we save frequently enough
that the worst case is losing only 5-30 seconds of progress.
2026-01-12 02:01:09 -06:00
vicrodh 19028ab232 feat(artist): enhance artist view sections 2026-01-12 00:37:03 -06:00
vicrodh bd578d8123 fix: z-index for menus/tooltips, sidebar dropdown, hi-res SVG icon
- Fix z-index across all menus and tooltips (10000+) to prevent overlap issues
- Redesign sidebar playlist header with dropdown menu: Sort by, Refresh, Import, Manage
- Add playlist tooltip on hover showing track count (lazy-loads artists)
- Fix submenu navigation with delayed close for better UX
- Replace hi-res PNG with SVG icon in QualityBadge
- Fix scrollbar spacing (8px from window edge) in main content
- Fix Svelte state_unsafe_mutation error in sidebar tooltip loading
2026-01-11 22:48:54 -06:00