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 @@ -19,6 +19,7 @@ deleteCommunityRoleActionTypes, } from '../actions/thread-actions.js'; import { + keyserverAuthActionTypes, logOutActionTypes, deleteKeyserverAccountActionTypes, logInActionTypes, @@ -30,6 +31,7 @@ threadStoreOpsHandlers, } from '../ops/thread-store-ops.js'; import { stateSyncSpecs } from '../shared/state-sync/state-sync-specs.js'; +import { getThreadIDsForKeyservers } from '../shared/thread-utils.js'; import { updateSpecs } from '../shared/updates/update-specs.js'; import type { BaseAction } from '../types/redux-types.js'; import { type ClientThreadInconsistencyReportCreationRequest } from '../types/report-types.js'; @@ -106,22 +108,86 @@ newThreadInconsistencies: [], threadStoreOperations, }; + } else if (action.type === keyserverAuthActionTypes.success) { + const keyserverIDs = Object.keys(action.payload.updatesCurrentAsOf); + const threadIDsToRemove = getThreadIDsForKeyservers( + Object.keys(state.threadInfos), + keyserverIDs, + ); + const newThreadInfos = action.payload.threadInfos; + + const threadStoreOperations = [ + { + type: 'remove', + payload: { ids: threadIDsToRemove }, + }, + ...Object.keys(newThreadInfos).map((id: string) => ({ + type: 'replace', + payload: { id, threadInfo: newThreadInfos[id] }, + })), + ]; + const updatedThreadStore = processThreadStoreOperations( + state, + threadStoreOperations, + ); + return { + threadStore: updatedThreadStore, + newThreadInconsistencies: [], + threadStoreOperations, + }; } else if ( action.type === logOutActionTypes.success || - action.type === deleteKeyserverAccountActionTypes.success || - (action.type === setNewSessionActionType && - action.payload.sessionChange.cookieInvalidated) + action.type === deleteKeyserverAccountActionTypes.success ) { - if (Object.keys(state.threadInfos).length === 0) { + const threadIDsToRemove = getThreadIDsForKeyservers( + Object.keys(state.threadInfos), + action.payload.keyserverIDs, + ); + + if (threadIDsToRemove.length === 0) { return { threadStore: state, newThreadInconsistencies: [], threadStoreOperations: [], }; } + const threadStoreOperations = [ { - type: 'remove_all', + type: 'remove', + payload: { ids: threadIDsToRemove }, + }, + ]; + const updatedThreadStore = processThreadStoreOperations( + state, + threadStoreOperations, + ); + return { + threadStore: updatedThreadStore, + newThreadInconsistencies: [], + threadStoreOperations, + }; + } else if ( + action.type === setNewSessionActionType && + action.payload.sessionChange.cookieInvalidated + ) { + const threadIDsToRemove = getThreadIDsForKeyservers( + Object.keys(state.threadInfos), + [action.payload.keyserverID], + ); + + if (threadIDsToRemove.length === 0) { + return { + threadStore: state, + newThreadInconsistencies: [], + threadStoreOperations: [], + }; + } + + const threadStoreOperations = [ + { + type: 'remove', + payload: { ids: threadIDsToRemove }, }, ]; const updatedThreadStore = processThreadStoreOperations( diff --git a/lib/shared/thread-utils.js b/lib/shared/thread-utils.js --- a/lib/shared/thread-utils.js +++ b/lib/shared/thread-utils.js @@ -110,6 +110,7 @@ UserInfo, } from '../types/user-types.js'; import { + extractKeyserverIDFromID, useDispatchActionPromise, useServerCall, } from '../utils/action-utils.js'; @@ -1803,6 +1804,19 @@ ); } +function getThreadIDsForKeyservers( + threadIDs: $ReadOnlyArray, + keyserverIDs: $ReadOnlyArray, +): $ReadOnlyArray { + if (keyserverIDs.length === 0) { + return []; + } + const keyserverIDsSet = new Set(keyserverIDs); + return threadIDs.filter(threadID => + keyserverIDsSet.has(extractKeyserverIDFromID(threadID)), + ); +} + export { threadHasPermission, viewerIsMember, @@ -1870,4 +1884,5 @@ getThreadsToDeleteText, useUserProfileThreadInfo, assertAllThreadInfosAreLegacy, + getThreadIDsForKeyservers, }; diff --git a/lib/shared/thread-utils.test.js b/lib/shared/thread-utils.test.js --- a/lib/shared/thread-utils.test.js +++ b/lib/shared/thread-utils.test.js @@ -1,6 +1,9 @@ // @flow -import { parsePendingThreadID } from './thread-utils.js'; +import { + parsePendingThreadID, + getThreadIDsForKeyservers, +} from './thread-utils.js'; import { threadTypes } from '../types/thread-types-enum.js'; describe('parsePendingThreadID(pendingThreadID: string)', () => { @@ -65,3 +68,37 @@ ); }); }); + +const keyserver1 = '256'; +const keyserver2 = '100'; +const keyserver3 = '200'; +const keyserver1ThreadIDs = [ + keyserver1 + '|1', + keyserver1 + '|2', + keyserver1 + '|3', +]; +const keyserver2ThreadIDs = [ + keyserver2 + '|1', + keyserver2 + '|2', + keyserver2 + '|3', +]; +const keyserver3ThreadIDs = [ + keyserver3 + '|1', + keyserver3 + '|2', + keyserver3 + '|3', +]; + +describe('getThreadIDsForKeyservers', () => { + it('should return thread belonging to specified keyservers', () => { + expect( + getThreadIDsForKeyservers( + [ + ...keyserver1ThreadIDs, + ...keyserver2ThreadIDs, + ...keyserver3ThreadIDs, + ], + [keyserver1, keyserver2], + ), + ).toEqual([...keyserver1ThreadIDs, ...keyserver2ThreadIDs]); + }); +});