Remove account_counters reducer and legacy follow actions

environments/review-change-ent-6o2wvy/deployments/3528
Alex Gleason 1 year ago
parent ad1718b5f9
commit 75dbeb65b6
No known key found for this signature in database
GPG Key ID: 7211D1F99744FBB7

@ -19,12 +19,10 @@ import {
fetchFollowing,
fetchFollowRequests,
fetchRelationships,
followAccount,
muteAccount,
removeFromFollowers,
subscribeAccount,
unblockAccount,
unfollowAccount,
unmuteAccount,
unsubscribeAccount,
} from '../accounts';
@ -381,169 +379,6 @@ describe('fetchAccountByUsername()', () => {
});
});
describe('followAccount()', () => {
describe('when logged out', () => {
beforeEach(() => {
const state = rootState.set('me', null);
store = mockStore(state);
});
it('should do nothing', async() => {
await store.dispatch(followAccount('1'));
const actions = store.getActions();
expect(actions).toEqual([]);
});
});
describe('when logged in', () => {
const id = '1';
beforeEach(() => {
const state = rootState.set('me', '123');
store = mockStore(state);
});
describe('with a successful API request', () => {
beforeEach(() => {
__stub((mock) => {
mock.onPost(`/api/v1/accounts/${id}/follow`).reply(200, { success: true });
});
});
it('should dispatch the correct actions', async() => {
const expectedActions = [
{
type: 'ACCOUNT_FOLLOW_REQUEST',
id,
locked: false,
skipLoading: true,
},
{
type: 'ACCOUNT_FOLLOW_SUCCESS',
relationship: { success: true },
alreadyFollowing: undefined,
skipLoading: true,
},
];
await store.dispatch(followAccount(id));
const actions = store.getActions();
expect(actions).toEqual(expectedActions);
});
});
describe('with an unsuccessful API request', () => {
beforeEach(() => {
__stub((mock) => {
mock.onPost(`/api/v1/accounts/${id}/follow`).networkError();
});
});
it('should dispatch the correct actions', async() => {
const expectedActions = [
{
type: 'ACCOUNT_FOLLOW_REQUEST',
id,
locked: false,
skipLoading: true,
},
{
type: 'ACCOUNT_FOLLOW_FAIL',
error: new Error('Network Error'),
locked: false,
skipLoading: true,
},
];
try {
await store.dispatch(followAccount(id));
} catch (e) {
const actions = store.getActions();
expect(actions).toEqual(expectedActions);
expect(e).toEqual(new Error('Network Error'));
}
});
});
});
});
describe('unfollowAccount()', () => {
describe('when logged out', () => {
beforeEach(() => {
const state = rootState.set('me', null);
store = mockStore(state);
});
it('should do nothing', async() => {
await store.dispatch(unfollowAccount('1'));
const actions = store.getActions();
expect(actions).toEqual([]);
});
});
describe('when logged in', () => {
const id = '1';
beforeEach(() => {
const state = rootState.set('me', '123');
store = mockStore(state);
});
describe('with a successful API request', () => {
beforeEach(() => {
__stub((mock) => {
mock.onPost(`/api/v1/accounts/${id}/unfollow`).reply(200, { success: true });
});
});
it('should dispatch the correct actions', async() => {
const expectedActions = [
{ type: 'ACCOUNT_UNFOLLOW_REQUEST', id: '1', skipLoading: true },
{
type: 'ACCOUNT_UNFOLLOW_SUCCESS',
relationship: { success: true },
statuses: ImmutableMap({}),
skipLoading: true,
},
];
await store.dispatch(unfollowAccount(id));
const actions = store.getActions();
expect(actions).toEqual(expectedActions);
});
});
describe('with an unsuccessful API request', () => {
beforeEach(() => {
__stub((mock) => {
mock.onPost(`/api/v1/accounts/${id}/unfollow`).networkError();
});
});
it('should dispatch the correct actions', async() => {
const expectedActions = [
{
type: 'ACCOUNT_UNFOLLOW_REQUEST',
id,
skipLoading: true,
},
{
type: 'ACCOUNT_UNFOLLOW_FAIL',
error: new Error('Network Error'),
skipLoading: true,
},
];
await store.dispatch(unfollowAccount(id));
const actions = store.getActions();
expect(actions).toEqual(expectedActions);
});
});
});
});
describe('blockAccount()', () => {
const id = '1';

@ -23,14 +23,6 @@ const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS';
const ACCOUNT_FETCH_FAIL = 'ACCOUNT_FETCH_FAIL';
const ACCOUNT_FOLLOW_REQUEST = 'ACCOUNT_FOLLOW_REQUEST';
const ACCOUNT_FOLLOW_SUCCESS = 'ACCOUNT_FOLLOW_SUCCESS';
const ACCOUNT_FOLLOW_FAIL = 'ACCOUNT_FOLLOW_FAIL';
const ACCOUNT_UNFOLLOW_REQUEST = 'ACCOUNT_UNFOLLOW_REQUEST';
const ACCOUNT_UNFOLLOW_SUCCESS = 'ACCOUNT_UNFOLLOW_SUCCESS';
const ACCOUNT_UNFOLLOW_FAIL = 'ACCOUNT_UNFOLLOW_FAIL';
const ACCOUNT_BLOCK_REQUEST = 'ACCOUNT_BLOCK_REQUEST';
const ACCOUNT_BLOCK_SUCCESS = 'ACCOUNT_BLOCK_SUCCESS';
const ACCOUNT_BLOCK_FAIL = 'ACCOUNT_BLOCK_FAIL';
@ -227,81 +219,6 @@ const fetchAccountFail = (id: string | null, error: AxiosError) => ({
skipAlert: true,
});
type FollowAccountOpts = {
reblogs?: boolean
notify?: boolean
};
const followAccount = (id: string, options?: FollowAccountOpts) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return null;
const alreadyFollowing = getState().relationships.get(id)?.following || undefined;
const locked = getState().accounts.get(id)?.locked || false;
dispatch(followAccountRequest(id, locked));
return api(getState)
.post(`/api/v1/accounts/${id}/follow`, options)
.then(response => dispatch(followAccountSuccess(response.data, alreadyFollowing)))
.catch(error => {
dispatch(followAccountFail(error, locked));
throw error;
});
};
const unfollowAccount = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return null;
dispatch(unfollowAccountRequest(id));
return api(getState)
.post(`/api/v1/accounts/${id}/unfollow`)
.then(response => dispatch(unfollowAccountSuccess(response.data, getState().statuses)))
.catch(error => dispatch(unfollowAccountFail(error)));
};
const followAccountRequest = (id: string, locked: boolean) => ({
type: ACCOUNT_FOLLOW_REQUEST,
id,
locked,
skipLoading: true,
});
const followAccountSuccess = (relationship: APIEntity, alreadyFollowing?: boolean) => ({
type: ACCOUNT_FOLLOW_SUCCESS,
relationship,
alreadyFollowing,
skipLoading: true,
});
const followAccountFail = (error: AxiosError, locked: boolean) => ({
type: ACCOUNT_FOLLOW_FAIL,
error,
locked,
skipLoading: true,
});
const unfollowAccountRequest = (id: string) => ({
type: ACCOUNT_UNFOLLOW_REQUEST,
id,
skipLoading: true,
});
const unfollowAccountSuccess = (relationship: APIEntity, statuses: ImmutableMap<string, Status>) => ({
type: ACCOUNT_UNFOLLOW_SUCCESS,
relationship,
statuses,
skipLoading: true,
});
const unfollowAccountFail = (error: AxiosError) => ({
type: ACCOUNT_UNFOLLOW_FAIL,
error,
skipLoading: true,
});
const blockAccount = (id: string) =>
(dispatch: AppDispatch, getState: () => RootState) => {
if (!isLoggedIn(getState)) return null;
@ -988,12 +905,6 @@ export {
ACCOUNT_FETCH_REQUEST,
ACCOUNT_FETCH_SUCCESS,
ACCOUNT_FETCH_FAIL,
ACCOUNT_FOLLOW_REQUEST,
ACCOUNT_FOLLOW_SUCCESS,
ACCOUNT_FOLLOW_FAIL,
ACCOUNT_UNFOLLOW_REQUEST,
ACCOUNT_UNFOLLOW_SUCCESS,
ACCOUNT_UNFOLLOW_FAIL,
ACCOUNT_BLOCK_REQUEST,
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_BLOCK_FAIL,
@ -1069,14 +980,6 @@ export {
fetchAccountRequest,
fetchAccountSuccess,
fetchAccountFail,
followAccount,
unfollowAccount,
followAccountRequest,
followAccountSuccess,
followAccountFail,
unfollowAccountRequest,
unfollowAccountSuccess,
unfollowAccountFail,
blockAccount,
unblockAccount,
blockAccountRequest,

@ -1,5 +1,6 @@
import { Entities } from 'soapbox/entity-store/entities';
import { useChangeEntity } from 'soapbox/entity-store/hooks';
import { useLoggedIn } from 'soapbox/hooks';
import { useApi } from 'soapbox/hooks/useApi';
import { type Account } from 'soapbox/schemas';
@ -8,8 +9,15 @@ function useChangeAccount() {
return { changeAccount };
}
interface FollowOpts {
reblogs?: boolean
notify?: boolean
languages?: string[]
}
function useFollow() {
const api = useApi();
const { isLoggedIn } = useLoggedIn();
const { changeAccount } = useChangeAccount();
function incrementFollowers(accountId: string) {
@ -26,7 +34,8 @@ function useFollow() {
}));
}
async function follow(accountId: string, options = {}) {
async function follow(accountId: string, options: FollowOpts = {}) {
if (!isLoggedIn) return;
incrementFollowers(accountId);
try {
@ -36,11 +45,12 @@ function useFollow() {
}
}
async function unfollow(accountId: string, options = {}) {
async function unfollow(accountId: string) {
if (!isLoggedIn) return;
decrementFollowers(accountId);
try {
await api.post(`/api/v1/accounts/${accountId}/unfollow`, options);
await api.post(`/api/v1/accounts/${accountId}/unfollow`);
} catch (e) {
incrementFollowers(accountId);
}

@ -7,7 +7,7 @@ import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useHistory } from 'react-router-dom';
import { blockAccount, followAccount, pinAccount, removeFromFollowers, unblockAccount, unmuteAccount, unpinAccount } from 'soapbox/actions/accounts';
import { blockAccount, pinAccount, removeFromFollowers, unblockAccount, unmuteAccount, unpinAccount } from 'soapbox/actions/accounts';
import { mentionCompose, directCompose } from 'soapbox/actions/compose';
import { blockDomain, unblockDomain } from 'soapbox/actions/domain-blocks';
import { openModal } from 'soapbox/actions/modals';
@ -15,6 +15,7 @@ import { initMuteModal } from 'soapbox/actions/mutes';
import { initReport, ReportableEntities } from 'soapbox/actions/reports';
import { setSearchAccount } from 'soapbox/actions/search';
import { getSettings } from 'soapbox/actions/settings';
import { useFollow } from 'soapbox/api/hooks';
import Badge from 'soapbox/components/badge';
import DropdownMenu, { Menu } from 'soapbox/components/dropdown-menu';
import StillImage from 'soapbox/components/still-image';
@ -87,6 +88,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
const features = useFeatures();
const ownAccount = useOwnAccount();
const { follow } = useFollow();
const { software } = useAppSelector((state) => parseVersion(state.instance.version));
@ -154,9 +156,9 @@ const Header: React.FC<IHeader> = ({ account }) => {
const onReblogToggle = () => {
if (account.relationship?.showing_reblogs) {
dispatch(followAccount(account.id, { reblogs: false }));
follow(account.id, { reblogs: false });
} else {
dispatch(followAccount(account.id, { reblogs: true }));
follow(account.id, { reblogs: true });
}
};

@ -2,8 +2,6 @@ import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import {
followAccount,
unfollowAccount,
blockAccount,
unblockAccount,
muteAccount,
@ -12,8 +10,9 @@ import {
rejectFollowRequest,
} from 'soapbox/actions/accounts';
import { openModal } from 'soapbox/actions/modals';
import { useFollow } from 'soapbox/api/hooks';
import { Button, HStack } from 'soapbox/components/ui';
import { useAppDispatch, useAppSelector, useFeatures } from 'soapbox/hooks';
import { useAppDispatch, useFeatures, useLoggedIn } from 'soapbox/hooks';
import type { Account } from 'soapbox/schemas';
import type { Account as AccountEntity } from 'soapbox/types/entities';
@ -53,13 +52,14 @@ const ActionButton: React.FC<IActionButton> = ({ account, actionType, small }) =
const features = useFeatures();
const intl = useIntl();
const me = useAppSelector((state) => state.me);
const { isLoggedIn, me } = useLoggedIn();
const { follow, unfollow } = useFollow();
const handleFollow = () => {
if (account.relationship?.following || account.relationship?.requested) {
dispatch(unfollowAccount(account.id));
unfollow(account.id);
} else {
dispatch(followAccount(account.id));
follow(account.id);
}
};
@ -187,7 +187,7 @@ const ActionButton: React.FC<IActionButton> = ({ account, actionType, small }) =
return null;
};
if (!me) {
if (!isLoggedIn) {
return renderLoggedOut();
}

@ -2,10 +2,10 @@ import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import {
followAccount,
subscribeAccount,
unsubscribeAccount,
} from 'soapbox/actions/accounts';
import { useFollow } from 'soapbox/api/hooks';
import { IconButton } from 'soapbox/components/ui';
import { useAppDispatch, useFeatures } from 'soapbox/hooks';
import toast from 'soapbox/toast';
@ -29,6 +29,7 @@ const SubscriptionButton = ({ account }: ISubscriptionButton) => {
const dispatch = useAppDispatch();
const features = useFeatures();
const intl = useIntl();
const { follow } = useFollow();
const isFollowing = account.relationship?.following;
const isRequested = account.relationship?.requested;
@ -53,11 +54,11 @@ const SubscriptionButton = ({ account }: ISubscriptionButton) => {
const onNotifyToggle = () => {
if (account.relationship?.notifying) {
dispatch(followAccount(account.id, { notify: false } as any))
follow(account.id, { notify: false })
?.then(() => onUnsubscribeSuccess())
.catch(() => onUnsubscribeFailure());
} else {
dispatch(followAccount(account.id, { notify: true } as any))
follow(account.id, { notify: true })
?.then(() => onSubscribeSuccess())
.catch(() => onSubscribeFailure());
}

@ -13,6 +13,7 @@ export { useFeatures } from './useFeatures';
export { useInstance } from './useInstance';
export { useLoading } from './useLoading';
export { useLocale } from './useLocale';
export { useLoggedIn } from './useLoggedIn';
export { useOnScreen } from './useOnScreen';
export { useOwnAccount } from './useOwnAccount';
export { usePrevious } from './usePrevious';

@ -0,0 +1,13 @@
import { useAppSelector } from './useAppSelector';
function useLoggedIn() {
const me = useAppSelector(state => state.me);
return {
isLoggedIn: typeof me === 'string',
isLoginLoading: me === null,
isLoginFailed: me === false,
me,
};
}
export { useLoggedIn };

@ -1,37 +0,0 @@
import { Map as ImmutableMap } from 'immutable';
import reducer from '../accounts-counters';
// import { ACCOUNT_FOLLOW_SUCCESS, ACCOUNT_UNFOLLOW_SUCCESS } from 'soapbox/actions/accounts';
// import relationship from 'soapbox/__fixtures__/relationship.json';
// import accounts_counter_initial from 'soapbox/__fixtures__/accounts_counter_initial.json';
// import accounts_counter_unfollow from 'soapbox/__fixtures__/accounts_counter_unfollow.json';
// import accounts_counter_follow from 'soapbox/__fixtures__/accounts_counter_follow.json';
describe('accounts_counters reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {} as any)).toEqual(ImmutableMap());
});
// it('should handle ACCOUNT_FOLLOW_SUCCESS', () => {
// const state = ImmutableList([accounts_counter_initial]);
// const action = {
// type: ACCOUNT_FOLLOW_SUCCESS,
// relationship: relationship,
// alreadyFollowing: false,
// };
// expect(reducer(state, action)).toEqual(
// ImmutableList([ accounts_counter_follow ]));
// });
//
// it('should handle ACCOUNT_UNFOLLOW_SUCCESS', () => {
// const state = ImmutableList([accounts_counter_initial]);
// const action = {
// type: ACCOUNT_UNFOLLOW_SUCCESS,
// relationship: relationship,
// alreadyFollowing: true,
// };
// expect(reducer(state, action)).toEqual(
// ImmutableList([accounts_counter_unfollow]));
// });
});

@ -1,64 +0,0 @@
import { List as ImmutableList, Map as ImmutableMap, Record as ImmutableRecord } from 'immutable';
import {
ACCOUNT_FOLLOW_SUCCESS,
ACCOUNT_UNFOLLOW_SUCCESS,
} from 'soapbox/actions/accounts';
import { ACCOUNT_IMPORT, ACCOUNTS_IMPORT } from 'soapbox/actions/importer';
import { STREAMING_FOLLOW_RELATIONSHIPS_UPDATE } from 'soapbox/actions/streaming';
import type { AnyAction } from 'redux';
import type { APIEntity } from 'soapbox/types/entities';
const CounterRecord = ImmutableRecord({
followers_count: 0,
following_count: 0,
statuses_count: 0,
});
type Counter = ReturnType<typeof CounterRecord>;
type State = ImmutableMap<string, Counter>;
type APIEntities = Array<APIEntity>;
const normalizeAccount = (state: State, account: APIEntity) => state.set(account.id, CounterRecord({
followers_count: account.followers_count,
following_count: account.following_count,
statuses_count: account.statuses_count,
}));
const normalizeAccounts = (state: State, accounts: ImmutableList<APIEntities>) => {
accounts.forEach(account => {
state = normalizeAccount(state, account);
});
return state;
};
const updateFollowCounters = (state: State, counterUpdates: APIEntities) => {
return state.withMutations(state => {
counterUpdates.forEach((counterUpdate) => {
state.update(counterUpdate.id, CounterRecord(), counters => counters.merge({
followers_count: counterUpdate.follower_count,
following_count: counterUpdate.following_count,
}));
});
});
};
export default function accountsCounters(state: State = ImmutableMap<string, Counter>(), action: AnyAction) {
switch (action.type) {
case ACCOUNT_IMPORT:
return normalizeAccount(state, action.account);
case ACCOUNTS_IMPORT:
return normalizeAccounts(state, action.accounts);
case ACCOUNT_FOLLOW_SUCCESS:
return action.alreadyFollowing ? state :
state.updateIn([action.relationship.id, 'followers_count'], 0, (count) => typeof count === 'number' ? count + 1 : 0);
case ACCOUNT_UNFOLLOW_SUCCESS:
return state.updateIn([action.relationship.id, 'followers_count'], 0, (count) => typeof count === 'number' ? Math.max(0, count - 1) : 0);
case STREAMING_FOLLOW_RELATIONSHIPS_UPDATE:
return updateFollowCounters(state, [action.follower, action.following]);
default:
return state;
}
}

@ -9,7 +9,6 @@ import entities from 'soapbox/entity-store/reducer';
import { immutableizeStore, type LegacyStore } from 'soapbox/utils/legacy';
import account_notes from './account-notes';
import accounts_counters from './accounts-counters';
import accounts_meta from './accounts-meta';
import admin from './admin';
import admin_announcements from './admin-announcements';
@ -78,7 +77,6 @@ import type { Account } from 'soapbox/schemas';
const reducers = {
accounts: ((state: any = {}) => state) as (state: any) => EntityStore<Account> & LegacyStore<Account>,
account_notes,
accounts_counters,
accounts_meta,
admin,
admin_announcements,

@ -6,12 +6,6 @@ import { type Relationship, relationshipSchema } from 'soapbox/schemas';
import { ACCOUNT_NOTE_SUBMIT_SUCCESS } from '../actions/account-notes';
import {
ACCOUNT_FOLLOW_SUCCESS,
ACCOUNT_FOLLOW_REQUEST,
ACCOUNT_FOLLOW_FAIL,
ACCOUNT_UNFOLLOW_SUCCESS,
ACCOUNT_UNFOLLOW_REQUEST,
ACCOUNT_UNFOLLOW_FAIL,
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_UNBLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
@ -101,16 +95,16 @@ export default function relationships(state: State = ImmutableMap<string, Relati
return importPleromaAccount(state, action.account);
case ACCOUNTS_IMPORT:
return importPleromaAccounts(state, action.accounts);
case ACCOUNT_FOLLOW_REQUEST:
return state.setIn([action.id, 'following'], true);
case ACCOUNT_FOLLOW_FAIL:
return state.setIn([action.id, 'following'], false);
case ACCOUNT_UNFOLLOW_REQUEST:
return state.setIn([action.id, 'following'], false);
case ACCOUNT_UNFOLLOW_FAIL:
return state.setIn([action.id, 'following'], true);
case ACCOUNT_FOLLOW_SUCCESS:
case ACCOUNT_UNFOLLOW_SUCCESS:
// case ACCOUNT_FOLLOW_REQUEST:
// return state.setIn([action.id, 'following'], true);
// case ACCOUNT_FOLLOW_FAIL:
// return state.setIn([action.id, 'following'], false);
// case ACCOUNT_UNFOLLOW_REQUEST:
// return state.setIn([action.id, 'following'], false);
// case ACCOUNT_UNFOLLOW_FAIL:
// return state.setIn([action.id, 'following'], true);
// case ACCOUNT_FOLLOW_SUCCESS:
// case ACCOUNT_UNFOLLOW_SUCCESS:
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_UNBLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:

@ -10,7 +10,6 @@ import sample from 'lodash/sample';
import {
ACCOUNT_BLOCK_SUCCESS,
ACCOUNT_MUTE_SUCCESS,
ACCOUNT_UNFOLLOW_SUCCESS,
} from '../actions/accounts';
import {
STATUS_CREATE_REQUEST,
@ -204,11 +203,11 @@ const buildReferencesTo = (statuses: ImmutableMap<string, Status>, status: Statu
.map(statusToReference) as ImmutableMap<string, [string, string]>
);
const filterTimeline = (state: State, timelineId: string, relationship: APIEntity, statuses: ImmutableList<ImmutableMap<string, any>>) =>
state.updateIn([timelineId, 'items'], ImmutableOrderedSet(), (ids) =>
(ids as ImmutableOrderedSet<string>).filterNot(statusId =>
statuses.getIn([statusId, 'account']) === relationship.id,
));
// const filterTimeline = (state: State, timelineId: string, relationship: APIEntity, statuses: ImmutableList<ImmutableMap<string, any>>) =>
// state.updateIn([timelineId, 'items'], ImmutableOrderedSet(), (ids) =>
// (ids as ImmutableOrderedSet<string>).filterNot(statusId =>
// statuses.getIn([statusId, 'account']) === relationship.id,
// ));
const filterTimelines = (state: State, relationship: APIEntity, statuses: ImmutableMap<string, Status>) => {
return state.withMutations(state => {
@ -356,8 +355,8 @@ export default function timelines(state: State = initialState, action: AnyAction
case ACCOUNT_BLOCK_SUCCESS:
case ACCOUNT_MUTE_SUCCESS:
return filterTimelines(state, action.relationship, action.statuses);
case ACCOUNT_UNFOLLOW_SUCCESS:
return filterTimeline(state, 'home', action.relationship, action.statuses);
// case ACCOUNT_UNFOLLOW_SUCCESS:
// return filterTimeline(state, 'home', action.relationship, action.statuses);
case TIMELINE_SCROLL_TOP:
return updateTop(state, action.timeline, action.top);
case TIMELINE_CONNECT:

@ -22,7 +22,6 @@ import type { Filter as FilterEntity, Notification, Status, Group } from 'soapbo
const normalizeId = (id: any): string => typeof id === 'string' ? id : '';
const getAccountBase = (state: RootState, id: string) => state.accounts.get(id);
const getAccountCounters = (state: RootState, id: string) => state.accounts_counters.get(id);
const getAccountRelationship = (state: RootState, id: string) => state.relationships.get(id);
const getAccountMoved = (state: RootState, id: string) => state.accounts.get(state.accounts.get(id)?.moved || '');
const getAccountMeta = (state: RootState, id: string) => state.accounts_meta.get(id);
@ -35,13 +34,12 @@ const getAccountPatron = (state: RootState, id: string) => {
export const makeGetAccount = () => {
return createSelector([
getAccountBase,
getAccountCounters,
getAccountRelationship,
getAccountMoved,
getAccountMeta,
getAccountAdminData,
getAccountPatron,
], (base, counters, relationship, moved, meta, admin, patron) => {
], (base, relationship, moved, meta, admin, patron) => {
if (!base) return null;
base.relationship = base.relationship ?? relationship;
return base;

Loading…
Cancel
Save