diff --git a/keyserver/src/creators/thread-creator.js b/keyserver/src/creators/thread-creator.js --- a/keyserver/src/creators/thread-creator.js +++ b/keyserver/src/creators/thread-creator.js @@ -423,8 +423,7 @@ sourceMessage.type !== messageTypes.REACTION && sourceMessage.type !== messageTypes.EDIT_MESSAGE && sourceMessage.type !== messageTypes.SIDEBAR_SOURCE && - sourceMessage.type !== messageTypes.TOGGLE_PIN && - sourceMessage.type !== messageTypes.CHANGE_ROLE, + sourceMessage.type !== messageTypes.TOGGLE_PIN, 'Invalid sidebar source type', ); diff --git a/keyserver/src/push/send.js b/keyserver/src/push/send.js --- a/keyserver/src/push/send.js +++ b/keyserver/src/push/send.js @@ -220,6 +220,9 @@ const { threadID } = firstNewMessageInfo; const threadInfo = threadInfos[threadID]; + const parentThreadInfo = threadInfo.parentThreadID + ? threadInfos[threadInfo.parentThreadID] + : null; const updateBadge = threadInfo.currentUser.subscription.home; const displayBanner = threadInfo.currentUser.subscription.pushNotifs; const username = userInfos[userID] && userInfos[userID].username; @@ -246,6 +249,7 @@ const notifTexts = await notifTextsForMessageInfo( allMessageInfos, threadInfo, + parentThreadInfo, notifTargetUserInfo, getENSNames, ); 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 @@ -26,6 +26,7 @@ threadIsPending, threadIsTopLevel, threadInChatList, + parseSourceMessageIDFromPendingSidebarID, } from '../shared/thread-utils.js'; import { messageTypes } from '../types/message-types-enum.js'; import { @@ -529,9 +530,16 @@ originalMessageInfo.type !== messageTypes.MULTIMEDIA, "Flow doesn't understand isComposableMessageType above", ); + const parentMessageID = + parseSourceMessageIDFromPendingSidebarID(threadID); + const parentThreadID = parentMessageID + ? messageStore.messages[parentMessageID]?.threadID + : ''; + const robotext = robotextForMessageInfo( originalMessageInfo, threadInfos[threadID], + threadInfos[parentThreadID], ); chatMessageItems.push({ itemType: 'message', diff --git a/lib/shared/message-utils.js b/lib/shared/message-utils.js --- a/lib/shared/message-utils.js +++ b/lib/shared/message-utils.js @@ -12,6 +12,7 @@ import { useStringForUser } from '../hooks/ens-cache.js'; import { contentStringForMediaArray } from '../media/media-utils.js'; import type { ChatMessageInfoItem } from '../selectors/chat-selectors.js'; +import { threadInfoSelector } from '../selectors/thread-selectors.js'; import { userIDsToRelativeUserInfos } from '../selectors/user-selectors.js'; import { type PlatformDetails, isWebPlatform } from '../types/device-types.js'; import type { Media } from '../types/media-types.js'; @@ -74,13 +75,14 @@ function robotextForMessageInfo( messageInfo: RobotextMessageInfo, threadInfo: ?ThreadInfo, + parentThreadInfo: ?ThreadInfo, ): EntityText { const messageSpec = messageSpecs[messageInfo.type]; invariant( messageSpec.robotext, `we're not aware of messageType ${messageInfo.type}`, ); - return messageSpec.robotext(messageInfo, { threadInfo }); + return messageSpec.robotext(messageInfo, { threadInfo, parentThreadInfo }); } function createMessageInfo( @@ -408,6 +410,7 @@ | ReactionMessageInfo | EditMessageInfo, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, markdownRules: ParserRules, ): EntityText { const { messageTitle } = messageSpecs[messageInfo.type]; @@ -423,7 +426,7 @@ messageInfo.type !== messageTypes.EDIT_MESSAGE, 'messageTitle can only be auto-generated for RobotextMessageInfo', ); - return robotextForMessageInfo(messageInfo, threadInfo); + return robotextForMessageInfo(messageInfo, threadInfo, parentThreadInfo); } function mergeThreadMessageInfos( @@ -508,6 +511,11 @@ messageInfo = originalMessageInfo; } + const { parentThreadID } = threadInfo; + const parentThreadInfo = useSelector(state => + parentThreadID ? threadInfoSelector(state)[parentThreadID] : null, + ); + const hasUsername = threadIsGroupChat(threadInfo) || threadInfo.name !== '' || @@ -538,8 +546,13 @@ if (!messageInfo) { return messageInfo; } - return getMessageTitle(messageInfo, threadInfo, markdownRules); - }, [messageInfo, threadInfo, markdownRules]); + return getMessageTitle( + messageInfo, + threadInfo, + parentThreadInfo, + markdownRules, + ); + }, [messageInfo, threadInfo, parentThreadInfo, markdownRules]); const threadID = threadInfo.id; const entityTextToStringParams = React.useMemo( @@ -647,8 +660,7 @@ messageType === messageTypes.REACTION || messageType === messageTypes.EDIT_MESSAGE || messageType === messageTypes.SIDEBAR_SOURCE || - messageType === messageTypes.TOGGLE_PIN || - messageType === messageTypes.CHANGE_ROLE + messageType === messageTypes.TOGGLE_PIN ); } diff --git a/lib/shared/message-utils.test.js b/lib/shared/message-utils.test.js --- a/lib/shared/message-utils.test.js +++ b/lib/shared/message-utils.test.js @@ -12,8 +12,7 @@ messageType === messageTypes.REACTION || messageType === messageTypes.EDIT_MESSAGE || messageType === messageTypes.SIDEBAR_SOURCE || - messageType === messageTypes.TOGGLE_PIN || - messageType === messageTypes.CHANGE_ROLE + messageType === messageTypes.TOGGLE_PIN ) { expect(shouldBeInvalidSidebarSource).toBe(true); } else { diff --git a/lib/shared/messages/add-members-message-spec.js b/lib/shared/messages/add-members-message-spec.js --- a/lib/shared/messages/add-members-message-spec.js +++ b/lib/shared/messages/add-members-message-spec.js @@ -112,6 +112,7 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, ): Promise { const addedMembersObject = {}; for (const messageInfo of messageInfos) { @@ -132,7 +133,11 @@ ); const mergedMessageInfo = { ...mostRecentMessageInfo, addedMembers }; - const robotext = notifRobotextForMessageInfo(mergedMessageInfo, threadInfo); + const robotext = notifRobotextForMessageInfo( + mergedMessageInfo, + threadInfo, + parentThreadInfo, + ); const merged = ET`${robotext} to ${ET.thread({ display: 'shortName', threadInfo, diff --git a/lib/shared/messages/change-role-message-spec.js b/lib/shared/messages/change-role-message-spec.js --- a/lib/shared/messages/change-role-message-spec.js +++ b/lib/shared/messages/change-role-message-spec.js @@ -129,10 +129,11 @@ users.map(user => ET`${ET.user({ userInfo: user })}`), ); - const { threadInfo } = params; - invariant(threadInfo, 'ThreadInfo should be set for CHANGE_ROLE message'); + const { threadInfo, parentThreadInfo } = params; - const threadRoleName = threadInfo.roles[messageInfo.newRole]?.name; + const threadRoleName = + threadInfo?.roles[messageInfo.newRole]?.name ?? + parentThreadInfo?.roles[messageInfo.newRole]?.name; const messageInfoRoleName = messageInfo.roleName; const roleName = threadRoleName ?? messageInfoRoleName; @@ -148,6 +149,7 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, ): Promise { const membersObject = {}; for (const messageInfo of messageInfos) { @@ -168,7 +170,11 @@ ); const mergedMessageInfo = { ...mostRecentMessageInfo, members }; - const robotext = notifRobotextForMessageInfo(mergedMessageInfo, threadInfo); + const robotext = notifRobotextForMessageInfo( + mergedMessageInfo, + threadInfo, + parentThreadInfo, + ); const merged = ET`${robotext} of ${ET.thread({ display: 'shortName', threadInfo, diff --git a/lib/shared/messages/change-settings-message-spec.js b/lib/shared/messages/change-settings-message-spec.js --- a/lib/shared/messages/change-settings-message-spec.js +++ b/lib/shared/messages/change-settings-message-spec.js @@ -148,13 +148,18 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, ): Promise { const mostRecentMessageInfo = messageInfos[0]; invariant( mostRecentMessageInfo.type === messageTypes.CHANGE_SETTINGS, 'messageInfo should be messageTypes.CHANGE_SETTINGS!', ); - const body = notifRobotextForMessageInfo(mostRecentMessageInfo, threadInfo); + const body = notifRobotextForMessageInfo( + mostRecentMessageInfo, + threadInfo, + parentThreadInfo, + ); return { merged: body, title: threadInfo.uiName, diff --git a/lib/shared/messages/create-sidebar-message-spec.js b/lib/shared/messages/create-sidebar-message-spec.js --- a/lib/shared/messages/create-sidebar-message-spec.js +++ b/lib/shared/messages/create-sidebar-message-spec.js @@ -187,6 +187,7 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, params: NotificationTextsParams, ): Promise { const createSidebarMessageInfo = messageInfos[0]; 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 @@ -43,6 +43,7 @@ export type RobotextParams = { +threadInfo: ?ThreadInfo, + +parentThreadInfo: ?ThreadInfo, }; export type NotificationTextsParams = { @@ -96,6 +97,7 @@ +notificationTexts?: ( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, params: NotificationTextsParams, ) => Promise, +notificationCollapseKey?: ( diff --git a/lib/shared/messages/remove-members-message-spec.js b/lib/shared/messages/remove-members-message-spec.js --- a/lib/shared/messages/remove-members-message-spec.js +++ b/lib/shared/messages/remove-members-message-spec.js @@ -112,6 +112,7 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, ): Promise { const removedMembersObject = {}; for (const messageInfo of messageInfos) { @@ -132,7 +133,11 @@ ); const mergedMessageInfo = { ...mostRecentMessageInfo, removedMembers }; - const robotext = notifRobotextForMessageInfo(mergedMessageInfo, threadInfo); + const robotext = notifRobotextForMessageInfo( + mergedMessageInfo, + threadInfo, + parentThreadInfo, + ); const merged = ET`${robotext} from ${ET.thread({ display: 'shortName', threadInfo, diff --git a/lib/shared/messages/text-message-spec.js b/lib/shared/messages/text-message-spec.js --- a/lib/shared/messages/text-message-spec.js +++ b/lib/shared/messages/text-message-spec.js @@ -190,6 +190,7 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, params: NotificationTextsParams, ): Promise { // We special-case sidebarCreations. Usually we don't send any notifs in diff --git a/lib/shared/notif-utils.js b/lib/shared/notif-utils.js --- a/lib/shared/notif-utils.js +++ b/lib/shared/notif-utils.js @@ -35,12 +35,14 @@ async function notifTextsForMessageInfo( messageInfos: MessageInfo[], threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, notifTargetUserInfo: UserInfo, getENSNames: ?GetENSNames, ): Promise { const fullNotifTexts = await fullNotifTextsForMessageInfo( messageInfos, threadInfo, + parentThreadInfo, notifTargetUserInfo, getENSNames, ); @@ -210,6 +212,7 @@ async function fullNotifTextsForMessageInfo( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, notifTargetUserInfo: UserInfo, getENSNames: ?GetENSNames, ): Promise { @@ -222,6 +225,7 @@ const unresolvedNotifTexts = await messageSpec.notificationTexts( messageInfos, threadInfo, + parentThreadInfo, { notifTargetUserInfo }, ); if (!unresolvedNotifTexts) { @@ -260,8 +264,13 @@ function notifRobotextForMessageInfo( messageInfo: RobotextMessageInfo, threadInfo: ThreadInfo, + parentThreadInfo: ?ThreadInfo, ): EntityText { - const robotext = robotextForMessageInfo(messageInfo, threadInfo); + const robotext = robotextForMessageInfo( + messageInfo, + threadInfo, + parentThreadInfo, + ); return robotext.map(entity => { if ( typeof entity !== 'string' && diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -266,6 +266,12 @@ return otherMembers[0].id; } +function parseSourceMessageIDFromPendingSidebarID(id: string): ?string { + const regex: RegExp = /(\d+\|\d+)/; + const match = regex.exec(id); + return match?.[1]; +} + function getPendingThreadID( threadType: ThreadType, memberIDs: $ReadOnlyArray, @@ -593,6 +599,7 @@ const messageTitleEntityText = getMessageTitle( sourceMessageInfo, parentThreadInfo, + parentThreadInfo, markdownRules, ); const messageTitle = entityTextToRawString(messageTitleEntityText, { @@ -626,6 +633,7 @@ const messageTitleEntityText = getMessageTitle( sourceMessageInfo, parentThreadInfo, + parentThreadInfo, markdownRules, ); const messageTitle = await getEntityTextAsString( @@ -1811,6 +1819,7 @@ threadIsPending, threadIsPendingSidebar, getSingleOtherUser, + parseSourceMessageIDFromPendingSidebarID, getPendingThreadID, parsePendingThreadID, createPendingThread,