import { memo, useEffect, useState } from 'react'; import { FileImage } from 'lucide-react'; import { loadCodingAttachmentPreview } from '@/lib/coding-attachments'; export const CodingAttachmentPreview = memo(function CodingAttachmentPreview({ attachmentId, mime, caption = '对话图片附件', }: { attachmentId: string; mime: string; caption?: string; }) { const [state, setState] = useState<{ attachmentId: string; previewUrl: string | null; failed: boolean; }>({ attachmentId, previewUrl: null, failed: false }); useEffect(() => { let active = true; let objectUrl: string | null = null; void loadCodingAttachmentPreview(attachmentId) .then((preview) => { if (!active) return; const bytes = Uint8Array.from(preview.bytes); objectUrl = URL.createObjectURL(new Blob([bytes], { type: preview.mime })); setState({ attachmentId, previewUrl: objectUrl, failed: false }); }) .catch(() => { if (active) setState({ attachmentId, previewUrl: null, failed: true }); }); return () => { active = false; if (objectUrl) URL.revokeObjectURL(objectUrl); }; }, [attachmentId]); const previewUrl = state.attachmentId === attachmentId ? state.previewUrl : null; const failed = state.attachmentId === attachmentId && state.failed; return (
{previewUrl ? ( {caption} ) : (
)}
{mime} · {attachmentId}
); });