import { useMemo } from "react"; import { useGalleryStore } from "../store"; function ProgressBar({ value }: { value: number }) { return (
); } export function BackgroundTasks() { const folders = useGalleryStore((state) => state.folders); const indexingProgress = useGalleryStore((state) => state.indexingProgress); const mediaJobProgress = useGalleryStore((state) => state.mediaJobProgress); const retryFailedEmbeddings = useGalleryStore((state) => state.retryFailedEmbeddings); const tasks = useMemo(() => { return folders .map((folder) => { const index = indexingProgress[folder.id]; const jobs = mediaJobProgress[folder.id]; const pendingMediaWork = (jobs?.thumbnail_pending ?? 0) + (jobs?.metadata_pending ?? 0) + (jobs?.embedding_pending ?? 0); const embeddingProcessed = (jobs?.embedding_ready ?? 0) + (jobs?.embedding_failed ?? 0); const embeddingTotal = embeddingProcessed + (jobs?.embedding_pending ?? 0); const hasFailedEmbeddings = (jobs?.embedding_failed ?? 0) > 0; if (!index && pendingMediaWork === 0 && !hasFailedEmbeddings) { return null; } const indexPercent = index && index.total > 0 ? (index.indexed / index.total) * 100 : 0; const embeddingPercent = embeddingTotal > 0 ? (embeddingProcessed / embeddingTotal) * 100 : 0; return { id: folder.id, name: folder.name, index, jobs, pendingMediaWork, indexPercent, embeddingProcessed, embeddingTotal, embeddingPercent, hasFailedEmbeddings, }; }) .filter((task) => task !== null); }, [folders, indexingProgress, mediaJobProgress]); if (tasks.length === 0) { return null; } return (

Background Tasks

{tasks.length} active
{tasks.map((task) => (

{task.name}

{task.index && !task.index.done ? `${task.index.indexed.toLocaleString()} of ${task.index.total.toLocaleString()} scanned` : task.hasFailedEmbeddings && task.pendingMediaWork === 0 ? `Embedding failures require attention` : `${task.pendingMediaWork.toLocaleString()} media jobs remaining`}

{task.jobs?.thumbnail_pending ?
{task.jobs.thumbnail_pending.toLocaleString()} thumbnails
: null} {task.jobs?.metadata_pending ?
{task.jobs.metadata_pending.toLocaleString()} metadata
: null} {task.embeddingTotal > 0 ? (
{task.embeddingProcessed.toLocaleString()} / {task.embeddingTotal.toLocaleString()} embeddings
) : null} {task.jobs?.embedding_failed ?
{task.jobs.embedding_failed.toLocaleString()} failed
: null}
{task.index && !task.index.done ? (

{task.index.current_file || "Scanning..."}

) : task.embeddingTotal > 0 && (task.jobs?.embedding_pending ?? 0) > 0 ? (

{task.embeddingProcessed.toLocaleString()} completed, {task.jobs?.embedding_pending?.toLocaleString() ?? 0} remaining

) : task.hasFailedEmbeddings ? (

{task.jobs?.embedding_failed?.toLocaleString() ?? 0} embedding failures need attention

) : task.pendingMediaWork > 0 ? (

Processing thumbnails, metadata, and embeddings

) : null}
))}
); }