Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 24 additions & 11 deletions src/features/file-system/hooks/use-file-system-folder-drop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<void>) => {
export const useFileSystemFolderDrop = (
onDrop: (paths: string[]) => void | Promise<void>,
treatLocalDropAsGlobal = false,
) => {
const [isDraggingOver, setIsDraggingOver] = useState(false);

useEffect(() => {
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -234,7 +247,7 @@ export const useFileSystemFolderDrop = (onDrop: (paths: string[]) => void | Prom
if (unlistenWebview) unlistenWebview();
if (domTeardown) domTeardown();
};
}, [onDrop]);
}, [onDrop, treatLocalDropAsGlobal]);

return { isDraggingOver };
};
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,12 @@ const LOCAL_DROP_TARGET_SELECTOR = [

export function getExternalFileDropRoute(
target: Pick<Element, "closest"> | 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";
}
2 changes: 1 addition & 1 deletion src/features/layout/components/main-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading