diff --git a/emain/preload.ts b/emain/preload.ts index 3ad8d25828..3869c47b3f 100644 --- a/emain/preload.ts +++ b/emain/preload.ts @@ -1,7 +1,7 @@ // Copyright 2025, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import { contextBridge, ipcRenderer, Rectangle, WebviewTag } from "electron"; +import { contextBridge, ipcRenderer, Rectangle, webUtils, WebviewTag } from "electron"; // update type in custom.d.ts (ElectronApi type) contextBridge.exposeInMainWorld("api", { @@ -69,6 +69,7 @@ contextBridge.exposeInMainWorld("api", { openBuilder: (appId?: string) => ipcRenderer.send("open-builder", appId), setBuilderWindowAppId: (appId: string) => ipcRenderer.send("set-builder-window-appid", appId), doRefresh: () => ipcRenderer.send("do-refresh"), + getPathForFile: (file: File): string => webUtils.getPathForFile(file), }); // Custom event for "new-window" diff --git a/frontend/app/view/term/termwrap.ts b/frontend/app/view/term/termwrap.ts index 45ba48351c..d4d2f2ec8b 100644 --- a/frontend/app/view/term/termwrap.ts +++ b/frontend/app/view/term/termwrap.ts @@ -8,6 +8,7 @@ import { TabRpcClient } from "@/app/store/wshrpcutil"; import { atoms, fetchWaveFile, + getApi, getOverrideConfigAtom, getSettingsKeyAtom, globalStore, @@ -197,6 +198,31 @@ export class TermWrap { this.heldData = []; this.handleResize_debounced = debounce(50, this.handleResize.bind(this)); this.terminal.open(this.connectElem); + + this.connectElem.addEventListener("dragover", (e: DragEvent) => { + e.preventDefault(); + if (e.dataTransfer) { + e.dataTransfer.dropEffect = "copy"; + } + }); + this.connectElem.addEventListener("drop", (e: DragEvent) => { + e.preventDefault(); + if (!e.dataTransfer || e.dataTransfer.files.length === 0) { + return; + } + const paths: string[] = []; + for (let i = 0; i < e.dataTransfer.files.length; i++) { + const file = e.dataTransfer.files[i]; + const filePath = getApi().getPathForFile(file); + if (filePath) { + const quoted = "'" + filePath.replace(/'/g, "'\\''") + "'"; + paths.push(quoted); + } + } + if (paths.length > 0) { + this.terminal.paste(paths.join(" ")); + } + }); this.handleResize(); const pasteHandler = this.pasteHandler.bind(this); this.connectElem.addEventListener("paste", pasteHandler, true); diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index d6d2d98f01..d81f3e7abf 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -135,6 +135,7 @@ declare global { openBuilder: (appId?: string) => void; // open-builder setBuilderWindowAppId: (appId: string) => void; // set-builder-window-appid doRefresh: () => void; // do-refresh + getPathForFile: (file: File) => string; // webUtils.getPathForFile }; type ElectronContextMenuItem = {