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:
vicrodh committed 2026-02-16 18:40:07 -06:00
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
+14
View File
@@ -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)
}
+85
View File
@@ -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,
+18
View File
@@ -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 || [],
+1 -1
View File
@@ -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 = {
+1 -1
View File
@@ -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
+13 -13
View File
@@ -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;
+2 -2
View File
@@ -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,
+2 -2
View File
@@ -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');
}
/**
+1 -1
View File
@@ -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;
+2 -2
View File
@@ -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
+4 -4
View File
@@ -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;
+3 -3
View File
@@ -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,
+6 -7
View File
@@ -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);
}
}
+1 -1
View File
@@ -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) {