Skip to content

Commit

Permalink
[native] Introduce useNativeSetUserAvatar and use throughout native
Browse files Browse the repository at this point in the history
Summary:
Basically D8339 but for `setUserAvatar` instead of `updateImageUserAvatar`.

`setUserAvatar` in `*EditUserAvatarProvider` previously had a call to `displayFailureAlert(...)`. However, this function is only relevant on `native` since we don't display alerts on `web`.

As part of making `EditUserAvatarProvider` platform-agnostic, we introduce the `useNativeSetUserAvatar` hook. It wraps the platform-agnostic `setUserAvatar` with a `try/catch` which displays an alert on `native` if an exception is caught in the `catch` block.

We replace usages of `setUserAvatar` on `native` with `nativeSetUserAvatar` (which is "created" via the hook).

This removes the final usage of `displayFailureAlert` in `*EditUserAvatarProvider`, so I'll remove the prop altogether in the next diff (to avoid cluttering up this one).

---

Depends on D8340

Test Plan: The modified flows continue to work as expected. When intentionally breaking the `update_user_avatar` endpoint, the alert continues to surface as expected.

Reviewers: ashoat, ginsu, rohan

Reviewed By: ashoat

Subscribers: tomek

Differential Revision: https://phab.comm.dev/D8341
  • Loading branch information
atulsmadhugiri committed Jul 28, 2023
1 parent 13c5d23 commit 1dae323
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 35 deletions.
13 changes: 3 additions & 10 deletions lib/components/base-edit-user-avatar-provider.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ type Props = {
+children: React.Node,
};
function BaseEditUserAvatarProvider(props: Props): React.Node {
const { displayFailureAlert, useUploadSelectedMedia, children } = props;
const { useUploadSelectedMedia, children } = props;

const registrationModeRef =
React.useRef<RegistrationMode>(registrationModeOff);
Expand Down Expand Up @@ -112,18 +112,11 @@ function BaseEditUserAvatarProvider(props: Props): React.Node {
return;
}

const promise = (async () => {
try {
return await updateUserAvatarCall(request);
} catch (e) {
displayFailureAlert && displayFailureAlert();
throw e;
}
})();
const promise = updateUserAvatarCall(request);
dispatchActionPromise(updateUserAvatarActionTypes, promise);
await promise;
},
[dispatchActionPromise, updateUserAvatarCall, displayFailureAlert],
[dispatchActionPromise, updateUserAvatarCall],
);

const setRegistrationMode = React.useCallback((mode: RegistrationMode) => {
Expand Down
8 changes: 5 additions & 3 deletions native/account/registration/emoji-avatar-selection.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { getDefaultAvatar } from 'lib/shared/avatar-utils.js';
import RegistrationContainer from './registration-container.react.js';
import RegistrationContentContainer from './registration-content-container.react.js';
import type { RegistrationNavigationProp } from './registration-navigator.react.js';
import { useNativeSetUserAvatar } from '../../avatars/avatar-hooks.js';
import EmojiAvatarCreation from '../../avatars/emoji-avatar-creation.react.js';
import type { NavigationRoute } from '../../navigation/route-names.js';
import { useStyles } from '../../themes/colors.js';
Expand All @@ -25,8 +26,9 @@ type Props = {
function EmojiAvatarSelection(props: Props): React.Node {
const editUserAvatarContext = React.useContext(EditUserAvatarContext);
invariant(editUserAvatarContext, 'editUserAvatarContext should be set');
const { userAvatarSaveInProgress } = editUserAvatarContext;

const { setUserAvatar, userAvatarSaveInProgress } = editUserAvatarContext;
const nativeSetUserAvatar = useNativeSetUserAvatar();

const { usernameOrEthAddress } = props.route.params;
const savedEmojiAvatarFunc = React.useCallback(
Expand All @@ -38,9 +40,9 @@ function EmojiAvatarSelection(props: Props): React.Node {
const onSuccess = React.useCallback(
avatarRequest => {
goBack();
return setUserAvatar(avatarRequest);
return nativeSetUserAvatar(avatarRequest);
},
[goBack, setUserAvatar],
[goBack, nativeSetUserAvatar],
);

const styles = useStyles(unboundStyles);
Expand Down
16 changes: 7 additions & 9 deletions native/account/registration/registration-server-call.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// @flow

import invariant from 'invariant';
import * as React from 'react';
import { Alert, Platform } from 'react-native';
import { useDispatch } from 'react-redux';

import { setDataLoadedActionType } from 'lib/actions/client-db-store-actions.js';
import { registerActionTypes, register } from 'lib/actions/user-actions.js';
import { EditUserAvatarContext } from 'lib/components/base-edit-user-avatar-provider.react.js';
import type { LogInStartingPayload } from 'lib/types/account-types.js';
import {
useServerCall,
Expand All @@ -20,7 +18,10 @@ import type {
UsernameAccountSelection,
AvatarData,
} from './registration-types.js';
import { useUploadSelectedMedia } from '../../avatars/avatar-hooks.js';
import {
useNativeSetUserAvatar,
useUploadSelectedMedia,
} from '../../avatars/avatar-hooks.js';
import { NavContext } from '../../navigation/navigation-context.js';
import { useSelector } from '../../redux/redux-utils.js';
import { nativeLogInExtraInfoSelector } from '../../selectors/account-selectors.js';
Expand Down Expand Up @@ -174,10 +175,7 @@ function useRegistrationServerCall(): RegistrationServerCallInput => Promise<voi
// STEP 2: SETTING AVATAR

const uploadSelectedMedia = useUploadSelectedMedia();

const editUserAvatarContext = React.useContext(EditUserAvatarContext);
invariant(editUserAvatarContext, 'editUserAvatarContext should be set');
const { setUserAvatar } = editUserAvatarContext;
const nativeSetUserAvatar = useNativeSetUserAvatar();

const hasCurrentUserInfo = useSelector(
state => !!state.currentUserInfo && !state.currentUserInfo.anonymous,
Expand Down Expand Up @@ -209,7 +207,7 @@ function useRegistrationServerCall(): RegistrationServerCallInput => Promise<voi
return;
}
}
await setUserAvatar(updateUserAvatarRequest);
await nativeSetUserAvatar(updateUserAvatarRequest);
} finally {
dispatch({
type: setDataLoadedActionType,
Expand All @@ -226,7 +224,7 @@ function useRegistrationServerCall(): RegistrationServerCallInput => Promise<voi
currentStep,
hasCurrentUserInfo,
uploadSelectedMedia,
setUserAvatar,
nativeSetUserAvatar,
dispatch,
]);

Expand Down
27 changes: 26 additions & 1 deletion native/avatars/avatar-hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import {
extensionFromFilename,
filenameFromPathOrURI,
} from 'lib/media/file-utils.js';
import type { ImageAvatarDBContent } from 'lib/types/avatar-types.js';
import type {
ImageAvatarDBContent,
UpdateUserAvatarRequest,
} from 'lib/types/avatar-types.js';
import type {
NativeMediaSelection,
MediaLibrarySelection,
Expand Down Expand Up @@ -192,6 +195,27 @@ function useUploadSelectedMedia(
);
}

function useNativeSetUserAvatar(): (
request: UpdateUserAvatarRequest,
) => Promise<void> {
const editUserAvatarContext = React.useContext(EditUserAvatarContext);
invariant(editUserAvatarContext, 'editUserAvatarContext must be defined');
const { setUserAvatar } = editUserAvatarContext;

const nativeSetUserAvatar = React.useCallback(
async (request: UpdateUserAvatarRequest) => {
try {
await setUserAvatar(request);
} catch {
displayAvatarUpdateFailureAlert();
}
},
[setUserAvatar],
);

return nativeSetUserAvatar;
}

function useNativeUpdateUserImageAvatar(): (
selection: NativeMediaSelection,
) => Promise<void> {
Expand Down Expand Up @@ -359,5 +383,6 @@ export {
useProcessSelectedMedia,
useShowAvatarActionSheet,
useSelectFromGalleryAndUpdateUserAvatar,
useNativeSetUserAvatar,
useNativeUpdateUserImageAvatar,
};
18 changes: 9 additions & 9 deletions native/avatars/edit-user-avatar.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getETHAddressForUserInfo } from 'lib/shared/account-utils.js';
import type { GenericUserInfoWithAvatar } from 'lib/types/avatar-types.js';

import {
useNativeSetUserAvatar,
useSelectFromGalleryAndUpdateUserAvatar,
useShowAvatarActionSheet,
} from './avatar-hooks.js';
Expand All @@ -35,11 +36,10 @@ type Props =
function EditUserAvatar(props: Props): React.Node {
const editUserAvatarContext = React.useContext(EditUserAvatarContext);
invariant(editUserAvatarContext, 'editUserAvatarContext should be set');
const {
userAvatarSaveInProgress,
setUserAvatar,
getRegistrationModeEnabled,
} = editUserAvatarContext;
const { userAvatarSaveInProgress, getRegistrationModeEnabled } =
editUserAvatarContext;

const nativeSetUserAvatar = useNativeSetUserAvatar();

const selectFromGalleryAndUpdateUserAvatar =
useSelectFromGalleryAndUpdateUserAvatar();
Expand Down Expand Up @@ -78,12 +78,12 @@ function EditUserAvatar(props: Props): React.Node {
}, [navigate, getRegistrationModeEnabled]);

const setENSUserAvatar = React.useCallback(() => {
setUserAvatar({ type: 'ens' });
}, [setUserAvatar]);
nativeSetUserAvatar({ type: 'ens' });
}, [nativeSetUserAvatar]);

const removeUserAvatar = React.useCallback(() => {
setUserAvatar({ type: 'remove' });
}, [setUserAvatar]);
nativeSetUserAvatar({ type: 'remove' });
}, [nativeSetUserAvatar]);

const hasCurrentAvatar = !!userInfo?.avatar;
const actionSheetConfig = React.useMemo(() => {
Expand Down
10 changes: 7 additions & 3 deletions native/profile/emoji-user-avatar-creation.react.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as React from 'react';
import { EditUserAvatarContext } from 'lib/components/base-edit-user-avatar-provider.react.js';
import { savedEmojiAvatarSelectorForCurrentUser } from 'lib/selectors/user-selectors.js';

import { useNativeSetUserAvatar } from '../avatars/avatar-hooks.js';
import EmojiAvatarCreation from '../avatars/emoji-avatar-creation.react.js';
import { displayActionResultModal } from '../navigation/action-result-modal.js';
import { useSelector } from '../redux/redux-utils.js';
Expand All @@ -15,14 +16,17 @@ function EmojiUserAvatarCreation(props: { ... }): React.Node {
const editUserAvatarContext = React.useContext(EditUserAvatarContext);
invariant(editUserAvatarContext, 'editUserAvatarContext should be set');

const { setUserAvatar, userAvatarSaveInProgress } = editUserAvatarContext;
const { userAvatarSaveInProgress } = editUserAvatarContext;

const nativeSetUserAvatar = useNativeSetUserAvatar();

const setAvatar = React.useCallback(
async avatarRequest => {
const result = await setUserAvatar(avatarRequest);
const result = await nativeSetUserAvatar(avatarRequest);
displayActionResultModal('Avatar updated!');
return result;
},
[setUserAvatar],
[nativeSetUserAvatar],
);

const savedEmojiAvatarFunc = useSelector(
Expand Down

0 comments on commit 1dae323

Please sign in to comment.