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;