Files
papercrate/frontend/src/hooks/documents/useFileDrop.ts
T

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;