'use client'; import React, { useState, useRef, useEffect } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { X, Play, Pause, Volume2, VolumeX, Upload, Library, Wand2, ZoomIn, RotateCw, Info, ChevronDown } from 'lucide-react'; import { cn } from '@/public/lib/utils'; import { AudioVisualizer } from './audio-visualizer'; interface MediaPropertiesModalProps { isOpen: boolean; onClose: () => void; taskSketch: any[]; currentSketchIndex: number; onSketchSelect: (index: number) => void; } export function MediaPropertiesModal({ isOpen, onClose, taskSketch = [], currentSketchIndex = 0, onSketchSelect }: MediaPropertiesModalProps) { const [activeTab, setActiveTab] = useState<'media' | 'audio'>('media'); const [selectedSketchIndex, setSelectedSketchIndex] = useState(currentSketchIndex); const [isPlaying, setIsPlaying] = useState(false); const [isMuted, setIsMuted] = useState(false); const [progress, setProgress] = useState(0); const [trimAutomatically, setTrimAutomatically] = useState(false); const [audioVolume, setAudioVolume] = useState(75); const videoPlayerRef = useRef(null); const thumbnailsRef = useRef(null); // 当弹窗打开时,同步当前选中的分镜 useEffect(() => { if (isOpen) { setSelectedSketchIndex(currentSketchIndex); } }, [isOpen, currentSketchIndex]); // 确保 taskSketch 是数组 const sketches = Array.isArray(taskSketch) ? taskSketch : []; // 模拟媒体属性数据 const currentSketch = sketches[selectedSketchIndex]; const mediaProperties = { duration: '00m : 10s : 500ms / 00m : 17s : 320ms', trim: { start: '0.0s', end: '10.5s' }, centerPoint: { x: 0.5, y: 0.5 }, zoom: 100, rotation: 0, transition: 'Auto', script: 'This part of the script is 21.00 seconds long.' }; const audioProperties = { sfxName: 'Background Music', sfxVolume: audioVolume }; // 自动滚动到选中项 useEffect(() => { if (thumbnailsRef.current && isOpen) { const thumbnailContainer = thumbnailsRef.current; const thumbnailWidth = thumbnailContainer.children[0]?.clientWidth ?? 0; const thumbnailGap = 16; const thumbnailScrollPosition = (thumbnailWidth + thumbnailGap) * selectedSketchIndex; thumbnailContainer.scrollTo({ left: thumbnailScrollPosition - thumbnailContainer.clientWidth / 2 + thumbnailWidth / 2, behavior: 'smooth' }); } }, [selectedSketchIndex, isOpen]); // 视频播放控制 useEffect(() => { if (videoPlayerRef.current) { if (isPlaying) { videoPlayerRef.current.play().catch(() => { setIsPlaying(false); }); } else { videoPlayerRef.current.pause(); } } }, [isPlaying, selectedSketchIndex]); // 更新进度条 const handleTimeUpdate = () => { if (videoPlayerRef.current) { const progress = (videoPlayerRef.current.currentTime / videoPlayerRef.current.duration) * 100; setProgress(progress); } }; const handleSketchSelect = (index: number) => { setSelectedSketchIndex(index); setProgress(0); }; if (sketches.length === 0) { return null; } return ( {isOpen && ( <> {/* 背景遮罩 */} {/* 弹窗内容 */}
{/* 标题栏 */}

More Properties

{/* 上部:分镜视频列表 */}
{sketches.map((sketch, index) => ( handleSketchSelect(index)} whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }} > ))}
{/* 下部:主要内容区域 */}
{/* 左侧 2/3:编辑选项 */}
{/* Media/Audio & SFX 切换按钮 */}
setActiveTab('media')} whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > Media setActiveTab('audio')} whileHover={{ scale: 1.02 }} whileTap={{ scale: 0.98 }} > Audio & SFX
{/* 内容区域 */}
{activeTab === 'media' ? ( <> {/* Duration - 只读 */}
{mediaProperties.duration}
{/* Trim - 可编辑 */}
from to
{/* Center point - 可编辑 */}
X Y
{/* Zoom & Rotation - 可编辑 */}
%
°
{/* Transition - 可编辑 */}
{/* Script - 只读 */}

{mediaProperties.script}

) : ( <> {/* SFX name - 只读 */}
{audioProperties.sfxName}
{/* SFX volume - 可编辑 */}
{audioProperties.sfxVolume}%
setAudioVolume(parseInt(e.target.value))} className="w-full h-2 bg-white/20 rounded-lg appearance-none cursor-pointer slider" style={{ background: `linear-gradient(to right, #3b82f6 0%, #3b82f6 ${audioProperties.sfxVolume}%, rgba(255,255,255,0.2) ${audioProperties.sfxVolume}%, rgba(255,255,255,0.2) 100%)` }} />
{/* Replace audio */}
Replace audio Stock SFX Generate SFX
)}
{/* 右侧 1/3:预览区域 */}
{/* 视频预览 */}
{/* 音频预览 */}
{/* 底部操作栏 */}
{ // TODO: 实现重置逻辑 console.log('Reset clicked'); }} > Reset { // TODO: 实现应用逻辑 console.log('Apply clicked'); onSketchSelect(selectedSketchIndex); onClose(); }} > Apply
)}
); }