diff --git a/web/avatars/edit-user-avatar-menu.react.js b/web/avatars/edit-user-avatar-menu.react.js index 8f17f0081..0591be2e7 100644 --- a/web/avatars/edit-user-avatar-menu.react.js +++ b/web/avatars/edit-user-avatar-menu.react.js @@ -1,156 +1,156 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { EditUserAvatarContext } from 'lib/components/edit-user-avatar-provider.react.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; import { useENSAvatar } from 'lib/hooks/ens-cache.js'; import { getETHAddressForUserInfo } from 'lib/shared/account-utils.js'; import { useUploadAvatarMedia } from './avatar-hooks.react.js'; import css from './edit-avatar-menu.css'; -import EmojiAvatarSelectionModal from './emoji-avatar-selection-modal.react.js'; +import UserEmojiAvatarSelectionModal from './user-emoji-avatar-selection-modal.react.js'; import CommIcon from '../CommIcon.react.js'; import MenuItem from '../components/menu-item.react.js'; import Menu from '../components/menu.react.js'; import { allowedMimeTypeString } from '../media/file-utils.js'; import { useSelector } from '../redux/redux-utils.js'; const editIcon = (
); function EditUserAvatarMenu(): React.Node { const currentUserInfo = useSelector(state => state.currentUserInfo); const ethAddress: ?string = React.useMemo( () => getETHAddressForUserInfo(currentUserInfo), [currentUserInfo], ); const ensAvatarURI: ?string = useENSAvatar(ethAddress); const editUserAvatarContext = React.useContext(EditUserAvatarContext); invariant(editUserAvatarContext, 'editUserAvatarContext should be set'); const { baseSetUserAvatar } = editUserAvatarContext; const removeUserAvatar = React.useCallback( () => baseSetUserAvatar({ type: 'remove' }), [baseSetUserAvatar], ); const { pushModal } = useModalContext(); const openEmojiSelectionModal = React.useCallback( - () => pushModal(), + () => pushModal(), [pushModal], ); const emojiMenuItem = React.useMemo( () => ( ), [openEmojiSelectionModal], ); const imageInputRef = React.useRef(); const onImageMenuItemClicked = React.useCallback( () => imageInputRef.current?.click(), [], ); const uploadAvatarMedia = useUploadAvatarMedia(); const onImageSelected = React.useCallback( async event => { const uploadResult = await uploadAvatarMedia(event.target.files[0]); baseSetUserAvatar({ type: 'image', uploadID: uploadResult.id }); }, [baseSetUserAvatar, uploadAvatarMedia], ); const imageMenuItem = React.useMemo( () => ( ), [onImageMenuItemClicked], ); const setENSUserAvatar = React.useCallback( () => baseSetUserAvatar({ type: 'ens' }), [baseSetUserAvatar], ); const ethereumIcon = React.useMemo( () => , [], ); const ensMenuItem = React.useMemo( () => ( ), [ethereumIcon, setENSUserAvatar], ); const removeMenuItem = React.useMemo( () => ( ), [removeUserAvatar], ); const menuItems = React.useMemo(() => { const items = [emojiMenuItem, imageMenuItem]; if (ensAvatarURI) { items.push(ensMenuItem); } if (currentUserInfo?.avatar) { items.push(removeMenuItem); } return items; }, [ currentUserInfo?.avatar, emojiMenuItem, ensAvatarURI, ensMenuItem, imageMenuItem, removeMenuItem, ]); return (
{menuItems}
); } export default EditUserAvatarMenu; diff --git a/web/avatars/emoji-avatar-selection-modal.react.js b/web/avatars/emoji-avatar-selection-modal.react.js index 2696d4ad8..8de4338e8 100644 --- a/web/avatars/emoji-avatar-selection-modal.react.js +++ b/web/avatars/emoji-avatar-selection-modal.react.js @@ -1,169 +1,155 @@ // @flow import data from '@emoji-mart/data'; import Picker from '@emoji-mart/react'; -import invariant from 'invariant'; import * as React from 'react'; -import { EditUserAvatarContext } from 'lib/components/edit-user-avatar-provider.react.js'; import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; -import { - defaultAnonymousUserEmojiAvatar, - getAvatarForUser, - getDefaultAvatar, -} from 'lib/shared/avatar-utils.js'; import type { ClientAvatar, ClientEmojiAvatar, } from 'lib/types/avatar-types.js'; import Avatar from './avatar.react.js'; import css from './emoji-avatar-selection-modal.css'; import Button, { buttonThemes } from '../components/button.react.js'; import Tabs from '../components/tabs.react.js'; import LoadingIndicator from '../loading-indicator.react.js'; import Modal from '../modals/modal.react.js'; import ColorSelector from '../modals/threads/color-selector.react.js'; -import { useSelector } from '../redux/redux-utils.js'; type TabType = 'emoji' | 'color'; -function EmojiAvatarSelectionModal(): React.Node { +type Props = { + +currentAvatar: ClientAvatar, + +defaultAvatar: ClientEmojiAvatar, + +setEmojiAvatar: (pendingEmojiAvatar: ClientEmojiAvatar) => Promise, + +avatarSaveInProgress: boolean, +}; +function EmojiAvatarSelectionModal(props: Props): React.Node { const { popModal } = useModalContext(); - const editUserAvatarContext = React.useContext(EditUserAvatarContext); - invariant(editUserAvatarContext, 'editUserAvatarContext should be set'); - - const { baseSetUserAvatar, userAvatarSaveInProgress } = editUserAvatarContext; + const { currentAvatar, defaultAvatar, setEmojiAvatar, avatarSaveInProgress } = + props; const [updateAvatarStatus, setUpdateAvatarStatus] = React.useState(); - const currentUserInfo = useSelector(state => state.currentUserInfo); - const currentUserAvatar: ClientAvatar = getAvatarForUser(currentUserInfo); - const defaultUserAvatar: ClientEmojiAvatar = currentUserInfo?.username - ? getDefaultAvatar(currentUserInfo.username) - : defaultAnonymousUserEmojiAvatar; - const [pendingAvatarEmoji, setPendingAvatarEmoji] = React.useState( - currentUserAvatar.type === 'emoji' - ? currentUserAvatar.emoji - : defaultUserAvatar.emoji, + currentAvatar.type === 'emoji' ? currentAvatar.emoji : defaultAvatar.emoji, ); const [pendingAvatarColor, setPendingAvatarColor] = React.useState( - currentUserAvatar.type === 'emoji' - ? currentUserAvatar.color - : defaultUserAvatar.color, + currentAvatar.type === 'emoji' ? currentAvatar.color : defaultAvatar.color, ); const pendingEmojiAvatar: ClientEmojiAvatar = React.useMemo( () => ({ type: 'emoji', emoji: pendingAvatarEmoji, color: pendingAvatarColor, }), [pendingAvatarColor, pendingAvatarEmoji], ); const onEmojiSelect = React.useCallback(selection => { setUpdateAvatarStatus(); setPendingAvatarEmoji(selection.native); }, []); const onColorSelection = React.useCallback((hex: string) => { setUpdateAvatarStatus(); setPendingAvatarColor(hex); }, []); const onSaveAvatar = React.useCallback(async () => { try { - await baseSetUserAvatar(pendingEmojiAvatar); + await setEmojiAvatar(pendingEmojiAvatar); setUpdateAvatarStatus('success'); } catch { setUpdateAvatarStatus('failure'); } - }, [pendingEmojiAvatar, baseSetUserAvatar]); + }, [setEmojiAvatar, pendingEmojiAvatar]); let saveButtonContent; let buttonColor; - if (userAvatarSaveInProgress) { + if (avatarSaveInProgress) { buttonColor = buttonThemes.standard; saveButtonContent = ; } else if (updateAvatarStatus === 'success') { buttonColor = buttonThemes.success; saveButtonContent = ( <> {'Avatar update succeeded.'} ); } else if (updateAvatarStatus === 'failure') { buttonColor = buttonThemes.danger; saveButtonContent = ( <> {'Avatar update failed. Please try again.'} ); } else { buttonColor = buttonThemes.standard; saveButtonContent = 'Save Avatar'; } const [currentTabType, setCurrentTabType] = React.useState('emoji'); return (
); } export default EmojiAvatarSelectionModal; diff --git a/web/avatars/user-emoji-avatar-selection-modal.react.js b/web/avatars/user-emoji-avatar-selection-modal.react.js new file mode 100644 index 000000000..6fb209b4a --- /dev/null +++ b/web/avatars/user-emoji-avatar-selection-modal.react.js @@ -0,0 +1,43 @@ +// @flow + +import invariant from 'invariant'; +import * as React from 'react'; + +import { EditUserAvatarContext } from 'lib/components/edit-user-avatar-provider.react.js'; +import { + defaultAnonymousUserEmojiAvatar, + getAvatarForUser, + getDefaultAvatar, +} from 'lib/shared/avatar-utils.js'; +import type { + ClientAvatar, + ClientEmojiAvatar, +} from 'lib/types/avatar-types.js'; + +import EmojiAvatarSelectionModal from './emoji-avatar-selection-modal.react.js'; +import { useSelector } from '../redux/redux-utils.js'; + +function UserEmojiAvatarSelectionModal(): React.Node { + const editUserAvatarContext = React.useContext(EditUserAvatarContext); + invariant(editUserAvatarContext, 'editUserAvatarContext should be set'); + + const { baseSetUserAvatar, userAvatarSaveInProgress } = editUserAvatarContext; + + const currentUserInfo = useSelector(state => state.currentUserInfo); + const currentUserAvatar: ClientAvatar = getAvatarForUser(currentUserInfo); + + const defaultUserAvatar: ClientEmojiAvatar = currentUserInfo?.username + ? getDefaultAvatar(currentUserInfo.username) + : defaultAnonymousUserEmojiAvatar; + + return ( + + ); +} + +export default UserEmojiAvatarSelectionModal;