diff --git a/web/avatars/edit-thread-avatar-menu.react.js b/web/avatars/edit-thread-avatar-menu.react.js index bf31b5fb5..bfec1fe4d 100644 --- a/web/avatars/edit-thread-avatar-menu.react.js +++ b/web/avatars/edit-thread-avatar-menu.react.js @@ -1,101 +1,122 @@ // @flow import invariant from 'invariant'; import * as React from 'react'; import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js'; +import { useModalContext } from 'lib/components/modal-provider.react.js'; import SWMansionIcon from 'lib/components/SWMansionIcon.react.js'; import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; import { useUploadAvatarMedia } from './avatar-hooks.react.js'; import css from './edit-avatar-menu.css'; +import ThreadEmojiAvatarSelectionModal from './thread-emoji-avatar-selection-modal.react.js'; import MenuItem from '../components/menu-item.react.js'; import Menu from '../components/menu.react.js'; import { allowedMimeTypeString } from '../media/file-utils.js'; const editIcon = (
); type Props = { +threadInfo: RawThreadInfo | ThreadInfo, }; function EditThreadAvatarMenu(props: Props): React.Node { const { threadInfo } = props; const editThreadAvatarContext = React.useContext(EditThreadAvatarContext); invariant(editThreadAvatarContext, 'editThreadAvatarContext should be set'); const { baseSetThreadAvatar } = editThreadAvatarContext; const removeThreadAvatar = React.useCallback( () => baseSetThreadAvatar(threadInfo.id, { type: 'remove' }), [baseSetThreadAvatar, threadInfo.id], ); const removeMenuItem = React.useMemo( () => ( ), [removeThreadAvatar], ); 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]); baseSetThreadAvatar(threadInfo.id, { type: 'image', uploadID: uploadResult.id, }); }, [baseSetThreadAvatar, threadInfo.id, uploadAvatarMedia], ); const imageMenuItem = React.useMemo( () => ( ), [onImageMenuItemClicked], ); + const { pushModal } = useModalContext(); + const openEmojiSelectionModal = React.useCallback( + () => + pushModal(), + [pushModal, threadInfo], + ); + + const emojiMenuItem = React.useMemo( + () => ( + + ), + [openEmojiSelectionModal], + ); + const menuItems = React.useMemo(() => { - const items = [imageMenuItem]; + const items = [emojiMenuItem, imageMenuItem]; if (threadInfo.avatar) { items.push(removeMenuItem); } return items; - }, [imageMenuItem, removeMenuItem, threadInfo.avatar]); + }, [emojiMenuItem, imageMenuItem, removeMenuItem, threadInfo.avatar]); return (
{menuItems}
); } export default EditThreadAvatarMenu; diff --git a/web/avatars/thread-emoji-avatar-selection-modal.react.js b/web/avatars/thread-emoji-avatar-selection-modal.react.js new file mode 100644 index 000000000..9e31bb1bf --- /dev/null +++ b/web/avatars/thread-emoji-avatar-selection-modal.react.js @@ -0,0 +1,53 @@ +// @flow + +import invariant from 'invariant'; +import * as React from 'react'; + +import { EditThreadAvatarContext } from 'lib/components/base-edit-thread-avatar-provider.react.js'; +import { + getDefaultAvatar, + useAvatarForThread, +} from 'lib/shared/avatar-utils.js'; +import type { + ClientAvatar, + ClientEmojiAvatar, +} from 'lib/types/avatar-types.js'; +import type { RawThreadInfo, ThreadInfo } from 'lib/types/thread-types.js'; + +import EmojiAvatarSelectionModal from './emoji-avatar-selection-modal.react.js'; + +type Props = { + +threadInfo: ThreadInfo | RawThreadInfo, +}; + +function ThreadEmojiAvatarSelectionModal(props: Props): React.Node { + const { threadInfo } = props; + const editThreadAvatarContext = React.useContext(EditThreadAvatarContext); + invariant(editThreadAvatarContext, 'editThreadAvatarContext should be set'); + + const { baseSetThreadAvatar, threadAvatarSaveInProgress } = + editThreadAvatarContext; + + const currentThreadAvatar: ClientAvatar = useAvatarForThread(threadInfo); + const defaultThreadAvatar: ClientEmojiAvatar = getDefaultAvatar( + threadInfo.id, + threadInfo.color, + ); + + const setEmojiAvatar = React.useCallback( + (pendingEmojiAvatar: ClientEmojiAvatar): Promise => + baseSetThreadAvatar(threadInfo.id, pendingEmojiAvatar), + [baseSetThreadAvatar, threadInfo.id], + ); + + return ( + + ); +} + +export default ThreadEmojiAvatarSelectionModal;