"use client";
import { useEffect, useRef, useState } from "react";
import {
ArrowUp,
Check,
ChevronDown,
Maximize2,
Play,
Plus,
Scissors,
Upload,
X,
} from "lucide-react";
import { editRatios, editResolutions } from "@/lib/video-canvas/smart-edit/contract";
import styles from "./SmartEditNode.module.css";
export type SmartEditSource = { id: string; name: string; url: string; duration?: number };
const modes = [
{ id: "auto", name: "默认模式" },
{ id: "explain", name: "讲解视频" },
{ id: "ads", name: "批量广告" },
{ id: "talk", name: "口播视频" },
{ id: "montage", name: "素材混剪" },
];
export function SmartEditNodeCard({
title,
previewUrl,
onOpen,
selected = false,
}: {
title: string;
selected?: boolean;
previewUrl?: string;
onOpen: () => void;
}) {
return (
{previewUrl &&
}
{Array.from({ length: 12 }, (_, i) => (
0:{String(i * 2).padStart(2, "0")}
))}
{[0, 1].map((row) => (
{Array.from({ length: 8 }, (_, i) => (
))}
))}
);
}
export function SmartEditNodeComposer({
anchor,
draft,
sources,
availableSources,
onDraft,
onAddSource,
onRemoveSource,
onUpload,
onReference,
onSubmit,
busy,
}: {
anchor: { centerX: number; bottomY: number; zoom: number };
draft: Record;
sources: SmartEditSource[];
availableSources: SmartEditSource[];
onDraft: (patch: Record) => void;
onAddSource: (id: string) => void;
onRemoveSource: (id: string) => void;
onUpload: (files: File[]) => void;
onReference?: () => void;
onSubmit: () => Promise;
busy: boolean;
}) {
const [menu, setMenu] = useState<"mode" | "settings" | "sources" | null>(null),
[expanded, setExpanded] = useState(false),
[error, setError] = useState(""),
[submitting, setSubmitting] = useState(false);
const root = useRef(null),
file = useRef(null);
useEffect(() => {
const close = (e: PointerEvent) => {
if (!root.current?.contains(e.target as Node)) setMenu(null);
};
document.addEventListener("pointerdown", close);
return () => document.removeEventListener("pointerdown", close);
}, []);
const ratio = draft.ratio || "16:9",
resolution = draft.resolution || "1080p",
duration = draft.targetDuration ?? 20,
mode = modes.find((m) => m.id === draft.mode) || modes[0];
const toggle = (value: typeof menu) => setMenu(menu === value ? null : value);
return (
e.stopPropagation()}
onWheel={(e) => e.stopPropagation()}
onKeyDown={(e) => e.stopPropagation()}
>
{!!sources.length && (
{sources.map((s, i) => (
{i + 1}
{s.duration ? `${s.duration.toFixed(1)}s` : "视频"}
))}
)}
);
}