diff --git a/keyserver/src/responders/redux-state-responders.js b/keyserver/src/responders/redux-state-responders.js --- a/keyserver/src/responders/redux-state-responders.js +++ b/keyserver/src/responders/redux-state-responders.js @@ -14,10 +14,7 @@ parsePendingThreadID, createPendingThread, } from 'lib/shared/thread-utils.js'; -import { - entryStoreValidator, - calendarQueryValidator, -} from 'lib/types/entry-types.js'; +import { entryStoreValidator } from 'lib/types/entry-types.js'; import { defaultCalendarFilters } from 'lib/types/filter-types.js'; import { inviteLinksStoreValidator } from 'lib/types/link-types.js'; import { @@ -38,7 +35,7 @@ import { tShape, ashoatKeyserverID } from 'lib/utils/validation-utils.js'; import { navInfoValidator } from 'web/types/nav-types.js'; import type { - InitialReduxState, + InitialReduxStateResponse, InitialKeyserverInfo, } from 'web/types/redux-types.js'; import { navInfoFromURL } from 'web/url-utils.js'; @@ -62,17 +59,15 @@ updatesCurrentAsOf: t.Number, }); -export const initialReduxStateValidator: TInterface = - tShape({ +export const initialReduxStateValidator: TInterface = + tShape({ navInfo: navInfoValidator, currentUserInfo: currentUserInfoValidator, entryStore: entryStoreValidator, threadStore: threadStoreValidator, userInfos: userInfosValidator, - actualizedCalendarQuery: calendarQueryValidator, messageStore: messageStoreValidator, pushApiPublicKey: t.maybe(t.String), - dataLoaded: t.Boolean, commServicesAccessToken: t.Nil, inviteLinksStore: inviteLinksStoreValidator, keyserverInfo: initialKeyserverInfoValidator, @@ -81,7 +76,7 @@ async function getInitialReduxStateResponder( viewer: Viewer, urlInfo: URLInfo, -): Promise { +): Promise { const hasNotAcknowledgedPoliciesPromise = hasAnyNotAcknowledgedPolicies( viewer.id, baseLegalPolicies, @@ -318,15 +313,13 @@ }; })(); - const initialReduxState: InitialReduxState = await promiseAll({ + const initialReduxState: InitialReduxStateResponse = await promiseAll({ navInfo: navInfoPromise, currentUserInfo: currentUserInfoPromise, entryStore: entryStorePromise, threadStore: threadStorePromise, userInfos: userInfosPromise, - actualizedCalendarQuery: calendarQueryPromise, messageStore: messageStorePromise, - dataLoaded: viewer.loggedIn, pushApiPublicKey: pushApiPublicKeyPromise, commServicesAccessToken: null, inviteLinksStore: inviteLinksStorePromise, diff --git a/web/redux/action-types.js b/web/redux/action-types.js --- a/web/redux/action-types.js +++ b/web/redux/action-types.js @@ -1,9 +1,17 @@ // @flow -import type { CallServerEndpoint } from 'lib/utils/call-server-endpoint.js'; +import { defaultCalendarFilters } from 'lib/types/filter-types.js'; +import { extractKeyserverIDFromID } from 'lib/utils/action-utils.js'; +import { useKeyserverCall } from 'lib/utils/keyserver-call.js'; +import type { CallKeyserverEndpoint } from 'lib/utils/keyserver-call.js'; import type { URLInfo } from 'lib/utils/url-utils.js'; +import { ashoatKeyserverID } from 'lib/utils/validation-utils.js'; -import type { InitialReduxState } from '../types/redux-types.js'; +import type { + InitialReduxState, + InitialReduxStateResponse, + InitialKeyserverInfo, +} from '../types/redux-types.js'; export const updateNavInfoActionType = 'UPDATE_NAV_INFO'; export const updateWindowDimensionsActionType = 'UPDATE_WINDOW_DIMENSIONS'; @@ -13,28 +21,129 @@ const getInitialReduxStateCallServerEndpointOptions = { timeout: 300000 }; const getInitialReduxState = ( - callServerEndpoint: CallServerEndpoint, - ): (URLInfo => Promise) => + callKeyserverEndpoint: CallKeyserverEndpoint, + allKeyserverIDs: $ReadOnlyArray, + ): ((input: URLInfo) => Promise) => async urlInfo => { - const response = await callServerEndpoint( - 'get_initial_redux_state', - urlInfo, - getInitialReduxStateCallServerEndpointOptions, - ); + const requests = {}; + const { thread, inviteSecret, ...rest } = urlInfo; + const threadKeyserverID = thread ? extractKeyserverIDFromID(thread) : null; + + for (const keyserverID of allKeyserverIDs) { + if (keyserverID === threadKeyserverID) { + requests[keyserverID] = urlInfo; + } else { + requests[keyserverID] = rest; + } + } + + const responses: { +[string]: InitialReduxStateResponse } = + await callKeyserverEndpoint( + 'get_initial_redux_state', + requests, + getInitialReduxStateCallServerEndpointOptions, + ); + + const { + currentUserInfo, + userInfos, + pushApiPublicKey, + commServicesAccessToken, + navInfo, + } = responses[ashoatKeyserverID]; + + const dataLoaded = currentUserInfo && !currentUserInfo.anonymous; + const actualizedCalendarQuery = { + startDate: navInfo.startDate, + endDate: navInfo.endDate, + filters: defaultCalendarFilters, + }; + + const entryStore = { + daysToEntries: {}, + entryInfos: {}, + lastUserInteractionCalendar: 0, + }; + const threadStore = { + threadInfos: {}, + }; + const messageStore = { + currentAsOf: {}, + local: {}, + messages: {}, + threads: {}, + }; + const inviteLinksStore = { + links: {}, + }; + let keyserverInfos: { [keyserverID: string]: InitialKeyserverInfo } = {}; + + for (const keyserverID in responses) { + entryStore.daysToEntries = { + ...entryStore.daysToEntries, + ...responses[keyserverID].entryStore.daysToEntries, + }; + entryStore.entryInfos = { + ...entryStore.entryInfos, + ...responses[keyserverID].entryStore.entryInfos, + }; + entryStore.lastUserInteractionCalendar = Math.max( + entryStore.lastUserInteractionCalendar, + responses[keyserverID].entryStore.lastUserInteractionCalendar, + ); + + threadStore.threadInfos = { + ...threadStore.threadInfos, + ...responses[keyserverID].threadStore.threadInfos, + }; + + messageStore.currentAsOf = { + ...messageStore.currentAsOf, + ...responses[keyserverID].messageStore.currentAsOf, + }; + messageStore.messages = { + ...messageStore.messages, + ...responses[keyserverID].messageStore.messages, + }; + messageStore.threads = { + ...messageStore.threads, + ...responses[keyserverID].messageStore.threads, + }; + + inviteLinksStore.links = { + ...inviteLinksStore.links, + ...responses[keyserverID].inviteLinksStore.links, + }; + + keyserverInfos = { + ...keyserverInfos, + [keyserverID]: responses[keyserverID].keyserverInfo, + }; + } + return { - navInfo: response.navInfo, - currentUserInfo: response.currentUserInfo, - entryStore: response.entryStore, - threadStore: response.threadStore, - userInfos: response.userInfos, - actualizedCalendarQuery: response.actualizedCalendarQuery, - messageStore: response.messageStore, - dataLoaded: response.dataLoaded, - pushApiPublicKey: response.pushApiPublicKey, - commServicesAccessToken: response.commServicesAccessToken, - inviteLinksStore: response.inviteLinksStore, - keyserverInfo: response.keyserverInfo, + navInfo: { + ...navInfo, + inviteSecret, + }, + currentUserInfo, + entryStore, + threadStore, + userInfos, + actualizedCalendarQuery, + messageStore, + dataLoaded, + pushApiPublicKey, + commServicesAccessToken, + inviteLinksStore, + keyserverInfos, }; }; -export { getInitialReduxState }; +function useGetInitialReduxState(): ( + input: URLInfo, +) => Promise { + return useKeyserverCall(getInitialReduxState); +} + +export { useGetInitialReduxState }; diff --git a/web/redux/initial-state-gate.js b/web/redux/initial-state-gate.js --- a/web/redux/initial-state-gate.js +++ b/web/redux/initial-state-gate.js @@ -5,12 +5,14 @@ import { PersistGate } from 'redux-persist/es/integration/react.js'; import type { Persistor } from 'redux-persist/es/types'; -import { useServerCall } from 'lib/utils/action-utils.js'; import { convertIDToNewSchema } from 'lib/utils/migration-utils.js'; import { infoFromURL } from 'lib/utils/url-utils.js'; import { ashoatKeyserverID } from 'lib/utils/validation-utils.js'; -import { getInitialReduxState, setInitialReduxState } from './action-types.js'; +import { + setInitialReduxState, + useGetInitialReduxState, +} from './action-types.js'; import { useSelector } from './redux-utils.js'; import Loading from '../loading.react.js'; @@ -20,7 +22,7 @@ }; function InitialReduxStateGate(props: Props): React.Node { const { children, persistor } = props; - const callGetInitialReduxState = useServerCall(getInitialReduxState); + const callGetInitialReduxState = useGetInitialReduxState(); const dispatch = useDispatch(); const [initError, setInitError] = React.useState(null); 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 @@ -124,20 +124,21 @@ let state = oldState; if (action.type === setInitialReduxState) { - const { userInfos, keyserverInfo, ...rest } = action.payload; + const { userInfos, keyserverInfos, ...rest } = action.payload; + const newKeyserverInfos = { ...state.keyserverStore.keyserverInfos }; + for (const keyserverID in keyserverInfos) { + newKeyserverInfos[keyserverID] = { + ...newKeyserverInfos[keyserverID], + ...keyserverInfos[keyserverID], + }; + } return validateState(oldState, { ...state, ...rest, userStore: { userInfos }, keyserverStore: { ...state.keyserverStore, - keyserverInfos: { - ...state.keyserverStore.keyserverInfos, - [ashoatKeyserverID]: { - ...state.keyserverStore.keyserverInfos[ashoatKeyserverID], - ...keyserverInfo, - }, - }, + keyserverInfos: newKeyserverInfos, }, initialStateLoaded: true, }); diff --git a/web/types/redux-types.js b/web/types/redux-types.js --- a/web/types/redux-types.js +++ b/web/types/redux-types.js @@ -8,21 +8,34 @@ import type { NavInfo } from '../types/nav-types.js'; -export type InitialReduxState = { +export type InitialReduxStateResponse = { +navInfo: NavInfo, +currentUserInfo: CurrentUserInfo, +entryStore: EntryStore, +threadStore: ThreadStore, +userInfos: UserInfos, - +actualizedCalendarQuery: CalendarQuery, +messageStore: MessageStore, - +dataLoaded: boolean, +pushApiPublicKey: ?string, +commServicesAccessToken: null, +inviteLinksStore: InviteLinksStore, +keyserverInfo: InitialKeyserverInfo, }; +export type InitialReduxState = { + +navInfo: NavInfo, + +currentUserInfo: CurrentUserInfo, + +entryStore: EntryStore, + +threadStore: ThreadStore, + +userInfos: UserInfos, + +messageStore: MessageStore, + +pushApiPublicKey: ?string, + +commServicesAccessToken: null, + +inviteLinksStore: InviteLinksStore, + +dataLoaded: boolean, + +actualizedCalendarQuery: CalendarQuery, + +keyserverInfos: { +[keyserverID: string]: InitialKeyserverInfo }, +}; + export type InitialKeyserverInfo = { +sessionID: ?string, +updatesCurrentAsOf: number,