import { Download, Pause, Play, RotateCcw, SplitSquareHorizontal, X } from "lucide-react" import { useCallback, useState } from "react" import { useTranslation } from "react-i18next" import { Button } from "@/components/ui/button" import { Separator } from "@/components/ui/separator" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { useModal } from "@/features/modals/services" import type { BaseEffect } from "../types" import { prepareEffectForExport, saveUserEffect } from "../utils/user-effects" import { EffectComparison } from "./effect-comparison" import { EffectIndicators } from "./effect-indicators" import { EffectParameterControls } from "./effect-parameter-controls" import { EffectPresets } from "./effect-presets" import { EffectPreview } from "./effect-preview" /** * Компонент для детального просмотра эффекта с возможностью настройки параметров */ export function EffectDetailModal() { const { modalData, closeModal } = useModal() const { effect, onApplyEffect } = (modalData as { effect?: BaseEffect; onApplyEffect?: any }) || {} const { i18n, t } = useTranslation() const [selectedPreset, setSelectedPreset] = useState() const [isPlaying, setIsPlaying] = useState(false) const [currentParameters, setCurrentParameters] = useState>({}) const [previewKey, setPreviewKey] = useState(0) // Для обновления превью const currentLang = i18n.language as "ru" | "en" // Helper функция для получения FFmpeg команды const getEffectFFmpegCommand = (effect: BaseEffect, params: Record = {}) => { if (!effect.processors?.ffmpeg) return "FFmpeg processor not available" // Преобразуем parameters массив в объект значений по умолчанию const defaultParams = effect.parameters.reduce>((acc, param) => { acc[param.id] = param.defaultValue return acc }, {}) const mergedParams = { ...defaultParams, ...params } return effect.processors.ffmpeg.filter(mergedParams) } // Обработчик применения пресета const handleApplyPreset = useCallback((presetName: string, params: Record) => { setSelectedPreset(presetName) setCurrentParameters(params) setPreviewKey((prev) => prev + 1) // Обновляем превью }, []) // Обработчик изменения параметров const handleParametersChange = useCallback( (params: Record) => { setCurrentParameters(params) setPreviewKey((prev) => prev + 1) // Обновляем превью // Сбрасываем выбранный пресет при ручном изменении if (selectedPreset) { setSelectedPreset(undefined) } }, [selectedPreset], ) // Обработчик сохранения пользовательского пресета const handleSavePreset = useCallback( (name: string, params: Record) => { try { // Получаем существующие пресеты для этого эффекта const storageKey = `effect_presets_${effect?.id}` const existingPresets = localStorage.getItem(storageKey) const presets = existingPresets ? JSON.parse(existingPresets) : {} // Добавляем новый пресет const presetId = `custom_${Date.now()}` presets[presetId] = { name: { [currentLang]: name, en: name, // fallback }, params, description: { [currentLang]: t("effects.customPreset", "Пользовательский пресет"), en: "Custom preset", }, createdAt: new Date().toISOString(), } // Сохраняем обратно в localStorage localStorage.setItem(storageKey, JSON.stringify(presets)) // Уведомляем пользователя об успешном сохранении console.log("Custom preset saved:", name, params) // Обновляем состояние компонента, если нужно показать новый пресет // Можно добавить toast уведомление здесь } catch (error) { console.error("Error saving custom preset:", error) } }, [effect?.id, currentLang, t], ) // Обработчик применения эффекта const handleApplyEffect = useCallback(() => { if (onApplyEffect) { onApplyEffect(effect!, selectedPreset, currentParameters) } closeModal() }, [effect, selectedPreset, currentParameters, onApplyEffect, closeModal]) // Обработчик сброса параметров const handleReset = useCallback(() => { setSelectedPreset(undefined) setCurrentParameters({}) setPreviewKey((prev) => prev + 1) }, []) // Обработчик экспорта эффекта const handleExportEffect = useCallback(async () => { try { const exportName = prompt(t("effects.enterExportName", "Введите название файла для экспорта:")) if (!exportName) return const effectToExport = prepareEffectForExport( effect!, Object.keys(currentParameters).length > 0 ? currentParameters : undefined, selectedPreset, ) const filePath = await saveUserEffect(effectToExport, exportName) console.log("Effect exported to:", filePath) // Можем добавить toast уведомление об успешном экспорте } catch (error) { console.error("Error exporting effect:", error) } }, [effect, currentParameters, selectedPreset, t]) // Ранний возврат, если эффект не передан if (!effect) return null const typedEffect = effect return (
{typedEffect?.name[currentLang] ?? typedEffect?.name?.en ?? "Unnamed effect"}
{/* Левая колонка - Превью */}
{t("effects.preview", "Превью")} {t("effects.comparison", "Сравнение")}
setIsPlaying(!isPlaying)} size={400} customParams={currentParameters} // Передаем текущие параметры /> {/* Контролы воспроизведения */}
{/* Информация об эффекте */}

{t("effects.detail.description", "Описание")}

{typedEffect?.description?.[currentLang] || typedEffect?.description?.en}

{/* Категория и теги */}

{t("effects.detail.category", "Категория")}

{typedEffect?.category} {typedEffect?.tags?.map((tag) => ( {tag} ))}
{/* Правая колонка - Настройки */}
{/* Пресеты */} {/* Интерактивные контролы параметров */} {/* FFmpeg команда */}

{t("effects.detail.ffmpegCommand", "FFmpeg команда")}

{typedEffect ? getEffectFFmpegCommand(typedEffect, currentParameters) : "No effect selected"}
{/* Кнопки действий */}
) }