diff --git a/lib/reducers/message-reducer.js b/lib/reducers/message-reducer.js --- a/lib/reducers/message-reducer.js +++ b/lib/reducers/message-reducer.js @@ -1929,7 +1929,6 @@ const messagesResult = mergeUpdatesWithMessageInfos( updatedRawMessageInfos, updateInfos, - {}, ); const { messageStoreOperations, messageStore: newMessageStore } = diff --git a/lib/reducers/thread-reducer.js b/lib/reducers/thread-reducer.js --- a/lib/reducers/thread-reducer.js +++ b/lib/reducers/thread-reducer.js @@ -580,7 +580,8 @@ threadStoreOperations: [], }; } else if (action.type === processDMOpsActionType) { - const { updateInfos, rawMessageInfos } = action.payload; + const { updateInfos, rawMessageInfos, messagesNotifyTypes } = + action.payload; if (updateInfos.length === 0 && rawMessageInfos.length === 0) { return { threadStore: state, @@ -591,12 +592,13 @@ const { threadStoreOperations, updatedThreadStore } = generateOpsAndProcessThreadUpdates(state, updateInfos); - const newMessagesUpdates = getThreadUpdatesForNewMessages( + const newMessagesUpdates = getThreadUpdatesForNewMessages({ rawMessageInfos, updateInfos, - updatedThreadStore.threadInfos, + threadInfos: updatedThreadStore.threadInfos, + messagesNotifyTypes, viewerID, - ); + }); if (newMessagesUpdates.length === 0) { return { diff --git a/lib/shared/dm-ops/dm-op-utils.js b/lib/shared/dm-ops/dm-op-utils.js --- a/lib/shared/dm-ops/dm-op-utils.js +++ b/lib/shared/dm-ops/dm-op-utils.js @@ -53,6 +53,10 @@ } from '../../types/update-types.js'; import { getContentSigningKey } from '../../utils/crypto-utils.js'; import { useSelector, useDispatch } from '../../utils/redux-utils.js'; +import { + type MessageNotifyType, + messageNotifyTypes, +} from '../messages/message-spec.js'; import { messageSpecs } from '../messages/message-specs.js'; import { expectedAccountDeletionUpdateTimeout, @@ -404,12 +408,24 @@ ); } +type GetThreadUpdatesForNewMessagesInputType = { + +rawMessageInfos: $ReadOnlyArray<RawMessageInfo>, + +updateInfos: $ReadOnlyArray<ClientUpdateInfo>, + +threadInfos: RawThreadInfos, + +messagesNotifyTypes: { +[messageID: string]: MessageNotifyType }, + +viewerID: ?string, +}; function getThreadUpdatesForNewMessages( - rawMessageInfos: $ReadOnlyArray<RawMessageInfo>, - updateInfos: $ReadOnlyArray<ClientUpdateInfo>, - threadInfos: RawThreadInfos, - viewerID: ?string, + input: GetThreadUpdatesForNewMessagesInputType, ): Array<ClientUpdateInfo> { + const { + rawMessageInfos, + updateInfos, + threadInfos, + messagesNotifyTypes, + viewerID, + } = input; + if (!viewerID) { return []; } @@ -448,16 +464,27 @@ threadInfo = newThreadInfo; } - const messagesFromOtherPeers = messagesByThreadID[threadID].filter( - message => message.creatorID !== viewerID, + const messagesAffectingUnreadStatus = messagesByThreadID[threadID].filter( + message => { + const { id } = message; + invariant(id, 'Thick thread RawMessageInfos should always have ID'); + const messageNotifyType = messagesNotifyTypes[id]; + return ( + message.creatorID !== viewerID && + (messageNotifyType === messageNotifyTypes.SET_UNREAD || + messageNotifyType === messageNotifyTypes.NOTIF_AND_SET_UNREAD) + ); + }, ); - if (messagesFromOtherPeers.length === 0) { + if (messagesAffectingUnreadStatus.length === 0) { continue; } // We take the most recent timestamp to make sure that // change_thread_read_status operation older // than it won't flip the status to read. - const time = Math.max(messagesFromOtherPeers.map(message => message.time)); + const time = Math.max( + messagesAffectingUnreadStatus.map(message => message.time), + ); invariant(threadInfo.thick, 'Thread should be thick'); if (threadInfo.timestamps.currentUser.unread < time) {