9bb4942ae7
Reviewed-on: https://git.genarrative.world/git/GenarrativeAI/Genarrative/pulls/95 Co-authored-by: 王德宇 <kvtodev@outlook.com> Co-committed-by: 王德宇 <kvtodev@outlook.com>
117 lines
3.7 KiB
TypeScript
117 lines
3.7 KiB
TypeScript
import { PlatformActionButton } from '@/src/components/common/PlatformActionButton.tsx';
|
|
import { PlatformToolModalShell } from '@/src/components/common/PlatformToolModalShell.tsx';
|
|
import { ResolvedAssetImage } from '@/src/components/ResolvedAssetImage.tsx';
|
|
|
|
import type {
|
|
AttachmentPickerTab,
|
|
EditorAgentAttachmentOption,
|
|
} from './useConversationAttachments.ts';
|
|
|
|
export function AttachmentPicker({
|
|
open,
|
|
tab,
|
|
canvasOptions,
|
|
libraryOptions,
|
|
selectedKeys,
|
|
attachmentError,
|
|
onTabChange,
|
|
onToggleKey,
|
|
onApply,
|
|
onClose,
|
|
}: {
|
|
open: boolean;
|
|
tab: AttachmentPickerTab;
|
|
canvasOptions: EditorAgentAttachmentOption[];
|
|
libraryOptions: EditorAgentAttachmentOption[];
|
|
selectedKeys: Set<string>;
|
|
attachmentError: string | null;
|
|
onTabChange: (tab: AttachmentPickerTab) => void;
|
|
onToggleKey: (key: string) => void;
|
|
onApply: () => void;
|
|
onClose: () => void;
|
|
}) {
|
|
const visibleOptions = tab === 'canvas' ? canvasOptions : libraryOptions;
|
|
|
|
return (
|
|
<PlatformToolModalShell
|
|
open={open}
|
|
title="选择图片附件"
|
|
size="md"
|
|
onClose={onClose}
|
|
footer={
|
|
<>
|
|
<PlatformActionButton tone="ghost" size="sm" onClick={onClose}>
|
|
取消
|
|
</PlatformActionButton>
|
|
<PlatformActionButton tone="primary" size="sm" onClick={onApply}>
|
|
应用
|
|
</PlatformActionButton>
|
|
</>
|
|
}
|
|
>
|
|
<div className="flex min-h-[18rem] flex-col gap-3">
|
|
<div className="flex gap-2">
|
|
<button
|
|
type="button"
|
|
className={`rounded-full px-3 py-1.5 text-sm ${
|
|
tab === 'canvas'
|
|
? 'bg-slate-900 text-white'
|
|
: 'bg-slate-100 text-slate-600'
|
|
}`}
|
|
onClick={() => onTabChange('canvas')}
|
|
>
|
|
画布
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className={`rounded-full px-3 py-1.5 text-sm ${
|
|
tab === 'library'
|
|
? 'bg-slate-900 text-white'
|
|
: 'bg-slate-100 text-slate-600'
|
|
}`}
|
|
onClick={() => onTabChange('library')}
|
|
>
|
|
素材库
|
|
</button>
|
|
</div>
|
|
{attachmentError ? (
|
|
<div className="rounded-2xl bg-amber-50 px-3 py-2 text-sm text-amber-700">
|
|
{attachmentError}
|
|
</div>
|
|
) : null}
|
|
<div className="grid grid-cols-2 gap-2 overflow-y-auto sm:grid-cols-3">
|
|
{visibleOptions.map((option) => {
|
|
const label =
|
|
option.attachment.label?.trim() || option.attachment.referenceId;
|
|
return (
|
|
<label
|
|
key={option.key}
|
|
className="flex cursor-pointer flex-col gap-2 rounded-2xl border border-slate-200 bg-white p-2 text-sm text-slate-700 shadow-sm"
|
|
>
|
|
<ResolvedAssetImage
|
|
src={
|
|
option.attachment.thumbnailSrc ?? option.attachment.imageSrc
|
|
}
|
|
objectKey={option.attachment.objectKey}
|
|
refreshKey={option.attachment.referenceId}
|
|
alt=""
|
|
className="aspect-square rounded-xl bg-slate-100 object-cover"
|
|
/>
|
|
<span className="flex items-center gap-2">
|
|
<input
|
|
type="checkbox"
|
|
aria-label={`选择${option.sourceLabel}图片 ${label}`}
|
|
checked={selectedKeys.has(option.key)}
|
|
onChange={() => onToggleKey(option.key)}
|
|
/>
|
|
<span className="truncate">{label}</span>
|
|
</span>
|
|
</label>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</PlatformToolModalShell>
|
|
);
|
|
}
|