diff --git a/native/avatars/avatar-hooks.js b/native/avatars/avatar-hooks.js --- a/native/avatars/avatar-hooks.js +++ b/native/avatars/avatar-hooks.js @@ -19,10 +19,12 @@ extensionFromFilename, filenameFromPathOrURI, } from 'lib/media/file-utils.js'; +import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import type { ImageAvatarDBContent, UpdateUserAvatarRemoveRequest, } from 'lib/types/avatar-types.js'; +import type { LoadingStatus } from 'lib/types/loading-types.js'; import type { MediaLibrarySelection, MediaMissionFailure, @@ -128,7 +130,13 @@ return selectFromGallery; } -function useSelectFromGalleryAndUpdateUserAvatar(): () => Promise { +const updateUserAvatarLoadingStatusSelector = createLoadingStatusSelector( + updateUserAvatarActionTypes, +); +function useSelectFromGalleryAndUpdateUserAvatar(): [ + () => Promise, + boolean, +] { const dispatchActionPromise = useDispatchActionPromise(); const updateUserAvatarCall = useServerCall(updateUserAvatar); @@ -136,6 +144,20 @@ const processSelectedMedia = useProcessSelectedMedia(); const uploadProcessedMedia = useUploadProcessedMedia(); + const [processingOrUploadInProgress, setProcessingOrUploadInProgress] = + React.useState(false); + + const updateUserAvatarLoadingStatus: LoadingStatus = useSelector( + updateUserAvatarLoadingStatusSelector, + ); + + const inProgress = React.useMemo( + () => + processingOrUploadInProgress || + updateUserAvatarLoadingStatus === 'loading', + [processingOrUploadInProgress, updateUserAvatarLoadingStatus], + ); + const selectFromGalleryAndUpdateUserAvatar = React.useCallback(async () => { const selection: ?MediaLibrarySelection = await selectFromGallery(); if (!selection) { @@ -143,26 +165,34 @@ return; } - const processedMedia = await processSelectedMedia(selection); - if (!processedMedia.success) { + setProcessingOrUploadInProgress(true); + let processedMedia; + try { + processedMedia = await processSelectedMedia(selection); + } catch (e) { console.log('MEDIA_PROCESSING_FAILED'); - // TODO (atul): Clean up any temporary files. + setProcessingOrUploadInProgress(false); + return; + } + + if (!processedMedia || !processedMedia.success) { + console.log('MEDIA_PROCESSING_FAILED'); + setProcessingOrUploadInProgress(false); return; } let uploadedMedia: ?UploadMultimediaResult; try { uploadedMedia = await uploadProcessedMedia(processedMedia); - // TODO (atul): Clean up any temporary files. } catch { console.log('MEDIA_UPLOAD_FAILED'); - // TODO (atul): Clean up any temporary files. + setProcessingOrUploadInProgress(false); return; } if (!uploadedMedia) { console.log('MEDIA_UPLOAD_FAILED'); - // TODO (atul): Clean up any temporary files. + setProcessingOrUploadInProgress(false); return; } @@ -175,6 +205,7 @@ updateUserAvatarActionTypes, updateUserAvatarCall(imageAvatarUpdateRequest), ); + setProcessingOrUploadInProgress(false); }, [ dispatchActionPromise, processSelectedMedia, @@ -183,7 +214,10 @@ uploadProcessedMedia, ]); - return selectFromGalleryAndUpdateUserAvatar; + return React.useMemo( + () => [selectFromGalleryAndUpdateUserAvatar, inProgress], + [selectFromGalleryAndUpdateUserAvatar, inProgress], + ); } function useSelectFromGalleryAndUpdateThreadAvatar( diff --git a/native/avatars/edit-user-avatar.react.js b/native/avatars/edit-user-avatar.react.js --- a/native/avatars/edit-user-avatar.react.js +++ b/native/avatars/edit-user-avatar.react.js @@ -19,7 +19,7 @@ function EditUserAvatar(props: Props): React.Node { const { userID, onPressEmojiAvatarFlow, disabled } = props; - const selectFromGalleryAndUpdateUserAvatar = + const [selectFromGalleryAndUpdateUserAvatar] = useSelectFromGalleryAndUpdateUserAvatar(); const removeUserAvatar = useRemoveUserAvatar();