import { useEffect, useMemo, useRef, useState } from "react"; import { useShallow } from "zustand/react/shallow"; import { Search, Wand2, ClipboardPaste, Loader2, X, Check } from "lucide-react"; import { useStore, selectStats } from "../store"; import { fmtTime } from "../lib/time"; import { timelineToSource, wordTimelineStart, type Word } from "../lib/timeline-model"; import { ModelSwitcher } from "./ModelSwitcher"; import { aiHeaders } from "../lib/aiKeys"; const LENGTHS = ["~30 sec", "~1 minute", "~2 minutes"]; const TONES = ["Friendly", "Authoritative", "Cinematic", "Energetic"]; // Script tools: generate the project's script with AI, or paste your own. Either one // REPLACES the transcript (estimated timing) and drives captions/timeline/preview. function ScriptTools() { const setScript = useStore((s) => s.setScript); const model = useStore((s) => s.model); const projectName = useStore((s) => s.projectName); const hasWords = useStore((s) => s.words.length > 0); const [mode, setMode] = useState(null); const [prompt, setPrompt] = useState(""); const [length, setLength] = useState(LENGTHS[1]); const [tone, setTone] = useState(TONES[0]); const [text, setText] = useState(""); const [busy, setBusy] = useState(false); const [err, setErr] = useState(""); async function generate() { setBusy(true); setErr(""); try { const d = await fetch("/api/script", { method: "POST", headers: { "Content-Type": "application/json", ...aiHeaders() }, body: JSON.stringify({ prompt: prompt.trim() || projectName, model, length, tone }) }).then((r) => r.json()); if (d.error || !d.script) throw new Error(d.error || "no script returned"); setText(d.script); setMode("paste"); // drop into the editable box to review before applying } catch (e) { setErr(e instanceof Error ? e.message : String(e)); } setBusy(false); } function apply() { if (!text.trim()) return; const st = useStore.getState(); if ((st.motion.length || st.videos.length) && !window.confirm("Replace the script? Your scenes and clips keep their positions but may no longer line up with the new timing.")) return; setScript(text.trim()); setMode(null); setText(""); setPrompt(""); } return (
{mode && }
{mode === "gen" && (