2026-03-22 03:56:44 +08:00
|
|
|
import { create } from "zustand";
|
|
|
|
|
|
|
|
|
|
interface FileState {
|
|
|
|
|
files: File[];
|
|
|
|
|
jobId: string | null;
|
|
|
|
|
processedUrl: string | null;
|
2026-03-22 04:03:30 +08:00
|
|
|
/** Blob URL for the original image (for before/after comparison). */
|
|
|
|
|
originalBlobUrl: string | null;
|
2026-03-22 03:56:44 +08:00
|
|
|
processing: boolean;
|
|
|
|
|
error: string | null;
|
|
|
|
|
originalSize: number | null;
|
|
|
|
|
processedSize: number | null;
|
|
|
|
|
setFiles: (files: File[]) => void;
|
|
|
|
|
setJobId: (id: string) => void;
|
|
|
|
|
setProcessedUrl: (url: string | null) => void;
|
2026-03-22 04:03:30 +08:00
|
|
|
setOriginalBlobUrl: (url: string | null) => void;
|
2026-03-22 03:56:44 +08:00
|
|
|
setProcessing: (v: boolean) => void;
|
|
|
|
|
setError: (e: string | null) => void;
|
|
|
|
|
setSizes: (original: number, processed: number) => void;
|
|
|
|
|
reset: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-22 04:03:30 +08:00
|
|
|
export const useFileStore = create<FileState>((set, get) => ({
|
2026-03-22 03:56:44 +08:00
|
|
|
files: [],
|
|
|
|
|
jobId: null,
|
|
|
|
|
processedUrl: null,
|
2026-03-22 04:03:30 +08:00
|
|
|
originalBlobUrl: null,
|
2026-03-22 03:56:44 +08:00
|
|
|
processing: false,
|
|
|
|
|
error: null,
|
|
|
|
|
originalSize: null,
|
|
|
|
|
processedSize: null,
|
2026-03-22 04:03:30 +08:00
|
|
|
setFiles: (files) => {
|
|
|
|
|
// Revoke old blob URL if any
|
|
|
|
|
const old = get().originalBlobUrl;
|
|
|
|
|
if (old) URL.revokeObjectURL(old);
|
|
|
|
|
// Create a blob URL for the first file for before/after preview
|
|
|
|
|
const blobUrl = files.length > 0 ? URL.createObjectURL(files[0]) : null;
|
|
|
|
|
set({ files, error: null, originalBlobUrl: blobUrl });
|
|
|
|
|
},
|
2026-03-22 03:56:44 +08:00
|
|
|
setJobId: (id) => set({ jobId: id }),
|
|
|
|
|
setProcessedUrl: (url) => set({ processedUrl: url }),
|
2026-03-22 04:03:30 +08:00
|
|
|
setOriginalBlobUrl: (url) => set({ originalBlobUrl: url }),
|
2026-03-22 03:56:44 +08:00
|
|
|
setProcessing: (v) => set({ processing: v }),
|
|
|
|
|
setError: (e) => set({ error: e, processing: false }),
|
|
|
|
|
setSizes: (original, processed) =>
|
|
|
|
|
set({ originalSize: original, processedSize: processed }),
|
2026-03-22 04:03:30 +08:00
|
|
|
reset: () => {
|
|
|
|
|
const old = get().originalBlobUrl;
|
|
|
|
|
if (old) URL.revokeObjectURL(old);
|
2026-03-22 03:56:44 +08:00
|
|
|
set({
|
|
|
|
|
files: [],
|
|
|
|
|
jobId: null,
|
|
|
|
|
processedUrl: null,
|
2026-03-22 04:03:30 +08:00
|
|
|
originalBlobUrl: null,
|
2026-03-22 03:56:44 +08:00
|
|
|
processing: false,
|
|
|
|
|
error: null,
|
|
|
|
|
originalSize: null,
|
|
|
|
|
processedSize: null,
|
2026-03-22 04:03:30 +08:00
|
|
|
});
|
|
|
|
|
},
|
2026-03-22 03:56:44 +08:00
|
|
|
}));
|