import { Text, useMediaQuery, useTheme, useToasts } from "@geist-ui/core/dist" 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" import byteToMB from "@lib/byte-to-mb" function FileDropzone({ setDocs }: { setDocs: (docs: Document[]) => void }) { const { palette } = useTheme() const { setToast } = useToasts() const isMobile = useMediaQuery("xs", { match: "down" }) 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) => { // 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}:
  • )) const verb = isMobile ? "tap" : "click" return (
    {!isDragActive && (

    Drag some files here, or {verb} to select files

    )} {isDragActive && Release to drop the files here}
    {fileRejections.length > 0 && ( )}
    ) } export default FileDropzone