mirror of
https://github.com/xuquan-nikkkki/FolderFile-Splitter-Plugin.git
synced 2026-07-22 12:00:27 +00:00
147 lines
3.6 KiB
TypeScript
147 lines
3.6 KiB
TypeScript
import {
|
|
DndContext,
|
|
DragEndEvent,
|
|
DragOverlay,
|
|
DragStartEvent,
|
|
PointerSensor,
|
|
pointerWithin,
|
|
useSensor,
|
|
useSensors,
|
|
} from "@dnd-kit/core";
|
|
import { snapCenterToCursor } from "@dnd-kit/modifiers";
|
|
import { TAbstractFile, TFile, TFolder } from "obsidian";
|
|
import { useState } from "react";
|
|
import { useShallow } from "zustand/react/shallow";
|
|
|
|
import { useExplorer } from "src/hooks/useExplorer";
|
|
import { useOpenDestinationFolder } from "src/hooks/useSettingsHandler";
|
|
import { ExplorerStore } from "src/store";
|
|
import { isFile, isFolder } from "src/utils";
|
|
|
|
import ExplorerContent from "./Content";
|
|
|
|
const DragAndDropExplorer = () => {
|
|
const { useExplorerStore, plugin } = useExplorer();
|
|
const { settings } = plugin;
|
|
|
|
const {
|
|
expandedFolderPaths,
|
|
moveFile,
|
|
moveFolder,
|
|
expandFolder,
|
|
changeFocusedFolder,
|
|
selectFileAndOpen,
|
|
} = useExplorerStore(
|
|
useShallow((store: ExplorerStore) => ({
|
|
expandedFolderPaths: store.expandedFolderPaths,
|
|
moveFile: store.moveFile,
|
|
moveFolder: store.moveFolder,
|
|
expandFolder: store.expandFolder,
|
|
changeFocusedFolder: store.changeFocusedFolder,
|
|
selectFileAndOpen: store.selectFileAndOpen,
|
|
}))
|
|
);
|
|
|
|
const { openDestinationFolderAfterMove } = settings;
|
|
const { openDestinationFolder } = useOpenDestinationFolder(
|
|
openDestinationFolderAfterMove
|
|
);
|
|
|
|
const [activeItem, setActiveItem] = useState<TAbstractFile | null>(null);
|
|
|
|
const sensors = useSensors(
|
|
useSensor(PointerSensor, {
|
|
activationConstraint: {
|
|
distance: 8,
|
|
},
|
|
})
|
|
);
|
|
|
|
const onDragStart = (e: DragStartEvent) => {
|
|
setActiveItem(e.active.data.current?.item);
|
|
};
|
|
|
|
const isMovingIlleagal = (
|
|
folder: TFolder,
|
|
item: TAbstractFile
|
|
): boolean => {
|
|
const isMovingToSameFolder = folder.path === item.parent?.path;
|
|
const isMovingIntoItself = folder.path === item?.path;
|
|
return isMovingToSameFolder || isMovingIntoItself;
|
|
};
|
|
|
|
const onMoveFile = async (
|
|
file: TFile,
|
|
targetFolder: TFolder
|
|
): Promise<void> => {
|
|
const newPath = targetFolder.path + "/" + file.name;
|
|
await moveFile(file, newPath);
|
|
if (openDestinationFolder) {
|
|
await changeFocusedFolder(targetFolder);
|
|
await selectFileAndOpen(file);
|
|
}
|
|
};
|
|
|
|
const onMoveFolder = async (
|
|
folder: TFolder,
|
|
targetFolder: TFolder
|
|
): Promise<void> => {
|
|
const newPath = targetFolder.path + "/" + folder.name;
|
|
await moveFolder(folder, newPath);
|
|
if (openDestinationFolder) {
|
|
await changeFocusedFolder(targetFolder);
|
|
}
|
|
};
|
|
|
|
const expandTargetFolder = (targetFolder: TFolder) => {
|
|
if (expandedFolderPaths.includes(targetFolder.path)) return;
|
|
expandFolder(targetFolder);
|
|
};
|
|
|
|
const onDragEnd = async (e: DragEndEvent) => {
|
|
const { active, over } = e;
|
|
|
|
const targetFolder = over?.data.current?.item as TFolder | undefined;
|
|
const item = active.data.current?.item as TAbstractFile;
|
|
|
|
if (!targetFolder || isMovingIlleagal(targetFolder, item)) return;
|
|
|
|
if (isFile(item)) {
|
|
await onMoveFile(item, targetFolder);
|
|
} else if (isFolder(item)) {
|
|
await onMoveFolder(item, targetFolder);
|
|
}
|
|
expandTargetFolder(targetFolder);
|
|
onClearActiveItem();
|
|
};
|
|
|
|
const onClearActiveItem = () => {
|
|
setActiveItem(null);
|
|
};
|
|
|
|
const renderOverlayContent = () => {
|
|
if (!activeItem) return null;
|
|
return (
|
|
<div className="ffs__drag-overlay">
|
|
{isFile(activeItem) ? "📄" : "📁"}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<DndContext
|
|
sensors={sensors}
|
|
collisionDetection={pointerWithin}
|
|
onDragStart={onDragStart}
|
|
onDragEnd={onDragEnd}
|
|
onDragCancel={onClearActiveItem}
|
|
>
|
|
<ExplorerContent />
|
|
<DragOverlay modifiers={[snapCenterToCursor]}>
|
|
{renderOverlayContent()}
|
|
</DragOverlay>
|
|
</DndContext>
|
|
);
|
|
};
|
|
|
|
export default DragAndDropExplorer;
|