"use client"; import { useState } from "react"; import { StreamActionLog } from "yt-dlp-transcript-common/components/StreamActionLog"; import { QueueControl } from "../../../../../../components/QueueControl"; import { cancelJobAction } from "../../../../../../jobs/actions"; import { transcribeOneAction, } from "../../videoActions"; import { Heading } from "./Heading"; import type { VideoFile } from "./videoFiles"; export function PerFileTranscribeRow({ slug, videoId, file, existingQueues, hasTranscript, replaceAutoSubs = false, }: { slug: string; videoId: string; file: VideoFile; existingQueues: string[]; hasTranscript: boolean; // The existing transcript is YouTube ASR: transcribing is offered (and // labelled as a replacement) rather than blocked. replaceAutoSubs?: boolean; }) { const [transcribeQueue, setTranscribeQueue] = useState(""); // `hasTranscript` is SERVER-derived (VideoPanel, the Transcribe card) and this row's own run // is what writes transcript.json — so the run's own router.refresh() used to // swap this panel for the "already present" line and take the log with it. // Same shape as the two banners: the row survives (it is keyed by file name), // the message and the run panel are separate slots, and the panel stays // mounted — disabled, since the transcript now exists — once a run has // started here. With no run it is still absent whenever a transcript is // already present, so the DOM is unchanged. const [ranHere, setRanHere] = useState(false); return (
Transcribe disabled — transcript already present.
) : null} {hasTranscript && !ranHere ? null : (