Files
Psychotoxical-psysonic/src/store/zipDownloadStore.ts
T
Psychotoxical ba670bd1e8 feat: fix UI freezes in ZIP and offline cache downloads
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>
2026-04-08 22:33:23 +02:00

47 lines
1.3 KiB
TypeScript

import { create } from 'zustand';
export interface ZipDownload {
id: string;
filename: string;
bytes: number;
/** null = Content-Length unbekannt (Navidrome on-the-fly ZIP) */
total: number | null;
done: boolean;
error: boolean;
}
interface ZipDownloadState {
downloads: ZipDownload[];
start: (id: string, filename: string) => void;
updateProgress: (id: string, bytes: number, total: number | null) => void;
complete: (id: string) => void;
fail: (id: string) => void;
dismiss: (id: string) => void;
}
export const useZipDownloadStore = create<ZipDownloadState>((set) => ({
downloads: [],
start: (id, filename) => set(state => ({
downloads: [...state.downloads, { id, filename, bytes: 0, total: null, done: false, error: false }],
})),
updateProgress: (id, bytes, total) => set(state => ({
downloads: state.downloads.map(d =>
d.id === id ? { ...d, bytes, total: total ?? d.total } : d
),
})),
complete: (id) => set(state => ({
downloads: state.downloads.map(d => d.id === id ? { ...d, done: true } : d),
})),
fail: (id) => set(state => ({
downloads: state.downloads.map(d => d.id === id ? { ...d, error: true } : d),
})),
dismiss: (id) => set(state => ({
downloads: state.downloads.filter(d => d.id !== id),
})),
}));