diff --git a/native/navigation/route-names.js b/native/navigation/route-names.js --- a/native/navigation/route-names.js +++ b/native/navigation/route-names.js @@ -25,6 +25,7 @@ import type { ImageModalParams } from '../media/image-modal.react.js'; import type { VideoPlaybackModalParams } from '../media/video-playback-modal.react.js'; import type { CustomServerModalParams } from '../profile/custom-server-modal.react.js'; +import type { EmojiAvatarCreationParams } from '../profile/emoji-avatar-creation.react.js'; import type { RelationshipListItemTooltipModalParams } from '../profile/relationship-list-item-tooltip-modal.react.js'; export const ActionResultModalRouteName = 'ActionResultModal'; @@ -49,6 +50,7 @@ export const DeleteThreadRouteName = 'DeleteThread'; export const DevToolsRouteName = 'DevTools'; export const EditPasswordRouteName = 'EditPassword'; +export const EmojiAvatarCreationRouteName = 'EmojiAvatarCreation'; export const FriendListRouteName = 'FriendList'; export const FullScreenThreadMediaGalleryRouteName = 'FullScreenThreadMediaGallery'; @@ -138,6 +140,7 @@ export type ProfileParamList = { +ProfileScreen: void, + +EmojiAvatarCreation: EmojiAvatarCreationParams, +EditPassword: void, +DeleteAccount: void, +BuildInfo: void, diff --git a/native/profile/emoji-avatar-creation.react.js b/native/profile/emoji-avatar-creation.react.js new file mode 100644 --- /dev/null +++ b/native/profile/emoji-avatar-creation.react.js @@ -0,0 +1,188 @@ +// @flow + +import * as React from 'react'; +import { View, Text, TouchableWithoutFeedback } from 'react-native'; +import EmojiPicker from 'rn-emoji-keyboard'; + +import { + updateUserAvatar, + updateUserAvatarActionTypes, +} from 'lib/actions/user-actions.js'; +import type { ClientEmojiAvatar } from 'lib/types/avatar-types.js'; +import { + useDispatchActionPromise, + useServerCall, +} from 'lib/utils/action-utils.js'; + +import type { ProfileNavigationProp } from './profile.react.js'; +import Avatar from '../components/avatar.react.js'; +import Button from '../components/button.react.js'; +import ColorRows from '../components/color-rows.react.js'; +import type { NavigationRoute } from '../navigation/route-names.js'; +import { useStyles } from '../themes/colors.js'; + +export type EmojiAvatarCreationParams = { + +emojiAvatarInfo: ClientEmojiAvatar, +}; + +type Props = { + +navigation: ProfileNavigationProp<'EmojiAvatarCreation'>, + +route: NavigationRoute<'EmojiAvatarCreation'>, +}; + +function EmojiAvatarCreation(props: Props): React.Node { + const { emoji: initalEmoji, color: initialColor } = + props.route.params.emojiAvatarInfo; + + const [pendingEmoji, setPendingEmoji] = React.useState(initalEmoji); + const [pendingColor, setPendingColor] = React.useState(initialColor); + const [emojiKeyboardOpen, setEmojiKeyboardOpen] = + React.useState(false); + + const styles = useStyles(unboundStyles); + + const dispatchActionPromise = useDispatchActionPromise(); + const callUpdateUserAvatar = useServerCall(updateUserAvatar); + + const onPressEditEmoji = React.useCallback(() => { + setEmojiKeyboardOpen(true); + }, []); + + const onPressSetAvatar = React.useCallback(() => { + const newEmojiAvatarRequest = { + type: 'emoji', + emoji: pendingEmoji, + color: pendingColor, + }; + + dispatchActionPromise( + updateUserAvatarActionTypes, + callUpdateUserAvatar(newEmojiAvatarRequest), + ); + props.navigation.goBack(); + }, [ + callUpdateUserAvatar, + dispatchActionPromise, + pendingColor, + pendingEmoji, + props.navigation, + ]); + + const onPressReset = React.useCallback(() => { + setPendingEmoji(initalEmoji); + setPendingColor(initialColor); + }, [initalEmoji, initialColor]); + + const onEmojiSelected = React.useCallback(emoji => { + setPendingEmoji(emoji.emoji); + }, []); + + const onEmojiKeyboardClose = React.useCallback( + () => setEmojiKeyboardOpen(false), + [], + ); + + const stagedAvatarInfo: ClientEmojiAvatar = React.useMemo( + () => ({ + type: 'emoji', + emoji: pendingEmoji, + color: pendingColor, + }), + [pendingColor, pendingEmoji], + ); + + return ( + + + + + + + Edit Emoji + + + + + + + + + + + + + + ); +} + +const unboundStyles = { + container: { + flex: 1, + justifyContent: 'space-between', + }, + emojiAvatarCreationContainer: { + paddingTop: 16, + }, + stagedAvatarSection: { + backgroundColor: 'panelForeground', + paddingVertical: 24, + alignItems: 'center', + }, + editEmojiText: { + color: '#7E57C2', + marginTop: 16, + fontWeight: '500', + fontSize: 16, + lineHeight: 24, + textAlign: 'center', + }, + colorRowsSection: { + paddingVertical: 24, + marginTop: 24, + backgroundColor: 'panelForeground', + alignItems: 'center', + }, + buttonsContainer: { + paddingHorizontal: 16, + paddingBottom: 8, + }, + saveButton: { + backgroundColor: '#7E57C2', + paddingVertical: 12, + borderRadius: 8, + }, + saveButtonText: { + color: '#FFFFFF', + textAlign: 'center', + fontWeight: '500', + fontSize: 16, + lineHeight: 24, + }, + resetButton: { + padding: 12, + borderRadius: 8, + marginTop: 8, + alignSelf: 'center', + }, + resetButtonText: { + color: '#B62602', + textAlign: 'center', + fontWeight: '500', + fontSize: 16, + lineHeight: 24, + }, +}; + +export default EmojiAvatarCreation;