From dfb3bf51ea9ee545f5eeb32ba867218e9302444b Mon Sep 17 00:00:00 2001 From: Xu Quan Date: Sat, 1 Mar 2025 12:13:28 +0800 Subject: [PATCH] feat: drag folder to change its path --- src/components/Folder.tsx | 50 +++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/src/components/Folder.tsx b/src/components/Folder.tsx index a97bad9..dece1aa 100644 --- a/src/components/Folder.tsx +++ b/src/components/Folder.tsx @@ -1,7 +1,7 @@ import { Menu, TFile, TFolder } from "obsidian"; import { StoreApi, UseBoundStore } from "zustand"; import { useShallow } from "zustand/react/shallow"; -import { useDrop } from "react-dnd"; +import { useDrag, useDrop } from "react-dnd"; import { ArrowDownIcon, ArrowRightIcon, FolderIcon } from "src/assets/icons"; import FolderFileSplitterPlugin from "src/main"; @@ -14,6 +14,8 @@ import { } from "src/hooks/useSettingsHandler"; import useRenderEditableName from "src/hooks/useRenderEditableName"; import { moveFileOrFolder } from "src/utils"; +import { useEffect, useRef } from "react"; +import { getEmptyImage } from "react-dnd-html5-backend"; type Props = { useFileTreeStore: UseBoundStore>; @@ -55,18 +57,33 @@ const Folder = ({ })) ); + const folderRef = useRef(null); + + const [{ isDragging }, drag, preview] = useDrag(() => ({ + type: "FOLDER", + item: folder, + collect: (monitor) => ({ + isDragging: !!monitor.isDragging(), + opacity: monitor.isDragging() ? 0.5 : 1, + }), + })); + const [{ isOver }, drop] = useDrop(() => ({ - accept: "FILE", - drop: (item) => { + accept: ["FILE", "FOLDER"], + drop: async (item: TFolder | TFile) => { + await moveFileOrFolder(plugin.app.fileManager, item, folder); if (item instanceof TFile) { - moveFileOrFolder(plugin.app.fileManager, item, folder).then( - () => { - if (focusedFolder?.path !== folder.path) { - setFocusedFolder(folder); - } - selectFile(item); - } - ); + if (focusedFolder?.path !== folder.path) { + setFocusedFolder(folder); + } + selectFile(item); + } else if (item instanceof TFolder) { + if (!isRoot && !expandedFolderPaths.includes(folder.path)) { + onToggleExpandState(); + } + if (focusedFolder?.path !== item.path) { + setFocusedFolder(item); + } } }, collect: (monitor) => ({ @@ -74,6 +91,8 @@ const Folder = ({ }), })); + drag(drop(folderRef)); + const isFolderExpanded = expandedFolderPaths.includes(folder.path); const folderName = isRoot ? plugin.app.vault.getName() : folder.name; @@ -86,6 +105,10 @@ const Folder = ({ settings.includeSubfolderFilesCount ); + useEffect(() => { + preview(getEmptyImage(), { captureDraggingState: true }); + }, [preview]); + const getFolderNameClassNames = (isEditing: boolean): string => { return ( "ffs-folder-name" + (isEditing ? " ffs-folder-name-edit-mode" : "") @@ -208,10 +231,13 @@ const Folder = ({ return (
setFocusedFolder(folder)} onContextMenu={onShowContextMenu} + style={{ + opacity: isDragging ? 0.5 : 1, + }} >