import { Image as ImageIcon, Trash2, Upload } from 'lucide-react'; import TextInputArea from '@/components/TextInputArea'; import { CopyButton } from '@/components/CopyButton'; import DecodeResultPaper from './DecodeResultPaper'; import { Button } from '@/components/ui/button'; import { downloadBlob } from '@/utils/base64Converter'; import { formatBytes } from '@/utils/format'; 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'; interface Base64ConverterSectionProps { mode: 'file' | 'image'; } export default function Base64ConverterSection({ mode }: Base64ConverterSectionProps) { const [direction, setDirection] = useStorageState( `base64Converter/${mode}Mode/direction`, 'encode', isValidDirection, ); const { result, info, isLoading, isDragging, setIsDragging, fileInputRef, encodeError, decodeInput, setDecodeInput, decoded, decodeError, decodedFileName, setCustomFileName, resetAll, handleFileSelect, maxFileSizeStr, } = useBase64Converter({ mode }); const handleDirectionChange = (next: Base64ConvertDirection) => { if (next === direction) return; resetAll(); setDirection(next); }; return (
{direction === 'encode' ? (
{ e.preventDefault(); setIsDragging(true); }} onDragLeave={() => setIsDragging(false)} onDrop={(e) => { e.preventDefault(); setIsDragging(false); const file = e.dataTransfer.files[0]; if (file) void handleFileSelect(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', 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) void handleFileSelect(file); }} /> {isLoading ? (
) : info ? (
{mode === 'image' && result && (
preview
)} {info.name} {formatBytes(info.size)} · {info.type} 点击或拖拽以替换文件
) : (
{mode === 'image' ? ( ) : ( )} {mode === 'image' ? '点击或拖拽图像到此处' : '点击或拖拽文件到此处'} 最大文件大小:{maxFileSizeStr} {mode === 'image' && ( 支持 PNG、JPG、WEBP、GIF、BMP、SVG 等格式 )}
)}
{encodeError && (
{encodeError}
)} {result && (
Base64 编码结果
2000 ? `${result.output.substring(0, 2000)}...` : result.output } showClear={false} minRows={4} />
原始大小:{' '} {formatBytes(result.originalBytes)} | 编码大小:{' '} {formatBytes(result.outputBytes)}
)}
) : (
{decoded && ( downloadBlob(decoded.blob, decodedFileName)} > {mode === 'image' && (
decoded preview
)}
)}
)}
); }