diff --git a/lib/shared/inline-engagement-utils.js b/lib/shared/inline-engagement-utils.js
index 67b2cc686..2a121bef6 100644
--- a/lib/shared/inline-engagement-utils.js
+++ b/lib/shared/inline-engagement-utils.js
@@ -1,13 +1,25 @@
// @flow
+import type { ReactionInfo } from '../selectors/chat-selectors.js';
import type { ThreadInfo } from '../types/thread-types.js';
function getInlineEngagementSidebarText(threadInfo: ?ThreadInfo): string {
if (!threadInfo) {
return '';
}
const repliesCount = threadInfo.repliesCount || 1;
return `${repliesCount} ${repliesCount > 1 ? 'replies' : 'reply'}`;
}
-export { getInlineEngagementSidebarText };
+function reactionsToRawString(reactions: ReactionInfo): string {
+ const reactionStringParts = [];
+
+ for (const reaction in reactions) {
+ const reactionInfo = reactions[reaction];
+ reactionStringParts.push(`${reaction}${reactionInfo.users.length}`);
+ }
+
+ return reactionStringParts.join('');
+}
+
+export { getInlineEngagementSidebarText, reactionsToRawString };
diff --git a/native/chat/chat-item-height-measurer.react.js b/native/chat/chat-item-height-measurer.react.js
index a5d2d139d..e616b8cac 100644
--- a/native/chat/chat-item-height-measurer.react.js
+++ b/native/chat/chat-item-height-measurer.react.js
@@ -1,192 +1,199 @@
// @flow
import invariant from 'invariant';
import * as React from 'react';
+import {
+ getInlineEngagementSidebarText,
+ reactionsToRawString,
+} from 'lib/shared/inline-engagement-utils.js';
import { messageID } from 'lib/shared/message-utils.js';
import {
messageTypes,
type MessageType,
} from 'lib/types/message-types-enum.js';
import { entityTextToRawString } from 'lib/utils/entity-text.js';
import type { MeasurementTask } from './chat-context-provider.react.js';
import { useComposedMessageMaxWidth } from './composed-message-width.js';
import { dummyNodeForRobotextMessageHeightMeasurement } from './inner-robotext-message.react.js';
import { dummyNodeForTextMessageHeightMeasurement } from './inner-text-message.react.js';
import type { NativeChatMessageItem } from './message-data.react.js';
import { MessageListContextProvider } from './message-list-types.js';
import { multimediaMessageContentSizes } from './multimedia-message-utils.js';
import { chatMessageItemKey } from './utils.js';
import NodeHeightMeasurer from '../components/node-height-measurer.react.js';
import { InputStateContext } from '../input/input-state.js';
type Props = {
+measurement: MeasurementTask,
};
const heightMeasurerKey = (item: NativeChatMessageItem) => {
if (item.itemType !== 'message') {
return null;
}
- const { messageInfo } = item;
+ const { messageInfo, threadCreatedFromMessage, reactions } = item;
+
if (messageInfo.type === messageTypes.TEXT) {
return JSON.stringify({ text: messageInfo.text });
} else if (item.robotext) {
const { threadID } = item.messageInfo;
return JSON.stringify({
robotext: entityTextToRawString(item.robotext, { threadID }),
+ sidebar: getInlineEngagementSidebarText(threadCreatedFromMessage),
+ reactions: reactionsToRawString(reactions),
});
}
return null;
};
// ESLint doesn't recognize that invariant always throws
// eslint-disable-next-line consistent-return
const heightMeasurerDummy = (item: NativeChatMessageItem) => {
invariant(
item.itemType === 'message',
'NodeHeightMeasurer asked for dummy for non-message item',
);
const { messageInfo } = item;
if (messageInfo.type === messageTypes.TEXT) {
return dummyNodeForTextMessageHeightMeasurement(messageInfo.text);
} else if (item.robotext) {
return dummyNodeForRobotextMessageHeightMeasurement(
item.robotext,
item.messageInfo.threadID,
item.threadCreatedFromMessage,
item.reactions,
);
}
invariant(false, 'NodeHeightMeasurer asked for dummy for non-text message');
};
function ChatItemHeightMeasurer(props: Props) {
const composedMessageMaxWidth = useComposedMessageMaxWidth();
const inputState = React.useContext(InputStateContext);
const inputStatePendingUploads = inputState?.pendingUploads;
const { measurement } = props;
const { threadInfo } = measurement;
const heightMeasurerMergeItem = React.useCallback(
(item: NativeChatMessageItem, height: ?number) => {
if (item.itemType !== 'message') {
return item;
}
const { messageInfo } = item;
const messageType: MessageType = messageInfo.type;
invariant(
messageType !== messageTypes.SIDEBAR_SOURCE,
'Sidebar source messages should be replaced by sourceMessage before being measured',
);
if (
messageInfo.type === messageTypes.IMAGES ||
messageInfo.type === messageTypes.MULTIMEDIA
) {
// Conditional due to Flow...
const localMessageInfo = item.localMessageInfo
? item.localMessageInfo
: null;
const id = messageID(messageInfo);
const pendingUploads = inputStatePendingUploads?.[id];
const sizes = multimediaMessageContentSizes(
messageInfo,
composedMessageMaxWidth,
);
return {
itemType: 'message',
messageShapeType: 'multimedia',
messageInfo,
localMessageInfo,
threadInfo,
startsConversation: item.startsConversation,
startsCluster: item.startsCluster,
endsCluster: item.endsCluster,
threadCreatedFromMessage: item.threadCreatedFromMessage,
pendingUploads,
reactions: item.reactions,
hasBeenEdited: item.hasBeenEdited,
isPinned: item.isPinned,
...sizes,
};
}
invariant(
height !== null && height !== undefined,
'height should be set',
);
if (messageInfo.type === messageTypes.TEXT) {
// Conditional due to Flow...
const localMessageInfo = item.localMessageInfo
? item.localMessageInfo
: null;
return {
itemType: 'message',
messageShapeType: 'text',
messageInfo,
localMessageInfo,
threadInfo,
startsConversation: item.startsConversation,
startsCluster: item.startsCluster,
endsCluster: item.endsCluster,
threadCreatedFromMessage: item.threadCreatedFromMessage,
contentHeight: height,
reactions: item.reactions,
hasBeenEdited: item.hasBeenEdited,
isPinned: item.isPinned,
};
}
invariant(
item.messageInfoType !== 'composable',
'ChatItemHeightMeasurer was handed a messageInfoType=composable, but ' +
`does not know how to handle MessageType ${messageInfo.type}`,
);
invariant(
item.messageInfoType === 'robotext',
'ChatItemHeightMeasurer was handed a messageInfoType that it does ' +
`not recognize: ${item.messageInfoType}`,
);
return {
itemType: 'message',
messageShapeType: 'robotext',
messageInfo,
threadInfo,
startsConversation: item.startsConversation,
startsCluster: item.startsCluster,
endsCluster: item.endsCluster,
threadCreatedFromMessage: item.threadCreatedFromMessage,
robotext: item.robotext,
contentHeight: height,
reactions: item.reactions,
};
},
[composedMessageMaxWidth, inputStatePendingUploads, threadInfo],
);
return (
);
}
const MemoizedChatItemHeightMeasurer: React.ComponentType =
React.memo(ChatItemHeightMeasurer);
export default MemoizedChatItemHeightMeasurer;