diff --git a/native/avatars/emoji-avatar-creation.react.js b/native/avatars/emoji-avatar-creation.react.js --- a/native/avatars/emoji-avatar-creation.react.js +++ b/native/avatars/emoji-avatar-creation.react.js @@ -9,50 +9,29 @@ } from 'react-native'; import EmojiPicker from 'rn-emoji-keyboard'; -import { changeThreadSettingsActionTypes } from 'lib/actions/thread-actions.js'; -import { updateUserAvatarActionTypes } from 'lib/actions/user-actions.js'; -import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; -import { savedEmojiAvatarSelectorForThread } from 'lib/selectors/thread-selectors.js'; -import { savedEmojiAvatarSelectorForCurrentUser } from 'lib/selectors/user-selectors.js'; -import type { ClientEmojiAvatar } from 'lib/types/avatar-types.js'; +import type { + UpdateUserAvatarRequest, + ClientEmojiAvatar, +} from 'lib/types/avatar-types'; import Avatar from './avatar.react.js'; import Button from '../components/button.react.js'; import ColorRows from '../components/color-rows.react.js'; import { useSelector } from '../redux/redux-utils.js'; +import type { AppState } from '../redux/state-types.js'; import { useStyles } from '../themes/colors.js'; -import { - useSaveUserAvatar, - useSaveThreadAvatar, -} from '../utils/avatar-utils.js'; - -const userAvatarLoadingStatusSelector = createLoadingStatusSelector( - updateUserAvatarActionTypes, -); - -const threadAvatarLoadingStatusSelector = createLoadingStatusSelector( - changeThreadSettingsActionTypes, - `${changeThreadSettingsActionTypes.started}:avatar`, -); - -export type EmojiAvatarCreationParams = { - +threadID?: string, - +containingThreadID?: ?string, -}; type Props = { - +threadID?: string, - +containingThreadID?: ?string, + +saveAvatarCall: (newAvatarRequest: UpdateUserAvatarRequest) => mixed, + +saveAvatarCallLoading: boolean, + +savedEmojiAvatarSelector: (state: AppState) => () => ClientEmojiAvatar, }; function EmojiAvatarCreation(props: Props): React.Node { - const { threadID, containingThreadID } = props; + const { saveAvatarCall, saveAvatarCallLoading, savedEmojiAvatarSelector } = + props; - const selector = threadID - ? savedEmojiAvatarSelectorForThread(threadID, containingThreadID) - : savedEmojiAvatarSelectorForCurrentUser; - - const savedEmojiAvatarFunc = useSelector(selector); + const savedEmojiAvatarFunc = useSelector(savedEmojiAvatarSelector); const [pendingEmoji, setPendingEmoji] = React.useState( () => savedEmojiAvatarFunc().emoji, @@ -65,16 +44,6 @@ const styles = useStyles(unboundStyles); - const saveUserAvatar = useSaveUserAvatar(); - const saveThreadAvatar = useSaveThreadAvatar(); - - const saveUserAvatarCallLoading = useSelector( - state => userAvatarLoadingStatusSelector(state) === 'loading', - ); - const saveThreadAvatarCallLoading = useSelector( - state => threadAvatarLoadingStatusSelector(state) === 'loading', - ); - const onPressEditEmoji = React.useCallback(() => { setEmojiKeyboardOpen(true); }, []); @@ -86,12 +55,8 @@ color: pendingColor, }; - if (!threadID) { - saveUserAvatar(newEmojiAvatarRequest); - } else { - saveThreadAvatar(newEmojiAvatarRequest, threadID); - } - }, [pendingColor, pendingEmoji, saveThreadAvatar, saveUserAvatar, threadID]); + saveAvatarCall(newEmojiAvatarRequest); + }, [pendingColor, pendingEmoji, saveAvatarCall]); const onPressReset = React.useCallback(() => { const resetEmojiAvatar = savedEmojiAvatarFunc(); @@ -119,7 +84,7 @@ ); const loadingContainer = React.useMemo(() => { - if (!saveUserAvatarCallLoading && !saveThreadAvatarCallLoading) { + if (!saveAvatarCallLoading) { return null; } @@ -128,11 +93,7 @@ ); - }, [ - saveThreadAvatarCallLoading, - saveUserAvatarCallLoading, - styles.loadingContainer, - ]); + }, [saveAvatarCallLoading, styles.loadingContainer]); return ( @@ -160,14 +121,14 @@ diff --git a/native/chat/settings/emoji-thread-avatar-creation.react.js b/native/chat/settings/emoji-thread-avatar-creation.react.js --- a/native/chat/settings/emoji-thread-avatar-creation.react.js +++ b/native/chat/settings/emoji-thread-avatar-creation.react.js @@ -1,36 +1,16 @@ // @flow import * as React from 'react'; -import { - View, - Text, - TouchableWithoutFeedback, - ActivityIndicator, -} from 'react-native'; -import EmojiPicker from 'rn-emoji-keyboard'; import { changeThreadSettingsActionTypes } from 'lib/actions/thread-actions.js'; -import { updateUserAvatarActionTypes } from 'lib/actions/user-actions.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; import { savedEmojiAvatarSelectorForThread } from 'lib/selectors/thread-selectors.js'; -import { savedEmojiAvatarSelectorForCurrentUser } from 'lib/selectors/user-selectors.js'; -import type { ClientEmojiAvatar } from 'lib/types/avatar-types.js'; -import Avatar from '../../avatars/avatar.react.js'; +import EmojiAvatarCreation from '../../avatars/emoji-avatar-creation.react.js'; import type { ChatNavigationProp } from '../../chat/chat.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 { useSelector } from '../../redux/redux-utils.js'; -import { useStyles } from '../../themes/colors.js'; -import { - useSaveUserAvatar, - useSaveThreadAvatar, -} from '../../utils/avatar-utils.js'; - -const userAvatarLoadingStatusSelector = createLoadingStatusSelector( - updateUserAvatarActionTypes, -); +import { useSaveThreadAvatar } from '../../utils/avatar-utils.js'; const threadAvatarLoadingStatusSelector = createLoadingStatusSelector( changeThreadSettingsActionTypes, @@ -38,7 +18,7 @@ ); export type EmojiThreadAvatarCreationParams = { - +threadID?: string, + +threadID: string, +containingThreadID?: ?string, }; @@ -50,207 +30,28 @@ function EmojiThreadAvatarCreation(props: Props): React.Node { const { threadID, containingThreadID } = props.route.params; - const selector = threadID - ? savedEmojiAvatarSelectorForThread(threadID, containingThreadID) - : savedEmojiAvatarSelectorForCurrentUser; - - const savedEmojiAvatarFunc = useSelector(selector); - - const [pendingEmoji, setPendingEmoji] = React.useState( - () => savedEmojiAvatarFunc().emoji, - ); - const [pendingColor, setPendingColor] = React.useState( - () => savedEmojiAvatarFunc().color, + const selector = savedEmojiAvatarSelectorForThread( + threadID, + containingThreadID, ); - const [emojiKeyboardOpen, setEmojiKeyboardOpen] = - React.useState(false); - const styles = useStyles(unboundStyles); - - const saveUserAvatar = useSaveUserAvatar(); const saveThreadAvatar = useSaveThreadAvatar(); - - const saveUserAvatarCallLoading = useSelector( - state => userAvatarLoadingStatusSelector(state) === 'loading', - ); const saveThreadAvatarCallLoading = useSelector( state => threadAvatarLoadingStatusSelector(state) === 'loading', ); - const onPressEditEmoji = React.useCallback(() => { - setEmojiKeyboardOpen(true); - }, []); - - const onPressSetAvatar = React.useCallback(() => { - const newEmojiAvatarRequest = { - type: 'emoji', - emoji: pendingEmoji, - color: pendingColor, - }; - - if (!threadID) { - saveUserAvatar(newEmojiAvatarRequest); - } else { - saveThreadAvatar(newEmojiAvatarRequest, threadID); - } - }, [pendingColor, pendingEmoji, saveThreadAvatar, saveUserAvatar, threadID]); - - const onPressReset = React.useCallback(() => { - const resetEmojiAvatar = savedEmojiAvatarFunc(); - - setPendingEmoji(resetEmojiAvatar.emoji); - setPendingColor(resetEmojiAvatar.color); - }, [savedEmojiAvatarFunc]); - - 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], + const saveThreadAvatarCallback = React.useCallback( + newAvatarRequest => saveThreadAvatar(newAvatarRequest, threadID), + [saveThreadAvatar, threadID], ); - const loadingContainer = React.useMemo(() => { - if (!saveUserAvatarCallLoading && !saveThreadAvatarCallLoading) { - return null; - } - - return ( - - - - ); - }, [ - saveThreadAvatarCallLoading, - saveUserAvatarCallLoading, - styles.loadingContainer, - ]); - return ( - - - - - - - - {loadingContainer} - - Edit Emoji - - - - - - - - - - - - - + ); } -const unboundStyles = { - container: { - flex: 1, - justifyContent: 'space-between', - }, - emojiAvatarCreationContainer: { - paddingTop: 16, - }, - stagedAvatarSection: { - backgroundColor: 'panelForeground', - paddingVertical: 24, - alignItems: 'center', - }, - editEmojiText: { - color: 'purpleLink', - marginTop: 16, - fontWeight: '500', - fontSize: 16, - lineHeight: 24, - textAlign: 'center', - }, - colorRowsSection: { - paddingVertical: 24, - marginTop: 24, - backgroundColor: 'panelForeground', - alignItems: 'center', - }, - selectedColorOuterRing: { - backgroundColor: 'modalSubtext', - }, - buttonsContainer: { - paddingHorizontal: 16, - paddingBottom: 8, - }, - saveButton: { - backgroundColor: 'purpleButton', - paddingVertical: 12, - borderRadius: 8, - }, - saveButtonText: { - color: 'whiteText', - textAlign: 'center', - fontWeight: '500', - fontSize: 16, - lineHeight: 24, - }, - resetButton: { - padding: 12, - borderRadius: 8, - marginTop: 8, - alignSelf: 'center', - }, - resetButtonText: { - color: 'redText', - textAlign: 'center', - fontWeight: '500', - fontSize: 16, - lineHeight: 24, - }, - loadingContainer: { - position: 'absolute', - backgroundColor: 'black', - width: 112, - height: 112, - borderRadius: 56, - opacity: 0.6, - justifyContent: 'center', - }, -}; - export default EmojiThreadAvatarCreation; 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 @@ -26,7 +26,6 @@ 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 { EmojiUserAvatarCreationParams } from '../profile/emoji-user-avatar-creation.react.js'; import type { RelationshipListItemTooltipModalParams } from '../profile/relationship-list-item-tooltip-modal.react.js'; export const ActionResultModalRouteName = 'ActionResultModal'; @@ -143,7 +142,7 @@ export type ProfileParamList = { +ProfileScreen: void, - +EmojiUserAvatarCreation: EmojiUserAvatarCreationParams, + +EmojiUserAvatarCreation: void, +EditPassword: void, +DeleteAccount: void, +BuildInfo: void, diff --git a/native/profile/emoji-user-avatar-creation.react.js b/native/profile/emoji-user-avatar-creation.react.js --- a/native/profile/emoji-user-avatar-creation.react.js +++ b/native/profile/emoji-user-avatar-creation.react.js @@ -1,256 +1,33 @@ // @flow import * as React from 'react'; -import { - View, - Text, - TouchableWithoutFeedback, - ActivityIndicator, -} from 'react-native'; -import EmojiPicker from 'rn-emoji-keyboard'; -import { changeThreadSettingsActionTypes } from 'lib/actions/thread-actions.js'; import { updateUserAvatarActionTypes } from 'lib/actions/user-actions.js'; import { createLoadingStatusSelector } from 'lib/selectors/loading-selectors.js'; -import { savedEmojiAvatarSelectorForThread } from 'lib/selectors/thread-selectors.js'; import { savedEmojiAvatarSelectorForCurrentUser } from 'lib/selectors/user-selectors.js'; -import type { ClientEmojiAvatar } from 'lib/types/avatar-types.js'; -import Avatar from '../avatars/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 type { ProfileNavigationProp } from '../profile/profile.react.js'; +import EmojiAvatarCreation from '../avatars/emoji-avatar-creation.react.js'; import { useSelector } from '../redux/redux-utils.js'; -import { useStyles } from '../themes/colors.js'; -import { - useSaveUserAvatar, - useSaveThreadAvatar, -} from '../utils/avatar-utils.js'; +import { useSaveUserAvatar } from '../utils/avatar-utils.js'; const userAvatarLoadingStatusSelector = createLoadingStatusSelector( updateUserAvatarActionTypes, ); -const threadAvatarLoadingStatusSelector = createLoadingStatusSelector( - changeThreadSettingsActionTypes, - `${changeThreadSettingsActionTypes.started}:avatar`, -); - -export type EmojiUserAvatarCreationParams = { - +threadID?: string, - +containingThreadID?: ?string, -}; - -type Props = { - +navigation: ProfileNavigationProp<'EmojiUserAvatarCreation'>, - +route: NavigationRoute<'EmojiUserAvatarCreation'>, -}; - -function EmojiUserAvatarCreation(props: Props): React.Node { - const { threadID, containingThreadID } = props.route.params; - - const selector = threadID - ? savedEmojiAvatarSelectorForThread(threadID, containingThreadID) - : savedEmojiAvatarSelectorForCurrentUser; - - const savedEmojiAvatarFunc = useSelector(selector); - - const [pendingEmoji, setPendingEmoji] = React.useState( - () => savedEmojiAvatarFunc().emoji, - ); - const [pendingColor, setPendingColor] = React.useState( - () => savedEmojiAvatarFunc().color, - ); - const [emojiKeyboardOpen, setEmojiKeyboardOpen] = - React.useState(false); - - const styles = useStyles(unboundStyles); - +// eslint-disable-next-line no-unused-vars +function EmojiUserAvatarCreation(props: { ... }): React.Node { const saveUserAvatar = useSaveUserAvatar(); - const saveThreadAvatar = useSaveThreadAvatar(); - const saveUserAvatarCallLoading = useSelector( state => userAvatarLoadingStatusSelector(state) === 'loading', ); - const saveThreadAvatarCallLoading = useSelector( - state => threadAvatarLoadingStatusSelector(state) === 'loading', - ); - - const onPressEditEmoji = React.useCallback(() => { - setEmojiKeyboardOpen(true); - }, []); - - const onPressSetAvatar = React.useCallback(() => { - const newEmojiAvatarRequest = { - type: 'emoji', - emoji: pendingEmoji, - color: pendingColor, - }; - - if (!threadID) { - saveUserAvatar(newEmojiAvatarRequest); - } else { - saveThreadAvatar(newEmojiAvatarRequest, threadID); - } - }, [pendingColor, pendingEmoji, saveThreadAvatar, saveUserAvatar, threadID]); - - const onPressReset = React.useCallback(() => { - const resetEmojiAvatar = savedEmojiAvatarFunc(); - - setPendingEmoji(resetEmojiAvatar.emoji); - setPendingColor(resetEmojiAvatar.color); - }, [savedEmojiAvatarFunc]); - - 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], - ); - - const loadingContainer = React.useMemo(() => { - if (!saveUserAvatarCallLoading && !saveThreadAvatarCallLoading) { - return null; - } - - return ( - - - - ); - }, [ - saveThreadAvatarCallLoading, - saveUserAvatarCallLoading, - styles.loadingContainer, - ]); return ( - - - - - - - - {loadingContainer} - - Edit Emoji - - - - - - - - - - - - - + ); } -const unboundStyles = { - container: { - flex: 1, - justifyContent: 'space-between', - }, - emojiAvatarCreationContainer: { - paddingTop: 16, - }, - stagedAvatarSection: { - backgroundColor: 'panelForeground', - paddingVertical: 24, - alignItems: 'center', - }, - editEmojiText: { - color: 'purpleLink', - marginTop: 16, - fontWeight: '500', - fontSize: 16, - lineHeight: 24, - textAlign: 'center', - }, - colorRowsSection: { - paddingVertical: 24, - marginTop: 24, - backgroundColor: 'panelForeground', - alignItems: 'center', - }, - selectedColorOuterRing: { - backgroundColor: 'modalSubtext', - }, - buttonsContainer: { - paddingHorizontal: 16, - paddingBottom: 8, - }, - saveButton: { - backgroundColor: 'purpleButton', - paddingVertical: 12, - borderRadius: 8, - }, - saveButtonText: { - color: 'whiteText', - textAlign: 'center', - fontWeight: '500', - fontSize: 16, - lineHeight: 24, - }, - resetButton: { - padding: 12, - borderRadius: 8, - marginTop: 8, - alignSelf: 'center', - }, - resetButtonText: { - color: 'redText', - textAlign: 'center', - fontWeight: '500', - fontSize: 16, - lineHeight: 24, - }, - loadingContainer: { - position: 'absolute', - backgroundColor: 'black', - width: 112, - height: 112, - borderRadius: 56, - opacity: 0.6, - justifyContent: 'center', - }, -}; - export default EmojiUserAvatarCreation; diff --git a/native/profile/profile-screen.react.js b/native/profile/profile-screen.react.js --- a/native/profile/profile-screen.react.js +++ b/native/profile/profile-screen.react.js @@ -194,10 +194,7 @@ } onPressEmojiAvatarFlow = () => { - this.props.navigation.navigate<'EmojiUserAvatarCreation'>({ - name: EmojiUserAvatarCreationRouteName, - params: {}, - }); + this.props.navigation.navigate(EmojiUserAvatarCreationRouteName); }; onPressLogOut = () => {