import { useEffect, useState, type ReactNode } from "react"; import { videoEditApi, type LayoutInfo, type LayoutSchema } from "../../api/endpoints"; import type { VideoCatalog, VideoJobState, VideoProjectData, VideoScene, } from "../../api/types"; import { ChevronIcon, TrashIcon } from "../icons/Icons"; import { ErrorText, errorMessage } from "../ui"; import { DeleteAssetModal, RemoveMediaModal } from "./SceneMedia"; import { Voiceovers } from "./Voiceovers"; /** What every panel gets from the editor page. */ export type PanelProps = { id: string; project: VideoProjectData; /** The template's layout_prop_schema (default font sizes per layout); null until loaded or if it failed. */ layoutSchema: LayoutSchema | null; /** The template's display names per layout id; null until loaded or if it failed. */ layoutNames: Record | null; /** Every layout of the template with its visual variants (Scene layout / Scene style in the scene editor). */ layoutInfo: LayoutInfo | null; disabled: boolean; /** Run a quick change, then reload the project. Resolves true on success, false when it failed. */ act: (fn: () => Promise, done?: string) => Promise; /** Start a background job and poll it until it finishes. */ startJob: (label: string, start: () => Promise, poll: () => Promise) => Promise; locked: () => void; }; const sorted = (scenes: VideoScene[]) => [...scenes].sort((a, b) => a.order - b.order); // Audio: each scene's voiceover /** Audio tab: each scene's voiceover, to play or record again. */ export function VoicePanel(p: PanelProps & { catalog: VideoCatalog | null }) { return ; } // Refresh the script: new titles and layouts, same narration export function ScriptPanel(p: PanelProps) { const [instruction, setInstruction] = useState(""); const [preview, setPreview] = useState | null>(null); const [error, setError] = useState(null); async function loadPreview() { setError(null); try { setPreview(await videoEditApi.refreshPreview(p.id)); } catch (e) { setError(errorMessage(e)); } } return (

Refresh the script

Rewrites titles, on-screen text and layouts. The narration and voiceovers stay.