// remix-screen.jsx — Remix flow (2 steps):
// Step 1: YouTube URL → transcript + explanation (lang A).
// Step 2: rewrite a new script (lang B) with optional user instructions.
// Self-contained. Reuses the AutoCut shell + CSS design tokens.
// Registered as a global component, rendered when appMode === "remix".
const TXT_REMIX = {
vi: {
title: "Viết lại kịch bản từ YouTube",
subtitle: "Bước 1: lấy transcript + nội dung video. Bước 2: viết lại kịch bản theo ý bạn.",
// step 1
urlLabel: "Link YouTube",
urlPlaceholder: "https://www.youtube.com/watch?v=…",
langA: "Ngôn ngữ giải thích (A)",
analyze: "Phân tích video",
analyzing: "Đang lấy transcript & phân tích nội dung…",
// results
transcript: "Transcript gốc",
sourceLang: "Ngôn ngữ gốc",
explanation: "Nội dung video",
newScript: "Kịch bản mới",
// step 2
step2Title: "Bước 2 — Viết lại kịch bản",
langB: "Ngôn ngữ kịch bản mới (B)",
instructions: "Hướng dẫn viết lại (tuỳ chọn)",
instructionsPlaceholder: "VD: viết ngắn gọn hơn, giọng hài hước, nhắm Gen Z, mở đầu bằng câu hỏi gây tò mò…",
rewrite: "Viết lại",
rewriting: "Đang viết lại kịch bản…",
rewriteAgain: "Viết lại lần nữa",
// actions
copy: "Copy",
copied: "Đã copy!",
download: "Tải .txt",
sendToStudio: "Đưa sang Studio",
newJob: "Làm video khác",
back: "Quay lại",
noTranscript: "Video này không có transcript. Hãy thử video khác có phụ đề.",
failed: "Thất bại",
},
en: {
title: "Remix a script from YouTube",
subtitle: "Step 1: grab the transcript + video content. Step 2: rewrite the script your way.",
urlLabel: "YouTube link",
urlPlaceholder: "https://www.youtube.com/watch?v=…",
langA: "Explanation language (A)",
analyze: "Analyze video",
analyzing: "Fetching transcript & analyzing content…",
transcript: "Original transcript",
sourceLang: "Source language",
explanation: "Video content",
newScript: "New script",
step2Title: "Step 2 — Rewrite the script",
langB: "New script language (B)",
instructions: "Rewrite instructions (optional)",
instructionsPlaceholder: "e.g. make it shorter, funny tone, target Gen Z, open with a curious question…",
rewrite: "Rewrite",
rewriting: "Rewriting the script…",
rewriteAgain: "Rewrite again",
copy: "Copy",
copied: "Copied!",
download: "Download .txt",
sendToStudio: "Send to Studio",
newJob: "New video",
back: "Back",
noTranscript: "This video has no transcript. Try another video that has captions.",
failed: "Failed",
},
};
const REMIX_LANG_OPTS = ["Vietnamese", "English", "Spanish", "French", "Japanese", "Korean", "Chinese"];
// ── small styled primitives (matching enhance-screen) ─────────────────────────
const rmxInput = {
background: "var(--bg-1)", border: "1px solid var(--line)", color: "var(--fg-0)",
borderRadius: "var(--radius)", padding: "8px 10px", fontSize: 13,
fontFamily: "var(--font-sans)", width: "100%", boxSizing: "border-box",
};
const rmxBtn = (primary) => ({
padding: "10px 18px", fontSize: 13.5, fontWeight: 600,
borderRadius: "var(--radius)", cursor: "pointer", border: "none",
background: primary ? "var(--accent)" : "var(--bg-3)",
color: primary ? "var(--accent-fg)" : "var(--fg-1)",
});
function RmxField({ label, children }) {
return (
);
}
function RmxSelect({ value, options, onChange }) {
return (
);
}
// A result block with a header, copy/download actions and scrollable body.
function RmxResultCard({ title, body, T, mono, maxHeight, accent, extraActions }) {
const [copied, setCopied] = React.useState(false);
const copy = async () => {
try { await navigator.clipboard.writeText(body || ""); setCopied(true); setTimeout(() => setCopied(false), 1400); } catch (e) {}
};
const download = () => {
const blob = new Blob([body || ""], { type: "text/plain;charset=utf-8" });
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = `${title.replace(/\s+/g, "_").toLowerCase()}.txt`;
a.click();
URL.revokeObjectURL(a.href);
};
return (
{title}
{error}
{T.subtitle}