Repository navigation
[Fix] Dragging files into the chat input fails unless Shift is held - #2184
zoomote2[bot] wants to merge 1 commit into
Conversation
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one): 1
Please check the settings in the CodeRabbit UI or the
|
|
1 issue outstanding. See session
Reviewed 92e4812 |
Review statusThis PR was opened by an automated account. A human maintainer must verify the change intent, provenance, and validation before merging. Current step: Mark the PR ready. Required CI must pass before CodeRabbit starts. Review-state labels are managed by this workflow; do not edit them manually. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
| // Data transfer types that signal a file-oriented drag rather than an in-webview | ||
| // text selection drag. "Files" covers drags from the OS file manager; the | ||
| // remaining types are set by VS Code when dragging resources from the Explorer | ||
| // or editor tabs, in local and remote workspaces alike (see fillEditorsDragData | ||
| // in VS Code's workbench drag-and-drop code). | ||
| const FILE_DRAG_DATA_TRANSFER_TYPES = [ | ||
| "Files", | ||
| "text/uri-list", | ||
| "ResourceURIs", | ||
| "application/vnd.code.files", | ||
| "application/vnd.code.uri-list", | ||
| ] | ||
|
|
||
| const isFileDrag = (dataTransfer: DataTransfer): boolean => | ||
| FILE_DRAG_DATA_TRANSFER_TYPES.some((type) => dataTransfer.types.includes(type)) |
There was a problem hiding this comment.
Two of these five types can never match a real drag in the webview, and the matching itself is case-sensitive against an API that lowercases.
- Chromium exposes custom drag types in
DataTransfer.typeslowercased. VS Code's owncontainsDragTypehelper (vs/platform/dnd/browser/dnd.ts) lowercases both sides for exactly this reason, with the comment "somehow the types are lowercase". Sotypes.includes("ResourceURIs")can never succeed. - The spelling is also stale: VS Code's
DataTransfers.RESOURCESis"ResourceURLs", not"ResourceURIs"(verified invs/base/browser/dnd.tson current main and 1.96; this repo pins VS Code types at 1.100). application/vnd.code.filesis not a VS Code type.fillEditorsDragDatasetstext/plain,text/uri-list,application/vnd.code.uri-list(INTERNAL_URI_LIST),ResourceURLs, andCodeEditors; the internal constants areCodeDataTransfers.EDITORS = "CodeEditors"andCodeDataTransfers.FILES = "CodeFiles".
The fix still works today because Explorer/editor-tab drags also carry application/vnd.code.uri-list and text/uri-list, which happen to be all-lowercase and match exactly. But the two dead entries give false confidence — the new tests pass only because they synthesize exact-case payloads Chromium cannot produce — and acceptance would silently regress to the issue #2139 behavior if VS Code ever stops setting the uri-list types. Comparing case-insensitively (mirroring containsDragType) and using the real type names removes both risks:
| // Data transfer types that signal a file-oriented drag rather than an in-webview | |
| // text selection drag. "Files" covers drags from the OS file manager; the | |
| // remaining types are set by VS Code when dragging resources from the Explorer | |
| // or editor tabs, in local and remote workspaces alike (see fillEditorsDragData | |
| // in VS Code's workbench drag-and-drop code). | |
| const FILE_DRAG_DATA_TRANSFER_TYPES = [ | |
| "Files", | |
| "text/uri-list", | |
| "ResourceURIs", | |
| "application/vnd.code.files", | |
| "application/vnd.code.uri-list", | |
| ] | |
| const isFileDrag = (dataTransfer: DataTransfer): boolean => | |
| FILE_DRAG_DATA_TRANSFER_TYPES.some((type) => dataTransfer.types.includes(type)) | |
| // Data transfer types that signal a file-oriented drag rather than an in-webview | |
| // text selection drag. Chromium exposes custom drag types in DataTransfer.types | |
| // lowercased (VS Code works around the same behavior in its containsDragType | |
| // helper), so every entry here is lowercase. "files" covers drags from the OS | |
| // file manager; the remaining types are set by VS Code when dragging resources | |
| // from the Explorer or editor tabs, in local and remote workspaces alike (see | |
| // fillEditorsDragData in VS Code's workbench drag-and-drop code). | |
| const FILE_DRAG_DATA_TRANSFER_TYPES = [ | |
| "files", | |
| "text/uri-list", | |
| "resourceurls", | |
| "codeeditors", | |
| "codefiles", | |
| "application/vnd.code.uri-list", | |
| ] | |
| const isFileDrag = (dataTransfer: DataTransfer): boolean => { | |
| const dragTypes = dataTransfer.types.map((type) => type.toLowerCase()) | |
| return FILE_DRAG_DATA_TRANSFER_TYPES.some((type) => dragTypes.includes(type)) | |
| } |
Related GitHub Issue
Closes: #2139
Description
Users cannot drag files from the Explorer into the chat input. The drop works only when they hold Shift. It also fails about 9 times of 10 with Shift held.
Root cause: PR #1953 added a Shift gate to the
onDragOverhandler of the chat input. The handler did not callpreventDefault()when Shift was not held. The browser then treated the input as an invalid drop target. Thedropevent never fired. This affects local and remote (SSH) workspaces alike.The drop was also not stable with Shift held. A drop target is valid only when the last
dragoverevent before the drop was canceled. Users press Shift after they start the drag. When the pointer does not move after that, no newdragoverevent fires. The last event still reportsshiftKey: false. The drop fails.This PR removes the gate for file-oriented drags. The handler now calls
preventDefault()when the drag payload contains a file-oriented data transfer type:Files- drags from the OS file manager.text/uri-list- URI list drags.ResourceURIs,application/vnd.code.files,application/vnd.code.uri-list- types that VS Code sets for Explorer and editor tab drags (seefillEditorsDragDatain the VS Code workbench).VS Code sets these types in local and remote (SSH) workspaces alike. The remote payload also works: the drop handler receives the plain-text path, and
convertToMentionPathalready stripsvscode-remote://prefixes.Plain text drags inside the input, such as moving a selection, keep the native browser behavior. Shift still works as before. It is no longer necessary.
Test Procedure
webview-ui/src/components/chat/__tests__/ChatTextArea.spec.tsxunderdragover acceptance. They cover: Explorer-style drags without Shift (accepted), OS file drags without Shift (accepted), each single file type (accepted), plain text drags without Shift (rejected, native behavior kept), and plain text drags with Shift (accepted).pnpm --dir webview-ui exec vitest run src/components/chat/__tests__/ChatTextArea.spec.tsx: 73 of 73 tests pass.pnpm --dir webview-ui exec eslinton both changed files: clean, no new suppressions.pnpm --dir webview-ui run check-types: clean.pnpm testfrom the repository root: 11,316 tests pass, 14 of 14 turbo tasks succeed. One unrelated test insrc/__tests__/extension.spec.tsfailed once under full-suite parallel load. It passed on retry and in isolation, on both clean and patched trees.Pre-Submission Checklist
webview-ui/AGENTS.md, behavior-only changes belong in Vitest, not in a*.visual.tsxsnapshot.Visual Snapshots
None. This change does not alter static rendered state. The Zoo Code webview runs only inside VS Code, so no browser screenshot of the extension UI was possible in this environment.
Videos (interaction / animation only)
None. The drag interaction cannot be recorded in this environment because the webview runs only inside VS Code. The Vitest suite covers the acceptance logic.
Documentation Updates
docs/tips-and-tricks.mdtold users to hold Shift while they drag files. A paired PR inZoo-Code-Org/Zoo-Code-Docsremoves that instruction. See the Related PRs section.Additional Notes
ResourceURIs,application/vnd.code.files, andapplication/vnd.code.uri-listtype names come from the VS Code workbench drag-and-drop source. They are stable public drag payload markers used across VS Code versions.Related PRs
Get in Touch
Discord: taltas1 (opened by Roomote on behalf of Toray Altas)