"use client"; import Link from "next/link"; import { Button } from "./ui/button"; import { ChevronLeft, Download } from "lucide-react"; import { useTimelineStore } from "@/stores/timeline-store"; import { HeaderBase } from "./header-base"; import { formatTimeCode } from "@/lib/time"; import { useProjectStore } from "@/stores/project-store"; import { KeyboardShortcutsHelp } from "./keyboard-shortcuts-help"; import { useState, useRef } from "react"; import { Input } from "@/components/ui/input"; import { toast } from "sonner"; import { useMediaStore } from "@/stores/media-store"; import { VideoExporter, downloadBlob, type ExportOptions, } from "@/lib/export-utils"; export function EditorHeader() { const { getTotalDuration, tracks } = useTimelineStore(); const { activeProject, renameProject } = useProjectStore(); const { mediaItems } = useMediaStore(); const [isEditing, setIsEditing] = useState(false); const [newName, setNewName] = useState(activeProject?.name || ""); const [isExporting, setIsExporting] = useState(false); const inputRef = useRef(null); const handleExport = async () => { if (!activeProject) { toast.error("No active project to export"); return; } if (tracks.length === 0) { toast.error("Timeline is empty - nothing to export"); return; } setIsExporting(true); try { const exportOptions: ExportOptions = { format: "mp4", quality: "medium", resolution: "1080p", fps: activeProject.fps || 30, }; const exporter = new VideoExporter((progress) => { toast.loading( `${progress.message} (${Math.round(progress.progress)}%)`, { id: "export-progress", } ); }); const exportedBlob = await exporter.exportProject( activeProject, tracks, mediaItems, exportOptions ); // Download the exported video const filename = `${activeProject.name}.${exportOptions.format}`; downloadBlob(exportedBlob, filename); toast.success("Video exported successfully!", { id: "export-progress", }); exporter.cleanup(); } catch (error) { console.error("Export failed:", error); toast.error( `Export failed: ${error instanceof Error ? error.message : "Unknown error"}`, { id: "export-progress", } ); } finally { setIsExporting(false); } }; const handleNameClick = () => { if (!activeProject) return; setNewName(activeProject.name); setIsEditing(true); }; const handleNameSave = async () => { if (activeProject && newName.trim() && newName !== activeProject.name) { try { await renameProject(activeProject.id, newName.trim()); } catch (error) { console.error("Failed to rename project:", error); setNewName(activeProject.name); } } setIsEditing(false); }; const handleInputKeyDown = (e: React.KeyboardEvent) => { if (e.key === "Enter") handleNameSave(); else if (e.key === "Escape") setIsEditing(false); }; const leftContent = (
{isEditing ? ( setNewName(e.target.value)} onBlur={handleNameSave} onKeyDown={handleInputKeyDown} onFocus={(e) => e.target.select()} maxLength={64} aria-label="Project name" autoFocus /> ) : ( e.key === "Enter" && handleNameClick()} >
{activeProject?.name}
)}
); const centerContent = (
{formatTimeCode( getTotalDuration(), "HH:MM:SS:FF", activeProject?.fps || 30 )}
); const rightContent = ( ); return ( ); }