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 @@ -21,6 +21,7 @@ robotextForMessageInfo, sortMessageInfoList, } from '../shared/message-utils.js'; +import { messageSpecs } from '../shared/messages/message-specs.js'; import { threadInChatList, threadIsPending, @@ -504,6 +505,41 @@ return result; })(); + const threadInfo = threadInfos[threadID]; + const parentThreadInfo = threadInfo?.parentThreadID + ? threadInfos[threadInfo.parentThreadID] + : null; + + const lastChatMessageItem = + chatMessageItems.length > 0 + ? chatMessageItems[chatMessageItems.length - 1] + : undefined; + const messageSpec = messageSpecs[originalMessageInfo.type]; + if ( + !threadCreatedFromMessage && + Object.keys(renderedReactions).length === 0 && + !hasBeenEdited && + !isPinned && + lastChatMessageItem && + lastChatMessageItem.itemType === 'message' && + lastChatMessageItem.messageInfoType === 'robotext' && + !lastChatMessageItem.threadCreatedFromMessage && + Object.keys(lastChatMessageItem.reactions).length === 0 && + !isComposableMessageType(originalMessageInfo.type) && + messageSpec?.mergeIntoPrecedingRobotextMessageItem + ) { + const { mergeIntoPrecedingRobotextMessageItem } = messageSpec; + const mergeResult = mergeIntoPrecedingRobotextMessageItem( + originalMessageInfo, + lastChatMessageItem, + { threadInfo, parentThreadInfo }, + ); + if (mergeResult.shouldMerge) { + chatMessageItems[chatMessageItems.length - 1] = mergeResult.item; + continue; + } + } + if (isComposableMessageType(originalMessageInfo.type)) { // We use these invariants instead of just checking the messageInfo.type // directly in the conditional above so that isComposableMessageType can @@ -536,11 +572,6 @@ originalMessageInfo.type !== messageTypes.MULTIMEDIA, "Flow doesn't understand isComposableMessageType above", ); - const threadInfo = threadInfos[threadID]; - const parentThreadInfo = threadInfo?.parentThreadID - ? threadInfos[threadInfo.parentThreadID] - : null; - const robotext = robotextForMessageInfo( originalMessageInfo, threadInfo, diff --git a/lib/shared/messages/message-spec.js b/lib/shared/messages/message-spec.js --- a/lib/shared/messages/message-spec.js +++ b/lib/shared/messages/message-spec.js @@ -2,6 +2,7 @@ import type { TType } from 'tcomb'; +import type { RobotextChatMessageInfoItem } from '../../selectors/chat-selectors.js'; import type { PlatformDetails } from '../../types/device-types.js'; import type { Media } from '../../types/media-types.js'; import type { @@ -71,6 +72,10 @@ parentThreadInfo: ?ThreadInfo, ) => Promise; +export type MergeRobotextMessageItemResult = + | { +shouldMerge: false } + | { +shouldMerge: true, +item: RobotextChatMessageInfoItem }; + export type MessageSpec = { +messageContentForServerDB?: (data: Data | RawInfo) => string, +messageContentForClientDB?: (data: RawInfo) => string, @@ -121,4 +126,9 @@ +parseDerivedMessages?: (row: Object, requiredIDs: Set) => void, +useCreationSideEffectsFunc?: () => CreationSideEffectsFunc, +validator: TType, + +mergeIntoPrecedingRobotextMessageItem?: ( + messageInfo: Info, + precedingMessageInfoItem: RobotextChatMessageInfoItem, + params: RobotextParams, + ) => MergeRobotextMessageItemResult, };