diff --git a/lib/selectors/chat-selectors.js b/lib/selectors/chat-selectors.js --- a/lib/selectors/chat-selectors.js +++ b/lib/selectors/chat-selectors.js @@ -40,7 +40,11 @@ maxUnreadSidebars, threadTypes, } from '../types/thread-types'; -import type { UserInfo, AccountUserInfo } from '../types/user-types'; +import type { + UserInfo, + AccountUserInfo, + RelativeUserInfo, +} from '../types/user-types'; import { threeDays } from '../utils/date-utils'; import memoize2 from '../utils/memoize'; import { @@ -289,8 +293,9 @@ export type ChatMessageItem = { itemType: 'loader' } | ChatMessageInfoItem; export type MessageReactionInfo = { +viewerReacted: boolean, - +users: $ReadOnlySet, + +users: $ReadOnlyArray, }; +type TargetMessageReactions = Map>; const msInFiveMinutes = 5 * 60 * 1000; function createChatMessageItems( @@ -312,12 +317,13 @@ ? sortMessageInfoList([...threadMessageInfos, ...additionalMessages]) : threadMessageInfos; - const targetMessageReactionsMap = new Map>>(); + const targetMessageReactionsMap = new Map(); // We need to iterate backwards to put the order of messages in chronological // order, starting with the oldest. This avoids the scenario where the most // recent message with the remove_reaction action may try to remove a user - // that hasn't been added to the usersSet, causing it to be skipped. + // that hasn't been added to the messageReactionUsersInfoMap, causing it + // to be skipped. for (let i = messages.length - 1; i >= 0; i--) { const messageInfo = messages[i]; if (messageInfo.type !== messageTypes.REACTION) { @@ -325,7 +331,7 @@ } if (!targetMessageReactionsMap.has(messageInfo.targetMessageID)) { - const reactsMap = new Map>(); + const reactsMap: TargetMessageReactions = new Map(); targetMessageReactionsMap.set(messageInfo.targetMessageID, reactsMap); } @@ -335,17 +341,25 @@ invariant(messageReactsMap, 'messageReactsInfo should be set'); if (!messageReactsMap.has(messageInfo.reaction)) { - const usersSet = new Set(); - messageReactsMap.set(messageInfo.reaction, usersSet); + const usersInfoMap = new Map(); + messageReactsMap.set(messageInfo.reaction, usersInfoMap); } - const messageReactionUsersSet = messageReactsMap.get(messageInfo.reaction); - invariant(messageReactionUsersSet, 'messageReactionUsersSet should be set'); + const messageReactionUsersInfoMap = messageReactsMap.get( + messageInfo.reaction, + ); + invariant( + messageReactionUsersInfoMap, + 'messageReactionUsersInfoMap should be set', + ); if (messageInfo.action === 'add_reaction') { - messageReactionUsersSet.add(messageInfo.creator.id); + messageReactionUsersInfoMap.set( + messageInfo.creator.id, + messageInfo.creator, + ); } else { - messageReactionUsersSet.delete(messageInfo.creator.id); + messageReactionUsersInfoMap.delete(messageInfo.creator.id); } } @@ -410,16 +424,18 @@ } for (const reaction of messageReactsMap.keys()) { - const reactionUsersSet = messageReactsMap.get(reaction); - invariant(reactionUsersSet, 'reactionUsersSet should be set'); + const reactionUsersInfoMap = messageReactsMap.get(reaction); + invariant(reactionUsersInfoMap, 'reactionUsersInfoMap should be set'); - if (reactionUsersSet.size === 0) { + if (reactionUsersInfoMap.size === 0) { continue; } + const reactionUserInfos = [...reactionUsersInfoMap.values()]; + const messageReactionInfo = { - users: reactionUsersSet, - viewerReacted: reactionUsersSet.has(viewerID), + users: reactionUserInfos, + viewerReacted: reactionUsersInfoMap.has(viewerID), }; result.set(reaction, messageReactionInfo); diff --git a/lib/shared/reaction-utils.js b/lib/shared/reaction-utils.js --- a/lib/shared/reaction-utils.js +++ b/lib/shared/reaction-utils.js @@ -22,7 +22,7 @@ invariant(reactionInfo, 'reactionInfo should be set'); reactionText.push(reaction); - const { size: numberOfReacts } = reactionInfo.users; + const { length: numberOfReacts } = reactionInfo.users; if (numberOfReacts <= 1) { continue; } diff --git a/lib/shared/reaction-utils.test.js b/lib/shared/reaction-utils.test.js --- a/lib/shared/reaction-utils.test.js +++ b/lib/shared/reaction-utils.test.js @@ -11,10 +11,13 @@ 'should return (👍 3) for a message with three user likes' + ' including the viewer', () => { - const messageLikesUsers = ['83810', '86622', '83889']; - const messageLikesUsersSet = new Set(messageLikesUsers); + const messageLikesUsers = [ + { id: '83810', isViewer: true, username: 'ginsu' }, + { id: '86622', isViewer: false, username: 'ashoat' }, + { id: '83889', isViewer: false, username: 'atul' }, + ]; const messageLikesInfo = { - users: messageLikesUsersSet, + users: messageLikesUsers, viewerReacted: true, }; @@ -29,10 +32,13 @@ 'should return (👍 3) for a message with three user likes' + ' not including the viewer', () => { - const messageLikesUsers = ['83810', '86622', '83889']; - const messageLikesUsersSet = new Set(messageLikesUsers); + const messageLikesUsers = [ + { id: '83810', isViewer: false, username: 'ginsu' }, + { id: '86622', isViewer: false, username: 'ashoat' }, + { id: '83889', isViewer: false, username: 'atul' }, + ]; const messageLikesInfo = { - users: messageLikesUsersSet, + users: messageLikesUsers, viewerReacted: false, }; @@ -47,10 +53,11 @@ 'should return (👍) for a message with one user like' + ' including the viewer', () => { - const messageLikesUsers = ['83810']; - const messageLikesUsersSet = new Set(messageLikesUsers); + const messageLikesUsers = [ + { id: '83810', isViewer: false, username: 'ginsu' }, + ]; const messageLikesInfo = { - users: messageLikesUsersSet, + users: messageLikesUsers, viewerReacted: true, }; @@ -65,10 +72,11 @@ 'should return (👍) for a message with one user like' + ' not including the viewer', () => { - const messageLikesUsers = ['86622']; - const messageLikesUsersSet = new Set(messageLikesUsers); + const messageLikesUsers = [ + { id: '83810', isViewer: false, username: 'ashoat' }, + ]; const messageLikesInfo = { - users: messageLikesUsersSet, + users: messageLikesUsers, viewerReacted: false, }; @@ -89,17 +97,21 @@ 'should return (👍 😆 3) for a message with one like not including' + ' the viewer and three laugh reactions including the viewer', () => { - const messageLikesUsers = ['86622']; - const messageLikesUsersSet = new Set(messageLikesUsers); + const messageLikesUsers = [ + { id: '83810', isViewer: false, username: 'varun' }, + ]; const messageLikesInfo = { - users: messageLikesUsersSet, + users: messageLikesUsers, viewerReacted: false, }; - const messageLaughsUsers = ['12345', '67890', '83889']; - const messageLaughsUsersSet = new Set(messageLaughsUsers); + const messageLaughsUsers = [ + { id: '12345', isViewer: true, username: 'ginsu' }, + { id: '67890', isViewer: false, username: 'ashoat' }, + { id: '83889', isViewer: false, username: 'atul' }, + ]; const messageLaughsInfo = { - users: messageLaughsUsersSet, + users: messageLaughsUsers, viewerReacted: true, }; @@ -116,22 +128,21 @@ ' not including the viewer', () => { const messageLikesUsers = [ - '86622', - '12345', - '67890', - '83889', - '49203', - '12932', - '83029', - '72902', - '49022', - '48902', - '80922', - '12890', + { id: '86622', isViewer: false, username: 'ginsu' }, + { id: '12345', isViewer: false, username: 'ashoat' }, + { id: '67890', isViewer: false, username: 'atul' }, + { id: '83889', isViewer: false, username: 'varun' }, + { id: '49203', isViewer: false, username: 'tomek' }, + { id: '83029', isViewer: false, username: 'max' }, + { id: '72902', isViewer: false, username: 'jon' }, + { id: '49022', isViewer: false, username: 'mark' }, + { id: '48902', isViewer: false, username: 'kamil' }, + { id: '80922', isViewer: false, username: 'marcin' }, + { id: '12890', isViewer: false, username: 'inka' }, + { id: '67891', isViewer: false, username: 'przemek' }, ]; - const messageLikesUsersSet = new Set(messageLikesUsers); const messageLikesInfo = { - users: messageLikesUsersSet, + users: messageLikesUsers, viewerReacted: false, };