-
Notifications
You must be signed in to change notification settings - Fork 650
Add drag-and-drop file support to terminal #2676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Implements drag-and-drop functionality for terminal, matching macOS Terminal behavior. Users can now drag files or folders from Finder directly into the terminal to insert their paths. Features: - Automatically inserts file paths when files are dropped - Handles multiple files (space-separated) - Auto-quotes paths containing spaces - Uses full file paths from Electron File API - Works with files, folders, and multiple selections Usage: Simply drag a file from Finder and drop it into any terminal block. The file path will be inserted at the cursor position. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
Use Electron's webUtils.getPathForFile() API to get the actual full file path instead of just the file name. This matches macOS Terminal behavior where dragging a file inserts its complete path. Before: CV_Document.pdf After: /Users/steven/Downloads/CV_Document.pdf 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
Expose webUtils.getPathForFile through the Electron preload API so the renderer process can get full file system paths from File objects during drag-and-drop operations. Changes: - Added getPathForFile method to preload script using webUtils - Updated ElectronApi TypeScript interface - Simplified terminal drag-drop to use new API via getApi() This properly implements macOS Terminal-style drag-and-drop with full file paths instead of just filenames. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
Added missing import of getApi from @/store/global to fix 'getApi is not defined' error when dropping files. Also added debug logging to help troubleshoot file path retrieval. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
|
Warning Rate limit exceeded@stevenvo has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 10 minutes and 54 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (3)
WalkthroughThe changes implement drag-and-drop file support for the terminal view. A new Electron preload API method Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes
Areas to examine:
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
frontend/types/custom.d.ts (1)
133-133: ElectronApi typing forgetPathForFileis consistent with preload implementationThe new
getPathForFile(file: File): stringentry matches whatemain/preload.tsexposes, so consumers ofgetApi()will be correctly typed. The use of the globalFiletype is consistent with other DOM usages in this file.Minor nit: the
// get-path-for-filecomment follows the “IPC channel name” convention used for other methods, but this function doesn’t go over an IPC channel—it delegates directly towebUtils. If you rely on these comments as a mapping index, consider clarifying or omitting it, but this is purely cosmetic.Based on learnings, these globals will be available everywhere without additional imports, so this addition should “just work” for all renderer code.
frontend/app/view/term/term.tsx (1)
10-10: Drag-and-drop file handling is solid; consider scoping to file drops, trimming logs, and tightening quotingThe overall flow—reading dropped files, resolving full paths via
getApi().getPathForFile, and inserting a space-separated list at the cursor—is good and matches the PR intent.A few refinements to consider:
- Don’t intercept non-file drops unless necessary
handleDragOver,handleDrop,handleDragEnter, andhandleDragLeavealways callpreventDefault/stopPropagation. That will also swallow non-file drops (e.g., text/URL drags), and may interfere with xterm.js’ default behavior for dropping text into the terminal.You can gate the custom behavior to only when files are present:
- // Handle drag and drop - const handleDragOver = React.useCallback((e: React.DragEvent) => { - e.preventDefault(); - e.stopPropagation(); - // Indicate that we can accept the drop - e.dataTransfer.dropEffect = "copy"; - }, []); + // Handle drag and drop of local files + const isFileDrop = (e: React.DragEvent) => + Array.from(e.dataTransfer?.types ?? []).includes("Files"); + + const handleDragOver = React.useCallback((e: React.DragEvent) => { + if (!isFileDrop(e)) { + return; + } + e.preventDefault(); + e.stopPropagation(); + // Indicate that we can accept the drop + e.dataTransfer.dropEffect = "copy"; + }, []); @@ - const handleDrop = React.useCallback((e: React.DragEvent) => { - e.preventDefault(); - e.stopPropagation(); - - // Get files from the drop - const files = Array.from(e.dataTransfer.files); + const handleDrop = React.useCallback((e: React.DragEvent) => { + if (!isFileDrop(e)) { + return; + } + e.preventDefault(); + e.stopPropagation(); + + // Get files from the drop + const files = Array.from(e.dataTransfer.files); @@ - const handleDragEnter = React.useCallback((e: React.DragEvent) => { - e.preventDefault(); - e.stopPropagation(); - }, []); + const handleDragEnter = React.useCallback((e: React.DragEvent) => { + if (!isFileDrop(e)) { + return; + } + e.preventDefault(); + e.stopPropagation(); + }, []); @@ - const handleDragLeave = React.useCallback((e: React.DragEvent) => { - e.preventDefault(); - e.stopPropagation(); - }, []); + const handleDragLeave = React.useCallback((e: React.DragEvent) => { + if (!isFileDrop(e)) { + return; + } + e.preventDefault(); + e.stopPropagation(); + }, []);
- Use debug logger instead of
console.logThe multiple
console.log/console.errorcalls ("Drop files:","Paths to insert:","Final path string:") are useful during development but can be noisy in production. Since this module already hasconst dlog = debug("wave:term");, consider using that or removing most logs once you’re confident in the behavior:- console.log("Drop files:", files); @@ - console.log("File:", file.name, "-> Full path:", fullPath); + dlog("file drop: %s -> %s", file.name, fullPath); @@ - console.log("Paths to insert:", paths); @@ - console.log("Final path string:", pathString);
- Quoting edge cases (optional)
Right now, only paths containing a space are wrapped in double quotes, and embedded double quotes are not escaped. That’s fine for most cases, but if you want to be more robust (especially on Windows with unusual folder names), you could:
- Always use double quotes and escape embedded
"; or- Reuse any existing shell-quoting helper you might have in the codebase.
Example (if you’re okay always quoting):
- const pathString = paths.map(path => { - // Quote paths that contain spaces - if (path.includes(" ")) { - return `"${path}"`; - } - return path; - }).join(" "); + const pathString = paths + .map((path) => `"${path.replace(/"/g, '\\"')}"`) + .join(" ");
- Optional UX tweak: keep or restore focus
If you notice that dropping files causes the terminal to lose focus, you may want to call
model.giveFocus()after sending the path so typing can continue seamlessly.Please verify whether xterm.js (or your
TermWrap) previously supported dropping plain text/URLs into the terminal and whether that behavior is still desired alongside file-path drops.Also applies to: 352-403, 405-413, 416-423
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
emain/preload.ts(2 hunks)frontend/app/view/term/term.tsx(2 hunks)frontend/types/custom.d.ts(1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-01T00:57:23.025Z
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 2504
File: frontend/app/aipanel/aipanel-contextmenu.ts:15-16
Timestamp: 2025-11-01T00:57:23.025Z
Learning: In the waveterm codebase, types defined in custom.d.ts are globally available and do not require explicit imports. Backend types defined in gotypes.d.ts are also globally available.
Applied to files:
frontend/types/custom.d.ts
📚 Learning: 2025-10-21T05:09:26.916Z
Learnt from: sawka
Repo: wavetermdev/waveterm PR: 2465
File: frontend/app/onboarding/onboarding-upgrade.tsx:13-21
Timestamp: 2025-10-21T05:09:26.916Z
Learning: In the waveterm codebase, clientData is loaded and awaited in wave.ts before React runs, ensuring it is always available when components mount. This means atoms.client will have data on first render.
Applied to files:
frontend/app/view/term/term.tsx
🔇 Additional comments (1)
emain/preload.ts (1)
4-4: Preload exposure ofgetPathForFileis correctImporting
webUtilsand exposinggetPathForFile(file: File)viacontextBridgematches Electron's documented API design. The implementation is a straightforward pass-through that aligns with the Electron API contract.Verification confirms
webUtils.getPathForFileis available on all Electron-supported platforms (macOS, Windows, and Linux), so no defensive error handling is necessary.Also applies to: 71-71
- Add isFileDrop helper to check if drag contains files - Only preventDefault for file drops, allow text/URL drops through - Remove debug console.log statements - Improve path quoting to handle special shell characters (spaces, quotes) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
5d12dcd to
16d7f51
Compare
Summary
Adds support for dragging files from Finder/Explorer and dropping them into the terminal, which inserts the full file path at the cursor position.
Changes
Use Cases
Test Plan
🤖 Generated with Claude Code