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< @@ -20,4 +24,13 @@ info, ); }, + 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,5 +1,6 @@ // @flow +import { createSelector } from 'reselect'; import t from 'tcomb'; import type { StateSyncSpec } from './state-sync-spec.js'; @@ -9,8 +10,9 @@ rawEntryInfoValidator, type RawEntryInfo, } from '../../types/entry-types.js'; +import type { AppState } from '../../types/redux-types.js'; import { convertClientIDsToServerIDs } from '../../utils/conversion-utils.js'; -import { values } from '../../utils/objects.js'; +import { values, combineUnorderedHashes, hash } from '../../utils/objects.js'; import { ashoatKeyserverID, tID } from '../../utils/validation-utils.js'; import { filterRawEntryInfosByCalendarQuery, @@ -40,4 +42,35 @@ filteredEntryInfos, ); }, + 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), + }), + ), }); + +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'; export type StateSyncSpec = { +hashKey: string, @@ -14,4 +15,17 @@ infos: Infos, calendarQuery: CalendarQuery, ) => Infos, + +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,14 +1,17 @@ // @flow +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 { type RawThreadInfos, type RawThreadInfo, rawThreadInfoValidator, } from '../../types/thread-types.js'; import { convertClientIDsToServerIDs } from '../../utils/conversion-utils.js'; +import { combineUnorderedHashes, values } from '../../utils/objects.js'; import { ashoatKeyserverID, tID } from '../../utils/validation-utils.js'; export const threadsStateSyncSpec: StateSyncSpec< @@ -28,4 +31,19 @@ infos, ); }, + 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, + }), + ), }); 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,12 +1,16 @@ // @flow +import { createSelector } from 'reselect'; + import type { StateSyncSpec } from './state-sync-spec.js'; +import type { AppState } from '../../types/redux-types'; import { type UserInfo, type UserInfos, userInfosValidator, } from '../../types/user-types.js'; import { convertClientIDsToServerIDs } from '../../utils/conversion-utils.js'; +import { combineUnorderedHashes, hash } from '../../utils/objects.js'; import { ashoatKeyserverID } from '../../utils/validation-utils.js'; export const usersStateSyncSpec: StateSyncSpec = @@ -27,4 +31,14 @@ infos, ); }, + 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), + }), + ), });