feat(coding): complete PI conversation UI
This commit is contained in:
1 parent
2613d6530b
commit
863f005203
21 files changed
+2040
-137
No files matched your search
@@ -0,0 +1,66 @@
|
||||
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 (
|
||||
<figure
|
||||
className="max-w-sm overflow-hidden rounded-2xl bg-foreground/[0.04] shadow-[0_0_0_1px_rgba(0,0,0,0.06)]"
|
||||
data-attachment-id={attachmentId}
|
||||
>
|
||||
{previewUrl
|
||||
? (
|
||||
<img
|
||||
src={previewUrl}
|
||||
alt={caption}
|
||||
className="max-h-80 w-full object-contain outline outline-1 -outline-offset-1 outline-black/10"
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<div className="flex min-h-28 items-center justify-center gap-2 px-4 text-sm text-muted-foreground">
|
||||
<FileImage className="h-5 w-5" aria-hidden="true" />
|
||||
{failed ? '附件预览不可用' : '正在加载附件…'}
|
||||
</div>
|
||||
)}
|
||||
<figcaption className="truncate px-3 py-2 font-mono text-[11px] text-muted-foreground">
|
||||
{mime} · {attachmentId}
|
||||
</figcaption>
|
||||
</figure>
|
||||
);
|
||||
});
|
||||
Reference in new issue
Block a user