diff --git a/lib/actions/aux-user-actions.js b/lib/actions/aux-user-actions.js new file mode 100644 --- /dev/null +++ b/lib/actions/aux-user-actions.js @@ -0,0 +1,5 @@ +// @flow + +const setFarcasterFriendsFIDActionType = 'SET_FARCASTER_FRIENDS_FID'; + +export { setFarcasterFriendsFIDActionType }; diff --git a/lib/reducers/aux-user-reducer.js b/lib/reducers/aux-user-reducer.js new file mode 100644 --- /dev/null +++ b/lib/reducers/aux-user-reducer.js @@ -0,0 +1,46 @@ +// @flow + +import { setFarcasterFriendsFIDActionType } from '../actions/aux-user-actions.js'; +import { + auxUserStoreOpsHandlers, + type AuxUserStoreOperation, + type ReplaceAuxUserInfoOperation, +} from '../ops/aux-user-store-ops.js'; +import type { AuxUserStore } from '../types/aux-user-types.js'; +import type { BaseAction } from '../types/redux-types'; + +const { processStoreOperations: processStoreOps } = auxUserStoreOpsHandlers; + +function reduceAuxUserStore( + state: AuxUserStore, + action: BaseAction, +): { + +auxUserStore: AuxUserStore, + +auxUserStoreOperations: $ReadOnlyArray, +} { + if (action.type === setFarcasterFriendsFIDActionType) { + const replaceOperations: ReplaceAuxUserInfoOperation[] = []; + action.payload.farcasterUsers.map(farcasterUser => { + replaceOperations.push({ + type: 'replace_aux_user_info', + payload: { + id: farcasterUser.userID, + auxUserInfo: { + ...state.auxUserInfos[farcasterUser.userID], + fid: farcasterUser.farcasterID, + }, + }, + }); + }); + return { + auxUserStore: processStoreOps(state, replaceOperations), + auxUserStoreOperations: replaceOperations, + }; + } + return { + auxUserStore: state, + auxUserStoreOperations: [], + }; +} + +export { reduceAuxUserStore }; diff --git a/lib/reducers/aux-user-reducer.test.js b/lib/reducers/aux-user-reducer.test.js new file mode 100644 --- /dev/null +++ b/lib/reducers/aux-user-reducer.test.js @@ -0,0 +1,38 @@ +// @flow + +import { reduceAuxUserStore } from './aux-user-reducer.js'; +import { setFarcasterFriendsFIDActionType } from '../actions/aux-user-actions.js'; + +jest.mock('../utils/config.js'); + +describe('reduceAuxUserStore', () => { + it('should update aux user store with new thread hash', () => { + const oldAuxUserStore = { + auxUserInfos: {}, + }; + + const updateAuxUserInfosAction = { + type: setFarcasterFriendsFIDActionType, + payload: { + farcasterUsers: [ + { + userID: 'userID_1', + username: 'username_1', + farcasterID: 'farcasterID_1', + }, + ], + }, + }; + + expect( + reduceAuxUserStore(oldAuxUserStore, updateAuxUserInfosAction) + .auxUserStore, + ).toEqual({ + auxUserInfos: { + userID_1: { + fid: 'farcasterID_1', + }, + }, + }); + }); +}); diff --git a/lib/reducers/db-ops-reducer.test.js b/lib/reducers/db-ops-reducer.test.js --- a/lib/reducers/db-ops-reducer.test.js +++ b/lib/reducers/db-ops-reducer.test.js @@ -13,6 +13,7 @@ keyserverStoreOperations: [], communityStoreOperations: [], integrityStoreOperations: [], + auxUserStoreOperations: [], }; describe('DB ops reducer', () => { 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,5 +1,6 @@ // @flow +import { reduceAuxUserStore } from './aux-user-reducer.js'; import reduceCalendarFilters from './calendar-filters-reducer.js'; import { reduceCommunityStore } from './community-reducer.js'; import reduceCustomerServer from './custom-server-reducer.js'; @@ -170,6 +171,11 @@ threadStoreOperations, ); + const { auxUserStore, auxUserStoreOperations } = reduceAuxUserStore( + state.auxUserStore, + action, + ); + return { state: { ...state, @@ -211,6 +217,7 @@ customServer: reduceCustomerServer(state.customServer, action), communityStore, dbOpsStore: reduceDBOpsStore(state.dbOpsStore, action), + auxUserStore, }, storeOperations: { draftStoreOperations, @@ -221,6 +228,7 @@ keyserverStoreOperations, communityStoreOperations, integrityStoreOperations, + auxUserStoreOperations, }, }; } diff --git a/lib/types/aux-user-types.js b/lib/types/aux-user-types.js --- a/lib/types/aux-user-types.js +++ b/lib/types/aux-user-types.js @@ -1,5 +1,7 @@ // @flow +import type { FarcasterUser } from './identity-service-types'; + export type AuxUserInfo = { +fid: string }; export type AuxUserInfos = { +[userID: string]: AuxUserInfo }; @@ -7,3 +9,7 @@ export type AuxUserStore = { +auxUserInfos: AuxUserInfos, }; + +export type SetFarcasterFriendsFIDPayload = { + +farcasterUsers: $ReadOnlyArray, +}; 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 @@ -15,6 +15,10 @@ QueueActivityUpdatesPayload, SetThreadUnreadStatusPayload, } from './activity-types.js'; +import type { + AuxUserStore, + SetFarcasterFriendsFIDPayload, +} from './aux-user-types.js'; import type { UpdateUserAvatarRequest, UpdateUserAvatarResponse, @@ -158,6 +162,7 @@ +customServer: ?string, +communityStore: CommunityStore, +dbOpsStore: DBOpsStore, + +auxUserStore: AuxUserStore, ... }; @@ -1366,6 +1371,10 @@ +type: 'SET_ACTIVE_SESSION_RECOVERY', +payload: SetActiveSessionRecoveryPayload, } + | { + +type: 'SET_FARCASTER_FRIENDS_FID', + +payload: SetFarcasterFriendsFIDPayload, + } | { +type: 'OPS_PROCESSING_FINISHED_ACTION_TYPE', +payload?: void, diff --git a/lib/types/store-ops-types.js b/lib/types/store-ops-types.js --- a/lib/types/store-ops-types.js +++ b/lib/types/store-ops-types.js @@ -18,6 +18,7 @@ import type { ClientDBAuxUserInfo, ClientDBAuxUserStoreOperation, + AuxUserStoreOperation, } from '../ops/aux-user-store-ops.js'; import type { ClientDBCommunityInfo, @@ -61,6 +62,7 @@ +keyserverStoreOperations: $ReadOnlyArray, +communityStoreOperations: $ReadOnlyArray, +integrityStoreOperations: $ReadOnlyArray, + +auxUserStoreOperations: $ReadOnlyArray, }; export type ClientDBStoreOperations = { 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 @@ -87,6 +87,9 @@ dbOpsStore: { queuedOps: [], }, + auxUserStore: { + auxUserInfos: {}, + }, }; state = { ...defaultState, 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 @@ -84,6 +84,9 @@ communityStore: { communityInfos: {}, }, + auxUserStore: { + auxUserInfos: {}, + }, dbOpsStore: { queuedOps: [], }, diff --git a/native/redux/redux-setup.js b/native/redux/redux-setup.js --- a/native/redux/redux-setup.js +++ b/native/redux/redux-setup.js @@ -300,6 +300,7 @@ keyserverStoreOperations, communityStoreOperations, integrityStoreOperations, + auxUserStoreOperations, } = storeOperations; const fixUnreadActiveThreadResult = fixUnreadActiveThread(state, action); @@ -319,6 +320,7 @@ keyserverStoreOperations, communityStoreOperations, integrityStoreOperations, + auxUserStoreOperations, }; state = { ...state, diff --git a/native/redux/redux-utils.js b/native/redux/redux-utils.js --- a/native/redux/redux-utils.js +++ b/native/redux/redux-utils.js @@ -2,6 +2,7 @@ import { useSelector as reactReduxUseSelector } from 'react-redux'; +import { auxUserStoreOpsHandlers } from 'lib/ops/aux-user-store-ops.js'; import { communityStoreOpsHandlers } from 'lib/ops/community-store-ops.js'; import { integrityStoreOpsHandlers } from 'lib/ops/integrity-store-ops.js'; import { @@ -37,6 +38,7 @@ keyserverStoreOperations, integrityStoreOperations, communityStoreOperations, + auxUserStoreOperations, } = storeOperations; const convertedThreadStoreOperations = @@ -55,6 +57,8 @@ getKeyserversToRemoveFromNotifsStore(keyserverStoreOperations); const convertedIntegrityStoreOperations = integrityStoreOpsHandlers.convertOpsToClientDBOps(integrityStoreOperations); + const convertedAuxUserStoreOperations = + auxUserStoreOpsHandlers.convertOpsToClientDBOps(auxUserStoreOperations); try { const promises = []; @@ -117,6 +121,13 @@ ), ); } + if (convertedAuxUserStoreOperations.length > 0) { + promises.push( + commCoreModule.processAuxUserStoreOperations( + convertedAuxUserStoreOperations, + ), + ); + } await Promise.all(promises); } catch (e) { if (isTaskCancelledError(e)) { 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 @@ -3,6 +3,7 @@ import type { Orientations } from 'react-native-orientation-locker'; import type { PersistState } from 'redux-persist/es/types.js'; +import type { AuxUserStore } from 'lib/types/aux-user-types.js'; import type { CommunityStore } from 'lib/types/community-types.js'; import type { DBOpsStore } from 'lib/types/db-ops-types'; import type { DraftStore } from 'lib/types/draft-types.js'; @@ -79,6 +80,7 @@ +integrityStore: IntegrityStore, +communityStore: CommunityStore, +dbOpsStore: DBOpsStore, + +auxUserStore: AuxUserStore, }; export { nonUserSpecificFieldsNative }; 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 @@ -83,6 +83,9 @@ dbOpsStore: { queuedOps: [], }, + auxUserStore: { + auxUserInfos: {}, + }, }); export { defaultWebState }; 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 @@ -126,6 +126,7 @@ keyserverStoreOperations: [], communityStoreOperations: [], integrityStoreOperations: [], + auxUserStoreOperations: [], }, currentLoggedInUserID, ); 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 @@ -28,6 +28,7 @@ invalidSessionDowngrade, identityInvalidSessionDowngrade, } from 'lib/shared/session-utils.js'; +import type { AuxUserStore } from 'lib/types/aux-user-types.js'; import type { CommunityStore } from 'lib/types/community-types.js'; import type { MessageID, DBOpsStore } from 'lib/types/db-ops-types.js'; import type { DraftStore } from 'lib/types/draft-types.js'; @@ -120,6 +121,7 @@ +customServer: ?string, +communityStore: CommunityStore, +dbOpsStore: DBOpsStore, + +auxUserStore: AuxUserStore, }; export type Action = $ReadOnly< @@ -152,6 +154,7 @@ keyserverStoreOperations: [], communityStoreOperations: [], integrityStoreOperations: [], + auxUserStoreOperations: [], }; if (action.type === setInitialReduxState) { diff --git a/web/shared-worker/utils/store.js b/web/shared-worker/utils/store.js --- a/web/shared-worker/utils/store.js +++ b/web/shared-worker/utils/store.js @@ -1,5 +1,6 @@ // @flow +import { auxUserStoreOpsHandlers } from 'lib/ops/aux-user-store-ops.js'; import { communityStoreOpsHandlers } from 'lib/ops/community-store-ops.js'; import { integrityStoreOpsHandlers } from 'lib/ops/integrity-store-ops.js'; import { keyserverStoreOpsHandlers } from 'lib/ops/keyserver-store-ops.js'; @@ -92,6 +93,7 @@ keyserverStoreOperations, communityStoreOperations, integrityStoreOperations, + auxUserStoreOperations, } = storeOperations; const canUseDatabase = canUseDatabaseOnWeb(userID); @@ -107,6 +109,8 @@ communityStoreOpsHandlers.convertOpsToClientDBOps(communityStoreOperations); const convertedIntegrityStoreOperations = integrityStoreOpsHandlers.convertOpsToClientDBOps(integrityStoreOperations); + const convertedAuxUserStoreOperations = + auxUserStoreOpsHandlers.convertOpsToClientDBOps(auxUserStoreOperations); if ( convertedThreadStoreOperations.length === 0 && @@ -114,7 +118,8 @@ draftStoreOperations.length === 0 && convertedKeyserverStoreOperations.length === 0 && convertedCommunityStoreOperations.length === 0 && - convertedIntegrityStoreOperations.length === 0 + convertedIntegrityStoreOperations.length === 0 && + convertedAuxUserStoreOperations.length === 0 ) { return; } @@ -134,6 +139,7 @@ keyserverStoreOperations: convertedKeyserverStoreOperations, communityStoreOperations: convertedCommunityStoreOperations, integrityStoreOperations: convertedIntegrityStoreOperations, + auxUserStoreOperations: convertedAuxUserStoreOperations, }, }); } catch (e) {