diff --git a/lib/reducers/invite-links-reducer.js b/lib/reducers/invite-links-reducer.js new file mode 100644 --- /dev/null +++ b/lib/reducers/invite-links-reducer.js @@ -0,0 +1,26 @@ +// @flow + +import { fetchPrimaryInviteLinkActionTypes } from '../actions/link-actions.js'; +import type { InviteLinksStore } from '../types/link-types.js'; +import type { BaseAction } from '../types/redux-types.js'; + +function reduceInviteLinks( + state: InviteLinksStore, + action: BaseAction, +): InviteLinksStore { + if (action.type === fetchPrimaryInviteLinkActionTypes.success) { + const links = {}; + for (const link of action.payload.links) { + links[link.communityID] = { + primaryLink: link, + ...state.links[link.communityID], + }; + } + return { + links, + }; + } + return state; +} + +export default reduceInviteLinks; 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 @@ -7,6 +7,7 @@ import { reduceDraftStore } from './draft-reducer.js'; import reduceEnabledApps from './enabled-apps-reducer.js'; import { reduceEntryInfos } from './entry-reducer.js'; +import reduceInviteLinks from './invite-links-reducer.js'; import reduceLifecycleState from './lifecycle-state-reducer.js'; import { reduceLoadingStatuses } from './loading-reducer.js'; import reduceNextLocalID from './local-id-reducer.js'; @@ -123,6 +124,7 @@ state.commServicesAccessToken, action, ), + inviteLinksStore: reduceInviteLinks(state.inviteLinksStore, action), }, storeOperations: { draftStoreOperations, diff --git a/lib/selectors/invite-links-selectors.js b/lib/selectors/invite-links-selectors.js new file mode 100644 --- /dev/null +++ b/lib/selectors/invite-links-selectors.js @@ -0,0 +1,24 @@ +// @flow + +import { createSelector } from 'reselect'; + +import type { InviteLink, InviteLinks } from '../types/link-types.js'; +import type { AppState } from '../types/redux-types.js'; + +const primaryInviteLinksSelector: (state: AppState) => { + [communityID: string]: InviteLink, +} = createSelector( + (state: AppState) => state.inviteLinksStore.links, + (links: InviteLinks) => { + const primaryLinks = {}; + for (const communityID in links) { + const communityLinks = links[communityID]; + if (communityLinks.primaryLink) { + primaryLinks[communityID] = communityLinks.primaryLink; + } + } + return primaryLinks; + }, +); + +export { primaryInviteLinksSelector }; diff --git a/lib/types/link-types.js b/lib/types/link-types.js --- a/lib/types/link-types.js +++ b/lib/types/link-types.js @@ -43,3 +43,15 @@ export type FetchInviteLinksResponse = { +links: $ReadOnlyArray, }; + +export type CommunityLinks = { + +primaryLink: ?InviteLink, +}; + +export type InviteLinks = { + +[communityID: string]: CommunityLinks, +}; + +export type InviteLinksStore = { + +links: InviteLinks, +}; 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 @@ -38,6 +38,7 @@ import type { LifecycleState } from './lifecycle-state-types.js'; import type { FetchInviteLinksResponse, + InviteLinksStore, InviteLinkVerificationResponse, } from './link-types.js'; import type { LoadingStatus, LoadingInfo } from './loading-types.js'; @@ -124,6 +125,7 @@ userPolicies: UserPolicies, deviceToken: ?string, +commServicesAccessToken: ?string, + +inviteLinksStore: InviteLinksStore, ... }; 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 @@ -119,6 +119,9 @@ frozen: false, userPolicies: {}, commServicesAccessToken: null, + inviteLinksStore: { + links: {}, + }, }: AppState); function reducer(state: AppState = defaultState, action: Action) { 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 @@ -8,6 +8,7 @@ import type { EntryStore } from 'lib/types/entry-types.js'; import type { CalendarFilter } from 'lib/types/filter-types.js'; import type { LifecycleState } from 'lib/types/lifecycle-state-types.js'; +import type { InviteLinksStore } from 'lib/types/link-types.js'; import type { LoadingStatus } from 'lib/types/loading-types.js'; import type { MessageStore } from 'lib/types/message-types.js'; import type { UserPolicies } from 'lib/types/policy-types.js'; @@ -57,4 +58,5 @@ frozen: boolean, userPolicies: UserPolicies, +commServicesAccessToken: ?string, + +inviteLinksStore: InviteLinksStore, }; 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 @@ -22,6 +22,7 @@ import type { EntryStore } from 'lib/types/entry-types.js'; import { type CalendarFilter } from 'lib/types/filter-types.js'; import type { LifecycleState } from 'lib/types/lifecycle-state-types.js'; +import type { InviteLinksStore } from 'lib/types/link-types.js'; import type { LoadingStatus } from 'lib/types/loading-types.js'; import type { MessageStore } from 'lib/types/message-types.js'; import type { UserPolicies } from 'lib/types/policy-types.js'; @@ -95,6 +96,7 @@ pushApiPublicKey: ?string, _persist: ?PersistState, +commServicesAccessToken: ?string, + +inviteLinksStore: InviteLinksStore, }; export type Action =