fix(webui): enable copy-paste and drag/drop for image and file uploads#546
fix(webui): enable copy-paste and drag/drop for image and file uploads#546Nithishvb wants to merge 2 commits intotruffle-ai:mainfrom
Conversation
|
@Nithishvb is attempting to deploy a commit to the Shaunak's projects Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughInputArea.tsx adds drag-and-drop and clipboard paste handling for images and PDFs, new handlers and state for drag events, file reading/validation flows, and a drag-overlay UI; attachments are stored as imageData/fileData and integrated with existing paste/change handlers. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Fix all issues with AI agents
In `@packages/webui/components/InputArea.tsx`:
- Around line 1025-1044: handleDrop currently iterates all dropped files but
imageData/fileData are single-value states so later files overwrite earlier
ones; change handleDrop to only process the first image and the first PDF found
(e.g., find the first file where file.type.startsWith('image/') and the first
where file.type === 'application/pdf') and call handlePasteImageFile and
handleFile at most once each, update the comment from "Process all dropped image
files" to reflect "Process first image and first PDF only", and optionally
trigger a user warning if more than one image/PDF was dropped.
- Around line 775-790: The handlePasteImageFile function currently has a
duplicated image type check and an unnecessary async signature; remove the
second redundant if (!file.type.startsWith('image/')) block and convert the
function to a plain (non-async) function, replace the initial
console.error('Invalid file type') with showUserError('Please select a valid
image file.') so user-facing validation uses showUserError, keep the
MAX_FILE_SIZE check and FileReader callback logic as-is, and ensure all early
returns remain after the appropriate showUserError calls.
- Around line 886-932: The handleFile function incorrectly rejects images while
claiming to accept them and is unnecessarily async; update handleFile so it
first checks file.type: if it's an image (file.type.startsWith('image/')) call
the existing handlePasteImageFile(file) (or forward the blob/data accordingly)
and return, otherwise if it's a PDF continue the existing FileReader-based PDF
processing (use MAX_FILE_SIZE for size check and showUserError for messages),
and remove the unnecessary async keyword from handleFile; ensure you keep/adjust
calls to setFileData, setFileUploadError, analyticsRef.current.trackFileAttached
and currentSessionId only in the PDF branch and correct error messages for each
branch.
🧹 Nitpick comments (3)
packages/webui/components/InputArea.tsx (3)
625-651: Consider usingstartsWithfor MIME type checks.Using
indexOf('image') !== -1is less precise thanstartsWith('image/')and could theoretically match unexpected MIME types. This matches the pattern used elsewhere in the file (e.g., line 777).Suggested change
- if (item.type.indexOf('image') !== -1) { + if (item.type.startsWith('image/')) {
1176-1197: Consider using lucide-react icon for consistency.The drag overlay uses an inline SVG while the rest of the component uses
lucide-reacticons. Consider usingImageIconorUploadfrom lucide-react for visual consistency.Suggested change
+import { + ... + Upload, +} from 'lucide-react'; // In the overlay: <p className="text-card-foreground font-medium flex items-center gap-2"> - <svg - className="w-5 h-5" - fill="none" - stroke="currentColor" - viewBox="0 0 24 24" - > - <path - strokeLinecap="round" - strokeLinejoin="round" - strokeWidth={2} - d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" - /> - </svg> + <Upload className="w-5 h-5" /> Drop images or PDFs here </p>
775-884: Consider extracting shared image processing logic.
handlePasteImageFile(lines 775-828) andhandleImageChange(lines 830-884) contain nearly identical logic for file validation, reading, MIME type extraction, state updates, analytics tracking, and error handling. This duplication could be reduced by extracting the shared logic into a helper function.
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/webui/components/InputArea.tsx (1)
606-652: Stop text handling after a file paste is consumed.
handlePastecontinues with text logic even after a file/picture paste is handled, which can inject unintended text (e.g., file path strings) alongside the attachment. Consider returning a boolean fromhandleFilePasteand early‑returning inhandlePaste.Suggested fix
- const handlePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => { - handleFilePaste(e); + const handlePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => { + if (handleFilePaste(e)) return; const pasted = e.clipboardData.getData('text/plain'); if (!pasted) return; if (pasted.length <= LARGE_PASTE_THRESHOLD) return; e.preventDefault(); const attach = window.confirm( 'Large text detected. Attach as a file instead of inflating the input?\n(OK = attach as file, Cancel = paste truncated preview)' ); if (attach) { setFileData({ data: toBase64(pasted), mimeType: 'text/plain', filename: 'pasted.txt', }); } else { const preview = pasted.slice(0, LARGE_PASTE_THRESHOLD); setText((prev) => prev + preview); } }; - const handleFilePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => { + const handleFilePaste = (e: React.ClipboardEvent<HTMLTextAreaElement>) => { const items = e.clipboardData?.items; - if (!items) return; + if (!items) return false; for (let i = 0; i < items.length; i++) { const item = items[i]; if (item.type.indexOf('image') !== -1) { e.preventDefault(); const file = item.getAsFile(); if (file) { handlePasteImageFile(file); } - return; + return true; } if (item.type === 'application/pdf') { e.preventDefault(); const file = item.getAsFile(); if (file) { handleFile(file); } - return; + return true; } } + return false; };
♻️ Duplicate comments (1)
packages/webui/components/InputArea.tsx (1)
1012-1031: Multi‑file drop still overwrites attachments.Same issue as previously noted: the loop processes all files, but state only stores one image/file, so later files overwrite earlier ones. This is still present.
Release Note
Closes #482
pnpm changeset(select packages + bump)Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.