GeneIT/geneit_app/src/widgets/forms/UploadPhotoButton.tsx

123 lines
3.2 KiB
TypeScript
Raw Normal View History

2023-08-10 10:10:09 +00:00
import { Button } from "@mui/material";
import { filesize } from "filesize";
import React from "react";
import { ServerApi } from "../../api/ServerApi";
import { ImageCropperDialog } from "../../dialogs/ImageCropperDialog";
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
import { Area } from "react-easy-crop";
import getCroppedImg from "../../utils/crop_image";
2023-08-10 11:53:23 +00:00
import UploadIcon from "@mui/icons-material/Upload";
import LinkIcon from "@mui/icons-material/Link";
import { isDebug } from "../../utils/debug_utils";
2023-08-10 10:10:09 +00:00
export function UploadPhotoButton(p: {
label: string;
onPhotoSelected: (b: Blob) => Promise<void>;
}): React.ReactElement {
const [processing, setProcessing] = React.useState(false);
const [imageBlob, setImageBlob] = React.useState<Blob>();
const [imageURL, setImageURL] = React.useState<string>();
const alert = useAlert();
const uploadPhoto = async () => {
try {
// Create file element
const fileEl = document.createElement("input");
fileEl.type = "file";
fileEl.accept =
ServerApi.Config.constraints.photo_allowed_types.join(",");
fileEl.click();
// Wait for a file to be chosen
await new Promise((res, _rej) =>
fileEl.addEventListener("change", () => res(null))
);
if ((fileEl.files?.length ?? 0) === 0) return null;
const file = fileEl.files![0];
// Check file size
if (file.size > ServerApi.Config.constraints.photo_max_size) {
await alert(
`Le fichier sélectionné est trop lourd ! (taille maximale acceptée : ${filesize(
ServerApi.Config.constraints.photo_max_size
)})`
);
return;
}
const tempURL = URL.createObjectURL(fileEl.files![0]);
setImageBlob(file);
setImageURL(tempURL);
} catch (e) {
console.error(e);
alert("Failed to upload custom account image!");
return null;
}
};
const uploadPhotoFromURL = async () => {
const URL = prompt("Image URL ?");
if (URL === null || URL.length === 0) return;
setImageURL(URL);
};
2023-08-10 10:10:09 +00:00
const cancelCrop = () => {
setImageURL(undefined);
};
const submitCrop = async (a: Area | undefined) => {
setProcessing(true);
try {
let blob = imageBlob!;
if (a) {
blob = await getCroppedImg(imageURL!, a!);
}
await p.onPhotoSelected(blob);
setImageBlob(undefined);
setImageURL(undefined);
} catch (e) {
console.error(e);
alert("Echec du traitement de la photo !");
}
setProcessing(false);
};
return (
<>
{/* Upload button */}
2023-08-10 11:53:23 +00:00
<Button
onClick={uploadPhoto}
variant="outlined"
startIcon={<UploadIcon />}
>
{p.label}
</Button>
{/* Upload button (from URL) */}{" "}
{isDebug() && (
<Button
onClick={uploadPhotoFromURL}
variant="outlined"
startIcon={<LinkIcon />}
>
{p.label} from URL
</Button>
)}{" "}
2023-08-10 10:10:09 +00:00
{/* Crop image dialog */}
{imageURL && (
<ImageCropperDialog
processing={processing}
src={imageURL!}
onCancel={cancelCrop}
onSubmit={submitCrop}
/>
)}
</>
);
}