diff --git a/lib/reducers/thread-activity-reducer.js b/lib/reducers/thread-activity-reducer.js index 257d76496..27b8e10b5 100644 --- a/lib/reducers/thread-activity-reducer.js +++ b/lib/reducers/thread-activity-reducer.js @@ -1,123 +1,151 @@ // @flow import invariant from 'invariant'; import { messageStorePruneActionType } from '../actions/message-actions.js'; import { changeThreadMemberRolesActionTypes, changeThreadSettingsActionTypes, deleteCommunityRoleActionTypes, deleteThreadActionTypes, joinThreadActionTypes, leaveThreadActionTypes, modifyCommunityRoleActionTypes, newThreadActionTypes, removeUsersFromThreadActionTypes, } from '../actions/thread-actions.js'; import { deleteKeyserverAccountActionTypes } from '../actions/user-actions.js'; import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js'; import { setNewSessionActionType } from '../keyserver-conn/keyserver-conn-types.js'; +import { threadActivityStoreOpsHandlers } from '../ops/thread-activity-store-ops.js'; import type { BaseAction } from '../types/redux-types.js'; import { incrementalStateSyncActionType } from '../types/socket-types.js'; import type { ThreadActivityStore } from '../types/thread-activity-types.js'; import { updateThreadLastNavigatedActionType } from '../types/thread-activity-types.js'; import { updateTypes } from '../types/update-types-enum.js'; import type { ClientUpdateInfo } from '../types/update-types.js'; import { processUpdatesActionType } from '../types/update-types.js'; +const { processStoreOperations: processStoreOps } = + threadActivityStoreOpsHandlers; + function reduceThreadActivity( state: ThreadActivityStore, action: BaseAction, ): ThreadActivityStore { if (action.type === updateThreadLastNavigatedActionType) { const { threadID, time } = action.payload; - const updatedThreadActivityStore = { - ...state, - [threadID]: { - ...state[threadID], - lastNavigatedTo: time, + const replaceOperation = { + type: 'replace_thread_activity_entry', + payload: { + id: threadID, + threadActivityStoreEntry: { + ...state[threadID], + lastNavigatedTo: time, + }, }, }; - return updatedThreadActivityStore; + return processStoreOps(state, [replaceOperation]); } else if (action.type === messageStorePruneActionType) { const now = Date.now(); - let updatedThreadActivityStore = { ...state }; + const replaceOperations = []; for (const threadID: string of action.payload.threadIDs) { - updatedThreadActivityStore = { - ...updatedThreadActivityStore, - [threadID]: { - ...updatedThreadActivityStore[threadID], - lastPruned: now, + const replaceOperation = { + type: 'replace_thread_activity_entry', + payload: { + id: threadID, + threadActivityStoreEntry: { + ...state[threadID], + lastPruned: now, + }, }, }; + replaceOperations.push(replaceOperation); } - return updatedThreadActivityStore; + return processStoreOps(state, replaceOperations); } else if ( action.type === joinThreadActionTypes.success || action.type === leaveThreadActionTypes.success || action.type === deleteThreadActionTypes.success || action.type === changeThreadSettingsActionTypes.success || action.type === removeUsersFromThreadActionTypes.success || action.type === changeThreadMemberRolesActionTypes.success || action.type === incrementalStateSyncActionType || action.type === processUpdatesActionType || action.type === newThreadActionTypes.success || action.type === modifyCommunityRoleActionTypes.success || action.type === deleteCommunityRoleActionTypes.success ) { const { newUpdates } = action.payload.updatesResult; if (newUpdates.length === 0) { return state; } const deleteThreadUpdates = newUpdates.filter( (update: ClientUpdateInfo) => update.type === updateTypes.DELETE_THREAD, ); if (deleteThreadUpdates.length === 0) { return state; } - let updatedState = { ...state }; + const threadIDsToRemove = []; for (const update: ClientUpdateInfo of deleteThreadUpdates) { invariant( update.type === updateTypes.DELETE_THREAD, 'update must be of type DELETE_THREAD', ); - const { [update.threadID]: _, ...stateSansRemovedThread } = updatedState; - updatedState = stateSansRemovedThread; + threadIDsToRemove.push(update.threadID); } - return updatedState; + const removeOperation = { + type: 'remove_thread_activity_entries', + payload: { + ids: threadIDsToRemove, + }, + }; + return processStoreOps(state, [removeOperation]); } else if (action.type === deleteKeyserverAccountActionTypes.success) { - let updatedState = { ...state }; + const threadIDsToRemove = []; const keyserverIDsSet = new Set(action.payload.keyserverIDs); for (const threadID in state) { if (!keyserverIDsSet.has(extractKeyserverIDFromID(threadID))) { continue; } - const { [threadID]: _, ...stateSansRemovedThread } = updatedState; - updatedState = stateSansRemovedThread; + threadIDsToRemove.push(threadID); } - return updatedState; + const removeOperation = { + type: 'remove_thread_activity_entries', + payload: { + ids: threadIDsToRemove, + }, + }; + + return processStoreOps(state, [removeOperation]); } else if ( action.type === setNewSessionActionType && action.payload.sessionChange.cookieInvalidated ) { + const threadIDsToRemove = []; const { keyserverID } = action.payload; - let updatedState = { ...state }; for (const threadID in state) { if (extractKeyserverIDFromID(threadID) !== keyserverID) { continue; } - const { [threadID]: _, ...stateSansRemovedThread } = updatedState; - updatedState = stateSansRemovedThread; + threadIDsToRemove.push(threadID); } - return updatedState; + const removeOperation = { + type: 'remove_thread_activity_entries', + payload: { + ids: threadIDsToRemove, + }, + }; + + return processStoreOps(state, [removeOperation]); } return state; } export { reduceThreadActivity };