Page MenuHomePhabricator

D5811.diff
No OneTemporary

D5811.diff

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
@@ -272,6 +272,7 @@
endsCluster: boolean,
+robotext: string,
+threadCreatedFromMessage: ?ThreadInfo,
+ +reactions: $ReadOnlyMap<string, MessageReactionInfo>,
};
export type ChatMessageInfoItem =
| RobotextChatMessageInfoItem
@@ -283,8 +284,14 @@
+startsCluster: boolean,
endsCluster: boolean,
+threadCreatedFromMessage: ?ThreadInfo,
+ +reactions: $ReadOnlyMap<string, MessageReactionInfo>,
};
export type ChatMessageItem = { itemType: 'loader' } | ChatMessageInfoItem;
+export type MessageReactionInfo = {
+ +viewerReacted: boolean,
+ +users: $ReadOnlySet<string>,
+};
+
const msInFiveMinutes = 5 * 60 * 1000;
function createChatMessageItems(
threadID: string,
@@ -293,6 +300,7 @@
threadInfos: { +[id: string]: ThreadInfo },
threadInfoFromSourceMessageID: { +[id: string]: ThreadInfo },
additionalMessages: $ReadOnlyArray<MessageInfo>,
+ viewerID: string,
): ChatMessageItem[] {
const thread = messageStore.threads[threadID];
@@ -304,6 +312,43 @@
? sortMessageInfoList([...threadMessageInfos, ...additionalMessages])
: threadMessageInfos;
+ const targetMessageReactionsMap = new Map<string, Map<string, Set<string>>>();
+
+ // 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.
+ for (let i = messages.length - 1; i >= 0; i--) {
+ const messageInfo = messages[i];
+ if (messageInfo.type !== messageTypes.REACTION) {
+ continue;
+ }
+
+ if (!targetMessageReactionsMap.has(messageInfo.targetMessageID)) {
+ const reactsMap = new Map<string, Set<string>>();
+ targetMessageReactionsMap.set(messageInfo.targetMessageID, reactsMap);
+ }
+
+ const messageReactsMap = targetMessageReactionsMap.get(
+ messageInfo.targetMessageID,
+ );
+ invariant(messageReactsMap, 'messageReactsInfo should be set');
+
+ if (!messageReactsMap.has(messageInfo.reaction)) {
+ const usersSet = new Set<string>();
+ messageReactsMap.set(messageInfo.reaction, usersSet);
+ }
+
+ const messageReactionUsersSet = messageReactsMap.get(messageInfo.reaction);
+ invariant(messageReactionUsersSet, 'messageReactionUsersSet should be set');
+
+ if (messageInfo.action === 'add_reaction') {
+ messageReactionUsersSet.add(messageInfo.creator.id);
+ } else {
+ messageReactionUsersSet.delete(messageInfo.creator.id);
+ }
+ }
+
const chatMessageItems = [];
let lastMessageInfo = null;
for (let i = messages.length - 1; i >= 0; i--) {
@@ -346,6 +391,43 @@
messageInfo.id && threadInfos[threadID]?.type !== threadTypes.SIDEBAR
? threadInfoFromSourceMessageID[messageInfo.id]
: undefined;
+
+ const renderedReactions: $ReadOnlyMap<
+ string,
+ MessageReactionInfo,
+ > = (() => {
+ const result = new Map<string, MessageReactionInfo>();
+
+ let messageReactsMap;
+ if (originalMessageInfo.id) {
+ messageReactsMap = targetMessageReactionsMap.get(
+ originalMessageInfo.id,
+ );
+ }
+
+ if (!messageReactsMap) {
+ return result;
+ }
+
+ for (const reaction of messageReactsMap.keys()) {
+ const reactionUsersSet = messageReactsMap.get(reaction);
+ invariant(reactionUsersSet, 'reactionUsersSet should be set');
+
+ if (reactionUsersSet.size === 0) {
+ continue;
+ }
+
+ const messageReactionInfo = {
+ users: reactionUsersSet,
+ viewerReacted: reactionUsersSet.has(viewerID),
+ };
+
+ result.set(reaction, messageReactionInfo);
+ }
+
+ return result;
+ })();
+
if (isComposableMessageType(originalMessageInfo.type)) {
// We use these invariants instead of just checking the messageInfo.type
// directly in the conditional above so that isComposableMessageType can
@@ -366,6 +448,7 @@
startsCluster,
endsCluster: false,
threadCreatedFromMessage,
+ reactions: renderedReactions,
});
} else {
invariant(
@@ -386,6 +469,7 @@
endsCluster: false,
threadCreatedFromMessage,
robotext,
+ reactions: renderedReactions,
});
}
lastMessageInfo = originalMessageInfo;
@@ -412,13 +496,16 @@
messageInfoSelector,
threadInfoSelector,
threadInfoFromSourceMessageIDSelector,
+ (state: BaseAppState<*>) =>
+ state.currentUserInfo && state.currentUserInfo.id,
(
messageStore: MessageStore,
messageInfos: { +[id: string]: ?MessageInfo },
threadInfos: { +[id: string]: ThreadInfo },
threadInfoFromSourceMessageID: { +[id: string]: ThreadInfo },
+ viewerID: ?string,
): ?(ChatMessageItem[]) => {
- if (!threadID) {
+ if (!threadID || !viewerID) {
return null;
}
return createChatMessageItems(
@@ -428,6 +515,7 @@
threadInfos,
threadInfoFromSourceMessageID,
additionalMessages,
+ viewerID,
);
},
);

File Metadata

Mime Type
text/plain
Expires
Mon, Nov 25, 2:49 AM (21 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2576560
Default Alt Text
D5811.diff (5 KB)

Event Timeline