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 @@ -252,6 +252,8 @@ const threads = {}; const reassignedThreadIDs = []; + const updatedThreads = {}; + const threadsToRemove = []; for (const threadID in messageStore.threads) { const threadMessageInfo = messageStore.threads[threadID]; const newThreadID = pendingToRealizedThreadIDs.get(threadID); @@ -263,6 +265,8 @@ if (!realizedThread) { reassignedThreadIDs.push(newThreadID); threads[newThreadID] = threadMessageInfo; + updatedThreads[newThreadID] = { ...threadMessageInfo }; + threadsToRemove.push(threadID); continue; } threads[newThreadID] = mergeThreadMessageInfos( @@ -270,7 +274,20 @@ realizedThread, messages, ); + updatedThreads[newThreadID] = { ...threads[newThreadID] }; } + messageStoreOperations.push({ + type: 'remove_thread', + payload: { + ids: threadsToRemove, + }, + }); + messageStoreOperations.push({ + type: 'replace_thread', + payload: { + threads: updatedThreads, + }, + }); return { messageStoreOperations, @@ -294,6 +311,7 @@ newMessageInfos: $ReadOnlyArray, truncationStatus: { [threadID: string]: MessageTruncationStatus }, threadInfos: { +[threadID: string]: RawThreadInfo }, + actionType: string, ): MergeNewMessagesResult { const { messageStoreOperations: updateWithLatestThreadInfosOps, @@ -306,6 +324,12 @@ updateWithLatestThreadInfosOps, ); + assertMessageStoreThreadsAreEqual( + messageStoreAfterUpdateOps, + messageStoreUpdatedWithLatestThreadInfos, + `${actionType} | reassignment and filtering`, + ); + const updatedMessageStore = { ...messageStoreUpdatedWithLatestThreadInfos, messages: messageStoreAfterUpdateOps.messages, @@ -443,16 +467,18 @@ const oldMessageInfosToCombine = []; const threadsThatNeedMessageIDsResorted = []; const local = {}; + const updatedThreads = {}; const threads = _flow( _mapValuesWithKeys((messageIDs: string[], threadID: string) => { const oldThread = updatedMessageStore.threads[threadID]; const truncate = truncationStatus[threadID]; if (!oldThread) { - return { + updatedThreads[threadID] = { ...newThread(), messageIDs, startReached: truncate === messageTruncationStatus.EXHAUSTIVE, }; + return { ...updatedThreads[threadID] }; } let oldMessageIDsUnchanged = true; const oldMessageIDs = oldThread.messageIDs.map(oldID => { @@ -472,12 +498,13 @@ type: 'remove_messages_for_threads', payload: { threadIDs: [threadID] }, }); - return { + updatedThreads[threadID] = { messageIDs, startReached: false, lastNavigatedTo: oldThread.lastNavigatedTo, lastPruned: oldThread.lastPruned, }; + return { ...updatedThreads[threadID] }; } const oldNotInNew = _difference(oldMessageIDs)(messageIDs); for (const id of oldNotInNew) { @@ -496,15 +523,17 @@ if (startReached === oldThread.startReached && oldMessageIDsUnchanged) { return oldThread; } - return { + updatedThreads[threadID] = { messageIDs: oldMessageIDs, startReached, lastNavigatedTo: oldThread.lastNavigatedTo, lastPruned: oldThread.lastPruned, }; + return { ...updatedThreads[threadID] }; } const mergedMessageIDs = [...messageIDs, ...oldNotInNew]; threadsThatNeedMessageIDsResorted.push(threadID); + //NOTE: this will be updated after sorting return { messageIDs: mergedMessageIDs, startReached, @@ -528,6 +557,8 @@ }; } threads[threadID] = thread; + updatedThreads[threadID] = { ...thread }; + for (const id of thread.messageIDs) { const messageInfo = updatedMessageStore.messages[id]; if (messageInfo) { @@ -564,6 +595,7 @@ threads[threadID].messageIDs = sortMessageIDs(messages)( threads[threadID].messageIDs, ); + updatedThreads[threadID] = { ...threads[threadID] }; } const currentAsOf = Math.max( @@ -571,22 +603,37 @@ updatedMessageStore.currentAsOf, ); + newMessageOps.push({ + type: 'replace_thread', + payload: { + threads: updatedThreads, + }, + }); + const processedMessageStore = processMessageStoreOperations( updatedMessageStore, newMessageOps, ); + const messageStore = { + messages: processedMessageStore.messages, + threads, + local, + currentAsOf, + }; + + assertMessageStoreThreadsAreEqual( + processedMessageStore, + messageStore, + `${actionType} | processed`, + ); + return { messageStoreOperations: [ ...updateWithLatestThreadInfosOps, ...newMessageOps, ], - messageStore: { - messages: processedMessageStore.messages, - threads, - local, - currentAsOf, - }, + messageStore, }; } @@ -627,6 +674,7 @@ } } + const updatedThreads = {}; for (const threadID in threadInfos) { const threadInfo = threadInfos[threadID]; if ( @@ -634,9 +682,22 @@ !filteredThreads[threadID] ) { filteredThreads[threadID] = newThread(); + updatedThreads[threadID] = { ...filteredThreads[threadID] }; } } + messageStoreOperations.push({ + type: 'remove_thread', + payload: { ids: threadsToRemoveMessagesFrom }, + }); + + messageStoreOperations.push({ + type: 'replace_thread', + payload: { + threads: updatedThreads, + }, + }); + messageStoreOperations.push({ type: 'remove_messages_for_threads', payload: { threadIDs: threadsToRemoveMessagesFrom }, @@ -767,6 +828,7 @@ messagesResult.rawMessageInfos, messagesResult.truncationStatuses, newThreadInfos, + action.type, ); } else if (action.type === processUpdatesActionType) { if (action.payload.updatesResult.newUpdates.length === 0) { @@ -784,6 +846,7 @@ messagesResult.rawMessageInfos, messagesResult.truncationStatuses, newThreadInfos, + action.type, ); return { messageStoreOperations, @@ -804,6 +867,7 @@ messagesResult.rawMessageInfos, messagesResult.truncationStatuses, newThreadInfos, + action.type, ); } else if ( action.type === fetchSingleMostRecentMessagesFromThreadsActionTypes.success @@ -813,6 +877,7 @@ action.payload.rawMessageInfos, action.payload.truncationStatuses, newThreadInfos, + action.type, ); } else if ( action.type === fetchMessagesBeforeCursorActionTypes.success || @@ -823,6 +888,7 @@ action.payload.rawMessageInfos, { [action.payload.threadID]: action.payload.truncationStatus }, newThreadInfos, + action.type, ); } else if ( action.type === logOutActionTypes.success || @@ -856,6 +922,7 @@ messagesResult.rawMessageInfos, messagesResult.truncationStatuses, newThreadInfos, + action.type, ); } else if (action.type === sendMessageReportActionTypes.success) { return mergeNewMessages( @@ -866,6 +933,7 @@ messageTruncationStatus.UNCHANGED, }, newThreadInfos, + action.type, ); } else if (action.type === registerActionTypes.success) { const truncationStatuses = {}; @@ -878,6 +946,7 @@ action.payload.rawMessageInfos, truncationStatuses, newThreadInfos, + action.type, ); } else if ( action.type === changeThreadSettingsActionTypes.success || @@ -893,6 +962,7 @@ action.payload.newMessageInfos, { [action.payload.threadID]: messageTruncationStatus.UNCHANGED }, newThreadInfos, + action.type, ); } else if (action.type === deleteEntryActionTypes.success) { const payload = action.payload; @@ -902,6 +972,7 @@ payload.newMessageInfos, { [payload.threadID]: messageTruncationStatus.UNCHANGED }, newThreadInfos, + action.type, ); } } else if (action.type === joinThreadActionTypes.success) { @@ -914,6 +985,7 @@ messagesResult.rawMessageInfos, messagesResult.truncationStatuses, newThreadInfos, + action.type, ); } else if (action.type === sendEditMessageActionTypes.success) { const { newMessageInfos } = action.payload; @@ -927,6 +999,7 @@ newMessageInfos, truncationStatuses, newThreadInfos, + action.type, ); } else if ( action.type === sendTextMessageActionTypes.started || @@ -1150,6 +1223,7 @@ action.payload.rawMessageInfos, truncationStatuses, newThreadInfos, + action.type, ); return { messageStoreOperations, @@ -1423,6 +1497,12 @@ messageStoreOperations, ); + assertMessageStoreThreadsAreEqual( + processedMessageStore, + messageStoreAfterReassignment, + `${action.type} | reassignment and filtering`, + ); + return { messageStoreOperations, messageStore: {