Commit Graph
7032 Commits
Author SHA1 Message Date
vicrodh f4e8d68538 feat(home): add recommendation store and data-driven home
Backend:
- Add reco_store module with SQLite-backed event storage
- Add reco_log_event, reco_get_home commands
- Add ML-lite scoring: reco_train_scores, reco_get_home_ml
- Score decay based on event age (configurable half-life)

Frontend:
- Add recoService.ts for event logging
- Log play/favorite/playlist_add events
- Add albumId/artistId to PlayingTrack for tracking
- Rework HomeView to fetch recommendations from reco_store
- Display recently played, continue listening, top artists, favorites

Integrated from home-reco and home-reco-ml branches
2026-01-10 08:10:34 -06:00
vicrodh 340fb2a72a feat(lyrics): smoother transitions and static lyrics at top
- Reduced transition durations from 300-400ms to 120-150ms
- Changed easing to ease-out for snappier feel
- Added will-change for GPU acceleration
- Non-synced lyrics now display at container top (no spacers)
- Added isSynced prop to all lyrics components
2026-01-10 07:37:04 -06:00
vicrodh b171a17b57 fix(lyrics): fix camelCase mismatch between Rust and TypeScript
Rust sends syncedLrc (camelCase) but TypeScript expected synced_lrc.
Updated TypeScript interface to match Rust serialization.
2026-01-10 07:29:32 -06:00
vicrodh ab705db9cd fix(lyrics): add User-Agent header and debug logging to LRCLIB requests
LRCLIB API may require User-Agent header. Added debug logging to
see raw response and parsing results.
2026-01-10 07:24:26 -06:00
vicrodh 6b2466a976 fix(lyrics): prefer synced lyrics from LRCLIB search
When /api/get returns results without synced lyrics, now also
tries /api/search to find a version with synced LRC timestamps
2026-01-10 07:18:59 -06:00
vicrodh 182479f6c2 feat(settings): add lyrics cache clear button
- Add Lyrics section to Settings with cache clear button
- Add explicit debug logging for lyrics fetch/parse
- Add track change detection logging to watcher
2026-01-10 07:15:21 -06:00
vicrodh baf8a57516 fix(lyrics): instant scroll sync when lyrics load late or user seeks
- Use instant scroll for initial sync when activeIndex > 0 (lyrics loaded after song started)
- Use instant scroll for jumps > 2 lines (user seek or catch-up)
- Use smooth scroll only for normal line-by-line progression
- Reset sync state when new lyrics load (track change)
2026-01-10 07:04:09 -06:00
vicrodh 4989802641 fix: make progressRef reactive in FocusMode 2026-01-10 07:03:15 -06:00
vicrodh 0676989c71 feat(lyrics): add auto-scroll, karaoke effects, and FocusMode integration
- LyricsLines: improved auto-scroll with prevActiveIndex tracking
- LyricsLines: added immersive mode for larger text in FocusMode
- LyricsLines: enhanced opacity fading and text-shadow for active line
- FocusMode: redesigned with blurred artwork background like Cider
- FocusMode: integrated lyrics panel on right side with proper styling
- FocusMode: added bottom bar with track info, controls, and progress
- +page.svelte: wire lyrics props to FocusMode component
- +page.svelte: start lyrics updates when either sidebar or FocusMode open
2026-01-10 07:02:22 -06:00
vicrodh c32f25ab5e fix: restore explicit height on .main-content to fix rendering 2026-01-10 06:55:32 -06:00
vicrodh 78522b99ac fix: improve lyrics display with theme colors and karaoke effect
- Use theme CSS variables instead of hardcoded Cider colors
- Add distance-based opacity fading for non-active lines
- Fix scroll to center active line with proper reactivity
- Add spacers to allow first/last lines to scroll to center
- Add karaoke progress gradient on active line
- Prefetch lyrics on track start instead of button click
- Remove provider badge (will add to About modal later)
- Add loading spinner animation
2026-01-10 06:43:15 -06:00
vicrodh 80ff8afa3a feat: integrate lyrics module with UI
- Add lyricsStore for frontend state management with LRC parsing
- Wire LyricsSidebar to main layout with toggle button in NowPlayingBar
- Fix Rust compile errors (add Clone to LrclibItem, remove unused import)
- Add lyrics active line tracking with binary search
- Auto-start/stop lyrics updates based on playback state
2026-01-10 06:31:12 -06:00
vicrodh a3a766ba34 feat(lyrics-ui): refine layouts and add mini view 2026-01-10 06:19:40 -06:00
vicrodh f0748910c2 feat(lyrics-ui): add isolated lyrics UI components 2026-01-10 06:19:36 -06:00
vicrodh 489d73496a feat(lyrics): add backend cache and provider chain 2026-01-10 06:19:31 -06:00
vicrodh 71156e9d0a feat: replace polling with Tauri events and add unit tests
- Backend now emits playback:state events every 250ms when state changes
- PlayerStore uses listen() instead of setInterval for real-time updates
- Added Vitest testing framework with mocked Tauri APIs
- Added 53 unit tests for playerStore and queueStore
2026-01-10 06:14:59 -06:00
vicrodh 6dfcc8adaa refactor: extract app bootstrap to $lib/app/bootstrap.ts
Create bootstrap module with:
- loadSavedTheme() - theme initialization
- restoreLastfmSession() - Last.fm session restore
- setupMouseNavigation() - mouse back/forward handlers
- bootstrapApp() - combined init with cleanup

+page.svelte: 1,229 → 1,194 lines (-35 lines)
2026-01-10 05:56:33 -06:00
vicrodh 7580948e8c refactor: remove unnecessary navigation wrappers
- Remove goBack(), goForward(), handlePlaylistSelect() wrappers
- Use navGoBack, navGoForward, selectPlaylist directly from store
- Keep navigateTo() wrapper (has debug logging)

+page.svelte: 1,241 → 1,229 lines (-12 lines)
2026-01-10 05:54:36 -06:00
vicrodh 58db1bedc1 refactor: consolidate playback handlers to use playTrack service
- Simplify handleTrackPlay: 55 → 20 lines
- Simplify handleAlbumTrackPlay: 82 → 36 lines
- Simplify playQueueTrack: 58 → 18 lines

All playback handlers now use the unified playTrack() service which
handles MPRIS, notifications, Last.fm, and favorites automatically.

+page.svelte: 1,361 → 1,241 lines (-120 lines, -9%)
2026-01-10 05:53:22 -06:00
vicrodh 5be437dd4e refactor: extract Qobuz adapters and unify DisplayTrack type
- Create $lib/adapters/qobuzAdapters.ts with:
  - formatDuration/formatDurationMinutes (removed duplicates)
  - getQobuzImage helper
  - formatQuality/formatAlbumQuality helpers
  - convertQobuzAlbum converter
  - convertQobuzArtist converter

- Add unified DisplayTrack type to $lib/types/index.ts

- Update +page.svelte:
  - Import adapters instead of inline functions
  - Remove duplicate converter functions (−57 lines)
  - Add handleDisplayTrackPlay for view components

- Fix TypeScript type narrowing in view closures
2026-01-10 05:51:48 -06:00
vicrodh 30a33cfc95 refactor: extract track actions to trackActions service
Centralize common track actions that components can import directly:
- Queue operations (queueTrackNext, queueTrackLater)
- Convenience queue functions for different track types
- Favorites handling
- Playlist modal integration
- Sharing (Qobuz link, Song.link)

Removes 100+ lines of duplicate wrapper functions from +page.svelte.
Reduces +page.svelte from 1525 to 1418 lines.
2026-01-10 05:16:32 -06:00
vicrodh ea066ded97 refactor: extract playback logic to playbackService
Move core playback operations to centralized service:
- playTrack() - unified track playback with all side effects
- MPRIS metadata updates
- System notifications
- Last.fm scrobbling and now playing
- Favorite status checking and toggling

Simplifies handlers: handlePlaylistTrackPlay, handleLocalTrackPlay, toggleFavorite.
Reduces +page.svelte from 1675 to 1525 lines.
2026-01-10 05:12:04 -06:00
vicrodh d3ea80c5d4 refactor: extract shared types to $lib/types/
Move type definitions to centralized location:
- Qobuz API types (QobuzTrack, QobuzAlbum, QobuzArtist)
- UI display types (Track, AlbumDetail, ArtistDetail, PlaylistTrack)
- Local library types (LocalLibraryTrack)
- External API types (SongLinkResponse)

Reduces +page.svelte from 1806 to 1675 lines.
2026-01-10 05:07:26 -06:00
vicrodh 3ea2bb937b fix: update playlist and local track play to use playerStore
handlePlaylistTrackPlay and handleLocalTrackPlay were still using
local state variables directly instead of playerStore functions,
causing the UI to not react to playback state changes.
2026-01-10 05:00:57 -06:00
vicrodh c60cfe0525 refactor: extract queue state into queueStore
Move queue management into dedicated store:
- Queue tracks, shuffle, repeat modes
- Local track ID tracking for library playback
- Queue operations: add, clear, sync, navigate
- Backend queue state synchronization
2026-01-10 04:53:00 -06:00
vicrodh 55ec44cdc2 refactor: extract player state into playerStore
Move playback state management into dedicated store:
- PlayingTrack interface
- isPlaying, currentTime, duration, volume, isFavorite
- Polling logic with setOnTrackEnded callback
- Playback controls (togglePlay, seek, setVolume)
2026-01-10 04:48:31 -06:00
vicrodh cef950b08b refactor: extract navigation state into navigationStore
- Create navigationStore.ts for view navigation and history
- Implement navigateTo, goBack, goForward actions
- Add selectPlaylist for playlist detail navigation
- Update +page.svelte to use store subscription and functions
- Simplify navigation wrapper functions
2026-01-10 04:32:44 -06:00
vicrodh e98ea146e3 refactor: extract authentication state into authStore
- Create authStore.ts for managing login state and user info
- Implement setLoggedIn and setLoggedOut actions
- Update +page.svelte to use store subscription
- Simplify handleLoginSuccess and handleLogout handlers
2026-01-10 04:30:11 -06:00
vicrodh 6edfb5db06 refactor: extract UI/overlay states into uiStore
- Create uiStore.ts for overlay and modal visibility states
- Centralize queue panel, fullscreen, focus mode, cast picker states
- Add playlist modal state management with mode and track IDs
- Implement handleEscapeKey for prioritized overlay closing
- Update +page.svelte to use store subscription and functions
2026-01-10 04:28:34 -06:00
vicrodh 0e8371d900 refactor: extract toast notifications into toastStore
- Create toastStore.ts with centralized toast state management
- Add auto-hide functionality with configurable durations per type
- Update +page.svelte to use store subscription instead of local state
- Maintains existing toast behavior with improved separation of concerns
2026-01-10 04:25:45 -06:00
vicrodh 95488014a6 feat: implement functional seek in audio player
- Add Seek command to AudioCommand enum
- Store audio data in audio thread for re-seeking
- Use rodio's skip_duration to seek to desired position
- Preserve play/pause state after seeking
- Update playback timer to account for seek position
2026-01-10 04:21:56 -06:00
vicrodh baa656a508 feat: add local library tracks to Qobuz playlists
- Create AddToPlaylistModal component for selecting playlists
- Update PlaylistDetailView to merge local and Qobuz tracks
- Add visual indicator (HardDrive icon) for local tracks
- Show notice that local tracks are device-specific
- Add "Add to Playlist" option in Local Library track menu
- Connect local track play handlers for playlists
- Hide download button for local tracks in playlists
2026-01-10 04:01:44 -06:00
vicrodh 93a6e9545a feat: hide download button for local library tracks 2026-01-10 03:50:29 -06:00
vicrodh 16939e02f4 fix: use asset:// protocol for local library artwork in players 2026-01-10 03:48:54 -06:00
vicrodh fbfa067b94 feat(cast): add multi-protocol support for Chromecast, DLNA, and AirPlay
- Update CastPicker to show protocol tabs with device counts
- Register DLNA and AirPlay state and commands in lib.rs
- Add Deserialize derive to DlnaMetadata and AirPlayMetadata
- Fix capabilities file (remove unavailable fs permissions)
- Remove unused IpAddr import in media_server.rs
2026-01-10 03:41:11 -06:00
vicrodh 762df3e122 fix: Last.fm scrobbling and LocalLibrary cover art
- Restore Last.fm session on app startup (not just when visiting Settings)
- Fix LocalLibrary artwork: use asset://localhost/ instead of file://
- Add fs:allow-read capability for asset protocol
- Enable assetProtocol in tauri.conf.json
2026-01-10 03:36:31 -06:00
vicrodh 2bf9856179 feat(favorites): add download button and search to all tabs
- Add download functionality to FavoritesView tracks tab
- Add search input for each tab (tracks, albums, artists)
- Filter displayed items based on search query
- Show "no results" message when search has no matches
- Display filtered/total counts in toolbar
- Use buildDisplayTrack helper for cleaner code
2026-01-09 20:20:27 -06:00
vicrodh 5a07408acf fix(download): persist download state across views
- Add downloadStateVersion prop to trigger reactivity in child components
- Use version in each block keys to force re-evaluation when state changes
- Ensures download status persists whether track was downloaded from
  album view or playlist view
2026-01-09 20:11:39 -06:00
vicrodh 6de37c296b feat(download): add download button to playlist view and album download button
- Add download functionality to PlaylistDetailView (track-by-track)
- Add handleDisplayTrackDownload handler for playlist tracks
- Add "Download Album" button to AlbumDetailView header actions
- handleDownloadAlbum queues all non-downloaded tracks for download
2026-01-09 20:02:59 -06:00
vicrodh 97951b2189 fix: use file storage as primary for credentials (more reliable in dev) 2026-01-09 19:53:02 -06:00
vicrodh 087fbbd567 fix: verify keyring save and fallback if verification fails 2026-01-09 19:48:36 -06:00
vicrodh 1aaf360bd5 fix: add logging to credential checking for debugging 2026-01-09 19:47:24 -06:00
vicrodh 9111165ee9 fix(share): fall back to song.link direct url 2026-01-09 19:44:46 -06:00
vicrodh 20c34caed0 feat: add download management section in Settings
- Download stats display (tracks count, size used)
- Storage limit dropdown (500MB to Unlimited)
- Clear downloads button
- Open folder button (sneaky feature)
2026-01-09 19:44:02 -06:00
vicrodh 7149cf5c4b feat: add download UI for offline listening
- DownloadButton component with status indicators
- TrackRow now shows download button on hover
- downloadState store for managing download states
- Tauri event listeners for download progress
- Integration with AlbumDetailView
2026-01-09 19:42:35 -06:00
vicrodh 45fb498b8b chore: move plan doc to qbz-nix-docs 2026-01-09 19:37:22 -06:00
vicrodh 3864fa8e4b feat: add download cache for offline listening
- SQLite-based index for tracking cached tracks
- Disk-based storage for audio files (~/.cache/qbz-nix/audio/)
- Download progress events via Tauri events
- LRU eviction with configurable cache size limit
- Integration with play_track for automatic local playback
- Open cache folder command for system file manager
2026-01-09 19:18:06 -06:00
vicrodh 5bf69bc877 fix(share): fall back to song.link url lookup 2026-01-09 19:05:12 -06:00
vicrodh 1ccb78ef52 fix: multiple UI and integration fixes
1. Credential storage fallback - when keyring (KWallet) unavailable,
   falls back to obfuscated file in config directory

2. Heart icon always visible - shows outlined when not favorite,
   filled when favorite, with hover states

3. Player favorite state - checks favorite status when track plays
   and updates the heart icon in NowPlayingBar

4. Song.link ISRC lookup - uses Spotify/Deezer search URLs with ISRC
   since Qobuz isn't directly supported by Odesli
2026-01-09 19:00:12 -06:00
vicrodh 657682fc5e fix(share): use Qobuz track URL for song.link instead of ISRC
Odesli API doesn't support direct ISRC lookup. Changed to use
Qobuz track URL (https://open.qobuz.com/track/{id}) which Odesli
can properly resolve to song.link.
2026-01-09 18:50:30 -06:00