import { Clock, Flag, Play, Scissors, Video } from "lucide-react" import { useCallback, useEffect, useState } from "react" import { useTranslation } from "react-i18next" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Checkbox } from "@/components/ui/checkbox" import { Input } from "@/components/ui/input" import { Label } from "@/components/ui/label" import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" import { ScrollArea } from "@/components/ui/scroll-area" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { useTimeline } from "@/features/timeline/hooks/use-timeline" import type { ExportSettings } from "../types/export-types" interface SectionExportTabProps { defaultSettings: ExportSettings onExport: (settings: ExportSettings & { sections: ExportSection[] }) => void onPreviewSection?: (startTime: number) => void } interface ExportSection { id: string name: string startTime: number endTime: number includeInExport: boolean customFileName?: string customSettings?: Partial } interface TimeMarker { id: string name: string time: number type: "start" | "end" | "marker" } export function SectionExportTab({ defaultSettings, onExport, onPreviewSection }: SectionExportTabProps) { const { t } = useTranslation() const { project, seek } = useTimeline() const [exportMode, setExportMode] = useState<"markers" | "manual" | "clips">("markers") const [sections, setSections] = useState([]) const [manualStart, setManualStart] = useState("00:00:00") const [manualEnd, setManualEnd] = useState("00:00:10") const [selectedQuality, setSelectedQuality] = useState<"preview" | "draft" | "final">("final") // Convert markers to sections useEffect(() => { if (exportMode === "markers" && project) { if (project.markers && project.markers.length > 0) { // Используем маркеры для создания секций const markerSections: ExportSection[] = [] const sortedMarkers = [...project.markers].sort((a, b) => a.time - b.time) for (let i = 0; i < sortedMarkers.length; i++) { const currentMarker = sortedMarkers[i] const nextMarker = sortedMarkers[i + 1] // Определяем конец секции как следующий маркер или конец проекта const endTime = nextMarker ? nextMarker.time : project.duration markerSections.push({ id: currentMarker.id, name: currentMarker.name, startTime: currentMarker.time, endTime: endTime, includeInExport: true, }) } setSections(markerSections) } else { // Fallback: используем секции проекта как маркеры const markerSections: ExportSection[] = project.sections.map((section) => ({ id: section.id, name: section.name, startTime: section.startTime, endTime: section.endTime, includeInExport: true, })) setSections(markerSections) } } }, [exportMode, project]) // Convert clips to sections useEffect(() => { if (exportMode === "clips" && project) { // Собираем все клипы из всех треков всех секций const clipSections: ExportSection[] = [] project.sections.forEach((section) => { section.tracks.forEach((track) => { track.clips.forEach((clip) => { clipSections.push({ id: clip.id, name: clip.name || `${track.name} - Clip`, startTime: section.startTime + clip.startTime, endTime: section.startTime + clip.startTime + clip.duration, includeInExport: true, }) }) }) }) // Сортируем по времени начала clipSections.sort((a, b) => a.startTime - b.startTime) setSections(clipSections) } }, [exportMode, project]) const handleToggleSection = (sectionId: string) => { setSections((prev) => prev.map((section) => section.id === sectionId ? { ...section, includeInExport: !section.includeInExport } : section, ), ) } const handleSelectAll = () => { const allSelected = sections.every((s) => s.includeInExport) setSections((prev) => prev.map((section) => ({ ...section, includeInExport: !allSelected }))) } const handleUpdateSectionName = (sectionId: string, name: string) => { setSections((prev) => prev.map((section) => (section.id === sectionId ? { ...section, customFileName: name } : section)), ) } const formatTimeShort = (seconds: number): string => { const hours = Math.floor(seconds / 3600) const minutes = Math.floor((seconds % 3600) / 60) const secs = Math.floor(seconds % 60) if (hours > 0) { return `${hours}:${minutes.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}` } return `${minutes}:${secs.toString().padStart(2, "0")}` } const parseTime = (timeStr: string): number => { const parts = timeStr.split(":").map((p) => Number.parseInt(p) || 0) return parts[0] * 3600 + parts[1] * 60 + parts[2] } const handleManualSection = () => { const startSeconds = parseTime(manualStart) const endSeconds = parseTime(manualEnd) if (startSeconds < endSeconds) { setSections([ { id: "manual-1", name: "Manual Section", startTime: startSeconds, endTime: endSeconds, includeInExport: true, }, ]) } } const getQualitySettings = (): Partial => { switch (selectedQuality) { case "preview": return { resolution: "720", bitrate: 2000, bitrateMode: "vbr", quality: "normal", } case "draft": return { resolution: "1080", bitrate: 5000, bitrateMode: "vbr", quality: "good", } default: return defaultSettings } } const handleStartExport = () => { const selectedSections = sections.filter((s) => s.includeInExport) const qualitySettings = getQualitySettings() onExport({ ...defaultSettings, ...qualitySettings, sections: selectedSections, }) } const handlePreviewSection = useCallback( (section: ExportSection) => { // Переход к началу секции для предпросмотра if (onPreviewSection) { onPreviewSection(section.startTime) } else if (seek) { void seek(section.startTime) } }, [onPreviewSection, seek], ) const selectedCount = sections.filter((s) => s.includeInExport).length return (
{/* Export Mode Selection */} {t("export.sections.exportMode")} {t("export.sections.exportModeDescription")} setExportMode(value as "markers" | "manual" | "clips")} >
{/* Manual Time Input */} {exportMode === "manual" && (
setManualStart(e.target.value)} placeholder="00:00:00" />
setManualEnd(e.target.value)} placeholder="00:00:10" />
)}
{/* Quality Settings */} {t("export.sections.qualityPreset")} {t("export.sections.qualityPresetDescription")} {/* Sections List */} {sections.length > 0 && (
{t("export.sections.sectionsTitle")} {t("export.sections.selectedCount", { selected: selectedCount, total: sections.length })}
{sections.map((section) => (
handleToggleSection(section.id)} />
handleUpdateSectionName(section.id, e.target.value)} className="h-7 text-sm" placeholder={t("export.sections.fileName")} />
{formatTimeShort(section.startTime)} - {formatTimeShort(section.endTime)}
{t("export.sections.duration", { duration: formatTimeShort(section.endTime - section.startTime), })}
))}
)} {/* Export Actions */}
) }