feat: native drag of files out of the desktop app

This commit is contained in:
LukeGus committed 2026-11-06 09:30:10 -06:00
1 parent a055291fa4
commit 30db4f8024
4 files changed
+28

No files matched your search

+1
View File
@@ -4,6 +4,7 @@
### Added
- Plugins in the desktop app can drag files out to Explorer or Finder
- Termix actions: plugins can declare what they do once, and it works from the API with permission checks, dry runs, run history and approvals
- API keys can be limited to reading or running actions, when an admin makes them
- A click on a host can open its host page, when a plugin offers one
+23
View File
@@ -657,6 +657,12 @@ function createManagedTempFile(fileName, content, encoding = "utf8") {
return { tempId, path: filePath };
}
function dragIcon() {
// Windows cancels a drag with an empty icon
const buf = Buffer.alloc(16 * 16 * 4, 0x99);
return nativeImage.createFromBitmap(buf, { width: 16, height: 16 });
}
function cleanupManagedTempFile(tempId) {
const temp = tempFiles.get(tempId);
if (!temp) return;
@@ -1961,6 +1967,23 @@ ipcMain.handle("start-drag-to-desktop", (event, dragData) => {
}
});
// Must run synchronously inside the renderer's dragstart, files must exist.
ipcMain.on("start-drag-files", (event, tempIds) => {
try {
const files = (Array.isArray(tempIds) ? tempIds : [])
.map((id) => tempFiles.get(id)?.path)
.filter((p) => p && fs.existsSync(p));
if (files.length === 0) return;
event.sender.startDrag({
file: files[0],
files,
icon: dragIcon(),
});
} catch (error) {
logToFile("Failed to start drag:", error.message);
}
});
ipcMain.handle("cleanup-temp-file", (_event, tempId) => {
try {
cleanupManagedTempFile(tempId);
+1
View File
@@ -91,6 +91,7 @@ contextBridge.exposeInMainWorld("electronAPI", {
ipcRenderer.invoke("create-temp-folder", folderData),
startDragToDesktop: (dragData) =>
ipcRenderer.invoke("start-drag-to-desktop", dragData),
startDragFiles: (tempIds) => ipcRenderer.send("start-drag-files", tempIds),
cleanupTempFile: (tempId) => ipcRenderer.invoke("cleanup-temp-file", tempId),
// Native web views placed over an element of the page (WebContentsView).
+3
View File
@@ -112,6 +112,9 @@ export interface ElectronAPI {
error?: string;
}>;
/** Start a native drag of temp files. Call it synchronously in dragstart. */
startDragFiles?: (tempIds: string[]) => void;
cleanupTempFile: (tempId: string) => Promise<{
success: boolean;
error?: string;