feat: Add clipboard image paste support (#651)

This commit is contained in:
teeverc 2025-10-31 18:00:30 -07:00 committed by GitHub
parent 25a9bfb1fd
commit 03d3095ad8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -232,6 +232,60 @@ function PureMultimodalInput({
[setAttachments, uploadFile] [setAttachments, uploadFile]
); );
const handlePaste = useCallback(
async (event: ClipboardEvent) => {
const items = event.clipboardData?.items;
if (!items) return;
const imageItems = Array.from(items).filter((item) =>
item.type.startsWith('image/'),
);
if (imageItems.length === 0) return;
// Prevent default paste behavior for images
event.preventDefault();
setUploadQueue((prev) => [...prev, 'Pasted image']);
try {
const uploadPromises = imageItems.map(async (item) => {
const file = item.getAsFile();
if (!file) return;
return uploadFile(file);
});
const uploadedAttachments = await Promise.all(uploadPromises);
const successfullyUploadedAttachments = uploadedAttachments.filter(
(attachment) =>
attachment !== undefined &&
attachment.url !== undefined &&
attachment.contentType !== undefined,
);
setAttachments((curr) => [
...curr,
...(successfullyUploadedAttachments as Attachment[]),
]);
} catch (error) {
console.error('Error uploading pasted images:', error);
toast.error('Failed to upload pasted image(s)');
} finally {
setUploadQueue([]);
}
},
[setAttachments],
);
// Add paste event listener to textarea
useEffect(() => {
const textarea = textareaRef.current;
if (!textarea) return;
textarea.addEventListener('paste', handlePaste);
return () => textarea.removeEventListener('paste', handlePaste);
}, [handlePaste]);
return ( return (
<div className={cn("relative flex w-full flex-col gap-4", className)}> <div className={cn("relative flex w-full flex-col gap-4", className)}>
{messages.length === 0 && {messages.length === 0 &&