diff --git a/web/avatars/emoji-avatar-selection-modal.css b/web/avatars/emoji-avatar-selection-modal.css index adb5f27b4..dd6306a9f 100644 --- a/web/avatars/emoji-avatar-selection-modal.css +++ b/web/avatars/emoji-avatar-selection-modal.css @@ -1,34 +1,35 @@ div.modalBody { display: flex; flex-direction: column; overflow: hidden; padding: 20px; } div.avatarContainer { display: flex; justify-content: center; padding-top: 20px; } div.emojiPickerContainer { display: flex; justify-content: center; align-items: center; } div.colorSelectorContainer { margin: 20px 60px; } div.saveButtonContainer { display: flex; flex-direction: column; } div.saveAvatarButtonContent { display: flex; justify-content: center; align-items: center; min-height: 24px; + gap: 4px; } diff --git a/web/avatars/emoji-avatar-selection-modal.react.js b/web/avatars/emoji-avatar-selection-modal.react.js index c0b299ed8..5066a43c9 100644 --- a/web/avatars/emoji-avatar-selection-modal.react.js +++ b/web/avatars/emoji-avatar-selection-modal.react.js @@ -1,112 +1,133 @@ // @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/base-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 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'; function EmojiAvatarSelectionModal(): React.Node { const { popModal } = useModalContext(); const editUserAvatarContext = React.useContext(EditUserAvatarContext); invariant(editUserAvatarContext, 'editUserAvatarContext should be set'); const { setUserAvatar, userAvatarSaveInProgress } = editUserAvatarContext; + const [errorMessage, setErrorMessage] = React.useState(); + const currentUserInfo = useSelector(state => state.currentUserInfo); const currentUserAvatar: ClientAvatar = getAvatarForUser(currentUserInfo); const defaultUserAvatar: ClientEmojiAvatar = currentUserInfo?.username ? getDefaultAvatar(currentUserInfo.username) : defaultAnonymousUserEmojiAvatar; // eslint-disable-next-line no-unused-vars const [pendingAvatarEmoji, setPendingAvatarEmoji] = React.useState( currentUserAvatar.type === 'emoji' ? currentUserAvatar.emoji : defaultUserAvatar.emoji, ); const [pendingAvatarColor, setPendingAvatarColor] = React.useState( currentUserAvatar.type === 'emoji' ? currentUserAvatar.color : defaultUserAvatar.color, ); const pendingEmojiAvatar: ClientEmojiAvatar = React.useMemo( () => ({ type: 'emoji', emoji: pendingAvatarEmoji, color: pendingAvatarColor, }), [pendingAvatarColor, pendingAvatarEmoji], ); const onEmojiSelect = React.useCallback(selection => { + setErrorMessage(); setPendingAvatarEmoji(selection.native); }, []); - const onSaveAvatar = React.useCallback( - () => setUserAvatar(pendingEmojiAvatar), - [pendingEmojiAvatar, setUserAvatar], - ); + const onColorSelection = React.useCallback((hex: string) => { + setErrorMessage(); + setPendingAvatarColor(hex); + }, []); + + const onSaveAvatar = React.useCallback(async () => { + try { + await setUserAvatar(pendingEmojiAvatar); + } catch { + setErrorMessage('Avatar update failed. Please try again.'); + } + }, [pendingEmojiAvatar, setUserAvatar]); let saveButtonContent; if (userAvatarSaveInProgress) { saveButtonContent = ; + } else if (errorMessage) { + saveButtonContent = ( + <> + + {errorMessage} + + ); } else { saveButtonContent = 'Save Avatar'; } return (
); } export default EmojiAvatarSelectionModal; diff --git a/web/avatars/web-edit-user-avatar-provider.react.js b/web/avatars/web-edit-user-avatar-provider.react.js index 5ce447e0d..49198fe7c 100644 --- a/web/avatars/web-edit-user-avatar-provider.react.js +++ b/web/avatars/web-edit-user-avatar-provider.react.js @@ -1,32 +1,31 @@ // @flow import * as React from 'react'; import { BaseEditUserAvatarProvider } from 'lib/components/base-edit-user-avatar-provider.react.js'; -const displayAvatarUpdateFailureAlert = () => - alert('Couldn’t save avatar. Please try again later.'); +const displayAvatarUpdateFailureAlert = () => null; // TODO: Implement `selectFromGallery(...)` for `web`. const selectFromGallery = async () => null; // TODO: Implement `useUploadSelectedMedia(...)` for `web`. const useUploadSelectedMedia = () => async () => null; type Props = { +children: React.Node, }; function WebEditUserAvatarProvider(props: Props): React.Node { const { children } = props; return ( {children} ); } export default WebEditUserAvatarProvider;