"use client"; import { useMemo } from "react"; import { useQueries, useQuery } from "@tanstack/react-query"; import type { StatsManifest, VideoStat } from "../lib/stats"; import { readerFor } from "../lib/archive/readers"; export type StatsState = { manifest: StatsManifest | null; stats: VideoStat[]; loadedPages: number; pageCount: number; ready: boolean; error: Error | null; }; export function useStatsManifest(origin = "") { return useQuery({ queryKey: ["stats-manifest", origin], queryFn: () => readerFor(origin).readStatsManifest(), }); } // Mirrors summariesCache.useSummaries: load the manifest, then fan out the // byte-capped page files via react-query and concatenate them. export function useStats(origin = ""): StatsState { const manifestQuery = useStatsManifest(origin); const manifest = manifestQuery.data ?? null; const pageCount = manifest?.pageCount ?? 0; const pageQueries = useQueries({ queries: Array.from({ length: pageCount }, (_, i) => ({ queryKey: ["stats-page", origin, i], queryFn: () => readerFor(origin).readStatsPage(i), enabled: pageCount > 0, })), }); const loadedPages = pageQueries.filter((q) => q.data).length; const ready = pageCount > 0 && loadedPages === pageCount; const stats = useMemo(() => { if (loadedPages === 0) return []; const out: VideoStat[] = []; for (const q of pageQueries) if (q.data) out.push(...q.data); return out; // eslint-disable-next-line react-hooks/exhaustive-deps }, [loadedPages, ready]); const error = manifestQuery.error instanceof Error ? manifestQuery.error : ((pageQueries.find((q) => q.error)?.error as Error | undefined) ?? null); return { manifest, stats, loadedPages, pageCount, ready, error }; }