diff --git a/lib/reducers/master-reducer.js b/lib/reducers/master-reducer.js --- a/lib/reducers/master-reducer.js +++ b/lib/reducers/master-reducer.js @@ -55,8 +55,14 @@ action: BaseAction, onStateDifference: (message: string) => mixed, ): { state: T, storeOperations: StoreOperations } { + const currentUserInfo = reduceCurrentUserInfo(state.currentUserInfo, action); + const viewerID = + currentUserInfo && !currentUserInfo.anonymous + ? state.currentUserInfo?.id + : null; + const { threadStore, newThreadInconsistencies, threadStoreOperations } = - reduceThreadInfos(state.threadStore, action); + reduceThreadInfos(state.threadStore, action, viewerID); const { threadInfos } = threadStore; const { @@ -220,7 +226,7 @@ draftStore, entryStore, loadingStatuses: reduceLoadingStatuses(state.loadingStatuses, action), - currentUserInfo: reduceCurrentUserInfo(state.currentUserInfo, action), + currentUserInfo, threadStore, userStore, messageStore, 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 @@ -1885,8 +1885,15 @@ outboundP2PMessages && outboundP2PMessages.length > 0; + // For composable DM messages, we pass `rawMessageInfos` to update + // the replies count, but we want to ignore it here, updating the message + // store is done using dedicated actions. + const updatedRawMessageInfos = sendingComposableDMMessageToPeers + ? [] + : rawMessageInfos; + if ( - rawMessageInfos.length === 0 && + updatedRawMessageInfos.length === 0 && updateInfos.length === 0 && !sendingComposableDMMessageToPeers ) { @@ -1894,7 +1901,7 @@ } const messagesResult = mergeUpdatesWithMessageInfos( - rawMessageInfos, + updatedRawMessageInfos, updateInfos, {}, ); 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 @@ -35,6 +35,7 @@ type ThreadStoreOperation, threadStoreOpsHandlers, } from '../ops/thread-store-ops.js'; +import { getThreadUpdatesForNewMessages } from '../shared/dm-ops/dm-op-utils.js'; import { stateSyncSpecs } from '../shared/state-sync/state-sync-specs.js'; import { updateSpecs } from '../shared/updates/update-specs.js'; import { processDMOpsActionType } from '../types/dm-ops.js'; @@ -121,6 +122,7 @@ function reduceThreadInfos( state: ThreadStore, action: BaseAction, + viewerID: ?string, ): ReduceThreadInfosResult { if (action.type === fullStateSyncActionType) { return handleFullStateSync( @@ -563,8 +565,8 @@ threadStoreOperations: [], }; } else if (action.type === processDMOpsActionType) { - const { updateInfos } = action.payload; - if (updateInfos.length === 0) { + const { updateInfos, rawMessageInfos } = action.payload; + if (updateInfos.length === 0 && rawMessageInfos.length === 0) { return { threadStore: state, newThreadInconsistencies: [], @@ -573,10 +575,34 @@ } const { threadStoreOperations, updatedThreadStore } = generateOpsAndProcessThreadUpdates(state, updateInfos); + + const repliesCountUpdates = getThreadUpdatesForNewMessages( + rawMessageInfos, + updateInfos, + updatedThreadStore.threadInfos, + viewerID, + ); + + if (repliesCountUpdates.length === 0) { + return { + threadStore: updatedThreadStore, + newThreadInconsistencies: [], + threadStoreOperations, + }; + } + + const { + threadStoreOperations: threadStoreOperationsWithUpdatedRepliesCount, + updatedThreadStore: threadStoreWithUpdatedRepliesCount, + } = generateOpsAndProcessThreadUpdates( + updatedThreadStore, + repliesCountUpdates, + ); + return { - threadStore: updatedThreadStore, + threadStore: threadStoreWithUpdatedRepliesCount, newThreadInconsistencies: [], - threadStoreOperations, + threadStoreOperations: threadStoreOperationsWithUpdatedRepliesCount, }; } 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 @@ -24,7 +24,6 @@ } from '../../types/dm-ops.js'; import type { RawMessageInfo } from '../../types/message-types.js'; import type { - RawThreadInfo, ThickRawThreadInfo, ThreadInfo, } from '../../types/minimally-encoded-thread-permissions-types.js'; @@ -37,7 +36,7 @@ assertThickThreadType, thickThreadTypes, } from '../../types/thread-types-enum.js'; -import type { LegacyRawThreadInfo } from '../../types/thread-types.js'; +import type { RawThreadInfos } from '../../types/thread-types.js'; import { type DMOperationP2PMessage, userActionsP2PMessageTypes, @@ -48,7 +47,6 @@ import { useSelector } from '../../utils/redux-utils.js'; import { messageSpecs } from '../messages/message-specs.js'; import { userHasDeviceList } from '../thread-utils.js'; -import { updateSpecs } from '../updates/update-specs.js'; function generateMessagesToPeers( message: DMOperation, @@ -343,9 +341,12 @@ function getThreadUpdatesForNewMessages( rawMessageInfos: $ReadOnlyArray, updateInfos: $ReadOnlyArray, - utilities: ProcessDMOperationUtilities, + threadInfos: RawThreadInfos, + viewerID: ?string, ): Array { - const { threadInfos, viewerID } = utilities; + if (!viewerID) { + return []; + } const { rawMessageInfos: allNewMessageInfos } = mergeUpdatesWithMessageInfos( rawMessageInfos, @@ -355,38 +356,22 @@ allNewMessageInfos, ); - const updatedThreadInfosByThreadID: { - [string]: RawThreadInfo | LegacyRawThreadInfo, - } = {}; - for (const threadID in messagesByThreadID) { - updatedThreadInfosByThreadID[threadID] = threadInfos[threadID]; - } - for (const update of updateInfos) { - const updatedThreadInfo = updateSpecs[update.type].getUpdatedThreadInfo?.( - update, - updatedThreadInfosByThreadID, - ); - if (updatedThreadInfo) { - updatedThreadInfosByThreadID[updatedThreadInfo.id] = updatedThreadInfo; - } - } - const newUpdateInfos: Array = []; for (const threadID in messagesByThreadID) { const repliesCountIncreasingMessages = messagesByThreadID[threadID].filter( message => messageSpecs[message.type].includedInRepliesCount, ); - let threadInfo = updatedThreadInfosByThreadID[threadID]; + let threadInfo = threadInfos[threadID]; if (repliesCountIncreasingMessages.length > 0) { const repliesCountIncreaseTime = Math.max( repliesCountIncreasingMessages.map(message => message.time), ); + const oldRepliesCount = threadInfo?.repliesCount ?? 0; const newThreadInfo = { ...threadInfo, - repliesCount: - threadInfo.repliesCount + repliesCountIncreasingMessages.length, + repliesCount: oldRepliesCount + repliesCountIncreasingMessages.length, }; newUpdateInfos.push({ type: updateTypes.UPDATE_THREAD, diff --git a/lib/shared/dm-ops/process-dm-ops.js b/lib/shared/dm-ops/process-dm-ops.js --- a/lib/shared/dm-ops/process-dm-ops.js +++ b/lib/shared/dm-ops/process-dm-ops.js @@ -11,7 +11,6 @@ useCreateMessagesToPeersFromDMOp, dmOperationSpecificationTypes, type OutboundComposableDMOperationSpecification, - getThreadUpdatesForNewMessages, useSendDMOperationUtils, } from './dm-op-utils.js'; import { useProcessBlobHolders } from '../../actions/holder-actions.js'; @@ -217,14 +216,6 @@ .filter(Boolean); void processBlobHolders(holderOps); - const newUpdateInfos = getThreadUpdatesForNewMessages( - rawMessageInfos, - updateInfos, - utilities, - ); - - updateInfos.push(...newUpdateInfos); - dispatchWithMetadata( { type: processDMOpsActionType, @@ -338,18 +329,12 @@ notificationsCreationDataPromise, ]); - const newUpdateInfos = getThreadUpdatesForNewMessages( - rawMessageInfos, - updateInfos, - utilities, - ); - dispatchWithMetadata( { type: processDMOpsActionType, payload: { - rawMessageInfos: [], - updateInfos: newUpdateInfos, + rawMessageInfos, + updateInfos, outboundP2PMessages, composableMessageID, notificationsCreationData,