2023-08-18 13:33:11 +00:00
|
|
|
import LinkIcon from "@mui/icons-material/Link";
|
|
|
|
import UploadIcon from "@mui/icons-material/Upload";
|
2023-08-10 10:10:09 +00:00
|
|
|
import { Button } from "@mui/material";
|
|
|
|
import React from "react";
|
2023-08-18 13:33:11 +00:00
|
|
|
import { Area } from "react-easy-crop";
|
2023-08-10 10:10:09 +00:00
|
|
|
import { ServerApi } from "../../api/ServerApi";
|
|
|
|
import { ImageCropperDialog } from "../../dialogs/ImageCropperDialog";
|
|
|
|
import { useAlert } from "../../hooks/context_providers/AlertDialogProvider";
|
|
|
|
import getCroppedImg from "../../utils/crop_image";
|
2023-08-11 08:30:04 +00:00
|
|
|
import { isDebug } from "../../utils/debug_utils";
|
2023-08-18 13:27:29 +00:00
|
|
|
import { selectFileToUpload } from "../../utils/files_utils";
|
2023-08-10 10:10:09 +00:00
|
|
|
|
|
|
|
export function UploadPhotoButton(p: {
|
|
|
|
label: string;
|
|
|
|
onPhotoSelected: (b: Blob) => Promise<void>;
|
2023-08-16 10:18:47 +00:00
|
|
|
aspect?: number;
|
2023-08-10 10:10:09 +00:00
|
|
|
}): 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 {
|
2023-08-18 13:27:29 +00:00
|
|
|
const file = await selectFileToUpload({
|
|
|
|
allowedTypes: ServerApi.Config.constraints.photo_allowed_types,
|
|
|
|
maxSize: ServerApi.Config.constraints.photo_max_size,
|
|
|
|
});
|
2023-08-10 10:10:09 +00:00
|
|
|
|
2023-08-18 13:27:29 +00:00
|
|
|
if (file === null) return;
|
2023-08-10 10:10:09 +00:00
|
|
|
|
2023-08-18 13:27:29 +00:00
|
|
|
const tempURL = URL.createObjectURL(file);
|
2023-08-10 10:10:09 +00:00
|
|
|
|
|
|
|
setImageBlob(file);
|
|
|
|
setImageURL(tempURL);
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
2023-08-18 13:27:29 +00:00
|
|
|
alert(`Échec de l'envoi de l'image ! (${e})`);
|
2023-08-10 10:10:09 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2023-08-11 08:30:04 +00:00
|
|
|
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>
|
2023-08-11 08:30:04 +00:00
|
|
|
{/* 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}
|
2023-08-16 10:18:47 +00:00
|
|
|
aspect={p.aspect}
|
2023-08-10 10:10:09 +00:00
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|