Commit Graph
461 Commits
Author SHA1 Message Date
vicrodh 5499add37d fix(home): use hybrid approach for Continue Listening to show recent plays immediately
Instead of relying solely on pre-computed scores (trained on login),
now merge the 4 most recent plays with scored items. This ensures
newly played tracks appear at the top without waiting for retraining.
2026-01-11 02:17:37 -06:00
vicrodh 6f8dc41a98 feat: add Qobuz featured albums (New Releases, Press Awards)
- Add album/getFeatured endpoint to API
- Create get_featured_albums Tauri command
- Add New Releases and Press Awards sections to HomeView
- Featured albums load first for faster perceived performance
2026-01-11 00:25:57 -06:00
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 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 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 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 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 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 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 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
vicrodh 2efa107aa7 fix(lastfm): handle subscriber field as integer from API
Last.fm returns subscriber as 0/1 integer, not boolean.
Added custom deserializer to convert integer to bool.
2026-01-09 18:44:45 -06:00
vicrodh 8b10a47a03 Enable Chromecast casting with thread-safe architecture
- Add ChromecastHandle with dedicated thread for rust_cast operations
- Fix thread safety issue (rust_cast uses Rc, not Arc) using channels
- Enable rupnp full_device_spec feature for DLNA discovery
- Fix media_server response type consistency
- Register all cast commands in lib.rs
- Add Deserialize to MediaMetadata for Tauri command args
2026-01-09 18:24:55 -06:00
vicrodh 2e0aaa4296 Fix Last.fm .env variable naming and add debug logging
- Support both LAST_FM_* and LASTFM_* naming conventions
- Match .env.example variable names (LAST_FM_API_KEY, LAST_FM_API_SHARED_SECRET)
- Add detailed logging for auth.getSession to help troubleshoot failures
- Include raw response in error messages for debugging
2026-01-09 18:12:15 -06:00
vicrodh e8c6f7372f fix: add clipboard write permission to capabilities 2026-01-09 17:43:04 -06:00
vicrodh 145186a06a feat: add casting module scaffolding (disabled)
Import Chromecast, AirPlay, and DLNA casting scaffolding from separate
branches. The module is currently disabled due to:

- Thread safety issues: rust_cast uses Rc internally (not Send)
- API compatibility: rupnp methods have changed

The scaffolding includes:
- Chromecast: mDNS discovery, device connection, media server
- AirPlay: Discovery scaffolding (RAOP playback pending)
- DLNA/UPnP: SSDP discovery scaffolding (playback pending)

To enable casting in the future:
1. Fix rust_cast thread safety (or use spawn_blocking)
2. Update rupnp API calls for current version
3. Add Deserialize derive to metadata types
4. Uncomment cast module in lib.rs
5. Wire up commands in invoke_handler
2026-01-09 17:40:26 -06:00
vicrodh e908d334c1 fix: use Tauri clipboard plugin for reliable share links
- Add tauri-plugin-clipboard-manager for reliable clipboard access
- Replace browser clipboard API with Tauri plugin
- Improve error messages in share functions to be more specific
- Add loading indicator for Song.link fetch
2026-01-09 17:35:18 -06:00
vicrodh e9151b6c55 feat(tracks): add share and queue actions menu 2026-01-09 17:15:55 -06:00
vicrodh cf584aa1b2 fix(playlists): include tracks in playlist fetch 2026-01-09 16:44:37 -06:00
vicrodh 905825177c fix: play button icon, playlist modal styling, and JSON parsing
- Fix play button by removing fill props and using CSS to style svg
- Add custom dropdown arrow and dark theme styling for select element
- Add #[serde(default)] to many model fields to handle missing data
- Add Default implementations for Artist, PlaylistOwner, ImageSet
2026-01-09 15:35:35 -06:00
vicrodh cdc06d8759 fix: multiple UX improvements and bug fixes
Playlist & Favorites:
- Fix playlist loading error (missing field `id` in JSON parsing)
- Add serde defaults for Track and PlaylistOwner optional fields
- Fix track favorites toggle to actually call backend API
- Add "Add to playlist" button on track rows in album view

Sidebar UI improvements:
- Increase sidebar width to 280px
- Reduce text size and margins throughout
- Normalize all icons to 14px (matching + and refresh buttons)
- Add text overflow with ellipsis and tooltip for playlist names

User card:
- Make user card more compact (smaller avatar, fonts, icons)
- Add collapsible toggle - when collapsed shows mini QBZ logo + username

Queue & Playback:
- Fix next_track spam when queue has only one song (queueEnded flag)

Other fixes:
- Fix TrackRow prop types (remove invalid hires, bitDepth, samplingRate props)
- Fix FavoritesView and PlaylistDetailView component prop types
- Add diagnostic logging to credential persistence
2026-01-09 14:55:53 -06:00
vicrodh 6eed045404 feat(auth): add secure credential persistence using system keyring
- Add keyring crate for secure credential storage (KWallet/GNOME Keyring)
- Create credentials module with save/load/clear functions
- Add auto_login command that uses saved credentials
- Add "Remember me" checkbox to login form (default: checked)
- Auto-login on app startup if credentials are saved
- Clear credentials from keyring on logout
- Show dynamic status during initialization (connecting, checking, logging in)
2026-01-09 14:37:49 -06:00
vicrodh 541f46e430 feat(integrations): add Discogs artwork fetch and fix Last.fm env loading
- Add Discogs API client for fetching missing album artwork
- Add UI button in Local Library settings to fetch missing artwork
- Load .env file at runtime using dotenvy for development
- Fix Last.fm to check runtime env vars as fallback to compile-time
- Use XDG Portal for dialog plugin (cross-desktop compatibility)
- Update README and .env.example with Discogs configuration
2026-01-09 14:30:35 -06:00
vicrodh f6dbf2ee2a feat(library): extract and display album artwork
- Extract embedded artwork from audio files during scan
- Save extracted artwork to cache directory (~/.cache/qbz/artwork)
- Fallback to folder artwork (cover.jpg, folder.jpg, front.jpg, etc.)
- Add get_artwork_cache_dir helper function
- Artwork now displays in album cards and detail views
2026-01-09 14:07:09 -06:00
vicrodh e8a61a45ce feat(library): improve local library UX and audio metrics
- Move Local Library section below Playlists in sidebar (Qobuz is main B.U.)
- Replace text input with native XDG folder picker dialog
- Add bit_depth and sample_rate to LocalAlbum model
- Display rich audio specs in album detail view (format, bit depth, sample rate, channels)
- Show format quality badge on album cards (e.g. "FLAC 24/96")
- Add Hi-Res visual indicator for 24-bit or >48kHz content
2026-01-09 14:05:17 -06:00
vicrodh b0a64b9caa feat: add tauri-plugin-dialog for file picker 2026-01-09 13:56:10 -06:00
vicrodh f7ca1a9557 feat(playlists): add local playlist enhancements
- Add playlist settings table for storing local-only features per playlist
- Add playlist local tracks table for mixing local tracks into Qobuz playlists
- Implement search within playlist (filters by title, artist, album)
- Add custom sorting (by title, artist, album, duration, ascending/descending)
- Add custom artwork selection with file picker
- Create .env.example for Last.fm credentials setup
- Update README with environment configuration instructions
2026-01-09 13:51:54 -06:00
vicrodh caca535cc0 feat(playlists): add Qobuz playlist management API
- Add create_playlist API method and command
- Add delete_playlist API method and command
- Add add_tracks_to_playlist API method and command
- Add remove_tracks_from_playlist API method and command
- Add update_playlist API method and command
- Register all new commands in invoke_handler
2026-01-09 13:39:02 -06:00
vicrodh 1895812830 feat(library): integrate local library module from Codex
Full local library implementation with:
- Filesystem scanner for FLAC, WAV, AIFF, APE, ALAC files
- Metadata extraction using lofty crate
- CUE sheet parsing for single-file albums
- SQLite persistence with WAL mode
- 13 Tauri commands for library management

Commands:
- library_add_folder, library_remove_folder, library_get_folders
- library_scan, library_get_scan_progress
- library_get_albums, library_get_album_tracks, library_get_artists
- library_search, library_get_stats, library_clear
- library_get_track, library_play_track (with CUE seek support)

Based on implementation by Codex in local-library worktree.
2026-01-09 13:23:32 -06:00
vicrodh 19bad7200b feat(lastfm): improve auth flow with embedded credentials support
- Add support for build-time credentials via LASTFM_API_KEY/LASTFM_API_SECRET env vars
- Add lastfm_has_embedded_credentials command to check for embedded keys
- Add lastfm_open_auth_url command to open browser via native opener
- Simplify UI flow: if embedded credentials exist, just click Connect
- Add cancel button during authorization flow
- Clean up UI when waiting for user to authorize in browser
2026-01-09 13:02:05 -06:00
vicrodh ddbe6b5706 fix(player): detect track completion to enable auto-advance
Change audio thread from blocking recv to recv_timeout, periodically
checking if the sink is empty. When playback finishes naturally, set
is_playing to false so the frontend can trigger auto-advance to next.
2026-01-09 12:43:58 -06:00
vicrodh 7a53d62341 fix(search): add offset parameter for proper pagination
- Add offset parameter to search_albums, search_tracks, search_artists
- Backend now properly passes offset to Qobuz API
- Fixes duplicate results when loading more search results
2026-01-09 12:35:29 -06:00
vicrodh 83654866f1 fix(playlist): fix state management in playlist commands
- Change playlist commands to use AppState instead of direct Arc<Mutex>
- Add playlist management endpoint paths for future use
2026-01-09 12:13:46 -06:00
vicrodh 8f4a47b2d8 fix(mpris): update progress during playback polling
- Update MPRIS position every time get_playback_state is polled (~500ms)
- Update MPRIS position when seeking
- Add Default derive to PlaybackState for error fallback
- System media controls now show accurate playback progress
2026-01-09 12:12:26 -06:00
vicrodh ff7b598522 Add song.link (Odesli) sharing integration
- Create share module with SongLinkClient for Odesli API
- Support for tracks via ISRC and albums via UPC
- In-memory cache with 1-hour TTL
- Commands: share_track_songlink, share_album_songlink
- Qobuz URL generators for tracks, albums, artists
- Proper error handling for missing identifiers
2026-01-09 12:07:48 -06:00
vicrodh 7e2740d297 Fix favorites commands using wrong state type
Commands were using State<Arc<Mutex<QobuzClient>>> directly instead of
State<AppState>. Changed to use AppState like all other commands.
2026-01-09 12:05:20 -06:00
vicrodh c7145e889b Add language setting and Last.fm integration
Settings:
- Add language dropdown (Auto, English, Español, etc.) with persistence

Last.fm:
- Create lastfm module with API client for authentication and scrobbling
- Add commands for auth flow, now playing, and scrobbling
- Full OAuth-style authentication with token exchange
- UI for entering API credentials and authorizing
- Automatic scrobbling after 50% of track or 4 minutes
- Update 'now playing' when tracks start
- Session persistence in localStorage
2026-01-09 11:23:01 -06:00
vicrodh 9d040fee55 Add audio device enumeration and streaming quality persistence
- Add get_audio_devices command to list available output devices
- Show real audio devices in Settings dropdown
- Persist streaming quality preference in localStorage
- Persist 'prefer highest available' setting
2026-01-09 11:13:43 -06:00
vicrodh 9b8e1352eb Wire settings: account info, themes, and cache management
- Account section now shows real user name and subscription
- Logout button connected to logout handler
- Theme switching with persistence (Dark/Light/OLED Black/Warm)
- Theme loads on app startup from localStorage
- Cache stats display (size, max, track count)
- Clear cache functionality with disabled state
2026-01-09 11:10:41 -06:00
vicrodh ef8feebc45 Add system notifications for track changes
- Add notify-rust dependency for desktop notifications
- Create notification.rs commands module with show_track_notification and show_notification
- Register notification commands in lib.rs
- Wire up notifications in frontend for all playback scenarios:
  - Search results playback
  - Album track playback
  - Playlist track playback
  - Queue navigation and auto-advance
2026-01-09 11:04:03 -06:00
vicrodh bda4ea5b76 Add playlist and favorites commands, update sidebar
Backend:
- Add playlist.rs commands: get_user_playlists, get_playlist, search_playlists
- Add favorites.rs commands: get_favorites, add_favorite, remove_favorite
- Add API client methods: search_playlists, add_favorite, remove_favorite

Frontend:
- Remove Radio and New from sidebar (no API support)
- Sidebar now loads and displays user playlists dynamically
- Add playlist and favorites views (placeholder for now)
- Pass selectedPlaylistId and onPlaylistSelect to Sidebar
2026-01-09 10:49:43 -06:00