import { Trash2, Upload } from 'lucide-react'; import TextInputArea from '@/components/TextInputArea'; import { useLazyTranslation } from '@/utils/useLazyTranslation'; import CopyButton from '@/components/CopyButton'; import DecodeResultPaper from '@/components/DecodeResultPaper'; import { Button } from '@/components/ui/button'; import { downloadBlob, formatFileSize, MAX_FILE_SIZE } from '@/utils/base64Converter'; import { useStorageState } from '@/utils/useStorageState'; import type { Base64ConvertDirection } from '@/types/storage'; import SwitchButtonGroup from '@/components/SwitchButtonGroup'; import { useBase64Converter } from './useBase64Converter'; // 💡 斩断重复代码 import { cn } from '@/lib/utils'; const isValidDirection = (val: unknown): val is Base64ConvertDirection => val === 'encode' || val === 'decode'; export default function FileMode() { const { t } = useLazyTranslation('base64Converter'); const [direction, setDirection] = useStorageState( 'base64Converter/fileMode/direction', 'encode', isValidDirection, ); const { result, info, isLoading, isDragging, setIsDragging, fileInputRef, encodeError, decodeInput, setDecodeInput, decoded, decodeError, decodedFileName, setCustomFileName, resetAll, safeFileSelect, } = useBase64Converter({ mode: 'file' }); const handleDownload = () => { if (decoded) downloadBlob(decoded.blob, decodedFileName); }; return (
{ if (next && next !== direction) { resetAll(); setDirection(next); } }} size="small" />
{direction === 'encode' ? (
{ e.preventDefault(); setIsDragging(true); }} onDragLeave={() => setIsDragging(false)} onDrop={(e) => { e.preventDefault(); setIsDragging(false); const file = e.dataTransfer.files[0]; if (file) safeFileSelect(file); }} onClick={() => fileInputRef.current?.click()} className={cn( 'flex flex-col items-center justify-center min-h-[190px] border-2 border-dashed rounded-2xl p-8 cursor-pointer transition-all duration-300', isDragging ? 'border-primary bg-primary/10' : info ? 'border-primary/60 bg-primary/5' : 'border-border bg-muted/40 hover:border-primary/80 hover:bg-muted/70', )} > { const file = e.target.files?.[0]; if (file) safeFileSelect(file); }} /> {isLoading ? (
) : info ? (
{info.name} {formatFileSize(info.size)} · {info.type} {t('clickOrDropToReplace')}
) : (
{t('clickOrDropToFile')} {t('maxFileSize', { max: `${MAX_FILE_SIZE / 1024 / 1024} MB` })}
)}
{encodeError && (
{encodeError}
)} {result && (
{t('base64Output')}
2000 ? `${result.output.substring(0, 2000)}...` : result.output } showClear={false} minRows={4} />
{t('originalSize')}:{' '} {formatFileSize(result.originalBytes)} | {t('encodedSize')}:{' '} {formatFileSize(result.outputBytes)}
)}
) : (
{decoded && ( )}
)}
); }