import React, { useEffect, useMemo, useRef } from "react"; import { Button, Stack, Text } from "@mantine/core"; import { useTranslation } from "react-i18next"; import DownloadIcon from "@mui/icons-material/Download"; import { useEndpointEnabled } from "../hooks/useEndpointConfig"; import { useFileContext } from "../contexts/FileContext"; import { useToolFileSelection } from "../contexts/FileSelectionContext"; import ToolStep, { ToolStepContainer } from "../components/tools/shared/ToolStep"; import OperationButton from "../components/tools/shared/OperationButton"; import ErrorNotification from "../components/tools/shared/ErrorNotification"; import FileStatusIndicator from "../components/tools/shared/FileStatusIndicator"; import ResultsPreview from "../components/tools/shared/ResultsPreview"; import ConvertSettings from "../components/tools/convert/ConvertSettings"; import { useConvertParameters } from "../hooks/tools/convert/useConvertParameters"; import { useConvertOperation } from "../hooks/tools/convert/useConvertOperation"; import { BaseToolProps } from "../types/tool"; const Convert = ({ onPreviewFile, onComplete, onError }: BaseToolProps) => { const { t } = useTranslation(); const { setCurrentMode } = useFileContext(); const { selectedFiles } = useToolFileSelection(); const scrollContainerRef = useRef(null); const convertParams = useConvertParameters(); const convertOperation = useConvertOperation(); // Endpoint validation const { enabled: endpointEnabled, loading: endpointLoading } = useEndpointEnabled( convertParams.getEndpointName() ); // Auto-scroll to bottom when content grows const scrollToBottom = () => { if (scrollContainerRef.current) { scrollContainerRef.current.scrollTo({ top: scrollContainerRef.current.scrollHeight, behavior: 'smooth' }); } }; // Calculate state variables first const hasFiles = selectedFiles.length > 0; const hasResults = convertOperation.downloadUrl !== null; const filesCollapsed = hasFiles; const settingsCollapsed = hasResults; // Auto-detect extension when files change - now with smart detection useEffect(() => { if (selectedFiles.length > 0) { convertParams.analyzeFileTypes(selectedFiles); } else { convertParams.resetParameters(); } }, [selectedFiles]); useEffect(() => { convertOperation.resetResults(); onPreviewFile?.(null); }, [convertParams.parameters, selectedFiles]); // Auto-scroll when settings step becomes visible (files selected) useEffect(() => { if (hasFiles) { setTimeout(scrollToBottom, 100); // Small delay to ensure DOM update } }, [hasFiles]); // Auto-scroll when results appear useEffect(() => { if (hasResults) { setTimeout(scrollToBottom, 100); // Small delay to ensure DOM update } }, [hasResults]); const handleConvert = async () => { try { await convertOperation.executeOperation( convertParams.parameters, selectedFiles ); if (convertOperation.files && onComplete) { onComplete(convertOperation.files); } } catch (error) { if (onError) { onError(error instanceof Error ? error.message : 'Convert operation failed'); } } }; const handleThumbnailClick = (file: File) => { onPreviewFile?.(file); sessionStorage.setItem('previousMode', 'convert'); setCurrentMode('viewer'); }; const handleSettingsReset = () => { convertOperation.resetResults(); onPreviewFile?.(null); setCurrentMode('convert'); }; const previewResults = useMemo(() => convertOperation.files?.map((file, index) => ({ file, thumbnail: convertOperation.thumbnails[index] })) || [], [convertOperation.files, convertOperation.thumbnails] ); return (
{/* Files Step */} {/* Settings Step */} {convertParams.parameters.fromExtension && convertParams.parameters.toExtension && ( )} {/* Results Step */} {convertOperation.status && ( {convertOperation.status} )} {convertOperation.downloadUrl && ( )}
); }; export default Convert;