React Dropzone: onDrop is not getting invoked in Safari

230 Views Asked by At

I have a React Dropzone Component with validators, but the alert I have put on the onDrop function doesn't get called in Safari. It works on Chrome but not on Safari. There are no errors in the console, I am not sure where to start debugging this.

Live Demo: https://codesandbox.io/embed/fast-monad-fmpjfw?fontsize=14&hidenavigation=1&theme=dark

Here is the code to reproduce the issue:

import "./styles.css";

import { useDropzone } from "react-dropzone";
import { fromEvent } from "file-selector";

async function getVideoDuration(videoFile: File | Blob | DataTransferItem) {
  return new Promise<number>((res, rej) => {
    if (!videoFile.type.startsWith("video/")) rej("File must be video");
    const video = document.createElement("video");
    video.preload = "metadata";
    video.onloadeddata = function () {
      res(video.duration);
    };
    let file;
    if (videoFile instanceof DataTransferItem) file = videoFile.getAsFile();
    else file = videoFile;
    if (!file) return res(1);
    video.src = URL.createObjectURL(file);
  });
}

function Basic(props) {
  const {
    getRootProps,
    getInputProps,
    isDragActive,
    isDragReject,
    fileRejections
  } = useDropzone({
    accept: {
      "video/*": []
    },
    noDragEventsBubbling: true,
    maxSize: 5e8,
    maxFiles: 1,
    multiple: false,
    async getFilesFromEvent(event) {
      let files = await fromEvent(event);
      console.log({ files });
      const fileRes = await Promise.all(
        files.map(async (file) => {
          const duration = await getVideoDuration(file).catch(() => 0);
          const isValid = duration < 15 * 60;
          return Object.defineProperty(file, "isValid", {
            value: isValid,
            writable: false
          });
        })
      );
      return fileRes;
    },

    validator(f) {
      let file: (File & { isValid?: boolean }) | null = f;
      if (file.size > 5e8)
        return { message: "File too large (max 500 MB)", code: "FileTooLarge" };
      if (file.isValid === false)
        return {
          message: "File Duration should be less than 15 minutes",
          code: "LargeFileDuration"
        };
      return null;
    },

    onDrop(files) {
      alert("DROPPED");
    }
  });

  return (
    <section className="container">
      <div {...getRootProps({ className: "dropzone" })}>
        <input {...getInputProps()} />
        <p>Drag 'n' drop some files here, or click to select files</p>
      </div>
      <aside>
        <h4>Files</h4>
        <strong style={{ color: "red" }}>
          {
            fileRejections[fileRejections.length - 1]?.errors[
              fileRejections[fileRejections.length - 1].errors.length - 1
            ]?.message
          }
        </strong>
      </aside>
    </section>
  );
}

export default function App() {
  return <Basic />;
}

0

There are 0 best solutions below