import { create } from "zustand"; import type { WebGenerationPreviewTask } from "../types"; export type QueueItemStatus = "pending" | "running" | "completed" | "failed" | "cancelled"; export interface GenerationQueueItem { id: string; taskId?: string; title: string; type: "image" | "video" | "agent" | "digital-human" | "character-mix" | "ecommerce-video"; status: QueueItemStatus; progress: number; prompt: string; createdAt: number; sourceView: string; // which page created this: "ecommerce", "workbench", "canvas", "agent" resultUrl?: string | null; error?: string | null; params?: Record; } interface PersistedQueueSnapshot { version: 1; items: GenerationQueueItem[]; savedAt: number; } const STORAGE_KEY = "omniai:generation-queue"; const MAX_ITEMS = 80; const STALE_MS = 2 * 60 * 60 * 1000; // 2 hours function loadPersistedQueue(): GenerationQueueItem[] { try { const raw = localStorage.getItem(STORAGE_KEY); if (!raw) return []; const snapshot = JSON.parse(raw) as PersistedQueueSnapshot; if (Date.now() - (snapshot.savedAt || 0) > STALE_MS) { localStorage.removeItem(STORAGE_KEY); return []; } return snapshot.items.filter( (item) => item.status === "pending" || item.status === "running", ); } catch { return []; } } function persistQueue(items: GenerationQueueItem[]): void { try { const snapshot: PersistedQueueSnapshot = { version: 1, items, savedAt: Date.now() }; localStorage.setItem(STORAGE_KEY, JSON.stringify(snapshot)); } catch { /* quota exceeded */ } } interface GenerationStoreState { queue: GenerationQueueItem[]; addTask: (item: GenerationQueueItem) => void; updateTask: (id: string, patch: Partial) => void; removeTask: (id: string) => void; getRunningTasks: () => GenerationQueueItem[]; getPendingTasks: () => GenerationQueueItem[]; getTasksByView: (sourceView: string) => GenerationQueueItem[]; clearTerminal: () => void; } function hashUserId(): string { try { const raw = localStorage.getItem("omniai-web-session"); if (!raw) return "anon"; const parsed = JSON.parse(raw) as { user?: { id?: number | string } }; return String(parsed?.user?.id || "anon"); } catch { return "anon"; } } const initialQueue = loadPersistedQueue(); export const useGenerationStore = create((set, get) => ({ queue: initialQueue, addTask: (item) => { set((state) => { const next = [item, ...state.queue].slice(0, MAX_ITEMS); persistQueue(next.filter((i) => i.status === "pending" || i.status === "running")); return { queue: next }; }); }, updateTask: (id, patch) => { set((state) => { const next = state.queue.map((item) => item.id === id ? { ...item, ...patch } : item, ); persistQueue(next.filter((i) => i.status === "pending" || i.status === "running")); return { queue: next }; }); }, removeTask: (id) => { set((state) => { const next = state.queue.filter((item) => item.id !== id); persistQueue(next.filter((i) => i.status === "pending" || i.status === "running")); return { queue: next }; }); }, getRunningTasks: () => get().queue.filter((i) => i.status === "running" || i.status === "pending"), getPendingTasks: () => get().queue.filter((i) => i.status === "pending"), getTasksByView: (sourceView) => get().queue.filter((i) => i.sourceView === sourceView), clearTerminal: () => { set((state) => { const next = state.queue.filter( (i) => i.status === "pending" || i.status === "running", ); persistQueue(next); return { queue: next }; }); }, }));