import React, { useEffect, useMemo, useRef, useState } from 'react' import { Plus, FileUp, Film, Trash2 } from 'lucide-react' import { Tooltip } from '../../components/ui/tooltip' import { shallow } from 'zustand/vanilla/shallow' import { selectActiveTimelineId, selectOpenTimelineIds, selectTimelineRenameState, selectTimelines, } from './editor-selectors' import { useEditorActions, useEditorStore } from './editor-store' export interface VideoEditorTimelineControlPanelProps { handleTimelineTabContextMenu: (e: React.MouseEvent, timelineId: string) => void } export function VideoEditorTimelineControlPanel(props: VideoEditorTimelineControlPanelProps) { const { handleTimelineTabContextMenu, } = props const { cancelTimelineRename, commitTimelineRename, createTimeline, deleteTimeline, openImportTimelineModal, setTimelineRenameValue, startTimelineRename, switchActiveTimeline, } = useEditorActions() const timelines = useEditorStore(selectTimelines) const activeTimelineId = useEditorStore(selectActiveTimelineId) const openTimelineIds = useEditorStore(selectOpenTimelineIds) const { renamingTimelineId, renameValue, renameSource } = useEditorStore(selectTimelineRenameState, shallow) const timelineItems = useMemo(() => ( timelines.map(timeline => ({ timeline, isActive: timeline.id === activeTimelineId, isOpen: openTimelineIds.has(timeline.id), isRenaming: renamingTimelineId === timeline.id, clipCount: timeline.clips.length, duration: timeline.clips.reduce((max, clip) => Math.max(max, clip.startTime + clip.duration), 0), })) ), [activeTimelineId, openTimelineIds, renamingTimelineId, timelines]) const [timelineAddMenuOpen, setTimelineAddMenuOpen] = useState(false) const addMenuRef = useRef(null) const setRenameValue = (value: string) => { setTimelineRenameValue(value) } const setRenamingTimelineId = (value: string | null) => { if (value === null) cancelTimelineRename() } const handleAddTimeline = () => { createTimeline() } const handleSwitchTimeline = (timelineId: string) => { switchActiveTimeline(timelineId) } const handleDeleteTimeline = (timelineId: string) => { deleteTimeline(timelineId) } const handleStartRename = (timelineId: string, currentName: string, source: 'tab' | 'panel' = 'panel') => { void currentName startTimelineRename(timelineId, source) } const handleFinishRename = () => { commitTimelineRename() } useEffect(() => { if (!timelineAddMenuOpen) return const onClickAway = (e: MouseEvent) => { if (!addMenuRef.current?.contains(e.target as Node)) { setTimelineAddMenuOpen(false) } } const timer = setTimeout(() => window.addEventListener('click', onClickAway), 0) return () => { clearTimeout(timer) window.removeEventListener('click', onClickAway) } }, [timelineAddMenuOpen]) return (

Timelines

{timelineAddMenuOpen && (
)}
{timelineItems.map(item => { const tl = item.timeline const isActive = item.isActive const clipCount = item.clipCount const tlDuration = item.duration const formatDur = (s: number) => { const m = Math.floor(s / 60) const sec = Math.floor(s % 60) return m > 0 ? `${m}m ${sec}s` : `${sec}s` } return (
{ if (isActive) { e.preventDefault(); return } e.dataTransfer.setData('timeline', JSON.stringify({ id: tl.id, name: tl.name })) e.dataTransfer.effectAllowed = 'copy' }} onClick={() => handleSwitchTimeline(tl.id)} onDoubleClick={() => handleStartRename(tl.id, tl.name, 'panel')} onContextMenu={(e) => handleTimelineTabContextMenu(e, tl.id)} >
{item.isRenaming && renameSource === 'panel' ? ( setRenameValue(e.target.value)} onBlur={handleFinishRename} onKeyDown={(e) => { if (e.key === 'Enter') handleFinishRename() if (e.key === 'Escape') { setRenamingTimelineId(null); setRenameValue('') } }} className="bg-zinc-900 border border-blue-500 rounded px-1 py-0.5 outline-none text-white text-xs w-full" autoFocus onClick={(e) => e.stopPropagation()} onDoubleClick={(e) => e.stopPropagation()} /> ) : (

{tl.name}

)}
{clipCount} clip{clipCount !== 1 ? 's' : ''} {clipCount > 0 && ( <> ยท {formatDur(tlDuration)} )}
{isActive ? ( Active ) : item.isOpen ? ( ) : null} {timelineItems.length > 1 && ( )}
) })}
) }