pl-fe: migrate more to tanstack query
Signed-off-by: mkljczk <git@mkljczk.pl>
This commit is contained in:
parent
86e38c391c
commit
d286c34ae0
9 changed files with 59 additions and 151 deletions
|
@ -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<Account>, 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<typeof fetchPinnedAccountsRequest>
|
||||
| ReturnType<typeof fetchPinnedAccountsSuccess>
|
||||
| ReturnType<typeof fetchPinnedAccountsFail>
|
||||
| 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,
|
||||
|
|
|
@ -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<FamiliarFollowersAction>({
|
||||
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<FamiliarFollowersAction>({
|
||||
type: FAMILIAR_FOLLOWERS_FETCH_SUCCESS,
|
||||
accountId,
|
||||
accounts,
|
||||
});
|
||||
})
|
||||
.catch(error => dispatch<FamiliarFollowersAction>({
|
||||
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<Account>;
|
||||
}
|
||||
| {
|
||||
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,
|
||||
};
|
|
@ -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 };
|
|
@ -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 };
|
|
@ -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<BaseModalProps & FamiliarFollowersModalProps> = ({ accountId, onClose }) => {
|
||||
const modalRef = useRef<HTMLDivElement>(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');
|
||||
|
|
|
@ -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<IPinnedAccountsPanel> = ({ 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 (
|
||||
|
|
|
@ -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<IProfileFamiliarFollowers> = ({ 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,
|
||||
|
|
|
@ -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: {},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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<NestedListKey, Record<string, List>>;
|
||||
|
||||
const initialState: State = {
|
||||
pinned: {},
|
||||
familiar_followers: {},
|
||||
group_blocks: {},
|
||||
};
|
||||
|
||||
|
@ -37,12 +33,8 @@ const normalizeList = (state: State, path: NestedListPath, accounts: Array<Pick<
|
|||
draft[path[0]][path[1]] = newList;
|
||||
});
|
||||
|
||||
const userLists = (state = initialState, action: AccountsAction | FamiliarFollowersAction | GroupsAction): State => {
|
||||
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:
|
||||
|
|
Loading…
Reference in a new issue