import { Text, useTheme, useToasts } from '@geist-ui/core' import { memo } from 'react' import { useDropzone } from 'react-dropzone' import styles from './drag-and-drop.module.css' import type { Document } from '@lib/types' import generateUUID from '@lib/generate-uuid' import { allowedFileTypes, allowedFileNames, allowedFileExtensions } from '@lib/constants' function FileDropzone({ setDocs }: { setDocs: ((docs: Document[]) => void) }) { const { palette } = useTheme() const { setToast } = useToasts() const onDrop = async (acceptedFiles: File[]) => { const newDocs = await Promise.all(acceptedFiles.map((file) => { return new Promise((resolve) => { const reader = new FileReader() reader.onabort = () => setToast({ text: 'File reading was aborted', type: 'error' }) reader.onerror = () => setToast({ text: 'File reading failed', type: 'error' }) reader.onload = () => { const content = reader.result as string resolve({ title: file.name, content, id: generateUUID() }) } reader.readAsText(file) }) })) setDocs(newDocs) } const validator = (file: File) => { const byteToMB = (bytes: number) => Math.round(bytes / 1024 / 1024 * 100) / 100 // TODO: make this configurable const maxFileSize = 50000000; if (file.size > maxFileSize) { return { code: 'file-too-big', message: 'File is too big. Maximum file size is ' + byteToMB(maxFileSize) + ' MB.', } } // We initially try to use the browser provided mime type, and then fall back to file names and finally extensions if (allowedFileTypes.includes(file.type) || allowedFileNames.includes(file.name) || allowedFileExtensions.includes(file.name?.split('.').pop() || '')) { return null } else { return { code: "not-plain-text", message: `Only plain text files are allowed.` }; } } const { getRootProps, getInputProps, isDragActive, fileRejections } = useDropzone({ onDrop, validator }) const fileRejectionItems = fileRejections.map(({ file, errors }) => (
  • {file.name}:
  • )); return (
    {!isDragActive && Drag some files here, or click to select files} {isDragActive && Release to drop the files here}
    {fileRejections.length > 0 && }
    ) } export default memo(FileDropzone)