diff --git a/lib/shared/state-sync/current-user-state-sync-spec.js b/lib/shared/state-sync/current-user-state-sync-spec.js --- a/lib/shared/state-sync/current-user-state-sync-spec.js +++ b/lib/shared/state-sync/current-user-state-sync-spec.js @@ -1,11 +1,15 @@ // @flow +import { createSelector } from 'reselect'; + import type { StateSyncSpec } from './state-sync-spec.js'; +import type { AppState } from '../../types/redux-types'; import { type CurrentUserInfo, currentUserInfoValidator, } from '../../types/user-types.js'; import { convertClientIDsToServerIDs } from '../../utils/conversion-utils.js'; +import { hash } from '../../utils/objects.js'; import { ashoatKeyserverID } from '../../utils/validation-utils.js'; export const currentUserStateSyncSpec: StateSyncSpec< @@ -24,4 +28,13 @@ findStoreInconsistencies() { return undefined; }, + selector: createSelector( + (state: AppState) => state.currentUserInfo, + currentUserInfo => ({ + ...currentUserStateSyncSpec, + getInfoHash: () => hash(currentUserInfo), + getAllInfosHash: () => hash(currentUserInfo), + getIDs: () => [], + }), + ), }); diff --git a/lib/shared/state-sync/entries-state-sync-spec.js b/lib/shared/state-sync/entries-state-sync-spec.js --- a/lib/shared/state-sync/entries-state-sync-spec.js +++ b/lib/shared/state-sync/entries-state-sync-spec.js @@ -1,6 +1,7 @@ // @flow import _isEqual from 'lodash/fp/isEqual.js'; +import { createSelector } from 'reselect'; import t from 'tcomb'; import type { StateSyncSpec } from './state-sync-spec.js'; @@ -10,6 +11,7 @@ rawEntryInfoValidator, type RawEntryInfo, } from '../../types/entry-types.js'; +import type { AppState } from '../../types/redux-types.js'; import { reportTypes, type ClientEntryInconsistencyReportCreationRequest, @@ -18,7 +20,7 @@ import { actionLogger } from '../../utils/action-logger.js'; import { getConfig } from '../../utils/config.js'; import { convertClientIDsToServerIDs } from '../../utils/conversion-utils.js'; -import { values } from '../../utils/objects.js'; +import { values, combineUnorderedHashes, hash } from '../../utils/objects.js'; import { generateReportID } from '../../utils/report-utils.js'; import { sanitizeActionSecrets } from '../../utils/sanitization.js'; import { ashoatKeyserverID, tID } from '../../utils/validation-utils.js'; @@ -87,6 +89,37 @@ }, ]; }, + selector: createSelector( + (state: AppState) => state.entryStore.entryInfos, + entryInfos => ({ + ...entriesStateSyncSpec, + getInfoHash: id => hash(entryInfos[`${ashoatKeyserverID}|${id}`]), + getAllInfosHash: calendarQuery => + getEntryInfosHash(entryInfos, calendarQuery), + getIDs: calendarQuery => getEntryIDs(entryInfos, calendarQuery), + }), + ), }); const emptyArray = []; + +function getEntryInfosHash( + entryInfos: RawEntryInfos, + calendarQuery: CalendarQuery, +) { + const filteredEntryInfos = filterRawEntryInfosByCalendarQuery( + serverEntryInfosObject(values(entryInfos)), + calendarQuery, + ); + + return combineUnorderedHashes(Object.values(filteredEntryInfos).map(hash)); +} + +function getEntryIDs(entryInfos: RawEntryInfos, calendarQuery: CalendarQuery) { + const filteredEntryInfos = filterRawEntryInfosByCalendarQuery( + serverEntryInfosObject(values(entryInfos)), + calendarQuery, + ); + + return Object.keys(filteredEntryInfos).map(id => id.split('|')[1]); +} diff --git a/lib/shared/state-sync/state-sync-spec.js b/lib/shared/state-sync/state-sync-spec.js --- a/lib/shared/state-sync/state-sync-spec.js +++ b/lib/shared/state-sync/state-sync-spec.js @@ -1,6 +1,7 @@ // @flow import type { CalendarQuery } from '../../types/entry-types.js'; +import type { AppState } from '../../types/redux-types.js'; import type { ProcessServerRequestAction } from '../../types/request-types.js'; export type StateSyncSpec = { @@ -20,4 +21,19 @@ beforeStateCheck: Infos, afterStateCheck: Infos, ) => Inconsistencies, + +selector: ( + state: AppState, + ) => BoundStateSyncSpec, +}; + +// All ids specified here (getInfoHash and getIDs) are server ids. +// E.g. in the case of threadStore or entryStore the keyserver prefix +// needs to be handled additionaly +export type BoundStateSyncSpec = { + // If these function depend on background hashing that is still not complete + // they should return null, to indicate that the hashes aren't available yet + +getInfoHash: (id: string) => ?number, + +getAllInfosHash: (query: CalendarQuery) => ?number, + +getIDs: (query: CalendarQuery) => ?Array, + ...StateSyncSpec, }; diff --git a/lib/shared/state-sync/threads-state-sync-spec.js b/lib/shared/state-sync/threads-state-sync-spec.js --- a/lib/shared/state-sync/threads-state-sync-spec.js +++ b/lib/shared/state-sync/threads-state-sync-spec.js @@ -1,9 +1,11 @@ // @flow import _isEqual from 'lodash/fp/isEqual.js'; +import { createSelector } from 'reselect'; import t from 'tcomb'; import type { StateSyncSpec } from './state-sync-spec.js'; +import type { AppState } from '../../types/redux-types.js'; import { reportTypes, type ClientThreadInconsistencyReportCreationRequest, @@ -17,6 +19,7 @@ import { actionLogger } from '../../utils/action-logger.js'; import { getConfig } from '../../utils/config.js'; import { convertClientIDsToServerIDs } from '../../utils/conversion-utils.js'; +import { combineUnorderedHashes, values } from '../../utils/objects.js'; import { generateReportID } from '../../utils/report-utils.js'; import { sanitizeActionSecrets } from '../../utils/sanitization.js'; import { ashoatKeyserverID, tID } from '../../utils/validation-utils.js'; @@ -60,6 +63,21 @@ }, ]; }, + selector: createSelector( + (state: AppState) => state.integrityStore.threadHashes, + (state: AppState) => + state.integrityStore.threadHashingStatus === 'completed', + (threadHashes, threadHashingComplete) => ({ + ...threadsStateSyncSpec, + getInfoHash: id => threadHashes[`${ashoatKeyserverID}|${id}`], + getAllInfosHash: threadHashingComplete + ? () => combineUnorderedHashes(values(threadHashes)) + : () => null, + getIDs: threadHashingComplete + ? () => Object.keys(threadHashes).map(id => id.split('|')[1]) + : () => null, + }), + ), }); const emptyArray = []; diff --git a/lib/shared/state-sync/users-state-sync-spec.js b/lib/shared/state-sync/users-state-sync-spec.js --- a/lib/shared/state-sync/users-state-sync-spec.js +++ b/lib/shared/state-sync/users-state-sync-spec.js @@ -1,8 +1,10 @@ // @flow import _isEqual from 'lodash/fp/isEqual.js'; +import { createSelector } from 'reselect'; import type { StateSyncSpec } from './state-sync-spec.js'; +import type { AppState } from '../../types/redux-types'; import { reportTypes, type UserInconsistencyReportCreationRequest, @@ -16,6 +18,7 @@ import { actionLogger } from '../../utils/action-logger.js'; import { getConfig } from '../../utils/config.js'; import { convertClientIDsToServerIDs } from '../../utils/conversion-utils.js'; +import { combineUnorderedHashes, hash } from '../../utils/objects.js'; import { generateReportID } from '../../utils/report-utils.js'; import { sanitizeActionSecrets } from '../../utils/sanitization.js'; import { ashoatKeyserverID } from '../../utils/validation-utils.js'; @@ -62,6 +65,16 @@ }, ]; }, + selector: createSelector( + (state: AppState) => state.userStore.userInfos, + userInfos => ({ + ...usersStateSyncSpec, + getInfoHash: id => hash(userInfos[id]), + getAllInfosHash: () => + combineUnorderedHashes(Object.values(userInfos).map(hash)), + getIDs: () => Object.keys(userInfos), + }), + ), }); const emptyArray = [];