diff --git a/components/system/Files/FileManager.tsx b/components/system/Files/FileManager.tsx index 479d6f1c..3303626e 100644 --- a/components/system/Files/FileManager.tsx +++ b/components/system/Files/FileManager.tsx @@ -1,4 +1,5 @@ import FileEntry from 'components/system/Files/FileEntry'; +import useFileDrop from 'hooks/useFileDrop'; import useFiles from 'hooks/useFiles'; import { basename, extname, resolve } from 'path'; import StyledFileManager from 'styles/components/system/Files/StyledFileManager'; @@ -7,16 +8,20 @@ type FileManagerProps = { directory: string; }; -const FileManager = ({ directory }: FileManagerProps): JSX.Element => ( - - {useFiles(directory, (file) => ( - - ))} - -); +const FileManager = ({ directory }: FileManagerProps): JSX.Element => { + const { files, getFiles } = useFiles(directory); + + return ( + + {files.map((file) => ( + + ))} + + ); +}; export default FileManager; diff --git a/hooks/useFileDrop.ts b/hooks/useFileDrop.ts new file mode 100644 index 00000000..95a7770c --- /dev/null +++ b/hooks/useFileDrop.ts @@ -0,0 +1,42 @@ +import { useFileSystem } from 'contexts/fileSystem'; +import { useCallback } from 'react'; + +const haltDragEvent = (event: React.DragEvent): void => { + event.preventDefault(); + event.stopPropagation(); +}; + +type FileDrop = { + onDragOver: (event: React.DragEvent) => void; + onDrop: (event: React.DragEvent) => void; +}; + +const useFileDrop = (directory: string, getFiles: () => void): FileDrop => { + const { fs } = useFileSystem(); + const onDrop = useCallback( + (event: React.DragEvent) => { + haltDragEvent(event); + + const { files: [file] = [] } = event.dataTransfer || {}; + const reader = new FileReader(); + + reader.onload = ({ target }) => { + fs?.writeFile( + `${directory}/${file.name}`, + Buffer.from(new Uint8Array(target?.result as ArrayBuffer)), + getFiles + ); + }; + + reader.readAsArrayBuffer(file); + }, + [directory, fs, getFiles] + ); + + return { + onDragOver: haltDragEvent, + onDrop + }; +}; + +export default useFileDrop; diff --git a/hooks/useFiles.ts b/hooks/useFiles.ts index 16a167f7..4ba9ba03 100644 --- a/hooks/useFiles.ts +++ b/hooks/useFiles.ts @@ -1,20 +1,25 @@ import { useFileSystem } from 'contexts/fileSystem'; -import { useEffect, useState } from 'react'; +import { useCallback, useEffect, useState } from 'react'; -const useFiles = ( - directory: string, - callback: (file: string) => JSX.Element -): JSX.Element[] => { +type Files = { + files: string[]; + getFiles: () => void; +}; + +const useFiles = (directory: string): Files => { const [files, setFiles] = useState([]); const { fs } = useFileSystem(); + const getFiles = useCallback( + () => fs?.readdir(directory, (_error, contents = []) => setFiles(contents)), + [directory, fs] + ); - useEffect(() => { - if (fs) { - fs.readdir(directory, (_error, contents = []) => setFiles(contents)); - } - }, [directory, fs]); + useEffect(getFiles, [getFiles]); - return files.map(callback); + return { + files, + getFiles + }; }; export default useFiles; diff --git a/tsconfig.json b/tsconfig.json index cf575c7e..a8aceb89 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "compilerOptions": { "baseUrl": ".", + "downlevelIteration": true, "target": "es5", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true,