mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-22 07:15:47 +00:00
ba670bd1e8
ZIP downloads (PlaylistDetail, Albums, NewReleases, RandomAlbums) now use
invoke('download_zip') via Rust streaming instead of fetch+blob+arrayBuffer,
eliminating JS heap saturation on large files. Progress shown in ZipDownloadOverlay.
Offline cache downloads (600+ songs) no longer freeze the UI: transient job
state moved to a separate non-persisted offlineJobStore, reducing localStorage
writes from ~1200 down to 2 for an entire download. Also adds playlist offline
toggle — clicking the cache button when already cached removes it from cache.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
47 lines
1.3 KiB
TypeScript
47 lines
1.3 KiB
TypeScript
import { create } from 'zustand';
|
|
|
|
export interface DownloadJob {
|
|
trackId: string;
|
|
albumId: string;
|
|
albumName: string;
|
|
trackTitle: string;
|
|
trackIndex: number;
|
|
totalTracks: number;
|
|
status: 'queued' | 'downloading' | 'done' | 'error';
|
|
}
|
|
|
|
interface OfflineJobState {
|
|
jobs: DownloadJob[];
|
|
bulkProgress: Record<string, { done: number; total: number }>;
|
|
cancelDownload: (albumId: string) => void;
|
|
cancelAllDownloads: () => void;
|
|
}
|
|
|
|
// Module-level cancellation set — checked by downloadAlbum before each batch.
|
|
export const cancelledDownloads = new Set<string>();
|
|
|
|
export const useOfflineJobStore = create<OfflineJobState>()((set, get) => ({
|
|
jobs: [],
|
|
bulkProgress: {},
|
|
|
|
cancelDownload: (albumId) => {
|
|
cancelledDownloads.add(albumId);
|
|
// Remove queued (not yet started) jobs immediately so the counter drops.
|
|
set(state => ({
|
|
jobs: state.jobs.filter(j => !(j.albumId === albumId && j.status === 'queued')),
|
|
}));
|
|
},
|
|
|
|
cancelAllDownloads: () => {
|
|
const unique = [...new Set(
|
|
get().jobs
|
|
.filter(j => j.status === 'queued' || j.status === 'downloading')
|
|
.map(j => j.albumId),
|
|
)];
|
|
unique.forEach(id => cancelledDownloads.add(id));
|
|
set(state => ({
|
|
jobs: state.jobs.filter(j => j.status !== 'queued'),
|
|
}));
|
|
},
|
|
}));
|