145 lines
3.7 KiB
JavaScript
145 lines
3.7 KiB
JavaScript
import React, { useState, useRef, useEffect } from "react";
|
|
|
|
import { useDropzone } from "react-dropzone";
|
|
import resizeImage from "resize-image";
|
|
|
|
import Loader from "../../loader";
|
|
|
|
import { toastr } from "../../";
|
|
|
|
import { ColorTheme, ThemeType } from "@docspace/common/components/ColorTheme";
|
|
import StyledDropzone from "./StyledDropzone";
|
|
|
|
const ONE_MEGABYTE = 1024 * 1024;
|
|
const COMPRESSION_RATIO = 2;
|
|
const NO_COMPRESSION_RATIO = 1;
|
|
|
|
const Dropzone = ({ t, setUploadedFile, isDisabled }) => {
|
|
const [loadingFile, setLoadingFile] = useState(false);
|
|
const mount = useRef(false);
|
|
const timer = useRef(null);
|
|
|
|
useEffect(() => {
|
|
mount.current = true;
|
|
return () => {
|
|
mount.current = false;
|
|
timer.current && clearTimeout(timer.current);
|
|
};
|
|
}, []);
|
|
|
|
async function resizeRecursiveAsync(
|
|
img,
|
|
canvas,
|
|
compressionRatio = COMPRESSION_RATIO,
|
|
depth = 0
|
|
) {
|
|
const data = resizeImage.resize(
|
|
canvas,
|
|
img.width / compressionRatio,
|
|
img.height / compressionRatio,
|
|
resizeImage.JPEG
|
|
);
|
|
|
|
const file = await fetch(data)
|
|
.then((res) => res.blob())
|
|
.then((blob) => {
|
|
const file = new File([blob], "File name", {
|
|
type: "image/jpg",
|
|
});
|
|
return file;
|
|
});
|
|
|
|
const stepMessage = `Step ${depth + 1}`;
|
|
const sizeMessage = `size = ${file.size} bytes`;
|
|
const compressionRatioMessage = `compressionRatio = ${compressionRatio}`;
|
|
|
|
console.log(`${stepMessage} ${sizeMessage} ${compressionRatioMessage}`);
|
|
|
|
if (file.size < ONE_MEGABYTE) {
|
|
return file;
|
|
}
|
|
|
|
if (depth > 5) {
|
|
console.log("start");
|
|
throw new Error("recursion depth exceeded");
|
|
}
|
|
|
|
return await resizeRecursiveAsync(
|
|
img,
|
|
canvas,
|
|
compressionRatio + 1,
|
|
depth + 1
|
|
);
|
|
}
|
|
|
|
const onDrop = async ([file]) => {
|
|
timer.current = setTimeout(() => {
|
|
setLoadingFile(true);
|
|
}, 50);
|
|
const imageBitMap = await createImageBitmap(file);
|
|
|
|
const width = imageBitMap.width;
|
|
const height = imageBitMap.height;
|
|
const canvas = resizeImage.resize2Canvas(imageBitMap, width, height);
|
|
|
|
resizeRecursiveAsync(
|
|
{ width, height },
|
|
canvas,
|
|
file.size > ONE_MEGABYTE ? COMPRESSION_RATIO : NO_COMPRESSION_RATIO
|
|
)
|
|
.then((file) => {
|
|
if (mount.current) {
|
|
setUploadedFile(file);
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
if (
|
|
error instanceof Error &&
|
|
error.message === "recursion depth exceeded"
|
|
) {
|
|
toastr.error(t("CreateEditRoomDialog:SizeImageLarge"));
|
|
}
|
|
console.error(error);
|
|
})
|
|
.finally(() => {
|
|
timer.current && clearTimeout(timer.current);
|
|
if (mount.current) {
|
|
setLoadingFile(false);
|
|
}
|
|
});
|
|
};
|
|
|
|
const { getRootProps, getInputProps } = useDropzone({
|
|
maxFiles: 1,
|
|
noClick: isDisabled,
|
|
noKeyboard: isDisabled,
|
|
// maxSize: 1000000,
|
|
accept: ["image/png", "image/jpeg"],
|
|
onDrop,
|
|
});
|
|
|
|
return (
|
|
<StyledDropzone $isLoading={loadingFile}>
|
|
{loadingFile && (
|
|
<Loader className="dropzone_loader" size="30px" type="track" />
|
|
)}
|
|
<div {...getRootProps({ className: "dropzone" })}>
|
|
<input {...getInputProps()} />
|
|
<div className="dropzone-link">
|
|
<ColorTheme className="dropzone-link-main" themeId={ThemeType.Link}>
|
|
{t("CreateEditRoomDialog:DropzoneTitleLink")}
|
|
</ColorTheme>
|
|
<span className="dropzone-link-secondary">
|
|
{t("CreateEditRoomDialog:DropzoneTitleSecondary")}
|
|
</span>
|
|
</div>
|
|
<div className="dropzone-exsts">
|
|
{t("CreateEditRoomDialog:DropzoneTitleExsts")}
|
|
</div>
|
|
</div>
|
|
</StyledDropzone>
|
|
);
|
|
};
|
|
|
|
export default Dropzone;
|