From 9be393b234f2a69746bd72f9f8334dc909a8d34f Mon Sep 17 00:00:00 2001 From: Ginsu Eddy Date: Fri, 23 Jun 2023 13:11:08 -0700 Subject: [PATCH] [lib/native] introduce getViewerAlreadySelectedMessageReactions Summary: This diff is the second 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 `true`. To handle this case we need to iterate through the `ReactionInfo` map and return an array of emojis that the user has already selected. I introduced a separate helper function called `getViewerAlreadySelectedMessageReactions` since `MultimediaMessageTooltipButton`, `TextMessageTooltipButton` and `RobotextMessageTooltipButton` will all need to do this similar functionality. 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 D8284 Test Plan: Please watch the demo video below: {F601071} Reviewers: atul, kamil Reviewed By: kamil Subscribers: ashoat, tomek Differential Revision: https://phab.comm.dev/D8288 --- lib/shared/reaction-utils.js | 17 +++++++++++++++++ .../multimedia-message-tooltip-button.react.js | 10 ++++++++-- .../robotext-message-tooltip-button.react.js | 10 ++++++++-- .../chat/text-message-tooltip-button.react.js | 10 ++++++++-- native/components/emoji-keyboard.react.js | 6 ++++++ 5 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lib/shared/reaction-utils.js b/lib/shared/reaction-utils.js index 5aa27ef2b1..df97cc007b 100644 --- a/lib/shared/reaction-utils.js +++ b/lib/shared/reaction-utils.js @@ -33,6 +33,22 @@ function stringForReactionList(reactions: ReactionInfo): string { return reactionText.join(' '); } +function getViewerAlreadySelectedMessageReactions( + reactions: ReactionInfo, +): $ReadOnlyArray { + const alreadySelectedEmojis = []; + + for (const reaction in reactions) { + const reactionInfo = reactions[reaction]; + + if (reactionInfo.viewerReacted) { + alreadySelectedEmojis.push(reaction); + } + } + + return alreadySelectedEmojis; +} + type MessageReactionListInfo = { +id: string, +isViewer: boolean, @@ -103,6 +119,7 @@ function useCanCreateReactionFromMessage( export { stringForReactionList, + getViewerAlreadySelectedMessageReactions, useMessageReactionsList, useCanCreateReactionFromMessage, }; diff --git a/native/chat/multimedia-message-tooltip-button.react.js b/native/chat/multimedia-message-tooltip-button.react.js index 74be16fa0e..10d3461ebf 100644 --- a/native/chat/multimedia-message-tooltip-button.react.js +++ b/native/chat/multimedia-message-tooltip-button.react.js @@ -4,7 +4,10 @@ import * as React from 'react'; import Animated from 'react-native-reanimated'; import { localIDPrefix } from 'lib/shared/message-utils.js'; -import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js'; +import { + getViewerAlreadySelectedMessageReactions, + useCanCreateReactionFromMessage, +} from 'lib/shared/reaction-utils.js'; import { TooltipInlineEngagement } from './inline-engagement.react.js'; import { InnerMultimediaMessage } from './inner-multimedia-message.react.js'; @@ -152,7 +155,10 @@ function MultimediaMessageTooltipButton(props: Props): React.Node { [sendReaction, dismissTooltip], ); - const alreadySelectedEmojis = React.useMemo(() => [], []); + const alreadySelectedEmojis = React.useMemo( + () => getViewerAlreadySelectedMessageReactions(item.reactions), + [item.reactions], + ); return ( <> diff --git a/native/chat/robotext-message-tooltip-button.react.js b/native/chat/robotext-message-tooltip-button.react.js index b32f0e4a41..00d409c0af 100644 --- a/native/chat/robotext-message-tooltip-button.react.js +++ b/native/chat/robotext-message-tooltip-button.react.js @@ -4,7 +4,10 @@ import * as React from 'react'; import Animated from 'react-native-reanimated'; import { localIDPrefix } from 'lib/shared/message-utils.js'; -import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js'; +import { + getViewerAlreadySelectedMessageReactions, + useCanCreateReactionFromMessage, +} from 'lib/shared/reaction-utils.js'; import { TooltipInlineEngagement } from './inline-engagement.react.js'; import { InnerRobotextMessage } from './inner-robotext-message.react.js'; @@ -135,7 +138,10 @@ function RobotextMessageTooltipButton(props: Props): React.Node { [sendReaction, dismissTooltip], ); - const alreadySelectedEmojis = React.useMemo(() => [], []); + const alreadySelectedEmojis = React.useMemo( + () => getViewerAlreadySelectedMessageReactions(item.reactions), + [item.reactions], + ); return ( <> diff --git a/native/chat/text-message-tooltip-button.react.js b/native/chat/text-message-tooltip-button.react.js index 499b12b54f..45996265b8 100644 --- a/native/chat/text-message-tooltip-button.react.js +++ b/native/chat/text-message-tooltip-button.react.js @@ -4,7 +4,10 @@ import * as React from 'react'; import Animated from 'react-native-reanimated'; import { localIDPrefix } from 'lib/shared/message-utils.js'; -import { useCanCreateReactionFromMessage } from 'lib/shared/reaction-utils.js'; +import { + getViewerAlreadySelectedMessageReactions, + useCanCreateReactionFromMessage, +} from 'lib/shared/reaction-utils.js'; import { TooltipInlineEngagement } from './inline-engagement.react.js'; import { InnerTextMessage } from './inner-text-message.react.js'; @@ -149,7 +152,10 @@ function TextMessageTooltipButton(props: Props): React.Node { [sendReaction, dismissTooltip], ); - const alreadySelectedEmojis = React.useMemo(() => [], []); + const alreadySelectedEmojis = React.useMemo( + () => getViewerAlreadySelectedMessageReactions(item.reactions), + [item.reactions], + ); return ( diff --git a/native/components/emoji-keyboard.react.js b/native/components/emoji-keyboard.react.js index 194c979c1a..60ef4b3e25 100644 --- a/native/components/emoji-keyboard.react.js +++ b/native/components/emoji-keyboard.react.js @@ -76,6 +76,12 @@ function EmojiKeyboard(props: Props): React.Node { (emoji: EmojiSelection) => { if (!selectMultipleEmojis) { setCurrentlySelected([emoji.name]); + } else if (emoji.alreadySelected) { + setCurrentlySelected(prev => + prev.filter(emojiName => emojiName !== emoji.name), + ); + } else { + setCurrentlySelected(prev => [...prev, emoji.name]); } onEmojiSelected(emoji); },