diff --git a/native/account/registration/avatar-selection.react.js b/native/account/registration/avatar-selection.react.js
index fc108ab8f..ac356abe9 100644
--- a/native/account/registration/avatar-selection.react.js
+++ b/native/account/registration/avatar-selection.react.js
@@ -1,69 +1,106 @@
// @flow
import * as React from 'react';
-import { Text } from 'react-native';
+import { Text, View } from 'react-native';
import type { SIWEResult } from 'lib/types/siwe-types.js';
import RegistrationButtonContainer from './registration-button-container.react.js';
import RegistrationButton from './registration-button.react.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 type { CoolOrNerdMode } from './registration-types.js';
+import EditUserAvatar from '../../avatars/edit-user-avatar.react.js';
import type { NavigationRoute } from '../../navigation/route-names.js';
import { useStyles } from '../../themes/colors.js';
type EthereumAccountSelections = {
+accountType: 'ethereum',
...SIWEResult,
};
type UsernameAccountSelections = {
+accountType: 'username',
+username: string,
+password: string,
};
export type AvatarSelectionParams = {
+userSelections: {
+coolOrNerdMode: CoolOrNerdMode,
+keyserverUsername: string,
+accountSelections: EthereumAccountSelections | UsernameAccountSelections,
},
};
type Props = {
+navigation: RegistrationNavigationProp<'AvatarSelection'>,
+route: NavigationRoute<'AvatarSelection'>,
};
-// eslint-disable-next-line no-unused-vars
function AvatarSelection(props: Props): React.Node {
+ const { userSelections } = props.route.params;
+ const { accountSelections } = userSelections;
+ const username =
+ accountSelections.accountType === 'username'
+ ? accountSelections.username
+ : accountSelections.address;
+
+ const [avatarData] = React.useState();
+
const onProceed = React.useCallback(() => {}, []);
+ const clientAvatar = avatarData?.clientAvatar;
+ const userInfoOverride = React.useMemo(
+ () => ({
+ username,
+ avatar: clientAvatar,
+ }),
+ [username, clientAvatar],
+ );
+
const styles = useStyles(unboundStyles);
return (
-
+
Pick an avatar
+
+
+
+
+
);
}
const unboundStyles = {
+ scrollViewContentContainer: {
+ paddingHorizontal: 0,
+ },
header: {
fontSize: 24,
color: 'panelForegroundLabel',
paddingBottom: 16,
+ paddingHorizontal: 16,
+ },
+ stagedAvatarSection: {
+ marginTop: 16,
+ backgroundColor: 'panelForeground',
+ paddingVertical: 24,
+ alignItems: 'center',
+ },
+ editUserAvatar: {
+ alignItems: 'center',
+ justifyContent: 'center',
},
};
export default AvatarSelection;
diff --git a/native/avatars/edit-user-avatar.react.js b/native/avatars/edit-user-avatar.react.js
index d8277e038..bdc61aab0 100644
--- a/native/avatars/edit-user-avatar.react.js
+++ b/native/avatars/edit-user-avatar.react.js
@@ -1,121 +1,132 @@
// @flow
import { useNavigation } from '@react-navigation/native';
import invariant from 'invariant';
import * as React from 'react';
import { ActivityIndicator, TouchableOpacity, View } from 'react-native';
import { useENSAvatar } from 'lib/hooks/ens-cache.js';
import { getETHAddressForUserInfo } from 'lib/shared/account-utils.js';
+import type { GenericUserInfoWithAvatar } from 'lib/types/avatar-types.js';
import { 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 {
EmojiUserAvatarCreationRouteName,
UserAvatarCameraModalRouteName,
} from '../navigation/route-names.js';
import { useSelector } from '../redux/redux-utils.js';
import { useStyles } from '../themes/colors.js';
-type Props = {
- +userID: ?string,
- +disabled?: boolean,
-};
+type Props =
+ | { +userID: ?string, +disabled?: boolean }
+ | { +userInfo: ?GenericUserInfoWithAvatar, +disabled?: boolean };
function EditUserAvatar(props: Props): React.Node {
- const styles = useStyles(unboundStyles);
- const { userID, disabled } = props;
-
const editUserAvatarContext = React.useContext(EditUserAvatarContext);
invariant(editUserAvatarContext, 'editUserAvatarContext should be set');
const {
userAvatarSaveInProgress,
selectFromGalleryAndUpdateUserAvatar,
setUserAvatar,
} = editUserAvatarContext;
const currentUserInfo = useSelector(state => state.currentUserInfo);
+ const userInfoProp = props.userInfo;
+ const userInfo: ?GenericUserInfoWithAvatar = userInfoProp ?? currentUserInfo;
+
const ethAddress = React.useMemo(
- () => getETHAddressForUserInfo(currentUserInfo),
- [currentUserInfo],
+ () => getETHAddressForUserInfo(userInfo),
+ [userInfo],
);
const ensAvatarURI = useENSAvatar(ethAddress);
const { navigate } = useNavigation();
const navigateToUserEmojiAvatarCreation = React.useCallback(() => {
navigate(EmojiUserAvatarCreationRouteName);
}, [navigate]);
const navigateToCamera = React.useCallback(() => {
navigate(UserAvatarCameraModalRouteName);
}, [navigate]);
const setENSUserAvatar = React.useCallback(() => {
setUserAvatar({ type: 'ens' });
}, [setUserAvatar]);
const removeUserAvatar = React.useCallback(() => {
setUserAvatar({ type: 'remove' });
}, [setUserAvatar]);
+ const hasCurrentAvatar = !!userInfo?.avatar;
const actionSheetConfig = React.useMemo(() => {
const configOptions = [
{ id: 'emoji', onPress: navigateToUserEmojiAvatarCreation },
{ id: 'image', onPress: selectFromGalleryAndUpdateUserAvatar },
{ id: 'camera', onPress: navigateToCamera },
];
if (ensAvatarURI) {
configOptions.push({ id: 'ens', onPress: setENSUserAvatar });
}
- if (currentUserInfo?.avatar) {
+ if (hasCurrentAvatar) {
configOptions.push({ id: 'remove', onPress: removeUserAvatar });
}
return configOptions;
}, [
- currentUserInfo?.avatar,
+ hasCurrentAvatar,
ensAvatarURI,
navigateToCamera,
navigateToUserEmojiAvatarCreation,
removeUserAvatar,
setENSUserAvatar,
selectFromGalleryAndUpdateUserAvatar,
]);
const showAvatarActionSheet = useShowAvatarActionSheet(actionSheetConfig);
+ const styles = useStyles(unboundStyles);
+
let spinner;
if (userAvatarSaveInProgress) {
spinner = (
);
}
+ const { userID } = props;
+ const userAvatar = userID ? (
+
+ ) : (
+
+ );
+
+ const { disabled } = props;
return (
-
+ {userAvatar}
{spinner}
{!disabled ? : null}
);
}
const unboundStyles = {
spinnerContainer: {
position: 'absolute',
alignItems: 'center',
justifyContent: 'center',
top: 0,
bottom: 0,
left: 0,
right: 0,
},
};
export default EditUserAvatar;
diff --git a/native/avatars/user-avatar.react.js b/native/avatars/user-avatar.react.js
index 4a3012388..9cbda8f52 100644
--- a/native/avatars/user-avatar.react.js
+++ b/native/avatars/user-avatar.react.js
@@ -1,35 +1,35 @@
// @flow
import * as React from 'react';
import {
getAvatarForUser,
useENSResolvedAvatar,
} from 'lib/shared/avatar-utils.js';
+import type { GenericUserInfoWithAvatar } from 'lib/types/avatar-types.js';
import Avatar from './avatar.react.js';
import { useSelector } from '../redux/redux-utils.js';
-type Props = {
- +userID: ?string,
- +size: 'micro' | 'small' | 'large' | 'profile',
-};
-
+type Size = 'micro' | 'small' | 'large' | 'profile';
+type Props =
+ | { +userID: ?string, +size: Size }
+ | { +userInfo: ?GenericUserInfoWithAvatar, +size: Size };
function UserAvatar(props: Props): React.Node {
- const { userID, size } = props;
+ const { userID, userInfo: userInfoProp, size } = props;
const currentUserInfo = useSelector(state => state.currentUserInfo);
const userInfo = useSelector(state =>
- userID ? state.userStore.userInfos[userID] : null,
+ userID ? state.userStore.userInfos[userID] : userInfoProp,
);
const avatarUserInfo =
userID === currentUserInfo?.id ? currentUserInfo : userInfo;
const avatarInfo = getAvatarForUser(avatarUserInfo);
const resolvedUserAvatar = useENSResolvedAvatar(avatarInfo, userInfo);
return ;
}
export default UserAvatar;