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 @@ -1028,27 +1028,33 @@ const { localID, threadID } = payload; invariant(localID, `localID should be set on ${action.type}`); + const messageIDs = messageStore.threads[threadID]?.messageIDs ?? []; + if (!messageStore.messages[localID]) { + for (const existingMessageID of messageIDs) { + const existingMessageInfo = messageStore.messages[existingMessageID]; + if (existingMessageInfo && existingMessageInfo.localID === localID) { + return { messageStoreOperations: [], messageStore }; + } + } + } + const messageStoreOperations = [ { type: 'replace', payload: { id: localID, messageInfo: payload }, }, ]; - const processedMessageStore = processMessageStoreOperations( - messageStore, - messageStoreOperations, - ); const now = Date.now(); - const messageIDs = messageStore.threads[threadID]?.messageIDs ?? []; + let threads; + let local = { ...messageStore.local }; if (messageStore.messages[localID]) { const messages = { ...messageStore.messages, [localID]: payload }; - const local = _pickBy( + local = _pickBy( (localInfo: LocalMessageInfo, key: string) => key !== localID, )(messageStore.local); const thread = messageStore.threads[threadID]; - const threads = { - ...messageStore.threads, + const updatedThreads = { [threadID]: { messageIDs: sortMessageIDs(messages)(messageIDs), startReached: thread?.startReached ?? true, @@ -1056,47 +1062,64 @@ lastPruned: thread?.lastPruned ?? now, }, }; - return { - messageStoreOperations, - messageStore: { - ...messageStore, - messages: processedMessageStore.messages, - threads, - local, + threads = { + ...messageStore.threads, + ...updatedThreads, + }; + messageStoreOperations.push({ + type: 'replace_threads', + payload: { + threads: { ...updatedThreads }, }, + }); + } else { + const updatedThreads = { + [threadID]: messageStore.threads[threadID] + ? { + ...messageStore.threads[threadID], + messageIDs: [localID, ...messageIDs], + } + : { + messageIDs: [localID], + startReached: true, + lastNavigatedTo: now, + lastPruned: now, + }, }; - } - for (const existingMessageID of messageIDs) { - const existingMessageInfo = messageStore.messages[existingMessageID]; - if (existingMessageInfo && existingMessageInfo.localID === localID) { - return { messageStoreOperations: [], messageStore }; - } + threads = { + ...messageStore.threads, + ...updatedThreads, + }; + messageStoreOperations.push({ + type: 'replace_threads', + payload: { + threads: { ...updatedThreads }, + }, + }); } - const threadState: ThreadMessageInfo = messageStore.threads[threadID] - ? { - ...messageStore.threads[threadID], - messageIDs: [localID, ...messageIDs], - } - : { - messageIDs: [localID], - startReached: true, - lastNavigatedTo: now, - lastPruned: now, - }; + const processedMessageStore = processMessageStoreOperations( + messageStore, + messageStoreOperations, + ); + + const newMessageStore = { + messages: processedMessageStore.messages, + threads, + local, + currentAsOf: messageStore.currentAsOf, + }; + + assertMessageStoreThreadsAreEqual( + processedMessageStore, + newMessageStore, + action.type, + ); return { messageStoreOperations, - messageStore: { - messages: processedMessageStore.messages, - threads: { - ...messageStore.threads, - [threadID]: threadState, - }, - local: messageStore.local, - currentAsOf: messageStore.currentAsOf, - }, + messageStore: newMessageStore, }; } else if ( action.type === sendTextMessageActionTypes.failed ||