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 @@ -529,9 +529,15 @@ 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, - threadInfos[threadID], + threadInfo, + parentThreadInfo, ); 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 @@ -2,7 +2,11 @@ import invariant from 'invariant'; -import type { CreateMessageInfoParams, MessageSpec } from './message-spec.js'; +import type { + CreateMessageInfoParams, + MessageSpec, + NotificationTextsParams, +} from './message-spec.js'; import { joinResult } from './utils.js'; import { messageTypes } from '../../types/message-types-enum.js'; import type { @@ -112,6 +116,7 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + params: NotificationTextsParams, ): Promise { const addedMembersObject = {}; for (const messageInfo of messageInfos) { @@ -132,7 +137,12 @@ ); const mergedMessageInfo = { ...mostRecentMessageInfo, addedMembers }; - const robotext = notifRobotextForMessageInfo(mergedMessageInfo, threadInfo); + const { parentThreadInfo } = params; + 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 @@ -7,6 +7,7 @@ type CreateMessageInfoParams, type MessageSpec, type RobotextParams, + type NotificationTextsParams, } from './message-spec.js'; import { joinResult } from './utils.js'; import type { PlatformDetails } from '../../types/device-types.js'; @@ -129,10 +130,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 +150,7 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + params: NotificationTextsParams, ): Promise { const membersObject = {}; for (const messageInfo of messageInfos) { @@ -168,7 +171,12 @@ ); const mergedMessageInfo = { ...mostRecentMessageInfo, members }; - const robotext = notifRobotextForMessageInfo(mergedMessageInfo, threadInfo); + const { parentThreadInfo } = params; + 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 @@ -6,6 +6,7 @@ pushTypes, type MessageSpec, type RobotextParams, + type NotificationTextsParams, } from './message-spec.js'; import { joinResult } from './utils.js'; import { messageTypes } from '../../types/message-types-enum.js'; @@ -148,13 +149,19 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + params: NotificationTextsParams, ): Promise { const mostRecentMessageInfo = messageInfos[0]; invariant( mostRecentMessageInfo.type === messageTypes.CHANGE_SETTINGS, 'messageInfo should be messageTypes.CHANGE_SETTINGS!', ); - const body = notifRobotextForMessageInfo(mostRecentMessageInfo, threadInfo); + const { parentThreadInfo } = params; + const body = notifRobotextForMessageInfo( + mostRecentMessageInfo, + threadInfo, + parentThreadInfo, + ); return { merged: body, title: threadInfo.uiName, 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,10 +43,12 @@ export type RobotextParams = { +threadInfo: ?ThreadInfo, + +parentThreadInfo: ?ThreadInfo, }; export type NotificationTextsParams = { +notifTargetUserInfo: UserInfo, + +parentThreadInfo: ?ThreadInfo, }; export type GeneratesNotifsParams = { 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 @@ -2,7 +2,11 @@ import invariant from 'invariant'; -import type { CreateMessageInfoParams, MessageSpec } from './message-spec.js'; +import type { + CreateMessageInfoParams, + MessageSpec, + NotificationTextsParams, +} from './message-spec.js'; import { joinResult } from './utils.js'; import { messageTypes } from '../../types/message-types-enum.js'; import type { @@ -112,6 +116,7 @@ async notificationTexts( messageInfos: $ReadOnlyArray, threadInfo: ThreadInfo, + params: NotificationTextsParams, ): Promise { const removedMembersObject = {}; for (const messageInfo of messageInfos) { @@ -132,7 +137,12 @@ ); const mergedMessageInfo = { ...mostRecentMessageInfo, removedMembers }; - const robotext = notifRobotextForMessageInfo(mergedMessageInfo, threadInfo); + const { parentThreadInfo } = params; + const robotext = notifRobotextForMessageInfo( + mergedMessageInfo, + threadInfo, + parentThreadInfo, + ); const merged = ET`${robotext} from ${ET.thread({ display: 'shortName', threadInfo, 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,7 +225,7 @@ const unresolvedNotifTexts = await messageSpec.notificationTexts( messageInfos, threadInfo, - { notifTargetUserInfo }, + { notifTargetUserInfo, parentThreadInfo }, ); if (!unresolvedNotifTexts) { return unresolvedNotifTexts; @@ -260,8 +263,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 @@ -593,6 +593,7 @@ const messageTitleEntityText = getMessageTitle( sourceMessageInfo, parentThreadInfo, + parentThreadInfo, markdownRules, ); const messageTitle = entityTextToRawString(messageTitleEntityText, { @@ -626,6 +627,7 @@ const messageTitleEntityText = getMessageTitle( sourceMessageInfo, parentThreadInfo, + parentThreadInfo, markdownRules, ); const messageTitle = await getEntityTextAsString(