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[] = []; + for (const farcasterUser of action.payload.farcasterUsers) { + 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 farcaster data for user', () => { + 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 @@ -14,6 +14,7 @@ communityStoreOperations: [], integrityStoreOperations: [], syncedMetadataStoreOperations: [], + 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'; @@ -176,6 +177,11 @@ const { syncedMetadataStore, syncedMetadataStoreOperations } = reduceSyncedMetadataStore(state.syncedMetadataStore, action); + const { auxUserStore, auxUserStoreOperations } = reduceAuxUserStore( + state.auxUserStore, + action, + ); + return { state: { ...state, @@ -218,6 +224,7 @@ communityStore, dbOpsStore: reduceDBOpsStore(state.dbOpsStore, action), syncedMetadataStore, + auxUserStore, }, storeOperations: { draftStoreOperations, @@ -229,6 +236,7 @@ communityStoreOperations, integrityStoreOperations, syncedMetadataStoreOperations, + 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, @@ -164,6 +168,7 @@ +communityStore: CommunityStore, +dbOpsStore: DBOpsStore, +syncedMetadataStore: SyncedMetadataStore, + +auxUserStore: AuxUserStore, ... }; @@ -1380,6 +1385,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 @@ -19,6 +19,7 @@ import type { ClientDBAuxUserInfo, ClientDBAuxUserStoreOperation, + AuxUserStoreOperation, } from '../ops/aux-user-store-ops.js'; import type { ClientDBCommunityInfo, @@ -67,6 +68,7 @@ +communityStoreOperations: $ReadOnlyArray, +integrityStoreOperations: $ReadOnlyArray, +syncedMetadataStoreOperations: $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 @@ -90,6 +90,9 @@ syncedMetadataStore: { syncedMetadata: {}, }, + 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 @@ -301,6 +301,7 @@ communityStoreOperations, integrityStoreOperations, syncedMetadataStoreOperations, + auxUserStoreOperations, } = storeOperations; const fixUnreadActiveThreadResult = fixUnreadActiveThread(state, action); @@ -321,6 +322,7 @@ communityStoreOperations, integrityStoreOperations, syncedMetadataStoreOperations, + 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 { @@ -39,6 +40,7 @@ integrityStoreOperations, communityStoreOperations, syncedMetadataStoreOperations, + auxUserStoreOperations, } = storeOperations; const convertedThreadStoreOperations = @@ -61,6 +63,8 @@ getKeyserversToRemoveFromNotifsStore(keyserverStoreOperations); const convertedIntegrityStoreOperations = integrityStoreOpsHandlers.convertOpsToClientDBOps(integrityStoreOperations); + const convertedAuxUserStoreOperations = + auxUserStoreOpsHandlers.convertOpsToClientDBOps(auxUserStoreOperations); try { const promises = []; @@ -130,6 +134,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'; @@ -81,6 +82,7 @@ +communityStore: CommunityStore, +dbOpsStore: DBOpsStore, +syncedMetadataStore: SyncedMetadataStore, + +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 @@ -86,6 +86,9 @@ syncedMetadataStore: { syncedMetadata: {}, }, + 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 @@ -127,6 +127,7 @@ communityStoreOperations: [], integrityStoreOperations: [], syncedMetadataStoreOperations: [], + 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 @@ -30,6 +30,7 @@ identityInvalidSessionDowngrade, invalidSessionRecovery, } 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'; @@ -124,6 +125,7 @@ +communityStore: CommunityStore, +dbOpsStore: DBOpsStore, +syncedMetadataStore: SyncedMetadataStore, + +auxUserStore: AuxUserStore, }; export type Action = $ReadOnly< @@ -157,6 +159,7 @@ communityStoreOperations: [], integrityStoreOperations: [], syncedMetadataStoreOperations: [], + auxUserStoreOperations: [], }; if ( 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'; @@ -103,6 +104,7 @@ communityStoreOperations, integrityStoreOperations, syncedMetadataStoreOperations, + auxUserStoreOperations, } = storeOperations; const canUseDatabase = canUseDatabaseOnWeb(userID); @@ -122,6 +124,8 @@ syncedMetadataStoreOpsHandlers.convertOpsToClientDBOps( syncedMetadataStoreOperations, ); + const convertedAuxUserStoreOperations = + auxUserStoreOpsHandlers.convertOpsToClientDBOps(auxUserStoreOperations); if ( convertedThreadStoreOperations.length === 0 && @@ -130,7 +134,8 @@ convertedKeyserverStoreOperations.length === 0 && convertedCommunityStoreOperations.length === 0 && convertedIntegrityStoreOperations.length === 0 && - convertedSyncedMetadataStoreOperations.length === 0 + convertedSyncedMetadataStoreOperations.length === 0 && + convertedAuxUserStoreOperations.length === 0 ) { return; } @@ -151,6 +156,7 @@ communityStoreOperations: convertedCommunityStoreOperations, integrityStoreOperations: convertedIntegrityStoreOperations, syncedMetadataStoreOperations: convertedSyncedMetadataStoreOperations, + auxUserStoreOperations: convertedAuxUserStoreOperations, }, }); } catch (e) {