mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 15:25:46 +00:00
refactor(ipc): complete tauri-specta typed-IPC cutover, contract guards, and layering cleanup (#1230)
This commit is contained in:
@@ -12,6 +12,12 @@ import { cancelledDownloads, useOfflineJobStore } from '@/features/offline/store
|
||||
import { useFavoritesOfflineSyncStore } from '@/features/offline/store/favoritesOfflineSyncStore';
|
||||
import { useLocalPlaybackStore } from '@/store/localPlaybackStore';
|
||||
import { getMediaDir } from '@/lib/media/mediaDir';
|
||||
import {
|
||||
cancelOfflineDownloads,
|
||||
clearOfflineCancel,
|
||||
deleteMediaFile,
|
||||
pruneEmptyMediaTierDirs,
|
||||
} from '@/lib/api/syncfs';
|
||||
import { resolveIndexKey, serverIndexKeyForProfile } from '@/lib/server/serverIndexKey';
|
||||
import { FAVORITES_OFFLINE_JOB_ID } from '@/features/offline/utils/favoritesOfflineConstants';
|
||||
import { isActiveServerReachable } from '@/lib/network/activeServerReachability';
|
||||
@@ -49,9 +55,9 @@ function cancelInFlightFavoritesDownloads(): void {
|
||||
cancelledDownloads.add(FAVORITES_OFFLINE_JOB_ID);
|
||||
const downloadIds = rustDownloadIdsForFavoritesJobs();
|
||||
if (downloadIds.length > 0) {
|
||||
invoke('cancel_offline_downloads', { downloadIds }).catch(() => {});
|
||||
cancelOfflineDownloads({ downloadIds }).catch(() => {});
|
||||
for (const id of downloadIds) {
|
||||
invoke('clear_offline_cancel', { downloadId: id }).catch(() => {});
|
||||
clearOfflineCancel({ downloadId: id }).catch(() => {});
|
||||
}
|
||||
}
|
||||
activeFavoritesDownloadId = null;
|
||||
@@ -149,10 +155,10 @@ async function pruneOrphanFavoriteAuto(
|
||||
if (entry.tier !== 'favorite-auto') continue;
|
||||
if (!entryBelongsToServer(entry, serverId)) continue;
|
||||
if (targetIds.has(entry.trackId)) continue;
|
||||
await invoke('delete_media_file', { localPath: entry.localPath, mediaDir }).catch(() => {});
|
||||
await deleteMediaFile({ localPath: entry.localPath, mediaDir }).catch(() => {});
|
||||
lp.removeEntry(entry.trackId, entry.serverIndexKey, 'favorite-unstar-prune');
|
||||
}
|
||||
await invoke('prune_empty_media_tier_dirs', { tier: 'favorite-auto', mediaDir }).catch(() => {});
|
||||
await pruneEmptyMediaTierDirs({ tier: 'favorite-auto', mediaDir }).catch(() => {});
|
||||
}
|
||||
|
||||
export async function disableFavoritesOfflineSync(): Promise<void> {
|
||||
@@ -284,8 +290,8 @@ async function runFavoritesOfflineSyncOneServer(serverId: string, token: number)
|
||||
jobStore.setState(state => ({
|
||||
jobs: state.jobs.filter(j => j.albumId !== FAVORITES_OFFLINE_JOB_ID),
|
||||
}));
|
||||
invoke('cancel_offline_downloads', { downloadIds: [downloadId] }).catch(() => {});
|
||||
invoke('clear_offline_cancel', { downloadId }).catch(() => {});
|
||||
cancelOfflineDownloads({ downloadIds: [downloadId] }).catch(() => {});
|
||||
clearOfflineCancel({ downloadId }).catch(() => {});
|
||||
activeFavoritesDownloadId = null;
|
||||
return;
|
||||
}
|
||||
@@ -329,7 +335,7 @@ async function runFavoritesOfflineSyncOneServer(serverId: string, token: number)
|
||||
|| cancelledDownloads.has(FAVORITES_OFFLINE_JOB_ID)
|
||||
|| !targetIds.has(song.id)
|
||||
) {
|
||||
await invoke('delete_media_file', { localPath: res.path, mediaDir }).catch(() => {});
|
||||
await deleteMediaFile({ localPath: res.path, mediaDir }).catch(() => {});
|
||||
return { song, error: 'CANCELLED' };
|
||||
}
|
||||
useLocalPlaybackStore.getState().upsertEntry({
|
||||
@@ -371,10 +377,10 @@ async function runFavoritesOfflineSyncOneServer(serverId: string, token: number)
|
||||
),
|
||||
}));
|
||||
if (activeFavoritesDownloadId === downloadId) {
|
||||
invoke('clear_offline_cancel', { downloadId }).catch(() => {});
|
||||
clearOfflineCancel({ downloadId }).catch(() => {});
|
||||
activeFavoritesDownloadId = null;
|
||||
}
|
||||
await invoke('prune_empty_media_tier_dirs', { tier: 'favorite-auto', mediaDir }).catch(() => {});
|
||||
await pruneEmptyMediaTierDirs({ tier: 'favorite-auto', mediaDir }).catch(() => {});
|
||||
}
|
||||
} catch (err) {
|
||||
if (token === runToken) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { frontendDebugLog } from '@/lib/api/debugLog';
|
||||
import { libraryGetTracksBatch } from '@/lib/api/library';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
import { useOfflineStore, type OfflineAlbumMeta } from '@/features/offline/store/offlineStore';
|
||||
@@ -6,18 +6,10 @@ import { useLocalPlaybackStore, type LocalPlaybackEntry, type PinSource } from '
|
||||
import { localPlaybackEntryKey } from '@/store/localPlaybackKeys';
|
||||
import { importLegacyLocalPlayback } from '@/store/localPlaybackMigration';
|
||||
import { getMediaDir } from '@/lib/media/mediaDir';
|
||||
import { migrateLegacyOfflineDisk } from '@/lib/api/syncfs';
|
||||
import { resolveServerIdForIndexKey } from '@/lib/server/serverLookup';
|
||||
import { resolveIndexKey } from '@/lib/server/serverIndexKey';
|
||||
|
||||
interface LegacyOfflineMigrationResult {
|
||||
trackId: string;
|
||||
serverIndexKey: string;
|
||||
path: string;
|
||||
size: number;
|
||||
layoutFingerprint: string;
|
||||
relocated: boolean;
|
||||
skippedReason?: string | null;
|
||||
}
|
||||
import type { LegacyOfflineMigrationResult } from '@/generated/bindings';
|
||||
|
||||
type PersistCapableStore = {
|
||||
persist: {
|
||||
@@ -44,10 +36,7 @@ function waitForStoreHydration(store: PersistCapableStore): Promise<void> {
|
||||
|
||||
function migrationDebug(payload: Record<string, unknown>): void {
|
||||
if (useAuthStore.getState().loggingMode !== 'debug') return;
|
||||
void invoke('frontend_debug_log', {
|
||||
scope: 'legacy-offline-migration',
|
||||
message: JSON.stringify(payload),
|
||||
}).catch(() => {});
|
||||
frontendDebugLog('legacy-offline-migration', JSON.stringify(payload));
|
||||
}
|
||||
|
||||
function resolveIndexKeyForServerId(serverId: string): string {
|
||||
@@ -192,7 +181,7 @@ export async function runLegacyOfflineFileMigration(serverIndexKey?: string): Pr
|
||||
const customOfflineDir = useAuthStore.getState().offlineDownloadDir?.trim() || null;
|
||||
let relocated = 0;
|
||||
try {
|
||||
const results = await invoke<LegacyOfflineMigrationResult[]>('migrate_legacy_offline_disk', {
|
||||
const results = await migrateLegacyOfflineDisk({
|
||||
mediaDir: getMediaDir(),
|
||||
customOfflineDir,
|
||||
serverIndexKeyFilter: serverIndexKey ?? null,
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
import { libraryUpsertSongsFromApi } from '@/lib/api/library';
|
||||
import { librarySqlServerId } from '@/lib/api/coverCache';
|
||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
import type { LocalPlaybackEntry, PinSource } from '@/store/localPlaybackStore';
|
||||
import { useLocalPlaybackStore } from '@/store/localPlaybackStore';
|
||||
import { getMediaDir } from '@/lib/media/mediaDir';
|
||||
import { discoverLibraryTierOnDisk, pruneOrphanLibraryTierFiles } from '@/lib/api/syncfs';
|
||||
import { resolveIndexKey, serverIndexKeyForProfile } from '@/lib/server/serverIndexKey';
|
||||
import {
|
||||
entryBelongsToServer,
|
||||
findLocalPlaybackEntry,
|
||||
indexKeyBelongsToServer,
|
||||
} from '@/store/localPlaybackResolve';
|
||||
import type { LibraryTierDiskHit } from '@/generated/bindings';
|
||||
|
||||
interface LibraryTrackProbeResult {
|
||||
path: string;
|
||||
@@ -20,14 +21,6 @@ interface LibraryTrackProbeResult {
|
||||
exists: boolean;
|
||||
}
|
||||
|
||||
interface LibraryTierDiskHit {
|
||||
trackId: string;
|
||||
path: string;
|
||||
size: number;
|
||||
layoutFingerprint: string;
|
||||
suffix: string;
|
||||
}
|
||||
|
||||
export interface LibraryTierReconcileResult {
|
||||
syncedFromDisk: number;
|
||||
removedStaleIndex: number;
|
||||
@@ -93,7 +86,7 @@ async function discoverLibraryTierHits(
|
||||
const serverIndexKey = serverIndexKeyForServerId(serverId);
|
||||
const libraryServerId = librarySqlServerId(serverId);
|
||||
try {
|
||||
return await invoke<LibraryTierDiskHit[]>('discover_library_tier_on_disk', {
|
||||
return await discoverLibraryTierOnDisk({
|
||||
serverIndexKey,
|
||||
libraryServerId,
|
||||
candidateTrackIds,
|
||||
@@ -186,7 +179,7 @@ export async function reconcileLibraryTierForServer(
|
||||
|
||||
let orphansRemoved: number;
|
||||
try {
|
||||
const removed = await invoke<string[]>('prune_orphan_library_tier_files', {
|
||||
const removed = await pruneOrphanLibraryTierFiles({
|
||||
serverIndexKey,
|
||||
keepPaths: [...keepPaths],
|
||||
mediaDir: getMediaDir(),
|
||||
@@ -258,7 +251,7 @@ export async function reconcileLibraryTierForAlbum(
|
||||
|
||||
let orphansRemoved: number;
|
||||
try {
|
||||
const removed = await invoke<string[]>('prune_orphan_library_tier_files', {
|
||||
const removed = await pruneOrphanLibraryTierFiles({
|
||||
serverIndexKey,
|
||||
keepPaths: [...keepPaths],
|
||||
mediaDir: getMediaDir(),
|
||||
|
||||
@@ -3,7 +3,6 @@ import { getAlbumForServer, filterSongsToServerLibrary } from '@/lib/api/subsoni
|
||||
import { getPlaylistForServer } from '@/lib/api/subsonicPlaylists';
|
||||
import { getArtistForServer } from '@/lib/api/subsonicArtists';
|
||||
import type { SubsonicSong } from '@/lib/api/subsonicTypes';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
import type { PinSource } from '@/store/localPlaybackStore';
|
||||
import { useLocalPlaybackStore } from '@/store/localPlaybackStore';
|
||||
@@ -11,6 +10,7 @@ import { useOfflineStore } from '@/features/offline/store/offlineStore';
|
||||
import { usePlaylistStore } from '@/features/playlist';
|
||||
import { isSmartPlaylistName } from '@/lib/format/playlistDetailHelpers';
|
||||
import { getMediaDir } from '@/lib/media/mediaDir';
|
||||
import { deleteMediaFile } from '@/lib/api/syncfs';
|
||||
import {
|
||||
isActiveServerReachable,
|
||||
onActiveServerBecameReachable,
|
||||
@@ -123,7 +123,7 @@ async function pruneRemovedPinTracks(
|
||||
if (!entry?.localPath || entry.tier !== 'library') continue;
|
||||
if (entry.pinSource?.kind !== kind || entry.pinSource.sourceId !== sourceId) continue;
|
||||
|
||||
await invoke('delete_media_file', { localPath: entry.localPath, mediaDir }).catch(() => {});
|
||||
await deleteMediaFile({ localPath: entry.localPath, mediaDir }).catch(() => {});
|
||||
lp.removeEntry(trackId, entry.serverIndexKey, `${kind}-sync-prune`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user