diff --git a/lib/components/base-edit-user-avatar-provider.react.js b/lib/components/base-edit-user-avatar-provider.react.js index 915605ea6..84b483999 100644 --- a/lib/components/base-edit-user-avatar-provider.react.js +++ b/lib/components/base-edit-user-avatar-provider.react.js @@ -1,191 +1,191 @@ // @flow import * as React from 'react'; import { updateUserAvatar, updateUserAvatarActionTypes, } from '../actions/user-actions.js'; import { createLoadingStatusSelector } from '../selectors/loading-selectors.js'; import type { ImageAvatarDBContent, UpdateUserAvatarRequest, } from '../types/avatar-types.js'; import type { LoadingStatus } from '../types/loading-types.js'; import type { MediaLibrarySelection, NativeMediaSelection, } from '../types/media-types.js'; import { useDispatchActionPromise, useServerCall, } from '../utils/action-utils.js'; import { useSelector } from '../utils/redux-utils.js'; export type UserAvatarSelection = | { +needsUpload: true, +mediaSelection: NativeMediaSelection } | { +needsUpload: false, +updateUserAvatarRequest: UpdateUserAvatarRequest }; type RegistrationMode = | { +registrationMode: 'off' } | { +registrationMode: 'on', +successCallback: UserAvatarSelection => mixed, }; const registrationModeOff = { registrationMode: 'off' }; export type EditUserAvatarContextType = { +userAvatarSaveInProgress: boolean, +selectFromGalleryAndUpdateUserAvatar: () => Promise, +updateImageUserAvatar: (selection: NativeMediaSelection) => Promise, +setUserAvatar: (avatarRequest: UpdateUserAvatarRequest) => Promise, +setRegistrationMode: (registrationMode: RegistrationMode) => void, +getRegistrationModeEnabled: () => boolean, }; const EditUserAvatarContext: React.Context = React.createContext(); const updateUserAvatarLoadingStatusSelector = createLoadingStatusSelector( updateUserAvatarActionTypes, ); type Props = { - +displayFailureAlert: () => mixed, + +displayFailureAlert?: () => mixed, +selectFromGallery: () => Promise, +useUploadSelectedMedia: ( setProcessingOrUploadInProgress?: (inProgress: boolean) => mixed, ) => (selection: NativeMediaSelection) => Promise, +children: React.Node, }; function BaseEditUserAvatarProvider(props: Props): React.Node { const { displayFailureAlert, selectFromGallery, useUploadSelectedMedia, children, } = props; const registrationModeRef = React.useRef(registrationModeOff); const dispatchActionPromise = useDispatchActionPromise(); const updateUserAvatarCall = useServerCall(updateUserAvatar); const [userAvatarMediaUploadInProgress, setUserAvatarMediaUploadInProgress] = React.useState(false); const updateUserAvatarLoadingStatus: LoadingStatus = useSelector( updateUserAvatarLoadingStatusSelector, ); const userAvatarSaveInProgress = userAvatarMediaUploadInProgress || updateUserAvatarLoadingStatus === 'loading'; const uploadSelectedMedia = useUploadSelectedMedia( setUserAvatarMediaUploadInProgress, ); const updateImageUserAvatar = React.useCallback( async (selection: NativeMediaSelection) => { if (registrationModeRef.current.registrationMode === 'on') { registrationModeRef.current.successCallback({ needsUpload: true, mediaSelection: selection, }); return; } const imageAvatarUpdateRequest = await uploadSelectedMedia(selection); if (!imageAvatarUpdateRequest) { return; } const promise = (async () => { setUserAvatarMediaUploadInProgress(false); try { return await updateUserAvatarCall(imageAvatarUpdateRequest); } catch (e) { - displayFailureAlert(); + displayFailureAlert && displayFailureAlert(); throw e; } })(); dispatchActionPromise(updateUserAvatarActionTypes, promise); await promise; }, [ uploadSelectedMedia, dispatchActionPromise, updateUserAvatarCall, displayFailureAlert, ], ); const selectFromGalleryAndUpdateUserAvatar = React.useCallback(async () => { const selection = await selectFromGallery(); if (!selection) { return; } await updateImageUserAvatar(selection); }, [selectFromGallery, updateImageUserAvatar]); const setUserAvatar = React.useCallback( async (request: UpdateUserAvatarRequest) => { const regMode = registrationModeRef.current; if (regMode.registrationMode === 'on') { regMode.successCallback({ needsUpload: false, updateUserAvatarRequest: request, }); return; } const promise = (async () => { try { return await updateUserAvatarCall(request); } catch (e) { - displayFailureAlert(); + displayFailureAlert && displayFailureAlert(); throw e; } })(); dispatchActionPromise(updateUserAvatarActionTypes, promise); await promise; }, [dispatchActionPromise, updateUserAvatarCall, displayFailureAlert], ); const setRegistrationMode = React.useCallback((mode: RegistrationMode) => { registrationModeRef.current = mode; }, []); const getRegistrationModeEnabled = React.useCallback( () => registrationModeRef.current.registrationMode === 'on', [], ); const context = React.useMemo( () => ({ userAvatarSaveInProgress, selectFromGalleryAndUpdateUserAvatar, updateImageUserAvatar, setUserAvatar, setRegistrationMode, getRegistrationModeEnabled, }), [ userAvatarSaveInProgress, selectFromGalleryAndUpdateUserAvatar, updateImageUserAvatar, setUserAvatar, setRegistrationMode, getRegistrationModeEnabled, ], ); return ( {children} ); } export { EditUserAvatarContext, BaseEditUserAvatarProvider }; diff --git a/web/avatars/web-edit-user-avatar-provider.react.js b/web/avatars/web-edit-user-avatar-provider.react.js index 49198fe7c..50e028182 100644 --- a/web/avatars/web-edit-user-avatar-provider.react.js +++ b/web/avatars/web-edit-user-avatar-provider.react.js @@ -1,31 +1,28 @@ // @flow import * as React from 'react'; import { BaseEditUserAvatarProvider } from 'lib/components/base-edit-user-avatar-provider.react.js'; -const displayAvatarUpdateFailureAlert = () => null; - // TODO: Implement `selectFromGallery(...)` for `web`. const selectFromGallery = async () => null; // TODO: Implement `useUploadSelectedMedia(...)` for `web`. const useUploadSelectedMedia = () => async () => null; type Props = { +children: React.Node, }; function WebEditUserAvatarProvider(props: Props): React.Node { const { children } = props; return ( {children} ); } export default WebEditUserAvatarProvider;