Skip to content

fix(webui): enable copy-paste and drag/drop for image and file uploads#546

Open
Nithishvb wants to merge 2 commits intotruffle-ai:mainfrom
Nithishvb:fix/webui-file-upload
Open

fix(webui): enable copy-paste and drag/drop for image and file uploads#546
Nithishvb wants to merge 2 commits intotruffle-ai:mainfrom
Nithishvb:fix/webui-file-upload

Conversation

@Nithishvb
Copy link
Copy Markdown

@Nithishvb Nithishvb commented Jan 21, 2026

Release Note

Closes #482

  • No release needed (docs/chore/test-only/private package)
  • Changeset added via pnpm changeset (select packages + bump)
    • Bump type: Patch / Minor / Major (choose patch for all if unsure)
    • Packages: ...

Summary by CodeRabbit

  • New Features
    • Drag-and-drop support for images and PDFs in the input area.
    • Clipboard paste support for images and PDFs.
    • Visual overlay feedback while dragging files over the input area.
    • Unified attachment handling: pasted or dropped files are surfaced and managed directly within the input area.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel bot commented Jan 21, 2026

@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.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 21, 2026

📝 Walkthrough

Walkthrough

InputArea.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

Cohort / File(s) Summary
Drag-and-drop support
packages/webui/components/InputArea.tsx
Added isDragging state and handlers (handleDragOver, handleDragEnter, handleDragLeave, handleDrop) to detect drops and toggle a drag-overlay prompting users to drop images or PDFs.
Clipboard paste support
packages/webui/components/InputArea.tsx
Added handleFilePaste to parse clipboard items and delegate to image/PDF handlers; integrated with existing handlePaste.
File processing & validation
packages/webui/components/InputArea.tsx
Implemented handlePasteImageFile to read image data URLs, validate size/type, extract MIME type, store as imageData, and emit analytics. Implemented handleFile to read PDFs/images as data URLs and store as fileData.
UI integration
packages/webui/components/InputArea.tsx
Integrated file paste/drop flows with handlePdfChange/handleImageChange and extended the editor UI to show/manage attachments and the drag overlay when isDragging is true.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped into the editor bright,
Dragged a screenshot down from flight,
Pasted a PDF with cheer,
Attachments now appear—
Hooray, the workflow feels just right! 📎✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main feature addition: enabling copy-paste and drag-and-drop for image and file uploads, which matches the core changes in the pull request.
Linked Issues check ✅ Passed The pull request implementation fully addresses the linked issue #482 requirements: it adds copy-paste support via clipboard handlers, drag-and-drop support via event handlers, and supports both images and files without requiring the traditional file upload path.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing copy-paste and drag-and-drop file upload functionality in the InputArea component, with no unrelated modifications introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 using startsWith for MIME type checks.

Using indexOf('image') !== -1 is less precise than startsWith('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-react icons. Consider using ImageIcon or Upload from 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) and handleImageChange (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.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

handlePaste continues 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 from handleFilePaste and early‑returning in handlePaste.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add copy-paste + drag/drop images/files for the webUI

1 participant