diff --git a/front/src/modules/settings/profile/components/ProfilePictureUploader.tsx b/front/src/modules/settings/profile/components/ProfilePictureUploader.tsx index 5cbe3dfd89aa..0741e53e2719 100644 --- a/front/src/modules/settings/profile/components/ProfilePictureUploader.tsx +++ b/front/src/modules/settings/profile/components/ProfilePictureUploader.tsx @@ -1,3 +1,4 @@ +import { useState } from 'react'; import { getOperationName } from '@apollo/client/utilities'; import { useRecoilState } from 'recoil'; @@ -14,19 +15,47 @@ export function ProfilePictureUploader() { const [uploadPicture] = useUploadProfilePictureMutation(); const [removePicture] = useRemoveProfilePictureMutation(); const [currentUser] = useRecoilState(currentUserState); - async function onUpload(file: File) { + const [uploadController, setUploadController] = + useState(null); + const [error, setError] = useState(null); + + async function handleUpload(file: File) { if (!file) { return; } - await uploadPicture({ - variables: { - file, - }, - refetchQueries: [getOperationName(GET_CURRENT_USER) ?? ''], - }); + + const controller = new AbortController(); + setUploadController(controller); + + try { + const result = await uploadPicture({ + variables: { + file, + }, + context: { + fetchOptions: { + signal: controller.signal, + }, + }, + refetchQueries: [getOperationName(GET_CURRENT_USER) ?? ''], + }); + + setUploadController(null); + setError(null); + return result; + } catch (error) { + setError(error as Error); + } + } + + async function handleAbort() { + if (uploadController) { + uploadController.abort(); + setUploadController(null); + } } - async function onRemove() { + async function handleRemove() { await removePicture({ variables: { where: { @@ -40,8 +69,10 @@ export function ProfilePictureUploader() { return ( ); } diff --git a/front/src/modules/ui/input/image/components/ImageInput.tsx b/front/src/modules/ui/input/image/components/ImageInput.tsx index 24b8f7f3d3b0..67f4aaa51389 100644 --- a/front/src/modules/ui/input/image/components/ImageInput.tsx +++ b/front/src/modules/ui/input/image/components/ImageInput.tsx @@ -75,6 +75,8 @@ type Props = Omit, 'children'> & { picture: string | null | undefined; onUpload?: (file: File) => void; onRemove?: () => void; + onAbort?: () => void; + error?: Error | null; disabled?: boolean; }; @@ -82,6 +84,8 @@ export function ImageInput({ picture, onUpload, onRemove, + onAbort, + error, disabled = false, ...restProps }: Props) { @@ -112,6 +116,7 @@ export function ImageInput({ { if (onUpload) { if (event.target.files) { @@ -136,10 +141,21 @@ export function ImageInput({ disabled={!picture || disabled} fullWidth /> + {onAbort && ( +