import type { Paths } from "yt-dlp-transcript-common/lib/paths"; import { readDuplicateOverrides } from "yt-dlp-transcript-common/controller/duplicateShorts"; import type { DuplicateOverrides, DuplicateReport, } from "yt-dlp-transcript-common/lib/duplicates"; import type { MediaScanOverrides, MediaScanReport, } from "yt-dlp-transcript-common/lib/mediaScan"; import { readMediaScanOverrides, readMediaScanReport, } from "yt-dlp-transcript-common/controller/scanCorruptMedia"; import { getSettings } from "yt-dlp-transcript-common/lib/settings"; import { autoPausedRows, type AutoPausedRow, } from "yt-dlp-transcript-common/views/review"; import { getDuplicateReport } from "../../lib/requestCache"; // The half of the old actionable summary that is a HUMAN judgement rather than // a lane's work: findings someone decides about, with the decisions kept beside // them. Split out of loadActionable because nothing but the review page ever // read these four — and the dashboard and the widget poll were paying the // 6.7 MB duplicates parse on every render for a list they never showed. export type ReviewSummary = { duplicates: DuplicateReport | null; // The human decisions kept alongside the report — a cluster's canonical // choice, "not a duplicate", and the `confirmed` flag that is the only thing // letting a needsReview cluster share derived work. Loaded here because the // review UI cannot show what has already been decided without it, and a // review queue that forgets its own answers re-asks every question. duplicateOverrides: DuplicateOverrides; // The corrupt-media scan, and the "reviewed, this one's fine" decisions kept // beside it. Null when the scan has never been run — which is NOT the same as // "nothing is wrong", and the section says so rather than rendering an // all-clear it has no evidence for. mediaScan: MediaScanReport | null; mediaScanOverrides: MediaScanOverrides; // WHAT THE MACHINE DECIDED ON ITS OWN. The storage watch forces a channel to // `paused` when the drive its media is on stops being there; until this, the // only surface saying so was a chip beside that one channel's tier on // /channels, so an operator whose platter went away found out by noticing a // channel had quietly stopped doing anything. // // It belongs here and not on /storage because the decision is about a // CHANNEL, and because the thing to do about it — resume, or leave it — is a // human judgement, which is what this page is. /storage is where the drive // gets fixed, and the section links there. // // FROM SETTINGS, NOT FROM DISK: `settings.channelPriority` is the record, and // reading it costs nothing (getSettings is memoized and every other page on // this render already called it). autoPaused: AutoPausedRow[]; }; export async function loadReviewSummary(paths: Paths): Promise { const [duplicates, duplicateOverrides, mediaScan, mediaScanOverrides] = await Promise.all([ getDuplicateReport(paths), readDuplicateOverrides(paths), readMediaScanReport(paths), readMediaScanOverrides(paths), ]); return { duplicates, duplicateOverrides, mediaScan, mediaScanOverrides, autoPaused: autoPausedRows(getSettings().channelPriority), }; }