import useTransferDialog from "components/system/Dialogs/Transfer/useTransferDialog"; import { getEventData, handleFileInputEvent, } from "components/system/Files/FileManager/functions"; import type { DragPosition } from "components/system/Files/FileManager/useDraggableEntries"; import type { CompleteAction } from "components/system/Files/FileManager/useFolder"; import { COMPLETE_ACTION } from "components/system/Files/FileManager/useFolder"; import { useFileSystem } from "contexts/fileSystem"; import { useProcesses } from "contexts/process"; import { useSession } from "contexts/session"; import { basename, extname, join, relative } from "path"; import { useCallback } from "react"; import { DESKTOP_PATH } from "utils/constants"; import { haltEvent, updateIconPositions } from "utils/functions"; export type FileDrop = { onDragLeave?: (event: DragEvent | React.DragEvent) => void; onDragOver: (event: DragEvent | React.DragEvent) => void; onDrop: (event: DragEvent | React.DragEvent) => void; }; type FileDropProps = { callback?: ( path: string, buffer?: Buffer, completeAction?: CompleteAction ) => Promise; directory?: string; id?: string; onDragLeave?: (event: DragEvent | React.DragEvent) => void; onDragOver?: (event: DragEvent | React.DragEvent) => void; updatePositions?: boolean; }; const useFileDrop = ({ callback, directory = DESKTOP_PATH, id, onDragLeave, onDragOver, updatePositions, }: FileDropProps): FileDrop => { const { url } = useProcesses(); const { iconPositions, sortOrders, setIconPositions } = useSession(); const { mkdirRecursive, updateFolder, writeFile } = useFileSystem(); const updateProcessUrl = useCallback( async ( filePath: string, fileData?: Buffer, completeAction?: CompleteAction ): Promise => { if (id) { if (fileData) { const tempPath = join(DESKTOP_PATH, filePath); await mkdirRecursive(DESKTOP_PATH); if (await writeFile(tempPath, fileData, true)) { if (completeAction === COMPLETE_ACTION.UPDATE_URL) { url(id, tempPath); } updateFolder(DESKTOP_PATH, filePath); } } else if (completeAction === COMPLETE_ACTION.UPDATE_URL) { url(id, filePath); } } }, [id, mkdirRecursive, updateFolder, url, writeFile] ); const { openTransferDialog } = useTransferDialog(); return { onDragLeave, onDragOver: (event) => { onDragOver?.(event); haltEvent(event); }, onDrop: (event) => { if (updatePositions && event.target instanceof HTMLElement) { const { files, text } = getEventData(event as React.DragEvent); if (files.length === 0 && text === "") return; const dragPosition = { x: event.clientX, y: event.clientY, } as DragPosition; let fileEntries: string[] = []; if (text) { try { fileEntries = JSON.parse(text) as string[]; } catch { // Ignore failed JSON parsing } if (!Array.isArray(fileEntries)) return; const [firstEntry] = fileEntries; if (!firstEntry) return; if ( firstEntry.startsWith(directory) && basename(firstEntry) === relative(directory, firstEntry) ) { return; } fileEntries = fileEntries.map((entry) => basename(entry)); } else if (files instanceof FileList) { fileEntries = [...files].map((file) => file.name); } else { fileEntries = [...files] .map((file) => file.getAsFile()?.name || "") .filter(Boolean); } fileEntries = fileEntries.map((fileEntry) => { if (!iconPositions[`${directory}/${fileEntry}`]) return fileEntry; let iteration = 0; let entryIteration = ""; do { iteration += 1; entryIteration = `${directory}/${basename( fileEntry, extname(fileEntry) )} (${iteration})${extname(fileEntry)}`; } while (iconPositions[entryIteration]); return basename(entryIteration); }); updateIconPositions( directory, event.target, iconPositions, sortOrders, dragPosition, fileEntries, setIconPositions ); } handleFileInputEvent( event as React.DragEvent, callback || updateProcessUrl, directory, openTransferDialog, Boolean(id) ); }, }; }; export default useFileDrop;