diff --git a/src/features/file-system/hooks/use-file-system-folder-drop.ts b/src/features/file-system/hooks/use-file-system-folder-drop.ts index eba53b129..ea577e3f3 100644 --- a/src/features/file-system/hooks/use-file-system-folder-drop.ts +++ b/src/features/file-system/hooks/use-file-system-folder-drop.ts @@ -89,23 +89,36 @@ function isExternalFileDrag(event: DragEvent): boolean { return isExternalFileDragTypeList(event.dataTransfer?.types); } -function getExternalFileDropRouteAtPosition(position?: { x: number; y: number }) { +function getExternalFileDropRouteAtPosition( + position: { x: number; y: number } | undefined, + treatLocalDropAsGlobal: boolean, +) { if (!position) return "global"; - return getExternalFileDropRoute(resolveClientPoint(position).element); + return getExternalFileDropRoute(resolveClientPoint(position).element, treatLocalDropAsGlobal); } -function isGlobalExternalFileDropEventTarget(event: DragEvent): boolean { +function isGlobalExternalFileDropEventTarget( + event: DragEvent, + treatLocalDropAsGlobal: boolean, +): boolean { return ( - getExternalFileDropRoute(event.target instanceof Element ? event.target : null) === "global" + getExternalFileDropRoute( + event.target instanceof Element ? event.target : null, + treatLocalDropAsGlobal, + ) === "global" ); } /** * Hook to handle drag-and-drop from OS into the application * @param onDrop - Callback when files/folders are dropped (array of paths) + * @param treatLocalDropAsGlobal - Whether local pane surfaces should fall through to onDrop * @returns isDraggingOver - Boolean indicating if a drag is over the window */ -export const useFileSystemFolderDrop = (onDrop: (paths: string[]) => void | Promise) => { +export const useFileSystemFolderDrop = ( + onDrop: (paths: string[]) => void | Promise, + treatLocalDropAsGlobal = false, +) => { const [isDraggingOver, setIsDraggingOver] = useState(false); useEffect(() => { @@ -141,7 +154,7 @@ export const useFileSystemFolderDrop = (onDrop: (paths: string[]) => void | Prom return; } const position = "position" in event.payload ? event.payload.position : undefined; - if (getExternalFileDropRouteAtPosition(position) !== "global") { + if (getExternalFileDropRouteAtPosition(position, treatLocalDropAsGlobal) !== "global") { setIsDraggingOver(false); return; } @@ -165,7 +178,7 @@ export const useFileSystemFolderDrop = (onDrop: (paths: string[]) => void | Prom return; } const position = "position" in event.payload ? event.payload.position : undefined; - if (getExternalFileDropRouteAtPosition(position) !== "global") { + if (getExternalFileDropRouteAtPosition(position, treatLocalDropAsGlobal) !== "global") { setIsDraggingOver(false); return; } @@ -175,7 +188,7 @@ export const useFileSystemFolderDrop = (onDrop: (paths: string[]) => void | Prom const onDomDragOver = (event: DragEvent) => { if (getInternalTabDragData()) return; if (!isExternalFileDrag(event)) return; - if (!isGlobalExternalFileDropEventTarget(event)) { + if (!isGlobalExternalFileDropEventTarget(event, treatLocalDropAsGlobal)) { setIsDraggingOver(false); return; } @@ -187,7 +200,7 @@ export const useFileSystemFolderDrop = (onDrop: (paths: string[]) => void | Prom return; } if (!isExternalFileDrag(event)) return; - if (!isGlobalExternalFileDropEventTarget(event)) { + if (!isGlobalExternalFileDropEventTarget(event, treatLocalDropAsGlobal)) { setIsDraggingOver(false); return; } @@ -197,7 +210,7 @@ export const useFileSystemFolderDrop = (onDrop: (paths: string[]) => void | Prom const onDomEnter = (event: DragEvent) => { if (getInternalTabDragData()) return; if (!isExternalFileDrag(event)) return; - if (!isGlobalExternalFileDropEventTarget(event)) { + if (!isGlobalExternalFileDropEventTarget(event, treatLocalDropAsGlobal)) { setIsDraggingOver(false); return; } @@ -234,7 +247,7 @@ export const useFileSystemFolderDrop = (onDrop: (paths: string[]) => void | Prom if (unlistenWebview) unlistenWebview(); if (domTeardown) domTeardown(); }; - }, [onDrop]); + }, [onDrop, treatLocalDropAsGlobal]); return { isDraggingOver }; }; diff --git a/src/features/file-system/tests/file-system-drop-controller.test.ts b/src/features/file-system/tests/file-system-drop-controller.test.ts index 28a4729de..4d25f50b2 100644 --- a/src/features/file-system/tests/file-system-drop-controller.test.ts +++ b/src/features/file-system/tests/file-system-drop-controller.test.ts @@ -104,6 +104,7 @@ describe("file system drop controller", () => { expect(getExternalFileDropRoute(target("[data-terminal-drop-target]"))).toBe("terminal"); expect(getExternalFileDropRoute(target("[data-pane-container]"))).toBe("local"); + expect(getExternalFileDropRoute(target("[data-pane-container]"), true)).toBe("global"); expect(getExternalFileDropRoute(target("[data-external-file-drop-scope]"))).toBe("local"); expect(getExternalFileDropRoute(target(null))).toBe("global"); expect(getExternalFileDropRoute(null)).toBe("global"); diff --git a/src/features/file-system/utils/file-system-drop-controller.ts b/src/features/file-system/utils/file-system-drop-controller.ts index e808c8672..fd8d4c259 100644 --- a/src/features/file-system/utils/file-system-drop-controller.ts +++ b/src/features/file-system/utils/file-system-drop-controller.ts @@ -67,9 +67,12 @@ const LOCAL_DROP_TARGET_SELECTOR = [ export function getExternalFileDropRoute( target: Pick | null | undefined, + treatLocalDropAsGlobal = false, ): ExternalFileDropRoute { if (!target) return "global"; if (target.closest(TERMINAL_DROP_TARGET_SELECTOR)) return "terminal"; - if (target.closest(LOCAL_DROP_TARGET_SELECTOR)) return "local"; + if (target.closest(LOCAL_DROP_TARGET_SELECTOR)) { + return treatLocalDropAsGlobal ? "global" : "local"; + } return "global"; } diff --git a/src/features/layout/components/main-layout.tsx b/src/features/layout/components/main-layout.tsx index 2edb6aa06..9c39ee11c 100644 --- a/src/features/layout/components/main-layout.tsx +++ b/src/features/layout/components/main-layout.tsx @@ -103,7 +103,7 @@ export function MainLayout() { if (result.openedFolderCount + result.openedFileCount === 0) { toast.warning("No supported dropped files or folders could be opened."); } - }); + }, !rootFolderPath); const sidebarPosition = settings.sidebarPosition; const terminalWidthMode = useTerminalStore((state) => state.widthMode);