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 />;
}