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 @@ -329,37 +329,6 @@ ); } -function useRemoveUserAvatar(): [() => void, boolean] { - const dispatchActionPromise = useDispatchActionPromise(); - const updateUserAvatarCall = useServerCall(updateUserAvatar); - const updateUserAvatarLoadingStatus: LoadingStatus = useSelector( - updateUserAvatarLoadingStatusSelector, - ); - - const removeUserAvatar = React.useCallback(() => { - const removeAvatarRequest: UpdateUserAvatarRemoveRequest = { - type: 'remove', - }; - - dispatchActionPromise( - updateUserAvatarActionTypes, - (async () => { - try { - return await updateUserAvatarCall(removeAvatarRequest); - } catch (e) { - Alert.alert('Avatar update failed', 'Unable to update avatar.'); - throw e; - } - })(), - ); - }, [dispatchActionPromise, updateUserAvatarCall]); - - return React.useMemo( - () => [removeUserAvatar, updateUserAvatarLoadingStatus === 'loading'], - [removeUserAvatar, updateUserAvatarLoadingStatus], - ); -} - function useRemoveThreadAvatar(threadID: string): [() => void, boolean] { const dispatchActionPromise = useDispatchActionPromise(); const changeThreadSettingsCall = useServerCall(changeThreadSettings); @@ -550,7 +519,6 @@ useShowAvatarActionSheet, useSelectFromGalleryAndUpdateUserAvatar, useSelectFromGalleryAndUpdateThreadAvatar, - useRemoveUserAvatar, useRemoveThreadAvatar, useENSUserAvatar, }; diff --git a/native/avatars/edit-user-avatar-provider.react.js b/native/avatars/edit-user-avatar-provider.react.js new file mode 100644 --- /dev/null +++ b/native/avatars/edit-user-avatar-provider.react.js @@ -0,0 +1,80 @@ +// @flow + +import * as React from 'react'; +import { Alert } from 'react-native'; + +import { + updateUserAvatar, + updateUserAvatarActionTypes, +} from 'lib/actions/user-actions.js'; +import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; +import type { UpdateUserAvatarRemoveRequest } from 'lib/types/avatar-types.js'; +import type { LoadingStatus } from 'lib/types/loading-types.js'; +import { + useDispatchActionPromise, + useServerCall, +} from 'lib/utils/action-utils.js'; + +import { useSelector } from '../redux/redux-utils.js'; + +export type EditUserAvatarContextType = { + +userAvatarSaveInProgress: boolean, + +removeUserAvatar: () => void, +}; + +const EditUserAvatarContext: React.Context = + React.createContext(); + +const updateUserAvatarLoadingStatusSelector = createLoadingStatusSelector( + updateUserAvatarActionTypes, +); + +type Props = { + +children: React.Node, +}; +function EditUserAvatarProvider(props: Props): React.Node { + const { children } = props; + + const dispatchActionPromise = useDispatchActionPromise(); + const updateUserAvatarCall = useServerCall(updateUserAvatar); + + const updateUserAvatarLoadingStatus: LoadingStatus = useSelector( + updateUserAvatarLoadingStatusSelector, + ); + + const userAvatarSaveInProgress = updateUserAvatarLoadingStatus === 'loading'; + + const removeUserAvatar = React.useCallback(() => { + const removeAvatarRequest: UpdateUserAvatarRemoveRequest = { + type: 'remove', + }; + + dispatchActionPromise( + updateUserAvatarActionTypes, + (async () => { + try { + return await updateUserAvatarCall(removeAvatarRequest); + } catch (e) { + Alert.alert('Avatar update failed', 'Unable to update avatar.'); + throw e; + } + })(), + ); + }, [dispatchActionPromise, updateUserAvatarCall]); + + const context = React.useMemo( + () => ({ + userAvatarSaveInProgress, + removeUserAvatar, + }), + [removeUserAvatar, userAvatarSaveInProgress], + ); + + return ( + + {children} + + ); +} + +export { EditUserAvatarContext, EditUserAvatarProvider }; 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 @@ -1,5 +1,6 @@ // @flow +import invariant from 'invariant'; import * as React from 'react'; import { ActivityIndicator, TouchableOpacity, View } from 'react-native'; @@ -8,11 +9,11 @@ import { useENSUserAvatar, - useRemoveUserAvatar, useSelectFromGalleryAndUpdateUserAvatar, useShowAvatarActionSheet, } from './avatar-hooks.js'; import EditAvatarBadge from './edit-avatar-badge.react.js'; +import { EditUserAvatarContext } from './edit-user-avatar-provider.react.js'; import UserAvatar from './user-avatar.react.js'; import { useSelector } from '../redux/redux-utils.js'; import { useStyles } from '../themes/colors.js'; @@ -26,6 +27,10 @@ const styles = useStyles(unboundStyles); const { userID, onPressEmojiAvatarFlow, disabled } = props; + const editUserAvatarContext = React.useContext(EditUserAvatarContext); + invariant(editUserAvatarContext, 'editUserAvatarContext should be set'); + const { userAvatarSaveInProgress, removeUserAvatar } = editUserAvatarContext; + const currentUserInfo = useSelector(state => state.currentUserInfo); const ethAddress = React.useMemo( () => getETHAddressForUserInfo(currentUserInfo), @@ -37,12 +42,11 @@ useSelectFromGalleryAndUpdateUserAvatar(); const [saveENSUserAvatar, isENSAvatarUpdateLoading] = useENSUserAvatar(); - const [removeUserAvatar, isRemoveAvatarUpdateLoading] = useRemoveUserAvatar(); const isAvatarUpdateInProgress = isGalleryAvatarUpdateLoading || - isRemoveAvatarUpdateLoading || - isENSAvatarUpdateLoading; + isENSAvatarUpdateLoading || + userAvatarSaveInProgress; const actionSheetConfig = React.useMemo(() => { const configOptions = [ diff --git a/native/root.react.js b/native/root.react.js --- a/native/root.react.js +++ b/native/root.react.js @@ -22,6 +22,7 @@ import { MediaCacheProvider } from 'lib/components/media-cache-provider.react.js'; import { actionLogger } from 'lib/utils/action-logger.js'; +import { EditUserAvatarProvider } from './avatars/edit-user-avatar-provider.react.js'; import ChatContextProvider from './chat/chat-context-provider.react.js'; import { FeatureFlagsProvider } from './components/feature-flags-provider.react.js'; import PersistedStateGate from './components/persisted-state-gate.js'; @@ -256,23 +257,25 @@ - - - - - - {gated} - - - - - {navigation} - - + + + + + + + {gated} + + + + + {navigation} + + +