diff --git a/packages/pl-fe/src/actions/accounts.ts b/packages/pl-fe/src/actions/accounts.ts index 4da5c5ee7..d20c14b46 100644 --- a/packages/pl-fe/src/actions/accounts.ts +++ b/packages/pl-fe/src/actions/accounts.ts @@ -38,10 +38,6 @@ const ACCOUNT_MUTE_REQUEST = 'ACCOUNT_MUTE_REQUEST' as const; const ACCOUNT_MUTE_SUCCESS = 'ACCOUNT_MUTE_SUCCESS' as const; const ACCOUNT_MUTE_FAIL = 'ACCOUNT_MUTE_FAIL' as const; -const PINNED_ACCOUNTS_FETCH_REQUEST = 'PINNED_ACCOUNTS_FETCH_REQUEST' as const; -const PINNED_ACCOUNTS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_FETCH_SUCCESS' as const; -const PINNED_ACCOUNTS_FETCH_FAIL = 'PINNED_ACCOUNTS_FETCH_FAIL' as const; - const ACCOUNT_SEARCH_REQUEST = 'ACCOUNT_SEARCH_REQUEST' as const; const ACCOUNT_SEARCH_SUCCESS = 'ACCOUNT_SEARCH_SUCCESS' as const; const ACCOUNT_SEARCH_FAIL = 'ACCOUNT_SEARCH_FAIL' as const; @@ -342,36 +338,6 @@ const updateNotificationSettings = (params: UpdateNotificationSettingsParams) => }); }; -const fetchPinnedAccounts = (accountId: string) => - (dispatch: AppDispatch, getState: () => RootState) => { - dispatch(fetchPinnedAccountsRequest(accountId)); - - return getClient(getState).accounts.getAccountEndorsements(accountId).then(response => { - dispatch(importEntities({ accounts: response })); - dispatch(fetchPinnedAccountsSuccess(accountId, response, null)); - }).catch(error => { - dispatch(fetchPinnedAccountsFail(accountId, error)); - }); - }; - -const fetchPinnedAccountsRequest = (accountId: string) => ({ - type: PINNED_ACCOUNTS_FETCH_REQUEST, - accountId, -}); - -const fetchPinnedAccountsSuccess = (accountId: string, accounts: Array, next: null) => ({ - type: PINNED_ACCOUNTS_FETCH_SUCCESS, - accountId, - accounts, - next, -}); - -const fetchPinnedAccountsFail = (accountId: string, error: unknown) => ({ - type: PINNED_ACCOUNTS_FETCH_FAIL, - accountId, - error, -}); - interface AccountSearchRequestAction { type: typeof ACCOUNT_SEARCH_REQUEST; params: { @@ -452,9 +418,6 @@ type AccountsAction = | NotificationSettingsRequestAction | NotificationSettingsSuccessAction | NotificationSettingsFailAction - | ReturnType - | ReturnType - | ReturnType | AccountSearchRequestAction | AccountSearchSuccessAction | AccountSearchFailAction @@ -475,9 +438,6 @@ export { ACCOUNT_MUTE_REQUEST, ACCOUNT_MUTE_SUCCESS, ACCOUNT_MUTE_FAIL, - PINNED_ACCOUNTS_FETCH_REQUEST, - PINNED_ACCOUNTS_FETCH_SUCCESS, - PINNED_ACCOUNTS_FETCH_FAIL, ACCOUNT_SEARCH_REQUEST, ACCOUNT_SEARCH_SUCCESS, ACCOUNT_SEARCH_FAIL, @@ -499,7 +459,6 @@ export { pinAccount, unpinAccount, updateNotificationSettings, - fetchPinnedAccounts, accountSearch, accountLookup, biteAccount, diff --git a/packages/pl-fe/src/actions/familiar-followers.ts b/packages/pl-fe/src/actions/familiar-followers.ts deleted file mode 100644 index c651abcf6..000000000 --- a/packages/pl-fe/src/actions/familiar-followers.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { AppDispatch, RootState } from 'pl-fe/store'; - -import { getClient } from '../api'; - -import { fetchRelationships } from './accounts'; -import { importEntities } from './importer'; - -import type { Account } from 'pl-api'; - -const FAMILIAR_FOLLOWERS_FETCH_REQUEST = 'FAMILIAR_FOLLOWERS_FETCH_REQUEST' as const; -const FAMILIAR_FOLLOWERS_FETCH_SUCCESS = 'FAMILIAR_FOLLOWERS_FETCH_SUCCESS' as const; -const FAMILIAR_FOLLOWERS_FETCH_FAIL = 'FAMILIAR_FOLLOWERS_FETCH_FAIL' as const; - -const fetchAccountFamiliarFollowers = (accountId: string) => (dispatch: AppDispatch, getState: () => RootState) => { - dispatch({ - type: FAMILIAR_FOLLOWERS_FETCH_REQUEST, - accountId, - }); - - getClient(getState()).accounts.getFamiliarFollowers([accountId]) - .then((data) => { - const accounts = data.find(({ id }: { id: string }) => id === accountId)!.accounts; - - dispatch(importEntities({ accounts })); - dispatch(fetchRelationships(accounts.map((item) => item.id))); - dispatch({ - type: FAMILIAR_FOLLOWERS_FETCH_SUCCESS, - accountId, - accounts, - }); - }) - .catch(error => dispatch({ - type: FAMILIAR_FOLLOWERS_FETCH_FAIL, - accountId, - error, - skipAlert: true, - })); -}; - -type FamiliarFollowersAction = - | { - type: typeof FAMILIAR_FOLLOWERS_FETCH_REQUEST; - accountId: string; - } - | { - type: typeof FAMILIAR_FOLLOWERS_FETCH_SUCCESS; - accountId: string; - accounts: Array; - } - | { - type: typeof FAMILIAR_FOLLOWERS_FETCH_FAIL; - accountId: string; - error: unknown; - skipAlert: true; - } - -export { - FAMILIAR_FOLLOWERS_FETCH_REQUEST, - FAMILIAR_FOLLOWERS_FETCH_SUCCESS, - FAMILIAR_FOLLOWERS_FETCH_FAIL, - fetchAccountFamiliarFollowers, - type FamiliarFollowersAction, -}; diff --git a/packages/pl-fe/src/api/hooks/account-lists/use-endorsed-accounts.ts b/packages/pl-fe/src/api/hooks/account-lists/use-endorsed-accounts.ts new file mode 100644 index 000000000..df02ab92a --- /dev/null +++ b/packages/pl-fe/src/api/hooks/account-lists/use-endorsed-accounts.ts @@ -0,0 +1,20 @@ +import { useQuery } from '@tanstack/react-query'; + +import { importEntities } from 'pl-fe/actions/importer'; +import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; +import { useClient } from 'pl-fe/hooks/use-client'; + +const useEndorsedAccounts = (accountId: string) => { + const client = useClient(); + const dispatch = useAppDispatch(); + + return useQuery({ + queryKey: ['accountsLists', 'endorsedAccounts', accountId], + queryFn: () => client.accounts.getAccountEndorsements(accountId).then((accounts) => { + dispatch(importEntities({ accounts })); + return accounts.map(({ id }) => id); + }), + }); +}; + +export { useEndorsedAccounts }; diff --git a/packages/pl-fe/src/api/hooks/account-lists/use-familiar-followers.ts b/packages/pl-fe/src/api/hooks/account-lists/use-familiar-followers.ts new file mode 100644 index 000000000..eeece0d65 --- /dev/null +++ b/packages/pl-fe/src/api/hooks/account-lists/use-familiar-followers.ts @@ -0,0 +1,28 @@ +import { useQuery } from '@tanstack/react-query'; + +import { importEntities } from 'pl-fe/actions/importer'; +import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; +import { useClient } from 'pl-fe/hooks/use-client'; +import { useFeatures } from 'pl-fe/hooks/use-features'; +import { useLoggedIn } from 'pl-fe/hooks/use-logged-in'; + +const useFamiliarFollowers = (accountId: string) => { + const client = useClient(); + const dispatch = useAppDispatch(); + const features = useFeatures(); + const { isLoggedIn } = useLoggedIn(); + + return useQuery({ + queryKey: ['accountsLists', 'endorsedAccounts', accountId], + queryFn: () => client.accounts.getFamiliarFollowers([accountId]).then((response) => { + const result = response.find(({ id }) => id === accountId); + if (!result) return []; + + dispatch(importEntities({ accounts: result.accounts })); + return result.accounts.map(({ id }) => id); + }), + enabled: isLoggedIn && features.familiarFollowers, + }); +}; + +export { useFamiliarFollowers }; diff --git a/packages/pl-fe/src/features/ui/components/modals/familiar-followers-modal.tsx b/packages/pl-fe/src/features/ui/components/modals/familiar-followers-modal.tsx index d90147511..520f73756 100644 --- a/packages/pl-fe/src/features/ui/components/modals/familiar-followers-modal.tsx +++ b/packages/pl-fe/src/features/ui/components/modals/familiar-followers-modal.tsx @@ -1,6 +1,7 @@ import React, { useRef } from 'react'; import { FormattedMessage } from 'react-intl'; +import { useFamiliarFollowers } from 'pl-fe/api/hooks/account-lists/use-familiar-followers'; import ScrollableList from 'pl-fe/components/scrollable-list'; import Modal from 'pl-fe/components/ui/modal'; import Spinner from 'pl-fe/components/ui/spinner'; @@ -20,7 +21,7 @@ interface FamiliarFollowersModalProps { const FamiliarFollowersModal: React.FC = ({ accountId, onClose }) => { const modalRef = useRef(null); const account = useAppSelector(state => getAccount(state, accountId)); - const familiarFollowerIds = useAppSelector(state => state.user_lists.familiar_followers[accountId]?.items || []); + const { data: familiarFollowerIds } = useFamiliarFollowers(accountId); const onClickClose = () => { onClose('FAMILIAR_FOLLOWERS'); diff --git a/packages/pl-fe/src/features/ui/components/panels/pinned-accounts-panel.tsx b/packages/pl-fe/src/features/ui/components/panels/pinned-accounts-panel.tsx index b4b7a5582..e2fe888cb 100644 --- a/packages/pl-fe/src/features/ui/components/panels/pinned-accounts-panel.tsx +++ b/packages/pl-fe/src/features/ui/components/panels/pinned-accounts-panel.tsx @@ -1,13 +1,11 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import { FormattedMessage } from 'react-intl'; -import { fetchPinnedAccounts } from 'pl-fe/actions/accounts'; +import { useEndorsedAccounts } from 'pl-fe/api/hooks/account-lists/use-endorsed-accounts'; import Widget from 'pl-fe/components/ui/widget'; import AccountContainer from 'pl-fe/containers/account-container'; import Emojify from 'pl-fe/features/emoji/emojify'; import { WhoToFollowPanel } from 'pl-fe/features/ui/util/async-components'; -import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; -import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; import type { Account } from 'pl-fe/normalizers/account'; @@ -17,12 +15,7 @@ interface IPinnedAccountsPanel { } const PinnedAccountsPanel: React.FC = ({ account, limit }) => { - const dispatch = useAppDispatch(); - const pinned = useAppSelector((state) => state.user_lists.pinned[account.id]?.items || []).slice(0, limit); - - useEffect(() => { - dispatch(fetchPinnedAccounts(account.id)); - }, []); + const { data: pinned = [] } = useEndorsedAccounts(accountId); if (!pinned.length) { return ( diff --git a/packages/pl-fe/src/features/ui/components/profile-familiar-followers.tsx b/packages/pl-fe/src/features/ui/components/profile-familiar-followers.tsx index 6730f1eaf..e31fc4beb 100644 --- a/packages/pl-fe/src/features/ui/components/profile-familiar-followers.tsx +++ b/packages/pl-fe/src/features/ui/components/profile-familiar-followers.tsx @@ -1,17 +1,15 @@ -import React, { useEffect } from 'react'; +import React from 'react'; import { FormattedList, FormattedMessage } from 'react-intl'; import { Link } from 'react-router-dom'; -import { fetchAccountFamiliarFollowers } from 'pl-fe/actions/familiar-followers'; +import { useFamiliarFollowers } from 'pl-fe/api/hooks/account-lists/use-familiar-followers'; import AvatarStack from 'pl-fe/components/avatar-stack'; import HoverAccountWrapper from 'pl-fe/components/hover-account-wrapper'; import HStack from 'pl-fe/components/ui/hstack'; import Text from 'pl-fe/components/ui/text'; import VerificationBadge from 'pl-fe/components/verification-badge'; import Emojify from 'pl-fe/features/emoji/emojify'; -import { useAppDispatch } from 'pl-fe/hooks/use-app-dispatch'; import { useAppSelector } from 'pl-fe/hooks/use-app-selector'; -import { useFeatures } from 'pl-fe/hooks/use-features'; import { makeGetAccount } from 'pl-fe/selectors'; import { useModalsStore } from 'pl-fe/stores/modals'; @@ -25,18 +23,9 @@ interface IProfileFamiliarFollowers { const ProfileFamiliarFollowers: React.FC = ({ account }) => { const { openModal } = useModalsStore(); - const dispatch = useAppDispatch(); - const me = useAppSelector((state) => state.me); - const features = useFeatures(); - const familiarFollowerIds = useAppSelector(state => state.user_lists.familiar_followers[account.id]?.items || []); + const { data: familiarFollowerIds = [] } = useFamiliarFollowers(account.id); const familiarFollowers = useAppSelector(state => familiarFollowerIds.slice(0, 2).map(accountId => getAccount(state, accountId))); - useEffect(() => { - if (me && features.familiarFollowers) { - dispatch(fetchAccountFamiliarFollowers(account.id)); - } - }, [account.id]); - const openFamiliarFollowersModal = () => { openModal('FAMILIAR_FOLLOWERS', { accountId: account.id, diff --git a/packages/pl-fe/src/reducers/user-lists.test.ts b/packages/pl-fe/src/reducers/user-lists.test.ts index a42d8c31f..bcb2bfa8f 100644 --- a/packages/pl-fe/src/reducers/user-lists.test.ts +++ b/packages/pl-fe/src/reducers/user-lists.test.ts @@ -1,20 +1,9 @@ -import { OrderedSet as ImmutableOrderedSet } from 'immutable'; - import reducer from './user-lists'; describe('user_lists reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {} as any)).toMatchObject({ - followers: {}, - following: {}, - reblogged_by: {}, - favourited_by: {}, - reactions: {}, - follow_requests: { next: null, items: ImmutableOrderedSet(), isLoading: false }, - blocks: { next: null, items: ImmutableOrderedSet(), isLoading: false }, - mutes: { next: null, items: ImmutableOrderedSet(), isLoading: false }, - pinned: {}, - familiar_followers: {}, + group_blocks: {}, }); }); }); diff --git a/packages/pl-fe/src/reducers/user-lists.ts b/packages/pl-fe/src/reducers/user-lists.ts index 3a1412f6f..857d7d810 100644 --- a/packages/pl-fe/src/reducers/user-lists.ts +++ b/packages/pl-fe/src/reducers/user-lists.ts @@ -1,7 +1,5 @@ import { create } from 'mutative'; -import { PINNED_ACCOUNTS_FETCH_SUCCESS, type AccountsAction } from 'pl-fe/actions/accounts'; -import { FAMILIAR_FOLLOWERS_FETCH_SUCCESS, type FamiliarFollowersAction } from 'pl-fe/actions/familiar-followers'; import { GROUP_BLOCKS_FETCH_REQUEST, GROUP_BLOCKS_FETCH_SUCCESS, @@ -18,13 +16,11 @@ interface List { isLoading: boolean; } -type NestedListKey = 'pinned' | 'familiar_followers' | 'group_blocks'; +type NestedListKey = 'group_blocks'; type State = Record>; const initialState: State = { - pinned: {}, - familiar_followers: {}, group_blocks: {}, }; @@ -37,12 +33,8 @@ const normalizeList = (state: State, path: NestedListPath, accounts: Array { +const userLists = (state = initialState, action: GroupsAction): State => { switch (action.type) { - case PINNED_ACCOUNTS_FETCH_SUCCESS: - return normalizeList(state, ['pinned', action.accountId], action.accounts, action.next); - case FAMILIAR_FOLLOWERS_FETCH_SUCCESS: - return normalizeList(state, ['familiar_followers', action.accountId], action.accounts); case GROUP_BLOCKS_FETCH_SUCCESS: return normalizeList(state, ['group_blocks', action.groupId], action.accounts, action.next); case GROUP_BLOCKS_FETCH_REQUEST: