fix(v2): complete command migration sweep and musician/blacklist flows
- migrate remaining frontend invokes to V2 names - add missing V2 command registrations and implementations - enforce commands_v2 backend purity (no legacy delegation) - restore blacklist/relationships/musician flows in V2 - align playlist/local-library/settings invoke paths with V2 cx
This commit is contained in:
1 parent
45b98c40d4
commit
37db48ea3d
19 files changed
+1062
-56
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -529,3 +529,17 @@ pub fn clear_favorites_cache(state: tauri::State<FavoritesCacheState>) -> Result
|
||||
let store = guard.as_ref().ok_or("No active session - please log in")?;
|
||||
store.clear_all()
|
||||
}
|
||||
|
||||
/// Check if a track is cached as favorite.
|
||||
#[tauri::command]
|
||||
pub fn is_track_favorite(
|
||||
track_id: i64,
|
||||
state: tauri::State<FavoritesCacheState>,
|
||||
) -> Result<bool, String> {
|
||||
let guard = state
|
||||
.store
|
||||
.lock()
|
||||
.map_err(|_| "Failed to lock favorites cache store".to_string())?;
|
||||
let store = guard.as_ref().ok_or("No active session - please log in")?;
|
||||
store.is_track_favorite(track_id)
|
||||
}
|
||||
@@ -600,6 +600,32 @@ pub fn run() {
|
||||
commands_v2::v2_get_user_info,
|
||||
commands_v2::v2_save_credentials,
|
||||
commands_v2::v2_clear_saved_credentials,
|
||||
// Temporary compatibility commands still invoked by frontend during migration
|
||||
offline_cache::commands::check_album_fully_cached,
|
||||
network::commands::check_network_path,
|
||||
offline::commands::create_pending_playlist,
|
||||
offline::commands::get_pending_playlist_count,
|
||||
offline::commands::queue_scrobble,
|
||||
offline::commands::get_queued_scrobbles,
|
||||
offline::commands::get_queued_scrobble_count,
|
||||
offline::commands::cleanup_sent_scrobbles,
|
||||
library::commands::discogs_has_credentials,
|
||||
library::commands::discogs_search_artwork,
|
||||
library::commands::discogs_download_artwork,
|
||||
library::commands::library_update_folder_settings,
|
||||
library::commands::get_track_by_path,
|
||||
commands::search::get_artist_basic,
|
||||
commands::search::get_artist_detail,
|
||||
commands::search::get_artist_tracks,
|
||||
commands::search::get_artist_albums,
|
||||
commands::search::get_releases_grid,
|
||||
commands::playback::get_pipewire_sinks,
|
||||
commands::playback::get_audio_output_status,
|
||||
flatpak::get_flatpak_help_text,
|
||||
config::legal_settings::get_qobuz_tos_accepted,
|
||||
updates::has_flatpak_welcome_been_shown,
|
||||
lyrics::commands::lyrics_get,
|
||||
config::favorites_cache::is_track_favorite,
|
||||
commands_v2::v2_set_api_locale,
|
||||
commands_v2::v2_set_use_system_titlebar,
|
||||
commands_v2::v2_set_enable_tray,
|
||||
@@ -610,6 +636,7 @@ pub fn run() {
|
||||
commands_v2::v2_set_show_context_icon,
|
||||
commands_v2::v2_get_playback_preferences,
|
||||
commands_v2::v2_get_favorites_preferences,
|
||||
commands_v2::v2_save_favorites_preferences,
|
||||
commands_v2::v2_get_cache_stats,
|
||||
commands_v2::v2_get_available_backends,
|
||||
commands_v2::v2_get_devices_for_backend,
|
||||
@@ -636,6 +663,8 @@ pub fn run() {
|
||||
commands_v2::v2_add_to_artist_blacklist,
|
||||
commands_v2::v2_remove_from_artist_blacklist,
|
||||
commands_v2::v2_set_blacklist_enabled,
|
||||
commands_v2::v2_get_artist_blacklist,
|
||||
commands_v2::v2_get_blacklist_settings,
|
||||
commands_v2::v2_clear_artist_blacklist,
|
||||
commands_v2::v2_plex_open_auth_url,
|
||||
commands_v2::v2_plex_cache_get_sections,
|
||||
@@ -650,6 +679,7 @@ pub fn run() {
|
||||
commands_v2::v2_plex_cache_clear,
|
||||
commands_v2::v2_cast_start_discovery,
|
||||
commands_v2::v2_cast_stop_discovery,
|
||||
commands_v2::v2_cast_get_devices,
|
||||
commands_v2::v2_cast_connect,
|
||||
commands_v2::v2_cast_disconnect,
|
||||
commands_v2::v2_cast_play_track,
|
||||
@@ -660,6 +690,7 @@ pub fn run() {
|
||||
commands_v2::v2_cast_set_volume,
|
||||
commands_v2::v2_dlna_start_discovery,
|
||||
commands_v2::v2_dlna_stop_discovery,
|
||||
commands_v2::v2_dlna_get_devices,
|
||||
commands_v2::v2_dlna_connect,
|
||||
commands_v2::v2_dlna_disconnect,
|
||||
commands_v2::v2_dlna_play_track,
|
||||
@@ -670,6 +701,7 @@ pub fn run() {
|
||||
commands_v2::v2_dlna_set_volume,
|
||||
commands_v2::v2_airplay_start_discovery,
|
||||
commands_v2::v2_airplay_stop_discovery,
|
||||
commands_v2::v2_airplay_get_devices,
|
||||
commands_v2::v2_airplay_connect,
|
||||
commands_v2::v2_airplay_disconnect,
|
||||
commands_v2::v2_airplay_load_media,
|
||||
@@ -682,6 +714,10 @@ pub fn run() {
|
||||
commands_v2::v2_library_check_folder_accessible,
|
||||
commands_v2::v2_library_clear_artwork_cache,
|
||||
commands_v2::v2_library_clear_thumbnails_cache,
|
||||
commands_v2::v2_library_get_thumbnail,
|
||||
commands_v2::v2_library_get_thumbnails_cache_size,
|
||||
commands_v2::v2_library_get_scan_progress,
|
||||
commands_v2::v2_library_get_tracks_by_ids,
|
||||
commands_v2::v2_library_play_track,
|
||||
commands_v2::v2_playlist_set_sort,
|
||||
commands_v2::v2_playlist_set_artwork,
|
||||
@@ -691,6 +727,8 @@ pub fn run() {
|
||||
commands_v2::v2_playlist_get_settings,
|
||||
commands_v2::v2_playlist_get_stats,
|
||||
commands_v2::v2_playlist_increment_play_count,
|
||||
commands_v2::v2_playlist_get_all_stats,
|
||||
commands_v2::v2_playlist_get_all_local_track_counts,
|
||||
commands_v2::v2_playlist_add_local_track,
|
||||
commands_v2::v2_playlist_remove_local_track,
|
||||
commands_v2::v2_playlist_set_hidden,
|
||||
@@ -699,13 +737,20 @@ pub fn run() {
|
||||
commands_v2::v2_playlist_init_custom_order,
|
||||
commands_v2::v2_playlist_set_custom_order,
|
||||
commands_v2::v2_playlist_move_track,
|
||||
commands_v2::v2_playlist_get_custom_order,
|
||||
commands_v2::v2_playlist_has_custom_order,
|
||||
commands_v2::v2_playlist_get_tracks_with_local_copies,
|
||||
commands_v2::v2_library_set_album_artwork,
|
||||
commands_v2::v2_library_set_album_hidden,
|
||||
commands_v2::v2_create_track_radio,
|
||||
commands_v2::v2_delete_playlist_folder,
|
||||
commands_v2::v2_reorder_playlist_folders,
|
||||
commands_v2::v2_move_playlist_to_folder,
|
||||
commands_v2::v2_get_playlist_folders,
|
||||
commands_v2::v2_create_playlist_folder,
|
||||
commands_v2::v2_update_playlist_folder,
|
||||
commands_v2::v2_lyrics_clear_cache,
|
||||
commands_v2::v2_lyrics_get_cache_stats,
|
||||
commands_v2::v2_musicbrainz_get_cache_stats,
|
||||
commands_v2::v2_musicbrainz_clear_cache,
|
||||
commands_v2::v2_set_show_partial_playlists,
|
||||
@@ -713,22 +758,50 @@ pub fn run() {
|
||||
commands_v2::v2_set_allow_immediate_scrobbling,
|
||||
commands_v2::v2_set_allow_accumulated_scrobbling,
|
||||
commands_v2::v2_set_show_network_folders_in_manual_offline,
|
||||
commands_v2::v2_get_offline_status,
|
||||
commands_v2::v2_get_offline_settings,
|
||||
commands_v2::v2_set_manual_offline,
|
||||
commands_v2::v2_check_network,
|
||||
commands_v2::v2_add_tracks_to_pending_playlist,
|
||||
commands_v2::v2_get_pending_playlists,
|
||||
commands_v2::v2_update_pending_playlist_qobuz_id,
|
||||
commands_v2::v2_mark_pending_playlist_synced,
|
||||
commands_v2::v2_delete_pending_playlist,
|
||||
commands_v2::v2_mark_scrobbles_sent,
|
||||
commands_v2::v2_remove_cached_track,
|
||||
commands_v2::v2_get_cached_tracks,
|
||||
commands_v2::v2_get_offline_cache_stats,
|
||||
commands_v2::v2_set_offline_cache_limit,
|
||||
commands_v2::v2_open_offline_cache_folder,
|
||||
commands_v2::v2_open_album_folder,
|
||||
commands_v2::v2_open_track_folder,
|
||||
commands_v2::v2_lastfm_open_auth_url,
|
||||
commands_v2::v2_lastfm_set_credentials,
|
||||
commands_v2::v2_lastfm_has_embedded_credentials,
|
||||
commands_v2::v2_remote_control_get_status,
|
||||
commands_v2::v2_remote_control_set_enabled,
|
||||
commands_v2::v2_remote_control_set_port,
|
||||
commands_v2::v2_remote_control_set_secure,
|
||||
commands_v2::v2_remote_control_regenerate_token,
|
||||
commands_v2::v2_remote_control_get_pairing_qr,
|
||||
commands_v2::v2_is_running_in_flatpak,
|
||||
commands_v2::v2_detect_legacy_cached_files,
|
||||
commands_v2::v2_reco_log_event,
|
||||
commands_v2::v2_reco_train_scores,
|
||||
commands_v2::v2_reco_get_home,
|
||||
commands_v2::v2_reco_get_home_ml,
|
||||
commands_v2::v2_reco_get_home_resolved,
|
||||
commands_v2::v2_library_get_cache_stats,
|
||||
commands_v2::v2_library_get_stats,
|
||||
commands_v2::v2_library_get_albums,
|
||||
commands_v2::v2_library_get_folders,
|
||||
commands_v2::v2_library_get_folders_with_metadata,
|
||||
commands_v2::v2_library_add_folder,
|
||||
commands_v2::v2_library_cleanup_missing_files,
|
||||
commands_v2::v2_library_fetch_missing_artwork,
|
||||
commands_v2::v2_library_get_artists,
|
||||
commands_v2::v2_library_search,
|
||||
commands_v2::v2_library_get_album_tracks,
|
||||
commands_v2::v2_library_update_folder_path,
|
||||
commands_v2::v2_library_cache_artist_image,
|
||||
commands_v2::v2_library_set_custom_artist_image,
|
||||
@@ -745,15 +818,22 @@ pub fn run() {
|
||||
commands_v2::v2_library_refresh_album_metadata_from_files,
|
||||
commands_v2::v2_factory_reset,
|
||||
commands_v2::v2_set_qobuz_tos_accepted,
|
||||
commands_v2::v2_get_update_preferences,
|
||||
commands_v2::v2_get_current_version,
|
||||
commands_v2::v2_check_for_updates,
|
||||
commands_v2::v2_fetch_release_for_version,
|
||||
commands_v2::v2_set_update_check_on_launch,
|
||||
commands_v2::v2_set_show_whats_new_on_launch,
|
||||
commands_v2::v2_acknowledge_release,
|
||||
commands_v2::v2_ignore_release,
|
||||
commands_v2::v2_has_whats_new_been_shown,
|
||||
commands_v2::v2_mark_whats_new_shown,
|
||||
commands_v2::v2_mark_flatpak_welcome_shown,
|
||||
commands_v2::v2_get_backend_logs,
|
||||
commands_v2::v2_upload_logs_to_paste,
|
||||
commands_v2::v2_get_download_settings,
|
||||
commands_v2::v2_set_show_downloads_in_library,
|
||||
commands_v2::v2_get_device_sample_rate_limit,
|
||||
commands_v2::v2_set_device_sample_rate_limit,
|
||||
commands_v2::v2_set_force_x11,
|
||||
commands_v2::v2_restart_app,
|
||||
@@ -776,6 +856,7 @@ pub fn run() {
|
||||
commands_v2::v2_search_albums,
|
||||
commands_v2::v2_search_tracks,
|
||||
commands_v2::v2_search_artists,
|
||||
commands_v2::v2_search_all,
|
||||
commands_v2::v2_get_album,
|
||||
commands_v2::v2_get_track,
|
||||
commands_v2::v2_get_artist,
|
||||
@@ -784,6 +865,7 @@ pub fn run() {
|
||||
commands_v2::v2_remove_favorite,
|
||||
commands_v2::v2_get_user_playlists,
|
||||
commands_v2::v2_get_playlist,
|
||||
commands_v2::v2_get_playlist_track_ids,
|
||||
commands_v2::v2_add_tracks_to_playlist,
|
||||
commands_v2::v2_remove_tracks_from_playlist,
|
||||
commands_v2::v2_create_playlist,
|
||||
@@ -840,6 +922,9 @@ pub fn run() {
|
||||
commands_v2::v2_musicbrainz_set_enabled,
|
||||
commands_v2::v2_musicbrainz_resolve_track,
|
||||
commands_v2::v2_musicbrainz_resolve_artist,
|
||||
commands_v2::v2_resolve_musician,
|
||||
commands_v2::v2_get_musician_appearances,
|
||||
commands_v2::v2_musicbrainz_get_artist_relationships,
|
||||
commands_v2::v2_lastfm_get_auth_url,
|
||||
commands_v2::v2_lastfm_complete_auth,
|
||||
commands_v2::v2_lastfm_is_authenticated,
|
||||
|
||||
@@ -55,10 +55,28 @@ pub mod thumbnails {
|
||||
pub use commands::LibraryState;
|
||||
pub use commands::{
|
||||
LibraryAlbumMetadataUpdateRequest,
|
||||
CleanupResult,
|
||||
library_add_folder,
|
||||
library_cleanup_missing_files,
|
||||
library_fetch_missing_artwork,
|
||||
library_get_album_tracks,
|
||||
library_get_artists,
|
||||
library_get_folders,
|
||||
library_get_folders_with_metadata,
|
||||
library_scan_impl,
|
||||
library_get_scan_progress,
|
||||
library_get_stats,
|
||||
library_get_thumbnail,
|
||||
library_get_thumbnails_cache_size,
|
||||
library_get_tracks_by_ids,
|
||||
library_search,
|
||||
library_stop_scan_impl,
|
||||
library_scan_folder_impl,
|
||||
library_clear_impl,
|
||||
playlist_get_custom_order,
|
||||
playlist_get_tracks_with_local_copies,
|
||||
playlist_has_custom_order,
|
||||
update_playlist_folder,
|
||||
library_update_album_metadata_impl,
|
||||
library_write_album_metadata_to_files_impl,
|
||||
library_refresh_album_metadata_from_files_impl,
|
||||
|
||||
@@ -690,7 +690,7 @@
|
||||
mbid?: string;
|
||||
name?: string;
|
||||
confidence: string;
|
||||
}>('musicbrainz_resolve_artist', { name: artist.name });
|
||||
}>('v2_musicbrainz_resolve_artist', { name: artist.name });
|
||||
|
||||
if (!resolved?.mbid || resolved.confidence === 'none') {
|
||||
mbRelationshipsLoading = false;
|
||||
@@ -705,7 +705,7 @@
|
||||
past_members: RelatedArtist[];
|
||||
groups: RelatedArtist[];
|
||||
collaborators: RelatedArtist[];
|
||||
}>('musicbrainz_get_artist_relationships', { mbid: resolved.mbid });
|
||||
}>('v2_musicbrainz_get_artist_relationships', { mbid: resolved.mbid });
|
||||
|
||||
mbRelationships = {
|
||||
members: relationships.members || [],
|
||||
|
||||
@@ -793,7 +793,7 @@
|
||||
const discoverPromise = fetchAllDiscoverData(genreIds);
|
||||
|
||||
// Single IPC call returns fully-resolved card data (3-tier cache in Rust)
|
||||
const mlPromise = invoke<HomeResolved>('reco_get_home_resolved', {
|
||||
const mlPromise = invoke<HomeResolved>('v2_reco_get_home_resolved', {
|
||||
limitRecentAlbums: homeLimits.recentAlbums,
|
||||
limitContinueTracks: homeLimits.continueTracks,
|
||||
limitTopArtists: homeLimits.topArtists,
|
||||
|
||||
@@ -1289,7 +1289,7 @@
|
||||
includeHidden: false,
|
||||
excludeNetworkFolders: excludeNetwork
|
||||
}),
|
||||
invoke<LibraryStats>('library_get_stats'),
|
||||
invoke<LibraryStats>('v2_library_get_stats'),
|
||||
includePlex
|
||||
? invoke<PlexCachedAlbum[]>('v2_plex_cache_get_albums').catch(() => [])
|
||||
: Promise.resolve([])
|
||||
@@ -1354,7 +1354,7 @@
|
||||
if (isOffline) {
|
||||
// When offline, get folders without calling is_network_path (blocks offline)
|
||||
// Use basic folder list command instead
|
||||
folders = await invoke<LibraryFolder[]>('library_get_folders');
|
||||
folders = await invoke<LibraryFolder[]>('v2_library_get_folders_with_metadata');
|
||||
console.log('[LocalLibrary] Received folders (offline mode):', folders.length);
|
||||
|
||||
// Mark all network folders as inaccessible, local folders as accessible
|
||||
@@ -1367,7 +1367,7 @@
|
||||
const timeoutPromise = new Promise<LibraryFolder[]>((_, reject) =>
|
||||
setTimeout(() => reject(new Error('Folder loading timeout')), 5000)
|
||||
);
|
||||
const foldersPromise = invoke<LibraryFolder[]>('library_get_folders_with_metadata');
|
||||
const foldersPromise = invoke<LibraryFolder[]>('v2_library_get_folders_with_metadata');
|
||||
|
||||
folders = await Promise.race([foldersPromise, timeoutPromise]);
|
||||
console.log('[LocalLibrary] Received folders (online mode):', folders.length);
|
||||
@@ -1407,7 +1407,7 @@
|
||||
console.log('[LocalLibrary] Calling library_get_artists + plex_cache_get_albums');
|
||||
const includePlex = isPlexLibraryEnabled();
|
||||
const [localArtists, plexAlbumsRaw] = await Promise.all([
|
||||
invoke<LocalArtist[]>('library_get_artists', {
|
||||
invoke<LocalArtist[]>('v2_library_get_artists', {
|
||||
excludeNetworkFolders: shouldExcludeNetworkFolders()
|
||||
}),
|
||||
includePlex
|
||||
@@ -1469,7 +1469,7 @@
|
||||
console.log('[LocalLibrary] Calling library_search + plex_cache_search_tracks');
|
||||
const includePlex = isPlexLibraryEnabled();
|
||||
const [localTracks, plexTracksRaw] = await Promise.all([
|
||||
invoke<LocalTrack[]>('library_search', {
|
||||
invoke<LocalTrack[]>('v2_library_search', {
|
||||
query,
|
||||
limit: 0, // 0 = no limit, virtualization handles any list size
|
||||
excludeNetworkFolders: shouldExcludeNetworkFolders()
|
||||
@@ -1534,7 +1534,7 @@
|
||||
|
||||
if (!selected || typeof selected !== 'string') return;
|
||||
|
||||
const newFolder = await invoke<LibraryFolder>('library_add_folder', { path: selected });
|
||||
const newFolder = await invoke<LibraryFolder>('v2_library_add_folder', { path: selected });
|
||||
await loadFolders();
|
||||
|
||||
// Show warning if network folder detected
|
||||
@@ -1694,7 +1694,7 @@
|
||||
cleaningUpMissingFiles = true;
|
||||
cleanupStatus = 'Scanning track paths...';
|
||||
try {
|
||||
const result = await invoke<{ checked: number; removed: number }>('library_cleanup_missing_files');
|
||||
const result = await invoke<{ checked: number; removed: number }>('v2_library_cleanup_missing_files');
|
||||
|
||||
if (result.removed > 0) {
|
||||
cleanupStatus = `Removed ${result.removed} of ${result.checked} tracks`;
|
||||
@@ -1783,7 +1783,7 @@
|
||||
|
||||
fetchingArtwork = true;
|
||||
try {
|
||||
const count = await invoke<number>('library_fetch_missing_artwork');
|
||||
const count = await invoke<number>('v2_library_fetch_missing_artwork');
|
||||
if (count > 0) {
|
||||
alert(`Fetched artwork for ${count} albums from Discogs.`);
|
||||
await loadLibraryData();
|
||||
@@ -1972,7 +1972,7 @@
|
||||
return await hydratePlexTrackQuality(mappedTracks);
|
||||
}
|
||||
|
||||
return await invoke<LocalTrack[]>('library_get_album_tracks', {
|
||||
return await invoke<LocalTrack[]>('v2_library_get_album_tracks', {
|
||||
albumGroupKey: album.id
|
||||
});
|
||||
} catch (err) {
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
error = null;
|
||||
|
||||
try {
|
||||
const result = await invoke<MusicianAppearances>('get_musician_appearances', {
|
||||
const result = await invoke<MusicianAppearances>('v2_get_musician_appearances', {
|
||||
name: musician.name,
|
||||
role: musician.role,
|
||||
limit: ITEMS_PER_PAGE,
|
||||
@@ -71,7 +71,7 @@
|
||||
isLoadingMore = true;
|
||||
|
||||
try {
|
||||
const result = await invoke<MusicianAppearances>('get_musician_appearances', {
|
||||
const result = await invoke<MusicianAppearances>('v2_get_musician_appearances', {
|
||||
name: musician.name,
|
||||
role: musician.role,
|
||||
limit: ITEMS_PER_PAGE,
|
||||
|
||||
@@ -602,7 +602,7 @@
|
||||
|
||||
if (pending.trackIds.length > 0) {
|
||||
try {
|
||||
const qobuzTracks = await invoke<PlaylistTrack[]>('get_tracks_by_ids', {
|
||||
const qobuzTracks = await invoke<PlaylistTrack[]>('v2_get_tracks_batch', {
|
||||
trackIds: pending.trackIds
|
||||
});
|
||||
tracks = qobuzTracks.map((track, idx) => mapPlaylistTrack(track, idx));
|
||||
@@ -619,9 +619,9 @@
|
||||
// === Regular playlist — decide strategy based on track count ===
|
||||
|
||||
// Phase 1: lightweight metadata + track IDs (always fast)
|
||||
console.log(`[Perf] invoke get_playlist_track_ids START (+${(performance.now() - _t0).toFixed(1)}ms)`);
|
||||
const meta = await invoke<PlaylistWithTrackIds>('get_playlist_track_ids', { playlistId });
|
||||
console.log(`[Perf] invoke get_playlist_track_ids DONE (+${(performance.now() - _t0).toFixed(1)}ms) — ${meta.track_ids.length} IDs`);
|
||||
console.log(`[Perf] invoke v2_get_playlist_track_ids START (+${(performance.now() - _t0).toFixed(1)}ms)`);
|
||||
const meta = await invoke<PlaylistWithTrackIds>('v2_get_playlist_track_ids', { playlistId });
|
||||
console.log(`[Perf] invoke v2_get_playlist_track_ids DONE (+${(performance.now() - _t0).toFixed(1)}ms) — ${meta.track_ids.length} IDs`);
|
||||
|
||||
// Set playlist metadata immediately
|
||||
playlist = {
|
||||
|
||||
@@ -492,7 +492,7 @@
|
||||
// Search based on active tab - reset to first page
|
||||
if (activeTab === 'all') {
|
||||
// Use title case for better most_popular results from Qobuz API
|
||||
const results = await invoke<SearchAllResults<Album, Track, Artist>>('search_all', {
|
||||
const results = await invoke<SearchAllResults<Album, Track, Artist>>('v2_search_all', {
|
||||
query: toTitleCase(searchQuery)
|
||||
});
|
||||
// Only apply if query hasn't changed while we were fetching
|
||||
|
||||
@@ -1000,7 +1000,7 @@
|
||||
async function loadLastfmState() {
|
||||
try {
|
||||
// Check if embedded (build-time) credentials are available
|
||||
hasEmbeddedCredentials = await invoke<boolean>('lastfm_has_embedded_credentials');
|
||||
hasEmbeddedCredentials = await invoke<boolean>('v2_lastfm_has_embedded_credentials');
|
||||
|
||||
// Load saved credentials from localStorage (for user-provided keys)
|
||||
const savedApiKey = getUserItem('qbz-lastfm-api-key');
|
||||
@@ -1647,7 +1647,7 @@
|
||||
|
||||
async function loadRemoteControlStatus() {
|
||||
try {
|
||||
const status = await invoke<RemoteControlStatus>('remote_control_get_status');
|
||||
const status = await invoke<RemoteControlStatus>('v2_remote_control_get_status');
|
||||
remoteControlStatus = status;
|
||||
remoteControlEnabled = status.enabled;
|
||||
remoteControlPort = status.port;
|
||||
@@ -1663,7 +1663,7 @@
|
||||
async function handleRemoteControlToggle(enabled: boolean) {
|
||||
remoteControlLoading = true;
|
||||
try {
|
||||
const status = await invoke<RemoteControlStatus>('remote_control_set_enabled', { enabled });
|
||||
const status = await invoke<RemoteControlStatus>('v2_remote_control_set_enabled', { enabled });
|
||||
remoteControlStatus = status;
|
||||
remoteControlEnabled = status.enabled;
|
||||
remoteControlPort = status.port;
|
||||
@@ -1685,7 +1685,7 @@
|
||||
if (!Number.isFinite(value)) return;
|
||||
remoteControlLoading = true;
|
||||
try {
|
||||
const status = await invoke<RemoteControlStatus>('remote_control_set_port', { port: value });
|
||||
const status = await invoke<RemoteControlStatus>('v2_remote_control_set_port', { port: value });
|
||||
remoteControlStatus = status;
|
||||
remoteControlEnabled = status.enabled;
|
||||
remoteControlPort = status.port;
|
||||
@@ -1710,7 +1710,7 @@
|
||||
}
|
||||
remoteControlLoading = true;
|
||||
try {
|
||||
const qr = await invoke<RemoteControlQr>('remote_control_get_pairing_qr');
|
||||
const qr = await invoke<RemoteControlQr>('v2_remote_control_get_pairing_qr');
|
||||
remoteControlQrData = qr.qrDataUrl;
|
||||
remoteControlUrl = qr.url;
|
||||
remoteControlQrOpen = true;
|
||||
@@ -1736,11 +1736,11 @@
|
||||
|
||||
remoteControlLoading = true;
|
||||
try {
|
||||
const qr = await invoke<RemoteControlQr>('remote_control_regenerate_token');
|
||||
const qr = await invoke<RemoteControlQr>('v2_remote_control_regenerate_token');
|
||||
remoteControlQrData = qr.qrDataUrl;
|
||||
remoteControlUrl = qr.url;
|
||||
remoteControlQrOpen = true;
|
||||
const status = await invoke<RemoteControlStatus>('remote_control_get_status');
|
||||
const status = await invoke<RemoteControlStatus>('v2_remote_control_get_status');
|
||||
remoteControlStatus = status;
|
||||
remoteControlEnabled = status.enabled;
|
||||
remoteControlPort = status.port;
|
||||
@@ -1777,7 +1777,7 @@
|
||||
async function handleRemoteControlSecureChange(secure: boolean) {
|
||||
remoteControlLoading = true;
|
||||
try {
|
||||
const status = await invoke<RemoteControlStatus>('remote_control_set_secure', { secure });
|
||||
const status = await invoke<RemoteControlStatus>('v2_remote_control_set_secure', { secure });
|
||||
remoteControlStatus = status;
|
||||
remoteControlEnabled = status.enabled;
|
||||
remoteControlPort = status.port;
|
||||
@@ -2068,7 +2068,7 @@
|
||||
|
||||
async function loadFlatpakStatus() {
|
||||
try {
|
||||
isFlatpak = await invoke<boolean>('is_running_in_flatpak');
|
||||
isFlatpak = await invoke<boolean>('v2_is_running_in_flatpak');
|
||||
if (isFlatpak) {
|
||||
flatpakHelpText = await invoke<string>('get_flatpak_help_text');
|
||||
}
|
||||
@@ -2378,7 +2378,7 @@
|
||||
|
||||
async function loadDeviceSampleRateLimit(deviceId: string) {
|
||||
try {
|
||||
const rate = await invoke<number | null>('get_device_sample_rate_limit', { deviceId });
|
||||
const rate = await invoke<number | null>('v2_get_device_sample_rate_limit', { deviceId });
|
||||
deviceMaxSampleRate = rate;
|
||||
console.log('[Audio] Loaded sample rate limit for', deviceId, ':', rate);
|
||||
} catch (err) {
|
||||
@@ -2453,7 +2453,7 @@
|
||||
|
||||
async function loadLyricsCacheStats() {
|
||||
try {
|
||||
const stats = await invoke<{ entries: number; sizeBytes: number }>('lyrics_get_cache_stats');
|
||||
const stats = await invoke<{ entries: number; sizeBytes: number }>('v2_lyrics_get_cache_stats');
|
||||
lyricsCacheStats = stats;
|
||||
} catch (err) {
|
||||
console.error('Failed to load lyrics cache stats:', err);
|
||||
@@ -2471,7 +2471,7 @@
|
||||
|
||||
async function loadDownloadSettings() {
|
||||
try {
|
||||
const settings = await invoke<{download_root: string, show_in_library: boolean}>('get_download_settings');
|
||||
const settings = await invoke<{download_root: string, show_in_library: boolean}>('v2_get_download_settings');
|
||||
showQobuzDownloadsInLibrary = settings.show_in_library;
|
||||
} catch (err) {
|
||||
console.error('Failed to load download settings:', err);
|
||||
@@ -2566,7 +2566,7 @@
|
||||
|
||||
async function checkLegacyCachedFiles() {
|
||||
try {
|
||||
const result = await invoke<{has_legacy_files: boolean, total_tracks: number}>('detect_legacy_cached_files');
|
||||
const result = await invoke<{has_legacy_files: boolean, total_tracks: number}>('v2_detect_legacy_cached_files');
|
||||
if (result.has_legacy_files && result.total_tracks > 0) {
|
||||
legacyTracksCount = result.total_tracks;
|
||||
showMigrationModal = true;
|
||||
|
||||
@@ -58,7 +58,7 @@ export async function getHomeSeeds(limits?: {
|
||||
topArtists?: number;
|
||||
favorites?: number;
|
||||
}): Promise<HomeSeeds> {
|
||||
return invoke<HomeSeeds>('reco_get_home', {
|
||||
return invoke<HomeSeeds>('v2_reco_get_home', {
|
||||
limitRecentAlbums: limits?.recentAlbums,
|
||||
limitContinueTracks: limits?.continueTracks,
|
||||
limitTopArtists: limits?.topArtists,
|
||||
@@ -86,7 +86,7 @@ export async function getHomeSeedsML(limits?: {
|
||||
topArtists?: number;
|
||||
favorites?: number;
|
||||
}): Promise<HomeSeeds> {
|
||||
return invoke<HomeSeeds>('reco_get_home_ml', {
|
||||
return invoke<HomeSeeds>('v2_reco_get_home_ml', {
|
||||
limitRecentAlbums: limits?.recentAlbums,
|
||||
limitContinueTracks: limits?.continueTracks,
|
||||
limitTopArtists: limits?.topArtists,
|
||||
|
||||
@@ -25,7 +25,7 @@ export async function getThumbnailUrl(artworkPath: string): Promise<string> {
|
||||
const requestPromise = (async () => {
|
||||
try {
|
||||
// Call backend to get/generate thumbnail
|
||||
const thumbnailPath = await invoke<string>('library_get_thumbnail', {
|
||||
const thumbnailPath = await invoke<string>('v2_library_get_thumbnail', {
|
||||
artworkPath,
|
||||
});
|
||||
|
||||
@@ -87,7 +87,7 @@ export async function clearAllThumbnails(): Promise<void> {
|
||||
* Get the size of the thumbnails cache in bytes.
|
||||
*/
|
||||
export async function getThumbnailsCacheSize(): Promise<number> {
|
||||
return invoke<number>('library_get_thumbnails_cache_size');
|
||||
return invoke<number>('v2_library_get_thumbnails_cache_size');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -140,7 +140,7 @@ export interface LaunchUpdateDecision {
|
||||
*/
|
||||
async function shouldShowFlatpakWelcome(): Promise<boolean> {
|
||||
try {
|
||||
const isFlatpak = await invoke<boolean>('is_running_in_flatpak');
|
||||
const isFlatpak = await invoke<boolean>('v2_is_running_in_flatpak');
|
||||
if (!isFlatpak) return false;
|
||||
const alreadyShown = await invoke<boolean>('has_flatpak_welcome_been_shown');
|
||||
return !alreadyShown;
|
||||
|
||||
@@ -81,7 +81,7 @@ function notifyListeners(): void {
|
||||
// Initialize offline cache states from backend
|
||||
export async function initOfflineCacheStates(): Promise<void> {
|
||||
try {
|
||||
const tracks = await invoke<CachedTrackInfo[]>('get_cached_tracks');
|
||||
const tracks = await invoke<CachedTrackInfo[]>('v2_get_cached_tracks');
|
||||
for (const track of tracks) {
|
||||
offlineCacheStates.set(track.trackId, {
|
||||
status: track.status,
|
||||
@@ -203,7 +203,7 @@ export async function removeCachedTrack(trackId: number): Promise<void> {
|
||||
|
||||
// Get offline cache stats
|
||||
export async function getOfflineCacheStats(): Promise<OfflineCacheStats> {
|
||||
return invoke<OfflineCacheStats>('get_offline_cache_stats');
|
||||
return invoke<OfflineCacheStats>('v2_get_offline_cache_stats');
|
||||
}
|
||||
|
||||
// Clear all offline cache
|
||||
|
||||
@@ -115,7 +115,7 @@ export function getOfflineReason(): OfflineReason | null {
|
||||
async function fetchStatus(): Promise<void> {
|
||||
try {
|
||||
const wasOffline = status.isOffline;
|
||||
const newStatus = await invoke<OfflineStatus>('get_offline_status');
|
||||
const newStatus = await invoke<OfflineStatus>('v2_get_offline_status');
|
||||
const changed = JSON.stringify(status) !== JSON.stringify(newStatus);
|
||||
status = newStatus;
|
||||
if (changed) {
|
||||
@@ -149,7 +149,7 @@ async function fetchStatus(): Promise<void> {
|
||||
*/
|
||||
async function fetchSettings(): Promise<void> {
|
||||
try {
|
||||
settings = await invoke<OfflineSettings>('get_offline_settings');
|
||||
settings = await invoke<OfflineSettings>('v2_get_offline_settings');
|
||||
notifyListeners();
|
||||
} catch (error) {
|
||||
const msg = String(error);
|
||||
@@ -166,7 +166,7 @@ async function fetchSettings(): Promise<void> {
|
||||
*/
|
||||
export async function checkNetwork(): Promise<boolean> {
|
||||
try {
|
||||
return await invoke<boolean>('check_network');
|
||||
return await invoke<boolean>('v2_check_network');
|
||||
} catch (error) {
|
||||
console.error('Failed to check network:', error);
|
||||
return false;
|
||||
@@ -184,7 +184,7 @@ export async function setManualOffline(enabled: boolean): Promise<void> {
|
||||
console.log('[Offline] wasOffline:', wasOffline);
|
||||
console.log('[Offline] ========================================');
|
||||
|
||||
const newStatus = await invoke<OfflineStatus>('set_manual_offline', { enabled });
|
||||
const newStatus = await invoke<OfflineStatus>('v2_set_manual_offline', { enabled });
|
||||
status = newStatus;
|
||||
settings.manualOfflineMode = enabled;
|
||||
|
||||
|
||||
@@ -139,7 +139,7 @@ export async function loadFolders(): Promise<void> {
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
const result = await invoke<PlaylistFolder[]>('get_playlist_folders');
|
||||
const result = await invoke<PlaylistFolder[]>('v2_get_playlist_folders');
|
||||
folders = result;
|
||||
lastError = null;
|
||||
} catch (err) {
|
||||
@@ -161,7 +161,7 @@ export async function createFolder(
|
||||
iconColor?: string
|
||||
): Promise<PlaylistFolder | null> {
|
||||
try {
|
||||
const folder = await invoke<PlaylistFolder>('create_playlist_folder', {
|
||||
const folder = await invoke<PlaylistFolder>('v2_create_playlist_folder', {
|
||||
name,
|
||||
iconType,
|
||||
iconPreset,
|
||||
@@ -193,7 +193,7 @@ export async function updateFolder(
|
||||
}
|
||||
): Promise<PlaylistFolder | null> {
|
||||
try {
|
||||
const folder = await invoke<PlaylistFolder>('update_playlist_folder', {
|
||||
const folder = await invoke<PlaylistFolder>('v2_update_playlist_folder', {
|
||||
id,
|
||||
name: updates.name,
|
||||
iconType: updates.iconType,
|
||||
|
||||
@@ -67,7 +67,7 @@ export async function initUpdatesStore(): Promise<void> {
|
||||
// Only fetch once.
|
||||
if (!versionLoaded) {
|
||||
try {
|
||||
currentVersion = await invoke<string>('get_current_version');
|
||||
currentVersion = await invoke<string>('v2_get_current_version');
|
||||
versionLoaded = true;
|
||||
} catch (error) {
|
||||
console.error('[Updates] Failed to get current version:', error);
|
||||
@@ -79,7 +79,7 @@ export async function initUpdatesStore(): Promise<void> {
|
||||
// so a pre-login failure doesn't lock in stale defaults.
|
||||
if (!prefsLoaded) {
|
||||
try {
|
||||
preferences = await invoke<UpdatePreferences>('get_update_preferences');
|
||||
preferences = await invoke<UpdatePreferences>('v2_get_update_preferences');
|
||||
prefsLoaded = true;
|
||||
} catch {
|
||||
// Expected before login — store not initialised yet.
|
||||
@@ -91,7 +91,7 @@ export async function initUpdatesStore(): Promise<void> {
|
||||
|
||||
export async function refreshUpdatePreferences(): Promise<void> {
|
||||
try {
|
||||
preferences = await invoke<UpdatePreferences>('get_update_preferences');
|
||||
preferences = await invoke<UpdatePreferences>('v2_get_update_preferences');
|
||||
notify();
|
||||
} catch (error) {
|
||||
console.debug('[Updates] Failed to refresh update preferences:', error);
|
||||
@@ -121,7 +121,7 @@ export async function setShowWhatsNewOnLaunch(enabled: boolean): Promise<void> {
|
||||
}
|
||||
|
||||
export async function checkForUpdates(mode: 'launch' | 'manual'): Promise<UpdateCheckResult> {
|
||||
const result = await invoke<UpdateCheckResult>('check_for_updates', { mode });
|
||||
const result = await invoke<UpdateCheckResult>('v2_check_for_updates', { mode });
|
||||
return {
|
||||
...result,
|
||||
release: result.release ?? null,
|
||||
@@ -130,7 +130,7 @@ export async function checkForUpdates(mode: 'launch' | 'manual'): Promise<Update
|
||||
|
||||
export async function fetchReleaseForVersion(version: string): Promise<ReleaseInfo | null> {
|
||||
try {
|
||||
const release = await invoke<ReleaseInfo | null>('fetch_release_for_version', { version });
|
||||
const release = await invoke<ReleaseInfo | null>('v2_fetch_release_for_version', { version });
|
||||
return release ?? null;
|
||||
} catch (error) {
|
||||
console.debug('[Updates] Failed to fetch release for version:', version, error);
|
||||
@@ -148,7 +148,7 @@ export async function ignoreRelease(version: string): Promise<void> {
|
||||
|
||||
export async function hasWhatsNewBeenShown(version: string): Promise<boolean> {
|
||||
try {
|
||||
return await invoke<boolean>('has_whats_new_been_shown', { version });
|
||||
return await invoke<boolean>('v2_has_whats_new_been_shown', { version });
|
||||
} catch (error) {
|
||||
console.debug('[Updates] Failed to check whats_new_shown:', version, error);
|
||||
return false;
|
||||
@@ -162,4 +162,3 @@ export async function markWhatsNewShown(version: string): Promise<void> {
|
||||
console.debug('[Updates] Failed to mark whats_new_shown:', version, error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -751,7 +751,7 @@
|
||||
async function handleMusicianClick(name: string, role: string) {
|
||||
showToast($t('toast.lookingUp', { values: { name } }), 'info');
|
||||
try {
|
||||
const musician = await invoke<ResolvedMusician>('resolve_musician', { name, role });
|
||||
const musician = await invoke<ResolvedMusician>('v2_resolve_musician', { name, role });
|
||||
console.log('Resolved musician:', musician);
|
||||
|
||||
switch (musician.confidence) {
|
||||
|
||||
Reference in new issue
Block a user