From b400d0b364f607f74c92827f4d195229240d95d4 Mon Sep 17 00:00:00 2001 From: Ginsu Eddy Date: Fri, 23 Jun 2023 13:10:24 -0700 Subject: [PATCH] [native] introudce selectMultipleEmojis and alreadySelectedEmojis to EmojiKeyboard component Summary: This diff is the first part to highlight the already selected emojis to indicate on the emoji keyboard what emojis the user has already selected. This diff handles the case when `selectMultipleEmojis` is equal to `false` and the next diff will handle the case when `selectMultipleEmojis` is equal to `true` The big obstacle I had to overcome to build this was that the `selectedEmojis ` prop needs to be [[ https://thewidlarzgroup.github.io/rn-emoji-keyboard/docs/api/modal#selectedemojis | an array of emoji names ]] and we only store the actual emoji in our database. To overcome this obstacle I index the `emojiData` by the `emoji` so that we can easily grab the correct emoji name and pass it into the `selectedEmojis` prop. Here is a link to an example to the docs that helped me with this implementation: https://thewidlarzgroup.github.io/rn-emoji-keyboard/docs/documentation/Examples/selected_emojis Linear Task: https://linear.app/comm/issue/ENG-3794/mobile-emoji-keyboard-highlight-emojis-that-a-user-has-already Depends on D8282 Test Plan: Please watch the demo video below: {F600937} Reviewers: atul, kamil Reviewed By: kamil Subscribers: ashoat, tomek Differential Revision: https://phab.comm.dev/D8284 --- native/avatars/emoji-avatar-creation.react.js | 7 ++++ ...multimedia-message-tooltip-button.react.js | 3 ++ .../robotext-message-tooltip-button.react.js | 3 ++ .../chat/text-message-tooltip-button.react.js | 3 ++ native/components/emoji-keyboard.react.js | 32 +++++++++++++++++-- 5 files changed, 46 insertions(+), 2 deletions(-) diff --git a/native/avatars/emoji-avatar-creation.react.js b/native/avatars/emoji-avatar-creation.react.js index 03defb4199..90d9c8c0ec 100644 --- a/native/avatars/emoji-avatar-creation.react.js +++ b/native/avatars/emoji-avatar-creation.react.js @@ -90,6 +90,11 @@ function EmojiAvatarCreation(props: Props): React.Node { ); }, [saveAvatarCallLoading, styles.loadingContainer]); + const alreadySelectedEmojis = React.useMemo( + () => [pendingEmoji], + [pendingEmoji], + ); + return ( @@ -132,6 +137,8 @@ function EmojiAvatarCreation(props: Props): React.Node { onEmojiSelected={onEmojiSelected} emojiKeyboardOpen={emojiKeyboardOpen} onEmojiKeyboardClose={onEmojiKeyboardClose} + selectMultipleEmojis={false} + alreadySelectedEmojis={alreadySelectedEmojis} /> ); diff --git a/native/chat/multimedia-message-tooltip-button.react.js b/native/chat/multimedia-message-tooltip-button.react.js index a474e8bbfa..74be16fa0e 100644 --- a/native/chat/multimedia-message-tooltip-button.react.js +++ b/native/chat/multimedia-message-tooltip-button.react.js @@ -152,6 +152,8 @@ function MultimediaMessageTooltipButton(props: Props): React.Node { [sendReaction, dismissTooltip], ); + const alreadySelectedEmojis = React.useMemo(() => [], []); + return ( <> @@ -171,6 +173,7 @@ function MultimediaMessageTooltipButton(props: Props): React.Node { onEmojiSelected={onEmojiSelected} emojiKeyboardOpen={emojiPickerOpen} onEmojiKeyboardClose={dismissTooltip} + alreadySelectedEmojis={alreadySelectedEmojis} /> ); diff --git a/native/chat/robotext-message-tooltip-button.react.js b/native/chat/robotext-message-tooltip-button.react.js index 6e0000d0d9..b32f0e4a41 100644 --- a/native/chat/robotext-message-tooltip-button.react.js +++ b/native/chat/robotext-message-tooltip-button.react.js @@ -135,6 +135,8 @@ function RobotextMessageTooltipButton(props: Props): React.Node { [sendReaction, dismissTooltip], ); + const alreadySelectedEmojis = React.useMemo(() => [], []); + return ( <> @@ -153,6 +155,7 @@ function RobotextMessageTooltipButton(props: Props): React.Node { onEmojiSelected={onEmojiSelected} emojiKeyboardOpen={emojiPickerOpen} onEmojiKeyboardClose={dismissTooltip} + alreadySelectedEmojis={alreadySelectedEmojis} /> ); diff --git a/native/chat/text-message-tooltip-button.react.js b/native/chat/text-message-tooltip-button.react.js index 6d6d525545..499b12b54f 100644 --- a/native/chat/text-message-tooltip-button.react.js +++ b/native/chat/text-message-tooltip-button.react.js @@ -149,6 +149,8 @@ function TextMessageTooltipButton(props: Props): React.Node { [sendReaction, dismissTooltip], ); + const alreadySelectedEmojis = React.useMemo(() => [], []); + return ( ); diff --git a/native/components/emoji-keyboard.react.js b/native/components/emoji-keyboard.react.js index 88a624ec5a..194c979c1a 100644 --- a/native/components/emoji-keyboard.react.js +++ b/native/components/emoji-keyboard.react.js @@ -1,8 +1,12 @@ // @flow import AsyncStorage from '@react-native-async-storage/async-storage'; +import _flatMap from 'lodash/fp/flatMap.js'; +import _flow from 'lodash/fp/flow.js'; +import _keyBy from 'lodash/fp/keyBy.js'; import * as React from 'react'; import EmojiPicker, { useRecentPicksPersistence } from 'rn-emoji-keyboard'; +import emojisData from 'rn-emoji-keyboard/src/assets/emojis.json'; const STORAGE_KEY = 'EMOJI_KEYBOARD_RECENT'; @@ -36,6 +40,7 @@ const useRecentPicksPersistenceArgs = { initialization: initializationCallback, onStateChange: onStateChangeCallback, }; +const keyedEmojiData = _flow(_flatMap('data'), _keyBy('emoji'))(emojisData); export type EmojiSelection = { +emoji: string, @@ -50,22 +55,45 @@ type Props = { +onEmojiSelected: (emoji: EmojiSelection) => mixed, +emojiKeyboardOpen: boolean, +onEmojiKeyboardClose: () => mixed, + +selectMultipleEmojis?: boolean, + +alreadySelectedEmojis: $ReadOnlyArray, }; function EmojiKeyboard(props: Props): React.Node { - const { onEmojiSelected, emojiKeyboardOpen, onEmojiKeyboardClose } = props; + const { + onEmojiSelected, + emojiKeyboardOpen, + onEmojiKeyboardClose, + selectMultipleEmojis, + alreadySelectedEmojis, + } = props; + + const [currentlySelected, setCurrentlySelected] = React.useState< + $ReadOnlyArray, + >(() => alreadySelectedEmojis.map(emoji => keyedEmojiData[emoji].name)); + + const handleOnEmojiSelected = React.useCallback( + (emoji: EmojiSelection) => { + if (!selectMultipleEmojis) { + setCurrentlySelected([emoji.name]); + } + onEmojiSelected(emoji); + }, + [onEmojiSelected, setCurrentlySelected, selectMultipleEmojis], + ); useRecentPicksPersistence(useRecentPicksPersistenceArgs); return ( ); }