104 lines
2.9 KiB
TypeScript
104 lines
2.9 KiB
TypeScript
import { MutableRefObject, useEffect } from 'react';
|
|
|
|
type FolderId = string | 'root' | null;
|
|
|
|
interface DropOverlayState {
|
|
active: boolean;
|
|
folderName: string | null;
|
|
}
|
|
|
|
interface UseFileDropOptions {
|
|
shellRef: MutableRefObject<HTMLElement | null>;
|
|
token?: string | null;
|
|
currentFolderName: string | null;
|
|
selectedFolder: FolderId;
|
|
handleFileDrop: (dataTransfer: DataTransfer, folderId: FolderId) => Promise<void>;
|
|
hasFiles: (event: DragEvent) => boolean;
|
|
defaultFolderName: string;
|
|
dragCounterRef: MutableRefObject<number>;
|
|
setDropOverlayState: (updater: ((prev: DropOverlayState) => DropOverlayState) | DropOverlayState) => void;
|
|
}
|
|
|
|
const useFileDrop = ({
|
|
shellRef,
|
|
token,
|
|
currentFolderName,
|
|
selectedFolder,
|
|
handleFileDrop,
|
|
hasFiles,
|
|
defaultFolderName,
|
|
dragCounterRef,
|
|
setDropOverlayState,
|
|
}: UseFileDropOptions) => {
|
|
|
|
useEffect(() => {
|
|
if (!token) {
|
|
setDropOverlayState((prev) => ({ ...prev, active: false }));
|
|
dragCounterRef.current = 0;
|
|
return undefined;
|
|
}
|
|
|
|
const handleDragEnter = (event: DragEvent) => {
|
|
if (!hasFiles(event)) return;
|
|
event.preventDefault();
|
|
dragCounterRef.current += 1;
|
|
setDropOverlayState({ active: true, folderName: currentFolderName });
|
|
};
|
|
|
|
const handleDragOver = (event: DragEvent) => {
|
|
if (!hasFiles(event)) return;
|
|
event.preventDefault();
|
|
event.dataTransfer.dropEffect = 'copy';
|
|
};
|
|
|
|
const handleDragLeave = (event: DragEvent) => {
|
|
if (!hasFiles(event)) return;
|
|
dragCounterRef.current = Math.max(0, dragCounterRef.current - 1);
|
|
if (dragCounterRef.current === 0) {
|
|
setDropOverlayState((prev) => ({ ...prev, active: false }));
|
|
}
|
|
};
|
|
|
|
const handleDrop = async (event: DragEvent) => {
|
|
if (!hasFiles(event)) return;
|
|
event.preventDefault();
|
|
dragCounterRef.current = 0;
|
|
setDropOverlayState((prev) => ({ ...prev, active: false }));
|
|
await handleFileDrop(event.dataTransfer, selectedFolder);
|
|
};
|
|
|
|
const dropTarget = shellRef.current;
|
|
if (!dropTarget) {
|
|
return undefined;
|
|
}
|
|
|
|
dropTarget.addEventListener('dragenter', handleDragEnter);
|
|
dropTarget.addEventListener('dragover', handleDragOver);
|
|
dropTarget.addEventListener('dragleave', handleDragLeave);
|
|
dropTarget.addEventListener('drop', handleDrop);
|
|
|
|
return () => {
|
|
dropTarget.removeEventListener('dragenter', handleDragEnter);
|
|
dropTarget.removeEventListener('dragover', handleDragOver);
|
|
dropTarget.removeEventListener('dragleave', handleDragLeave);
|
|
dropTarget.removeEventListener('drop', handleDrop);
|
|
dragCounterRef.current = 0;
|
|
setDropOverlayState((prev) => ({ ...prev, active: false }));
|
|
};
|
|
}, [
|
|
token,
|
|
handleFileDrop,
|
|
currentFolderName,
|
|
defaultFolderName,
|
|
selectedFolder,
|
|
hasFiles,
|
|
shellRef,
|
|
dragCounterRef,
|
|
setDropOverlayState,
|
|
]);
|
|
|
|
return null;
|
|
};
|
|
|
|
export default useFileDrop;
|