import { open } from "@tauri-apps/plugin-dialog" import { RefreshCw, Upload, X } from "lucide-react" import { useCallback, useMemo, useState } from "react" import { useTranslation } from "react-i18next" import { Button } from "@/components/ui/button" import { Label } from "@/components/ui/label" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" import { Switch } from "@/components/ui/switch" import { useColorGrading } from "../../services/color-grading-provider" import { ParameterSlider } from "../controls/parameter-slider" // Предустановленные LUT const PRESET_LUTS = [ { id: "none", name: "None", category: "default" }, // Film Emulation { id: "film-kodak-2383", name: "Kodak 2383", category: "film" }, { id: "film-fuji-3510", name: "Fuji 3510", category: "film" }, { id: "film-kodak-5218", name: "Kodak 5218", category: "film" }, // Creative Looks { id: "orange-teal", name: "Orange & Teal", category: "creative" }, { id: "day-for-night", name: "Day for Night", category: "creative" }, { id: "vintage-fade", name: "Vintage Fade", category: "creative" }, { id: "moody-blue", name: "Moody Blue", category: "creative" }, // Technical { id: "bw-contrast", name: "B&W High Contrast", category: "technical" }, { id: "rec709-to-rec2020", name: "Rec.709 to Rec.2020", category: "technical" }, { id: "log-to-rec709", name: "Log to Rec.709", category: "technical" }, ] // Миниатюры для превью const PREVIEW_INTENSITIES = [0, 25, 50, 75, 100] export function LUTSection() { const { t } = useTranslation() const { state, dispatch } = useColorGrading() const [selectedLUT, setSelectedLUT] = useState(state.lut.file || "none") const [customLUTs, setCustomLUTs] = useState>([]) const [isLoading, setIsLoading] = useState(false) // Объединяем предустановленные и кастомные LUT const allLUTs = useMemo(() => { const grouped: Record = { film: [], creative: [], technical: [], custom: [], } PRESET_LUTS.forEach((lut) => { if (lut.category !== "default") { grouped[lut.category].push(lut) } }) customLUTs.forEach((lut) => { grouped.custom.push({ ...lut, category: "custom" }) }) return grouped }, [customLUTs]) // Обработчик выбора LUT const handleLUTChange = useCallback( (lutId: string) => { setSelectedLUT(lutId) if (lutId === "none") { dispatch({ type: "TOGGLE_LUT", enabled: false }) dispatch({ type: "LOAD_LUT", file: null }) } else { dispatch({ type: "LOAD_LUT", file: lutId }) dispatch({ type: "TOGGLE_LUT", enabled: true }) } }, [dispatch], ) // Обработчик изменения интенсивности const handleIntensityChange = useCallback( (value: number) => { dispatch({ type: "SET_LUT_INTENSITY", value }) }, [dispatch], ) // Обработчик переключения LUT const handleToggleLUT = useCallback( (checked: boolean) => { dispatch({ type: "TOGGLE_LUT", enabled: checked }) }, [dispatch], ) // Импорт .cube файла const handleImportLUT = useCallback(async () => { try { setIsLoading(true) const selected = await open({ multiple: false, filters: [ { name: "LUT Files", extensions: ["cube", "3dl", "dat", "look", "mga", "m3d"], }, ], }) if (selected) { // В реальном приложении здесь будет парсинг файла через Tauri команду const fileName = selected.split("/").pop() || "Custom LUT" const newLUT = { id: `custom-${Date.now()}`, name: fileName.replace(/\.(cube|3dl|dat|look|mga|m3d)$/i, ""), path: selected, } setCustomLUTs([...customLUTs, newLUT]) handleLUTChange(newLUT.id) } } catch (error) { console.error("Error importing LUT:", error) } finally { setIsLoading(false) } }, [customLUTs, handleLUTChange]) // Удаление кастомного LUT const handleRemoveCustomLUT = useCallback( (lutId: string) => { setCustomLUTs(customLUTs.filter((lut) => lut.id !== lutId)) if (selectedLUT === lutId) { handleLUTChange("none") } }, [customLUTs, selectedLUT, handleLUTChange], ) // Обновление превью const handleRefreshPreviews = useCallback(() => { // В реальном приложении здесь будет обновление превью через WebGL console.log("Refreshing LUT previews...") }, []) return (
{/* Заголовок секции */}
{t("colorGrading.lut.description", "Apply professional color looks with LUT files")}
{/* Выбор LUT файла */}
{/* Enable/Disable переключатель */} {selectedLUT !== "none" && (
)} {/* Слайдер интенсивности */} {selectedLUT !== "none" && ( `${v}%`} disabled={!state.lut.isEnabled} /> )} {/* Превью эффектов */} {selectedLUT !== "none" && state.lut.isEnabled && (
{t("colorGrading.lut.preview", "Preview")}
{PREVIEW_INTENSITIES.map((intensity) => (
{/* В реальном приложении здесь будет реальное превью с WebGL */}
{intensity === 0 ? "Original" : `${intensity}%`}
))}
)} {/* Информация о поддерживаемых форматах */}
{t("colorGrading.lut.supportedFormats", "Supported formats: .cube, .3dl, .dat, .look, .mga, .m3d")}
) }