diff --git a/lib/reducers/calendar-query-reducer.js b/lib/reducers/calendar-query-reducer.js deleted file mode 100644 --- a/lib/reducers/calendar-query-reducer.js +++ /dev/null @@ -1,67 +0,0 @@ -// @flow - -import { removeKeyserverThreadIDsFromFilterList } from './calendar-filters-reducer.js'; -import { updateCalendarQueryActionTypes } from '../actions/entry-actions.js'; -import { siweAuthActionTypes } from '../actions/siwe-actions.js'; -import { - logOutActionTypes, - deleteKeyserverAccountActionTypes, - logInActionTypes, - keyserverRegisterActionTypes, - deleteAccountActionTypes, -} from '../actions/user-actions.js'; -import { setNewSessionActionType } from '../keyserver-conn/keyserver-conn-types.js'; -import { defaultCalendarQuery } from '../types/entry-types.js'; -import type { CalendarQuery } from '../types/entry-types.js'; -import { type BaseAction } from '../types/redux-types.js'; -import { - fullStateSyncActionType, - incrementalStateSyncActionType, -} from '../types/socket-types.js'; -import { getConfig } from '../utils/config.js'; - -function reduceCalendarQuery( - state: CalendarQuery, - action: BaseAction, -): CalendarQuery { - if ( - action.type === logOutActionTypes.success || - action.type === deleteAccountActionTypes.success - ) { - return defaultCalendarQuery(getConfig().platformDetails.platform); - } else if ( - action.type === setNewSessionActionType && - action.payload.sessionChange.cookieInvalidated - ) { - return { - ...state, - filters: removeKeyserverThreadIDsFromFilterList(state.filters, [ - action.payload.keyserverID, - ]), - }; - } else if (action.type === deleteKeyserverAccountActionTypes.success) { - return { - ...state, - filters: removeKeyserverThreadIDsFromFilterList( - state.filters, - action.payload.keyserverIDs, - ), - }; - } else if ( - action.type === logInActionTypes.success || - action.type === siweAuthActionTypes.success - ) { - return action.payload.calendarResult.calendarQuery; - } else if ( - action.type === keyserverRegisterActionTypes.success || - action.type === updateCalendarQueryActionTypes.success || - action.type === fullStateSyncActionType || - action.type === incrementalStateSyncActionType - ) { - return action.payload.calendarQuery; - } - - return state; -} - -export { reduceCalendarQuery }; diff --git a/lib/reducers/keyserver-reducer.js b/lib/reducers/keyserver-reducer.js --- a/lib/reducers/keyserver-reducer.js +++ b/lib/reducers/keyserver-reducer.js @@ -1,5 +1,6 @@ // @flow +import { filterThreadIDsInFilterList } from './calendar-filters-reducer.js'; import { unsupervisedBackgroundActionType } from './lifecycle-state-reducer.js'; import { updateActivityActionTypes } from '../actions/activity-actions.js'; import { setClientDBStoreActionType } from '../actions/client-db-store-actions.js'; @@ -7,6 +8,7 @@ updateLastCommunicatedPlatformDetailsActionType, setDeviceTokenActionTypes, } from '../actions/device-actions.js'; +import { updateCalendarQueryActionTypes } from '../actions/entry-actions.js'; import { addKeyserverActionType, removeKeyserverActionType, @@ -21,6 +23,7 @@ logInActionTypes, resetUserStateActionType, } from '../actions/user-actions.js'; +import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js'; import { setNewSessionActionType, updateConnectionStatusActionType, @@ -35,7 +38,9 @@ type RemoveKeyserversOperation, type KeyserverStoreOperation, } from '../ops/keyserver-store-ops.js'; +import { nonThreadCalendarFilters } from '../selectors/calendar-filter-selectors.js'; import { queueActivityUpdatesActionType } from '../types/activity-types.js'; +import { defaultCalendarQuery } from '../types/entry-types.js'; import type { KeyserverInfos, KeyserverStore, @@ -170,6 +175,12 @@ if (sessionChange.cookieInvalidated) { newKeyserverInfo = { ...newKeyserverInfo, + actualizedCalendarQuery: { + ...newKeyserverInfo.actualizedCalendarQuery, + filters: nonThreadCalendarFilters( + newKeyserverInfo.actualizedCalendarQuery.filters, + ), + }, connection: { ...newKeyserverInfo.connection, queuedActivityUpdates: [], @@ -215,6 +226,11 @@ const operations: ReplaceKeyserverOperation[] = []; for (const keyserverID in updatesCurrentAsOf) { + const calendarFilters = filterThreadIDsInFilterList( + action.payload.calendarResult.calendarQuery.filters, + (threadID: string) => + extractKeyserverIDFromID(threadID) === keyserverID, + ); operations.push({ type: 'replace_keyserver', payload: { @@ -223,6 +239,10 @@ ...state.keyserverInfos[keyserverID], updatesCurrentAsOf: updatesCurrentAsOf[keyserverID], lastCommunicatedPlatformDetails: getConfig().platformDetails, + actualizedCalendarQuery: { + ...action.payload.calendarResult.calendarQuery, + filters: calendarFilters, + }, connection: { ...state.keyserverInfos[keyserverID].connection, connectionIssue: null, @@ -243,6 +263,7 @@ id: keyserverID, keyserverInfo: { ...state.keyserverInfos[keyserverID], + actualizedCalendarQuery: action.payload.calendarQuery, updatesCurrentAsOf: action.payload.updatesCurrentAsOf, }, }, @@ -270,6 +291,7 @@ id: keyserverID, keyserverInfo: { ...state.keyserverInfos[keyserverID], + actualizedCalendarQuery: action.payload.calendarQuery, updatesCurrentAsOf: action.payload.updatesResult.currentAsOf, deviceToken, }, @@ -338,6 +360,7 @@ id: authoritativeKeyserverID(), keyserverInfo: { ...state.keyserverInfos[authoritativeKeyserverID()], + actualizedCalendarQuery: action.payload.calendarQuery, lastCommunicatedPlatformDetails: getConfig().platformDetails, }, }, @@ -466,6 +489,9 @@ id: authoritativeKeyserverID(), keyserverInfo: { ...state.keyserverInfos[authoritativeKeyserverID()], + actualizedCalendarQuery: defaultCalendarQuery( + getConfig().platformDetails.platform, + ), connection: { ...oldConnection, connectionIssue: null, @@ -497,6 +523,9 @@ id: authoritativeKeyserverID(), keyserverInfo: { ...state.keyserverInfos[authoritativeKeyserverID()], + actualizedCalendarQuery: defaultCalendarQuery( + getConfig().platformDetails.platform, + ), connection: { ...oldConnection, connectionIssue: null, @@ -630,6 +659,31 @@ keyserverStore: state, keyserverStoreOperations: [], }; + } else if (action.type === updateCalendarQueryActionTypes.success) { + const operations: ReplaceKeyserverOperation[] = []; + for (const keyserverID of action.payload.keyserverIDs) { + operations.push({ + type: 'replace_keyserver', + payload: { + id: keyserverID, + keyserverInfo: { + ...state.keyserverInfos[keyserverID], + actualizedCalendarQuery: { + ...action.payload.calendarQuery, + filters: filterThreadIDsInFilterList( + action.payload.calendarQuery.filters, + (threadID: string) => + extractKeyserverIDFromID(threadID) === keyserverID, + ), + }, + }, + }, + }); + } + return { + keyserverStore: processStoreOps(state, operations), + keyserverStoreOperations: operations, + }; } return { diff --git a/lib/reducers/keyserver-reducer.test.js b/lib/reducers/keyserver-reducer.test.js --- a/lib/reducers/keyserver-reducer.test.js +++ b/lib/reducers/keyserver-reducer.test.js @@ -5,6 +5,8 @@ import { defaultKeyserverInfo } from '../types/keyserver-types.js'; import { authoritativeKeyserverID } from '../utils/authoritative-keyserver.js'; +jest.mock('../utils/config.js'); + describe('reduceKeyserverStore', () => { it('removes from the store keyservers the user has disconnected from', () => { const oldKeyserverStore = { 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 @@ -1,7 +1,6 @@ // @flow import reduceCalendarFilters from './calendar-filters-reducer.js'; -import { reduceCalendarQuery } from './calendar-query-reducer.js'; import reduceCustomerServer from './custom-server-reducer.js'; import reduceDataLoaded from './data-loaded-reducer.js'; import { reduceDraftStore } from './draft-reducer.js'; @@ -176,10 +175,6 @@ state.notifPermissionAlertInfo, action, ), - actualizedCalendarQuery: reduceCalendarQuery( - state.actualizedCalendarQuery, - action, - ), lifecycleState: reduceLifecycleState(state.lifecycleState, action), enabledApps: reduceEnabledApps(state.enabledApps, action), reportStore, diff --git a/lib/socket/calendar-query-handler.react.js b/lib/socket/calendar-query-handler.react.js --- a/lib/socket/calendar-query-handler.react.js +++ b/lib/socket/calendar-query-handler.react.js @@ -11,7 +11,6 @@ import type { UpdateCalendarQueryInput } from '../actions/entry-actions.js'; import { extractKeyserverIDFromID } from '../keyserver-conn/keyserver-call-utils.js'; import { filterThreadIDsInFilterList } from '../reducers/calendar-filters-reducer.js'; -import { connectionSelector } from '../selectors/keyserver-selectors.js'; import { timeUntilCalendarRangeExpiration } from '../selectors/nav-selectors.js'; import { useIsAppForegrounded } from '../shared/lifecycle-utils.js'; import type { @@ -131,8 +130,11 @@ const ConnectedCalendarQueryHandler: React.ComponentType = React.memo(function ConnectedCalendarQueryHandler(props) { const { currentCalendarQuery, keyserverID } = props; - const connection = useSelector(connectionSelector(keyserverID)); - invariant(connection, 'keyserver missing from keyserverStore'); + const keyserverInfo = useSelector( + state => state.keyserverStore.keyserverInfos[keyserverID], + ); + invariant(keyserverInfo, 'keyserver missing from keyserverStore'); + const { connection, actualizedCalendarQuery } = keyserverInfo; const lastUserInteractionCalendar = useSelector( state => state.entryStore.lastUserInteractionCalendar, ); @@ -140,7 +142,6 @@ const foreground = useIsAppForegrounded(); const callUpdateCalendarQuery = useUpdateCalendarQuery(); const dispatchActionPromise = useDispatchActionPromise(); - const calendarQuery = useSelector(state => state.actualizedCalendarQuery); const getCurrentCalendarQuery = React.useCallback(() => { const query = currentCalendarQuery(); @@ -158,7 +159,7 @@ KeyserverInfo = urlPrefix => ({ - cookie: null, - updatesCurrentAsOf: 0, - urlPrefix, - connection: defaultConnectionInfo, - lastCommunicatedPlatformDetails: null, - deviceToken: null, -}); + platform?: Platform, +) => KeyserverInfo = (urlPrefix, platform) => { + let currentPlatform = platform; + if (!currentPlatform) { + currentPlatform = getConfig().platformDetails.platform; + } + return { + cookie: null, + updatesCurrentAsOf: 0, + urlPrefix, + connection: defaultConnectionInfo, + lastCommunicatedPlatformDetails: null, + deviceToken: null, + actualizedCalendarQuery: defaultCalendarQuery(currentPlatform), + }; +}; export type KeyserverInfos = { +[key: string]: KeyserverInfo }; @@ -61,6 +76,7 @@ connection: connectionInfoValidator, lastCommunicatedPlatformDetails: t.maybe(tPlatformDetails), deviceToken: t.maybe(t.String), + actualizedCalendarQuery: calendarQueryValidator, }); export const keyserverStoreValidator: TInterface = diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js --- a/lib/types/redux-types.js +++ b/lib/types/redux-types.js @@ -36,7 +36,6 @@ FetchEntryInfosResult, CalendarQueryUpdateResult, CalendarQueryUpdateStartingPayload, - CalendarQuery, FetchRevisionsForEntryPayload, } from './entry-types.js'; import type { @@ -141,7 +140,6 @@ +loadingStatuses: { [key: string]: { [idx: number]: LoadingStatus } }, +calendarFilters: $ReadOnlyArray, +notifPermissionAlertInfo: NotifPermissionAlertInfo, - +actualizedCalendarQuery: CalendarQuery, +watchedThreadIDs: $ReadOnlyArray, +lifecycleState: LifecycleState, +enabledApps: EnabledApps, diff --git a/lib/utils/__mocks__/config.js b/lib/utils/__mocks__/config.js new file mode 100644 --- /dev/null +++ b/lib/utils/__mocks__/config.js @@ -0,0 +1,27 @@ +// @flow + +import { type Config } from '../config.js'; + +const getConfig = (): Config => ({ + resolveKeyserverSessionInvalidationUsingNativeCredentials: null, + setSessionIDOnRequest: true, + calendarRangeInactivityLimit: null, + platformDetails: { + platform: 'web', + codeVersion: 70, + stateVersion: 50, + }, + authoritativeKeyserverID: '123', + olmAPI: { + initializeCryptoAccount: jest.fn(), + encrypt: jest.fn(), + decrypt: jest.fn(), + contentInboundSessionCreator: jest.fn(), + getOneTimeKeys: jest.fn(), + validateAndUploadPrekeys: jest.fn(), + }, +}); + +const hasConfig = (): boolean => true; + +export { getConfig, hasConfig }; diff --git a/lib/utils/reducers-utils.test.js b/lib/utils/reducers-utils.test.js --- a/lib/utils/reducers-utils.test.js +++ b/lib/utils/reducers-utils.test.js @@ -8,6 +8,8 @@ import { defaultKeyserverInfo } from '../types/keyserver-types.js'; import { defaultGlobalThemeInfo } from '../types/theme-types.js'; +jest.mock('./config.js'); + describe('resetUserSpecificState', () => { let defaultState; let state; diff --git a/native/redux/default-state.js b/native/redux/default-state.js --- a/native/redux/default-state.js +++ b/native/redux/default-state.js @@ -4,7 +4,6 @@ import Orientation from 'react-native-orientation-locker'; import { defaultEnabledApps } from 'lib/types/enabled-apps.js'; -import { defaultCalendarQuery } from 'lib/types/entry-types.js'; import { defaultCalendarFilters } from 'lib/types/filter-types.js'; import { defaultKeyserverInfo } from 'lib/types/keyserver-types.js'; import { defaultGlobalThemeInfo } from 'lib/types/theme-types.js'; @@ -45,7 +44,6 @@ dataLoaded: false, customServer: natNodeServer, notifPermissionAlertInfo: defaultNotifPermissionAlertInfo, - actualizedCalendarQuery: defaultCalendarQuery(Platform.OS), watchedThreadIDs: [], lifecycleState: 'active', enabledApps: defaultEnabledApps, @@ -72,7 +70,10 @@ }, keyserverStore: { keyserverInfos: { - [authoritativeKeyserverID]: defaultKeyserverInfo(defaultURLPrefix), + [authoritativeKeyserverID]: defaultKeyserverInfo( + defaultURLPrefix, + Platform.OS, + ), }, }, localSettings: { diff --git a/native/redux/persist.js b/native/redux/persist.js --- a/native/redux/persist.js +++ b/native/redux/persist.js @@ -15,6 +15,7 @@ convertCalendarFilterToNewIDSchema, convertConnectionInfoToNewIDSchema, } from 'lib/_generated/migration-utils.js'; +import { extractKeyserverIDFromID } from 'lib/keyserver-conn/keyserver-call-utils.js'; import { type ClientDBKeyserverStoreOperation, keyserverStoreOpsHandlers, @@ -38,6 +39,7 @@ convertUserInfosToReplaceUserOps, userStoreOpsHandlers, } from 'lib/ops/user-store-ops.js'; +import { filterThreadIDsInFilterList } from 'lib/reducers/calendar-filters-reducer.js'; import { highestLocalIDSelector } from 'lib/selectors/local-id-selectors.js'; import { createAsyncMigrate } from 'lib/shared/create-async-migrate.js'; import { inconsistencyResponsesToReports } from 'lib/shared/report-utils.js'; @@ -1084,6 +1086,46 @@ } return state; }, + [63]: async (state: any) => { + const { actualizedCalendarQuery, ...rest } = state; + const operations: $ReadOnlyArray = entries( + state.keyserverStore.keyserverInfos, + ).map(([id, keyserverInfo]) => ({ + type: 'replace_keyserver', + payload: { + id, + keyserverInfo: { + ...keyserverInfo, + actualizedCalendarQuery: { + ...actualizedCalendarQuery, + filters: filterThreadIDsInFilterList( + actualizedCalendarQuery.filters, + (threadID: string) => extractKeyserverIDFromID(threadID) === id, + ), + }, + }, + }, + })); + const dbOperations: $ReadOnlyArray = + keyserverStoreOpsHandlers.convertOpsToClientDBOps(operations); + + const newState = { + ...rest, + keyserverStore: keyserverStoreOpsHandlers.processStoreOperations( + rest.keyserverStore, + operations, + ), + }; + try { + await commCoreModule.processKeyserverStoreOperations(dbOperations); + } catch (exception) { + if (isTaskCancelledError(exception)) { + return newState; + } + return handleReduxMigrationFailure(newState); + } + return newState; + }, }; // After migration 31, we'll no longer want to persist `messageStore.messages` @@ -1151,7 +1193,7 @@ storage: AsyncStorage, blacklist: persistBlacklist, debug: __DEV__, - version: 62, + version: 63, transforms: [ messageStoreMessagesBlocklistTransform, reportStoreTransform, diff --git a/native/redux/state-types.js b/native/redux/state-types.js --- a/native/redux/state-types.js +++ b/native/redux/state-types.js @@ -5,7 +5,7 @@ import type { DraftStore } from 'lib/types/draft-types.js'; import type { EnabledApps } from 'lib/types/enabled-apps.js'; -import type { EntryStore, CalendarQuery } from 'lib/types/entry-types.js'; +import type { EntryStore } from 'lib/types/entry-types.js'; import type { CalendarFilter } from 'lib/types/filter-types.js'; import type { IntegrityStore } from 'lib/types/integrity-types.js'; import type { KeyserverStore } from 'lib/types/keyserver-types.js'; @@ -56,7 +56,6 @@ +dataLoaded: boolean, +customServer: ?string, +notifPermissionAlertInfo: NotifPermissionAlertInfo, - +actualizedCalendarQuery: CalendarQuery, +watchedThreadIDs: $ReadOnlyArray, +lifecycleState: LifecycleState, +enabledApps: EnabledApps, diff --git a/web/database/queries/keyservers-queries.test.js b/web/database/queries/keyservers-queries.test.js --- a/web/database/queries/keyservers-queries.test.js +++ b/web/database/queries/keyservers-queries.test.js @@ -4,6 +4,7 @@ convertKeyserverInfoToClientDBKeyserverInfo, keyserverStoreOpsHandlers, } from 'lib/ops/keyserver-store-ops.js'; +import { defaultCalendarFilters } from 'lib/types/filter-types.js'; import type { KeyserverInfo } from 'lib/types/keyserver-types.js'; import { defaultConnectionInfo } from 'lib/types/socket-types.js'; @@ -23,6 +24,11 @@ }, deviceToken: 'token', lastCommunicatedPlatformDetails: null, + actualizedCalendarQuery: { + startDate: '', + endDate: '', + filters: defaultCalendarFilters, + }, }; const TEST_KEYSERVER_2: KeyserverInfo = { cookie: 'testCookie2', @@ -33,6 +39,11 @@ }, deviceToken: 'token', lastCommunicatedPlatformDetails: null, + actualizedCalendarQuery: { + startDate: '', + endDate: '', + filters: defaultCalendarFilters, + }, }; describe('Keyserver Store queries', () => { diff --git a/web/redux/default-state.js b/web/redux/default-state.js --- a/web/redux/default-state.js +++ b/web/redux/default-state.js @@ -8,6 +8,7 @@ import type { AppState } from './redux-setup.js'; import { authoritativeKeyserverID } from '../authoritative-keyserver.js'; +import electron from '../electron.js'; declare var keyserverURL: string; @@ -63,15 +64,13 @@ inviteLinksStore: { links: {}, }, - actualizedCalendarQuery: { - startDate: '', - endDate: '', - filters: defaultCalendarFilters, - }, communityPickerStore: { chat: null, calendar: null }, keyserverStore: { keyserverInfos: { - [authoritativeKeyserverID]: defaultKeyserverInfo(keyserverURL), + [authoritativeKeyserverID]: defaultKeyserverInfo( + keyserverURL, + electron?.platform ?? 'web', + ), }, }, threadActivityStore: {}, diff --git a/web/redux/redux-setup.js b/web/redux/redux-setup.js --- a/web/redux/redux-setup.js +++ b/web/redux/redux-setup.js @@ -29,7 +29,7 @@ import type { CryptoStore } from 'lib/types/crypto-types.js'; import type { DraftStore } from 'lib/types/draft-types.js'; import type { EnabledApps } from 'lib/types/enabled-apps.js'; -import type { EntryStore, CalendarQuery } from 'lib/types/entry-types.js'; +import type { EntryStore } from 'lib/types/entry-types.js'; import { type CalendarFilter } from 'lib/types/filter-types.js'; import type { IntegrityStore } from 'lib/types/integrity-types.js'; import type { KeyserverStore } from 'lib/types/keyserver-types.js'; @@ -98,7 +98,6 @@ +communityPickerStore: CommunityPickerStore, +windowDimensions: WindowDimensions, +notifPermissionAlertInfo: NotifPermissionAlertInfo, - +actualizedCalendarQuery: CalendarQuery, +watchedThreadIDs: $ReadOnlyArray, +lifecycleState: LifecycleState, +enabledApps: EnabledApps, @@ -147,7 +146,8 @@ }; if (action.type === setInitialReduxState) { - const { userInfos, keyserverInfos, ...rest } = action.payload; + const { userInfos, keyserverInfos, actualizedCalendarQuery, ...rest } = + action.payload; const replaceOperations: ReplaceKeyserverOperation[] = []; for (const keyserverID in keyserverInfos) { replaceOperations.push({ @@ -157,6 +157,7 @@ keyserverInfo: { ...state.keyserverStore.keyserverInfos[keyserverID], ...keyserverInfos[keyserverID], + actualizedCalendarQuery, }, }, });