diff --git a/lib/utils/keyserver-call.js b/lib/utils/keyserver-call.js --- a/lib/utils/keyserver-call.js +++ b/lib/utils/keyserver-call.js @@ -1,14 +1,19 @@ // @flow +import _memoize from 'lodash/memoize.js'; import * as React from 'react'; import { useDispatch } from 'react-redux'; +import { createSelector } from 'reselect'; import { bindCookieAndUtilsIntoCallServerEndpoint } from './action-utils.js'; -import type { CallServerEndpointOptions } from './call-server-endpoint.js'; +import type { BindServerCallsParams } from './action-utils.js'; +import type { CallServerEndpointOptions } from './call-server-endpoint'; import { useSelector } from './redux-utils.js'; +import type { PlatformDetails } from '../types/device-types.js'; import type { Endpoint } from '../types/endpoints.js'; import type { KeyserverInfo } from '../types/keyserver-types.js'; import type { Dispatch } from '../types/redux-types.js'; +import type { ConnectionStatus } from '../types/socket-types.js'; import type { CurrentUserInfo } from '../types/user-types.js'; export type CallKeyserverEndpoint> = ( @@ -34,22 +39,51 @@ +config: KeyserverCallConfig, }; -export type ExtractAndBindCookieAndUtilsParams< - Args: $ReadOnlyArray, - Return, -> = { +const boundCallServerEndpointSelector = createSelector( + (state: BindServerCallsParams) => state.dispatch, + (state: BindServerCallsParams) => state.cookie, + (state: BindServerCallsParams) => state.urlPrefix, + (state: BindServerCallsParams) => state.sessionID, + (state: BindServerCallsParams) => state.currentUserInfo, + (state: BindServerCallsParams) => state.connectionStatus, + (state: BindServerCallsParams) => state.lastCommunicatedPlatformDetails, + ( + dispatch: Dispatch, + cookie: ?string, + urlPrefix: string, + sessionID: ?string, + currentUserInfo: ?CurrentUserInfo, + connectionStatus: ConnectionStatus, + lastCommunicatedPlatformDetails: ?PlatformDetails, + ) => { + return bindCookieAndUtilsIntoCallServerEndpoint({ + dispatch, + cookie, + urlPrefix, + sessionID, + currentUserInfo, + connectionStatus, + lastCommunicatedPlatformDetails, + }); + }, +); + +export type BindKeyserverCallParams = { +dispatch: Dispatch, +currentUserInfo: ?CurrentUserInfo, +keyserverInfos: { +[keyserverID: string]: KeyserverInfo }, - +keyserverCall: KeyserverCall, }; -function getCallKeyserverEndpoint, Return>( - params: ExtractAndBindCookieAndUtilsParams, -): CallKeyserverEndpoint { - const { dispatch, keyserverInfos, currentUserInfo, keyserverCall } = params; +export type GetCallKeyserverEndpointParams> = { + ...BindKeyserverCallParams, + +keyserverCallConfig: KeyserverCallConfig, +}; - const { config: serverCallConfig } = keyserverCall; +function getCallKeyserverEndpoint>( + params: GetCallKeyserverEndpointParams, +): CallKeyserverEndpoint { + const { dispatch, keyserverInfos, currentUserInfo, keyserverCallConfig } = + params; return ( endpoint: Endpoint, @@ -58,10 +92,10 @@ options?: ?CallServerEndpointOptions, ) => { // TODO - if (serverCallConfig.keyserverSelection === 'fanout') { + if (keyserverCallConfig.keyserverSelection === 'fanout') { return Promise.all([]); } - const keyserverID = serverCallConfig.keyserverIDExtractor(...args); + const keyserverID = keyserverCallConfig.keyserverIDExtractor(...args); const { cookie, urlPrefix, @@ -70,7 +104,7 @@ lastCommunicatedPlatformDetails, } = keyserverInfos[keyserverID]; - const boundCallServerEndpoint = bindCookieAndUtilsIntoCallServerEndpoint({ + const boundCallServerEndpoint = boundCallServerEndpointSelector({ dispatch, currentUserInfo, cookie, @@ -79,29 +113,65 @@ connectionStatus: connection.status, lastCommunicatedPlatformDetails, }); + return boundCallServerEndpoint(endpoint, data, options); }; } +const baseCreateBoundKeyserverCallActionSelector = < + Args: $ReadOnlyArray, + Return, +>( + keyserverCall: KeyserverCall, +): (BindKeyserverCallParams => (...Args) => Promise) => + createSelector( + (state: BindKeyserverCallParams) => state.dispatch, + (state: BindKeyserverCallParams) => state.currentUserInfo, + (state: BindKeyserverCallParams) => state.keyserverInfos, + ( + dispatch: Dispatch, + currentUserInfo: ?CurrentUserInfo, + keyserverInfos: { +[keyserverID: string]: KeyserverInfo }, + ) => { + const callKeyserverEndpoint = getCallKeyserverEndpoint({ + dispatch, + currentUserInfo, + keyserverInfos, + keyserverCallConfig: keyserverCall.config, + }); + return keyserverCall.actionFunc(callKeyserverEndpoint); + }, + ); + +type CreateBoundKeyserverCallActionSelectorType = < + Args: $ReadOnlyArray, + Return, +>( + keyserverCall: KeyserverCall, +) => BindKeyserverCallParams => (...Args) => Promise; +const createBoundKeyserverCallActionSelector: CreateBoundKeyserverCallActionSelectorType = + _memoize(baseCreateBoundKeyserverCallActionSelector); + function useKeyserverCall, Return>( keyserverCall: KeyserverCall, - paramOverride?: ?$Shape>, + paramOverride?: ?$Shape, ): (...Args) => Promise { const dispatch = useDispatch(); const keyserverInfos = useSelector( state => state.keyserverStore.keyserverInfos, ); const currentUserInfo = useSelector(state => state.currentUserInfo); - return React.useMemo(() => { - const callKeyserverEndpoint = getCallKeyserverEndpoint({ - dispatch, - currentUserInfo, - keyserverInfos, - keyserverCall, - ...paramOverride, - }); - return keyserverCall.actionFunc(callKeyserverEndpoint); - }, [dispatch, currentUserInfo, keyserverInfos, keyserverCall, paramOverride]); + return React.useMemo( + () => + createBoundKeyserverCallActionSelector(keyserverCall)({ + dispatch, + currentUserInfo, + keyserverInfos, + ...paramOverride, + }), + + [dispatch, currentUserInfo, keyserverInfos, keyserverCall, paramOverride], + ); } export { useKeyserverCall };