"use client"; import Link from "next/link"; import { useState, useTransition } from "react"; import { Button } from "yt-dlp-transcript-common/components/ui/button"; import { fetchMissingEvidenceAction, type FetchMissingEvidenceResult, } from "../../channels/[slug]/videos/fetchWindowsAction"; // "Fetch missing evidence": every window the site's published reports cite and // the disk does not hold, fetched as one paced job per platform // (fetch-windows). Preview answers the same question without starting // anything. It is not a streamed log because a run can start two jobs (YouTube // and Rumble side by side); each is linked, and its log is on /jobs. export function FetchMissingEvidenceButton({ siteId }: { siteId: string }) { const [pending, start] = useTransition(); const [result, setResult] = useState(null); const run = (dryRun: boolean) => { start(async () => { setResult(await fetchMissingEvidenceAction(siteId, { dryRun })); }); }; return (
{result && }
); } function FetchSummary({ result }: { result: FetchMissingEvidenceResult }) { if (!result.ok) { return (

{result.error}

); } const toFetch = result.groups.reduce((n, g) => n + g.items.length, 0); return (

{result.onDisk} cited span(s) on disk · {toFetch} window(s) to fetch {result.cached.length > 0 && <> · {result.cached.length} already fetched} {result.unfetchable.length > 0 && <> · {result.unfetchable.length} cannot be fetched}

{result.dryRun ? result.groups.map((g) => (

{g.platform}: {g.items.length} window(s) on {g.queueKey}

)) : result.jobs.map((j) => (

{j.platform}: {j.items} window(s) —{" "} {j.jobId}

))} {!result.dryRun && result.refused.map((r) => (

{r.platform}: {r.items} window(s) not started — {r.error}

))} {result.unresolved.map((u) => (

{u.item.clipId ?? `${u.item.slug}/${u.item.id}`}: {u.error}

))} {result.unfetchable.length > 0 && ( )}
); }