Commit Graph
2240 Commits
Author SHA1 Message Date
vicrodh 1de7c7830e refactor(frontend): migrate Cast/DLNA/AirPlay commands to V2
Update all casting invocations to use v2_* commands:
- castStore: connect, disconnect, play, pause, stop, seek, volume
- CastPicker: device discovery
2026-02-16 02:25:32 -06:00
vicrodh 3ede4e2fc6 refactor(frontend): migrate Plex commands to V2
Update all Plex invocations to use v2_plex_* commands:
- SettingsView: auth, ping, cache operations
- LocalLibraryView: albums, tracks, search, hydration
- playerStore/playbackService: play_track
2026-02-16 01:47:33 -06:00
vicrodh 5dbd383bab feat(v2): add Plex V2 command wrappers
Wrap all 18 Plex commands with V2 RuntimeError handling:
- Network: ping, get_music_sections, get_section_tracks, get_track_metadata
- Auth: auth_pin_start, auth_pin_check, open_auth_url
- Cache: get_sections, save_sections, get_tracks, get_albums,
  get_album_tracks, search_tracks, save_tracks, update_track_quality,
  get_tracks_needing_hydration, clear
- Playback: play_track

Completes the Plex category of V2 migration.
2026-02-16 01:03:45 -06:00
vicrodh e565b964a5 feat(v2): add Other V2 commands
Add V2 commands for miscellaneous categories:

Audio Backends (7):
- v2_get_available_backends, v2_get_devices_for_backend
- v2_get_alsa_plugins, v2_check_alsa_utils_installed
- v2_get_default_device_name, v2_get_linux_distro
- v2_query_dac_capabilities

Audio Diagnostics (3):
- v2_get_hardware_audio_status
- v2_start_bitdepth_capture, v2_stop_bitdepth_capture

Radio (5):
- v2_create_artist_radio, v2_create_track_radio
- v2_refill_radio_queue, v2_get_queue_remaining
- v2_create_infinite_radio

Share (3):
- v2_get_qobuz_track_url/album_url/artist_url

Additional (7):
- v2_is_visualizer_enabled
- v2_get_current_queue_track, v2_peek_next_track
- v2_get_shuffle, v2_get_repeat
- v2_get_current_user_id
- v2_has_saved_credentials, v2_save_credentials

Total 25 new V2 commands.
2026-02-16 01:00:18 -06:00
vicrodh d39fe148ed feat(v2): add Cast/DLNA/AirPlay V2 commands
Add 39 V2 commands for casting:

Chromecast (14):
- v2_cast_start_discovery, v2_cast_stop_discovery
- v2_cast_get_devices, v2_cast_connect, v2_cast_disconnect
- v2_cast_get_status, v2_cast_get_position
- v2_cast_play_track, v2_cast_play_local_track
- v2_cast_play, v2_cast_pause, v2_cast_stop
- v2_cast_seek, v2_cast_set_volume

DLNA (14):
- v2_dlna_start_discovery, v2_dlna_stop_discovery
- v2_dlna_get_devices, v2_dlna_connect, v2_dlna_disconnect
- v2_dlna_get_status, v2_dlna_get_position
- v2_dlna_play_track, v2_dlna_load_media
- v2_dlna_play, v2_dlna_pause, v2_dlna_stop
- v2_dlna_seek, v2_dlna_set_volume

AirPlay (11):
- v2_airplay_start_discovery, v2_airplay_stop_discovery
- v2_airplay_get_devices, v2_airplay_connect
- v2_airplay_disconnect, v2_airplay_get_status
- v2_airplay_load_media
- v2_airplay_play, v2_airplay_pause, v2_airplay_stop
- v2_airplay_set_volume

All commands wrap existing implementations with RuntimeError.
2026-02-16 00:52:57 -06:00
vicrodh d269acc709 feat(v2): add playlist custom V2 commands
Add 10 V2 commands for playlist customization:
- v2_playlist_set_sort
- v2_playlist_set_artwork
- v2_playlist_add_local_track
- v2_playlist_remove_local_track
- v2_playlist_set_hidden
- v2_playlist_set_favorite
- v2_playlist_reorder (reorder playlists in sidebar)
- v2_playlist_init_custom_order
- v2_playlist_set_custom_order
- v2_playlist_move_track

All commands wrap existing library implementations with
proper type signatures and RuntimeError handling.
2026-02-16 00:50:57 -06:00
vicrodh a405954846 feat(v2): add V2 commands for cache management (clear cache, artist cache, vector store, offline cache, credentials) 2026-02-16 00:11:21 -06:00
vicrodh 477b032abe feat(v2): add V2 commands for settings (tray, graphics, window, developer, playback, favorites prefs, visualizer, blacklist, locale) 2026-02-16 00:07:12 -06:00
vicrodh 18e7303aaf fix: update remaining sync_cached_favorite_tracks to V2 2026-02-15 22:07:51 -06:00
vicrodh 68aec71fdf fix(v2): migrate favorites cache, session, and context stores to V2 commands
- Add v2_save_session_state and v2_load_session_state commands
- Update favoritesStore to use V2 cache commands
- Update albumFavoritesStore to use V2 cache commands
- Update artistFavoritesStore to use V2 cache commands
- Update sessionService to use V2 session commands
- Update playbackContextStore to use V2 context commands
2026-02-15 21:55:15 -06:00
vicrodh 35758d07df feat(v2): add V2 commands for playback context, session, and favorites cache
- Add ContextType::Search variant
- Add V2 playback context commands (get, set, clear, has)
- Add V2 session persistence commands (save position/volume/mode, clear)
- Add V2 favorites cache commands (get/sync/add/remove for tracks/albums/artists)
- Register all new commands in lib.rs
2026-02-15 21:41:43 -06:00
vicrodh 7337b7e026 fix(v2): match V2QueueTrack field names to frontend interface
Remove serde rename attributes that caused mismatch:
- Frontend sends 'duration_secs', backend expected 'duration'
- Frontend sends 'artwork_url', backend expected 'artwork'

Now V2QueueTrack field names match BackendQueueTrack exactly.
2026-02-15 20:36:47 -06:00
vicrodh 045cf24a61 fix(v2): unify queue architecture - all commands use CoreBridge
Previously, V2 queue commands had a dual-queue bug:
- Writes (v2_set_queue, v2_add_to_queue, etc.) went to AppState.queue (legacy)
- Reads (v2_get_queue_state) came from CoreBridge/QbzCore queue
- Result: frontend sets queue, syncs, gets empty/stale data

This commit fixes the architecture:
- All V2 queue commands now use CoreBridge methods
- Added queue methods to QbzCore: add_track, add_tracks, add_track_next,
  set_queue, remove_track, remove_upcoming_track, move_track, play_index,
  next_track, previous_track, peek_upcoming
- Added corresponding methods to CoreBridge
- Fixed v2_set_shuffle to use CoreBridge (was using legacy AppState)
- Fixed runtime requirements: v2_toggle_shuffle and v2_clear_queue now
  use RequiresUserSession like other queue commands (consistency)
- Prefetch now gets upcoming tracks from CoreBridge, not legacy queue
- Updated tests to match V2 behavior (v2_toggle_shuffle, available field)
2026-02-15 20:07:01 -06:00
vicrodh 8d26f547d1 fix(frontend): resolve all remaining TypeScript errors
- HomeView: fix OfflineCacheStatus type for getTrackOfflineCacheStatus prop
- PlaylistDetailView: fix trackToReplace null access in console.log
- SearchView: add id and isViewMore to Album/Artist interfaces
- Toast: add 'warning' type support
- playbackContextStore: add 'search' to ContextType union
- queueStore: add trackId to QueueTrack interface
- trackActions: add queueDisplayTrackNext/Later and buildQueueTrackFromDisplayTrack
- +page.svelte: fix numerous type issues including:
  - selectedAlbum closure captures for TypeScript narrowing
  - handleDisplayTrackDownload signature for DisplayTrack
  - handleSearchTrackDownload for SearchView's Track type
  - ImportSummary callback signature
  - QobuzTrack hires_streamable property usage
  - album.tracks.items instead of .data

npm run check now passes with 0 errors (138 warnings remain, mostly a11y)
2026-02-15 17:20:05 -06:00
vicrodh e7d617d46d fix(frontend): additional type error fixes
- SearchView.svelte: Fix async onMount pattern to properly return cleanup
- vite.config.js: Add ts-nocheck to suppress Node.js global errors

Reduces npm run check errors from 42 to 40.
2026-02-15 16:29:57 -06:00
vicrodh 8becf36842 fix(frontend): resolve type errors in multiple components
- miniplayerService.ts: Use PhysicalSize/PhysicalPosition classes instead of plain objects
- AudioOutputBadges.svelte: Add null checks for settings
- SettingsView.svelte: Add gapless_enabled to AudioSettings interface, fix return types
- SearchView.svelte: Fix variable declaration ordering for $derived dependencies
- LocalLibraryView.svelte: Add tick import, fix loadAlbums -> loadLibraryData, wrap onclick handler

Reduces npm run check errors from 66 to 42.
2026-02-15 16:27:53 -06:00
vicrodh 81e9279add fix(v2): proper teardown for V2 integration state
ListenBrainzV2State::clear_credentials() now resets internal client to
fresh state, not just wrapper fields.

LastFmV2State:
- Added clear_session() method that clears session_key AND pending_token
- init_with_session(None) now calls clear_session() instead of no-op

Ensures no credentials leak across sessions on logout/deactivate.

Closes Must-Fix #2 from MUST_FIX_BEFORE_RELEASE_RUNTIME_V2.md
2026-02-15 16:06:43 -06:00
vicrodh af910c4617 fix(v2): add transactional auth rollback on login failures
Added rollback_auth_state() helper that clears legacy_auth, corebridge_auth,
and emits AuthChanged event on partial login failures.

Applied to all error paths in v2_auto_login, v2_manual_login, and v2_login:
- CoreBridge auth failure now rolls back
- Session activation failure now rolls back

Ensures runtime_get_status never reports half-authenticated state.

Closes Must-Fix #1 from MUST_FIX_BEFORE_RELEASE_RUNTIME_V2.md
2026-02-15 16:06:37 -06:00
vicrodh 233d3c87ef refactor(frontend): migrate all integration calls to V2 commands
Complete frontend migration eliminating "double brain" pattern:

- bootstrap.ts: Last.fm session restore uses v2_lastfm_set_session
- playbackService.ts: All scrobbling uses V2 ListenBrainz and Last.fm
- SettingsView.svelte: All integration settings use V2 commands
  - Last.fm auth flow: v2_lastfm_get_auth_url, v2_lastfm_complete_auth
  - ListenBrainz: v2_listenbrainz_get_status, connect, disconnect
  - MusicBrainz: v2_musicbrainz_is_enabled, set_enabled
  - Audio reinit: removed legacy reinit_audio_device, V2 only

Frontend now uses ZERO legacy integration commands.
2026-02-15 15:37:16 -06:00
vicrodh 130c95dbdf feat(v2): add MusicBrainz metadata support to ListenBrainz commands
V2 ListenBrainz now_playing and scrobble commands now accept optional
MusicBrainz identifiers (recording_mbid, release_mbid, artist_mbids),
ISRC, and duration_ms parameters for richer scrobbles.

The AdditionalInfo struct is populated when any metadata is provided,
automatically including QBZ media player identification.
2026-02-15 15:37:10 -06:00
vicrodh 53927b5c6f Add missing V2 commands and deprecate legacy integration commands
New V2 commands:
- v2_lastfm_set_session: Set session key for restored sessions
- v2_listenbrainz_queue_listen: Queue listen for offline (uses legacy cache)

Deprecated legacy commands (with #[deprecated] markers):
- ListenBrainz: get_status, is_enabled, set_enabled, connect, disconnect,
  now_playing, scrobble, queue_listen
- Last.fm: is_authenticated, get_auth_url, authenticate, set_session,
  disconnect, scrobble, now_playing
- MusicBrainz: is_enabled, set_enabled
- Audio: reinit_audio_device

All deprecated commands point to their V2 replacements in the note.
Frontend migration to V2 commands is next.
2026-02-15 15:29:59 -06:00
vicrodh 943f886637 Add V2 integration states to session lifecycle
Integrates ListenBrainzV2State, MusicBrainzV2State, and LastFmV2State
from qbz-integrations crate into the session activation/deactivation
lifecycle.

In activate_session:
- After legacy integrations init (which loads from SQLite), sync
  credentials to V2 states
- ListenBrainz V2: gets token, user_name, enabled from legacy client
- MusicBrainz V2: gets enabled state (use_proxy defaults to true)
- LastFm V2: initialized to clean state (no legacy equivalent)

In deactivate_session:
- Clear V2 state credentials to prevent cross-user leaks
- Reset states to defaults

This ensures V2 commands (using qbz-integrations crate) have access
to the same credentials as legacy commands, enabling a smooth
migration path.
2026-02-15 15:06:59 -06:00
vicrodh 856ceb796d Enforce ToS gate in backend for all login entrypoints
Add centralized require_tos_accepted() helper function that checks
ToS acceptance before any authentication attempt. This prevents
non-UI clients (TUI/CLI/tests) from bypassing the ToS gate.

Affected commands:
- v2_auto_login: Returns tos_not_accepted error code
- v2_manual_login: Returns tos_not_accepted error code
- v2_login: Returns RuntimeError::Internal

The ToS check was already in runtime_bootstrap, but these commands
could be called directly. Now the gate is enforced at the backend
level regardless of entry point.

Also updates obsolete comment about frontend handling ToS.
2026-02-15 15:02:15 -06:00
vicrodh d0fb30a5b1 fix(auth): enforce ToS gate and session activation severity parity
Fixes login consistency issues:

1. ToS gate enforcement:
   - LegalSettingsState now initialized GLOBALLY at app startup (not per-session)
   - runtime_bootstrap checks ToS BEFORE attempting auto-login
   - If ToS not accepted, skip auto-login and return to login screen

2. Session activation severity parity:
   - runtime_bootstrap now treats activate_session failure as FATAL
   - On failure: rollback auth state, set degraded, return error
   - Matches behavior of v2_auto_login/v2_manual_login

3. LegalSettings is now truly global:
   - Removed from session_lifecycle activate/deactivate
   - ToS acceptance persists across sessions
   - Can be checked before user is logged in

Acceptance criteria:
- ToS false + credentials -> no auto-login
- ToS true + credentials + activation OK -> session restored
- ToS true + credentials + activation fails -> error, no session
2026-02-15 14:55:14 -06:00
vicrodh 63994c0a20 refactor(cast): extract qbz-cast crate
Extract casting functionality (Chromecast, AirPlay, DLNA) to standalone
qbz-cast crate. This crate is Tauri-agnostic and can be used by TUI/CLI
clients.

- Move device connection, discovery, threading, and media server to crate
- Keep only Tauri commands in src-tauri/src/cast/
- Thin re-exports in src-tauri for backwards compatibility
- Remove duplicate dependencies from src-tauri Cargo.toml
2026-02-15 14:51:06 -06:00
vicrodh deece54bcb fix: eliminate double-brain session lifecycle (legacy vs V2)
Backend:
- v2_auto_login/v2_manual_login now FAIL if activate_session fails
  (was: log and continue with success:true, causing "logged in but not ready")
- Session activation is now REQUIRED, not optional

Frontend:
- Remove duplicate activate_user_session call from handleLoginSuccess
  (V2 login already activates session internally)
- Remove duplicate deactivate_user_session call from handleLogout
  (v2_logout already deactivates session internally)
- LoginView now uses runtime_bootstrap as SINGLE SOURCE OF TRUTH
  (was: v2_init_client + legacy is_logged_in/get_user_info checks)
- PlaylistDetailView uses runtime_get_status for user_id
  (was: legacy get_current_user_id)

This eliminates the "double-brain" where frontend used both legacy
and V2 paths, causing state divergence and intermittent failures.
2026-02-15 14:39:44 -06:00
vicrodh 59e3141aa6 fix: address 7 code review findings for V2 architecture
HIGH priority fixes:
- Enable WAL mode in qbz-integrations caches (ADR-002)
- v2_auto_login/v2_manual_login now call activate_session()
- RequiresUserSession allows offline sessions (only checks session_activated)

MEDIUM priority fixes:
- Consolidate lifecycle: legacy commands delegate to session_lifecycle
- ListenBrainz teardown now calls disconnect() to clear tokens
- Add SessionActivationFailed degraded reason and emit event on failure
2026-02-15 12:21:17 -06:00
vicrodh d6e4b3349b feat(qbz-library): extract local library management to standalone crate
Create qbz-library crate with:
- LibraryScanner: directory scanning for audio files
- MetadataExtractor: audio metadata extraction via lofty
- LibraryDatabase: SQLite persistence with WAL mode
- CueParser: CUE sheet parsing for single-file albums
- Thumbnails: artwork extraction and thumbnail generation
- Tag sidecar: album metadata override files

src-tauri re-exports from qbz-library for backwards compatibility.
Enables TUI/headless clients to manage local libraries without Tauri.
2026-02-15 12:12:52 -06:00
vicrodh 384459d4d7 feat(qbz-cache): extract audio caching to standalone crate
Create qbz-cache crate with:
- AudioCache: L1 in-memory LRU cache (~300MB)
- PlaybackCache: L2 disk-based cache (~500MB)
- LRU eviction with spillover from L1 to L2

src-tauri now re-exports from qbz-cache for backwards compatibility.
This enables TUI/headless clients to use caching without Tauri.
2026-02-15 11:27:38 -06:00
vicrodh a66d5a2af3 refactor(v2): use RuntimeError in remaining V2 commands
Convert all remaining V2 commands from Result<T, String> to Result<T, RuntimeError>:
- runtime_get_status, v2_is_logged_in
- v2_login, v2_logout, v2_activate_offline_session
- v2_play_track, v2_get_discover_albums
- Search commands: v2_search_albums, v2_search_tracks, v2_search_artists
- Catalog commands: v2_get_album, v2_get_track, v2_get_artist
- Favorites commands: v2_get_favorites, v2_add_favorite, v2_remove_favorite
- Playlist commands: full suite including CRUD operations
- Extended catalog: v2_get_tracks_batch, v2_get_genres, v2_get_discover_*
- Artist commands: v2_get_artist_page, v2_get_similar_artists, v2_get_artist_with_albums
- v2_get_label

Only v2_auto_login/v2_manual_login retain String (intentional - use V2LoginResponse error fields)
and download_audio (internal utility wrapped by callers).
2026-02-15 11:23:16 -06:00
vicrodh 8a6050f2f3 refactor(v2): use RuntimeError in queue and playback commands
Convert queue commands (16) and playback commands (10) from String
errors to typed RuntimeError:
- Queue: get_queue_state, set_repeat_mode, toggle_shuffle, etc.
- Playback: pause, resume, stop, seek, volume, get_state, etc.

Runtime checks now use direct ? propagation instead of map_err.
Bridge method errors wrapped with RuntimeError::Internal.
2026-02-15 11:15:13 -06:00
vicrodh 0c50c67a61 feat(v2): add integrations V2 commands using qbz-integrations crate
Wire qbz-integrations to Tauri via new V2 commands:

ListenBrainz V2:
- v2_listenbrainz_get_status, is_enabled, set_enabled
- v2_listenbrainz_connect, disconnect
- v2_listenbrainz_now_playing, scrobble

MusicBrainz V2:
- v2_musicbrainz_is_enabled, set_enabled
- v2_musicbrainz_resolve_track, resolve_artist

Last.fm V2:
- v2_lastfm_get_auth_url, complete_auth
- v2_lastfm_is_authenticated, disconnect
- v2_lastfm_now_playing, scrobble

New module integrations_v2.rs provides Tauri state wrappers for the
Tauri-independent clients from qbz-integrations crate.
2026-02-15 11:11:35 -06:00
vicrodh 6310e9b216 chore: add qbz-integrations crate dependency
Wire qbz-integrations to src-tauri Cargo.toml. The crate provides
Tauri-independent implementations of Last.fm, ListenBrainz, and
MusicBrainz integrations.

Next step: Create V2 commands that use the new crate, then gradually
deprecate the existing in-tree implementations.
2026-02-15 11:05:33 -06:00
vicrodh fbb7f3c226 refactor(v2): use RuntimeError in audio settings commands
Replace String errors with typed RuntimeError variants across all 17
audio settings V2 commands for consistent error handling:
- Lock errors: RuntimeError::Internal
- Session not active: RuntimeError::UserSessionNotActivated
- Store errors: RuntimeError::Internal

This aligns with the runtime contract (ADR_RUNTIME_SESSION_CONTRACT.md)
for typed errors that clients can pattern match.
2026-02-15 10:58:09 -06:00
vicrodh e70c577181 refactor: centralize session lifecycle, make runtime_bootstrap autocontenido
Addresses multiple review findings for V2 architecture:

1. Create session_lifecycle.rs module:
   - activate_session(): Full session activation callable from anywhere
   - deactivate_session(): Full teardown with proper runtime state cleanup
   - activate_offline_session(): Minimal session for offline/local-only use

2. Make runtime_bootstrap autocontenido:
   - Now activates session after successful auth (Step 4)
   - No longer delegates to frontend for session activation

3. Fix v2_login to be canonical:
   - Performs full flow: legacy auth -> corebridge auth -> session activation
   - Updates all runtime state flags

4. Fix v2_logout to be canonical:
   - Calls deactivate_session (teardown stores + clear runtime state)
   - Proper cleanup of legacy and corebridge auth

5. Fix deactivate_session:
   - Now clears session_activated flag (was missing)
   - Now clears corebridge_auth flag (was missing)
   - Emits UserSessionDeactivated event

6. Add v2_set_repeat_mode runtime check:
   - Now requires RequiresUserSession like other queue mutations

7. Fix LoginView early session activation:
   - Removed premature activate_user_session call before auto-login confirmed
   - ToS check uses localStorage fallback if no session

8. Fix offline mode:
   - Add v2_activate_offline_session command
   - Offline mode now activates minimal session so queue commands work
2026-02-15 10:53:49 -06:00
vicrodh bd30e7cf24 feat(qbz-integrations): create third-party integrations crate
New crate for Last.fm, ListenBrainz, and MusicBrainz integrations.
Designed to work WITHOUT Tauri for TUI/headless clients.

Modules:
- lastfm: Scrobbling and now-playing via Cloudflare Workers proxy
- listenbrainz: Direct API client with user token auth
- musicbrainz: Entity resolution with rate limiting

Features:
- `cache` (default): SQLite persistence for offline support
  - ListenBrainz: Credential storage, offline listen queue
  - MusicBrainz: Resolved entity cache with TTL

Architecture:
- Pure async Rust, no Tauri dependencies
- Shared error types via IntegrationError enum
- Rate limiting for MusicBrainz (1 req/sec direct, faster via proxy)
2026-02-15 10:36:53 -06:00
vicrodh cfe931e8ee fix: address critical login state and queue command issues
Issue 1 (HIGH): Fix UI/backend login state divergence
- Move setLoggedIn() AFTER successful activate_user_session
- Prevents UI entering logged-in state when backend fails

Issue 2 (HIGH): Fix userId fallback to 0
- Add validation in LoginView for both auto_login and manual_login
- Reject success responses with invalid user_id (0 or missing)

Issue 3 (HIGH): Add runtime requirement checks to queue commands
- All queue mutation commands now require authenticated user session
- CoreBridge-based commands require RequiresCoreBridgeAuth
- AppState-based commands require RequiresUserSession

Issue 6 (MEDIUM): Remove V1 auth surface
- Remove login, logout, auto_login from invoke_handler
- Frontend must use v2_login, v2_logout, v2_auto_login
2026-02-15 10:30:47 -06:00
vicrodh efb707d972 feat(v2): add v2_get_discover_albums command
Add get_discover_albums to qbz-core, CoreBridge, and commands_v2.
Supports endpoints: newReleases, idealDiscography, mostStreamed,
qobuzissimes, albumOfTheWeek, pressAward.

Migrate DiscoverBrowseView to use v2_get_discover_albums.
2026-02-15 05:32:33 -06:00
vicrodh 214f578618 fix(frontend): use V2 favorites commands in QueuePanel
The toggleCurrentTrackFavorite function was calling non-existent
add_track_to_favorites/remove_track_from_favorites commands.
Updated to use v2_add_favorite/v2_remove_favorite with proper params.
2026-02-15 04:34:14 -06:00
vicrodh 20580b170c feat(frontend): migrate discover and playlist commands to V2
- HomeView: use v2_get_discover_index and v2_get_discover_playlists
- DiscoverPlaylistsBrowseView: use v2_get_discover_playlists
- PlaylistModal: use v2_delete_playlist

Part of V2 migration to enable TUI/headless usage without Tauri.
2026-02-15 04:30:38 -06:00
vicrodh 2f7cae58f4 feat(v2): add extended catalog and playlist V2 commands
Add missing API methods to QbzCore, CoreBridge, and V2 commands:
- Playlist management: create, delete, update, search
- Catalog: genres, discover index/playlists, playlist tags, featured albums
- Artists: artist page, similar artists, artist with albums pagination
- Labels: label details
- Tracks: batch fetch

All methods follow the V2 architecture with RuntimeManager requirements.
2026-02-15 04:25:31 -06:00
vicrodh 87d03d427a refactor(frontend): migrate get_audio_settings to v2_get_audio_settings
Migrate all frontend get_audio_settings invoke calls to use V2:
- +page.svelte (normalization state loading)
- SettingsView.svelte (audio settings page)
- ExpandedPlayer.svelte (DAC passthrough status)
- AudioOutputBadges.svelte (output device status)
2026-02-15 04:12:37 -06:00
vicrodh 1416bed807 refactor(frontend): migrate get_favorites calls to v2_get_favorites
Migrate all frontend get_favorites invoke calls to use V2 command:
- FavoritesView.svelte
- ArtistDetailView.svelte
- favoritesStore.ts
- albumFavoritesStore.ts
- artistFavoritesStore.ts
- playbackService.ts

All favorites API calls now go through CoreBridge V2 architecture.
2026-02-15 04:10:30 -06:00
vicrodh ed80981852 feat(runtime): add requirement checks to catalog and playback commands
Add RuntimeManagerState and check_requirements to:
- v2_get_album/track/artist (RequiresCoreBridgeAuth)
- v2_pause/resume/stop_playback (RequiresClientInit)
- v2_seek, v2_set_volume (RequiresClientInit)

Playback commands use RequiresClientInit since they operate on
the local player and don't need API auth, just initialized state.
2026-02-15 04:08:06 -06:00
vicrodh 645cfe9194 feat(runtime): apply check_requirements to critical V2 commands
Add RuntimeManagerState parameter and CommandRequirement check to:
- v2_play_track (RequiresCoreBridgeAuth)
- v2_search_albums/tracks/artists (RequiresCoreBridgeAuth)
- v2_get_favorites/add_favorite/remove_favorite (RequiresCoreBridgeAuth)
- v2_get_user_playlists/get_playlist (RequiresCoreBridgeAuth)
- v2_add_tracks_to_playlist/remove_tracks_from_playlist (RequiresCoreBridgeAuth)

This enforces the ADR Runtime Session Contract at the command level.
V2 commands now fail with typed RuntimeError if auth state is invalid.
2026-02-15 04:05:38 -06:00
vicrodh 58f1957a05 feat(runtime): implement phased V2 login commands for runtime contract
Add V2 commands that implement the ADR Runtime Session Contract:
- v2_init_client: Phase 1 - init client only (bundle tokens)
- v2_auto_login: Phase 2 - auto-login with blocking V2 auth
- v2_manual_login: Manual login with blocking V2 auth

This allows frontend to control ToS check between init and auth:
1. v2_init_client() -> InitializedNoAuth
2. activate_user_session() -> restore session
3. loadTosAcceptance() -> check ToS
4. v2_auto_login() or v2_manual_login() -> Ready

V2 CoreBridge auth is now REQUIRED per ADR - login fails if V2 fails.

Migrate LoginView.svelte to use new V2 commands:
- Replace init_client with v2_init_client
- Replace auto_login with v2_auto_login
- Replace login with v2_manual_login

Add i18n keys for V2 auth errors in all 4 locales.
2026-02-15 04:02:34 -06:00
vicrodh 854088c3de fix(v2): make CoreBridge auth blocking per ADR
- auto_login now fails if V2 CoreBridge auth fails
- runtime_bootstrap now fails if V2 CoreBridge auth fails
- Add V2AuthFailed and V2NotInitialized runtime error variants
- Consistent with login command which was already blocking
2026-02-15 03:54:27 -06:00
vicrodh 8a844612ff feat(v2): migrate audio settings commands to V2
- Add V2 audio settings commands (output device, exclusive mode, DAC
  passthrough, sample rate, backend type, ALSA plugin, gapless,
  normalization, streaming only, quality limiting, etc.)
- Update frontend SettingsView to use V2 audio commands
- Update +page.svelte to use V2 normalization command
2026-02-15 03:52:48 -06:00
vicrodh daf5372c34 feat(v2): migrate logout to v2_logout 2026-02-15 00:46:35 -06:00
vicrodh 846da0270e feat(v2): migrate playlist commands to V2 architecture
- Add playlist methods to QbzCore (get_user_playlists, get_playlist,
  add_tracks_to_playlist, remove_tracks_from_playlist)
- Add playlist methods to CoreBridge
- Create V2 Tauri commands for all playlist operations
- Update frontend to use V2 playlist commands
- Support both playlistTrackIds and trackIds in remove command
  (with automatic resolution like legacy)
2026-02-15 00:41:48 -06:00