import { useEffect, useMemo, useRef, useCallback } from "react"; import type { GenerationQueueItem } from "../stores/useGenerationStore"; import { useGenerationStore } from "../stores/useGenerationStore"; import { startBackgroundPolling, subscribeToTaskUpdates, } from "../services/backgroundTaskRunner"; interface UseGenerationTasksOptions { sourceView: string; autoResume?: boolean; } export function useGenerationTasks(options: UseGenerationTasksOptions) { const { sourceView, autoResume = true } = options; const store = useGenerationStore(); const pollingStartedRef = useRef(false); // ── Auto-resume: re-subscribe to running tasks on mount ──── useEffect(() => { if (!autoResume || pollingStartedRef.current) return; pollingStartedRef.current = true; const active = store.getRunningTasks().filter((t) => t.sourceView === sourceView); if (active.length > 0) { startBackgroundPolling(); } return () => { pollingStartedRef.current = false; }; }, [autoResume, sourceView, store]); // ── Subscribe to live updates ─────────────────────────── useEffect(() => { return subscribeToTaskUpdates((updated) => { store.updateTask(updated.id, updated); }); }, [store]); // ── View-scoped computed lists ────────────────────────── const myTasks = useMemo( () => store.queue.filter((t) => t.sourceView === sourceView), [store.queue, sourceView], ); const activeTasks = useMemo( () => myTasks.filter((t) => t.status === "running" || t.status === "pending"), [myTasks], ); const completedTasks = useMemo( () => myTasks.filter((t) => t.status === "completed"), [myTasks], ); const failedTasks = useMemo( () => myTasks.filter((t) => t.status === "failed"), [myTasks], ); // ── Actions ───────────────────────────────────────────── const submitTask = useCallback( (task: Omit) => { const id = `gen-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`; store.addTask({ ...task, id, createdAt: Date.now() }); return id; }, [store], ); const updateTask = useCallback( (id: string, patch: Partial) => { store.updateTask(id, patch); }, [store], ); const markCompleted = useCallback( (id: string, resultUrl: string) => { store.updateTask(id, { status: "completed", progress: 100, resultUrl }); }, [store], ); const markFailed = useCallback( (id: string, error: string) => { store.updateTask(id, { status: "failed", error }); }, [store], ); const retryTask = useCallback( (id: string) => { const task = store.queue.find((t) => t.id === id); if (task) { store.updateTask(id, { status: "pending", progress: 0, error: null }); } }, [store], ); return { tasks: myTasks, activeTasks, completedTasks, failedTasks, submitTask, updateTask, markCompleted, markFailed, retryTask, hasActiveTasks: activeTasks.length > 0, }; }