pl-fe: more migrations

Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
This commit is contained in:
Nicole Mikołajczyk
2025-05-05 22:05:28 +02:00
parent afeb743ec3
commit 2d4892cc1e
8 changed files with 83 additions and 114 deletions

View File

@ -1,79 +0,0 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import { Entities } from 'pl-fe/entity-store/entities';
import { useClient } from 'pl-fe/hooks/use-client';
import { type Account, normalizeAccount } from 'pl-fe/normalizers/account';
import { flattenPages } from 'pl-fe/utils/queries';
import { useRelationships } from './use-relationships';
import type { PaginatedResponse, Account as BaseAccount } from 'pl-api';
import type { EntityFn } from 'pl-fe/entity-store/hooks/types';
const useAccountList = (listKey: string[], entityFn: EntityFn<void>) => {
const getAccounts = async (pageParam?: Pick<PaginatedResponse<BaseAccount>, 'next'>) => {
const response = await (pageParam?.next ? pageParam.next() : entityFn()) as PaginatedResponse<BaseAccount>;
return {
...response,
items: response.items.map(normalizeAccount),
};
};
const queryInfo = useInfiniteQuery({
queryKey: [Entities.ACCOUNTS, ...listKey],
queryFn: ({ pageParam }) => getAccounts(pageParam),
enabled: true,
initialPageParam: { next: null as (() => Promise<PaginatedResponse<BaseAccount>>) | null },
getNextPageParam: (config) => config.next ? config : undefined,
});
const data = flattenPages<Account>(queryInfo.data as any) || [];
const { relationships } = useRelationships(
listKey,
data.map(({ id }) => id),
);
const accounts = data.map((account) => ({
...account,
relationship: relationships[account.id],
}));
return { accounts, ...queryInfo };
};
const useBlocks = () => {
const client = useClient();
return useAccountList(['blocks'], () => client.filtering.getBlocks());
};
const useMutes = () => {
const client = useClient();
return useAccountList(['mutes'], () => client.filtering.getMutes());
};
const useFollowing = (accountId: string | undefined) => {
const client = useClient();
return useAccountList(
[accountId!, 'following'],
() => client.accounts.getAccountFollowing(accountId!),
);
};
const useFollowers = (accountId: string | undefined) => {
const client = useClient();
return useAccountList(
[accountId!, 'followers'],
() => client.accounts.getAccountFollowers(accountId!),
);
};
export {
useBlocks,
useMutes,
useFollowing,
useFollowers,
};

View File

@ -59,7 +59,6 @@ const BirthdayPanel = ({ limit }: IBirthdayPanel) => {
{birthdaysToRender.map(accountId => (
<AccountContainer
key={accountId}
// @ts-ignore: TS thinks `id` is passed to <Account>, but it isn't
id={accountId}
withRelationship={false}
/>

View File

@ -1,13 +1,13 @@
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useFollowers } from 'pl-fe/api/hooks/accounts/use-account-list';
import { useAccountLookup } from 'pl-fe/api/hooks/accounts/use-account-lookup';
import Account from 'pl-fe/components/account';
import MissingIndicator from 'pl-fe/components/missing-indicator';
import ScrollableList from 'pl-fe/components/scrollable-list';
import Column from 'pl-fe/components/ui/column';
import Spinner from 'pl-fe/components/ui/spinner';
import AccountContainer from 'pl-fe/containers/account-container';
import { useFollowers } from 'pl-fe/queries/account-lists/use-follows';
const messages = defineMessages({
heading: { id: 'column.followers', defaultMessage: 'Followers' },
@ -26,9 +26,10 @@ const Followers: React.FC<IFollowers> = ({ params }) => {
const { account, isUnavailable } = useAccountLookup(params?.username);
const {
accounts,
data = [],
hasNextPage,
fetchNextPage,
isFetching,
isLoading,
} = useFollowers(account?.id);
@ -60,10 +61,14 @@ const Followers: React.FC<IFollowers> = ({ params }) => {
onLoadMore={fetchNextPage}
emptyMessage={<FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />}
itemClassName='pb-4'
isLoading={isFetching}
>
{accounts.map((account) =>
<Account key={account.id} account={account} />,
)}
{data.map((accountId) => (
<AccountContainer
key={accountId}
id={accountId}
/>
))}
</ScrollableList>
</Column>
);

View File

@ -1,13 +1,13 @@
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useFollowing } from 'pl-fe/api/hooks/accounts/use-account-list';
import { useAccountLookup } from 'pl-fe/api/hooks/accounts/use-account-lookup';
import Account from 'pl-fe/components/account';
import MissingIndicator from 'pl-fe/components/missing-indicator';
import ScrollableList from 'pl-fe/components/scrollable-list';
import Column from 'pl-fe/components/ui/column';
import Spinner from 'pl-fe/components/ui/spinner';
import AccountContainer from 'pl-fe/containers/account-container';
import { useFollowing } from 'pl-fe/queries/account-lists/use-follows';
const messages = defineMessages({
heading: { id: 'column.following', defaultMessage: 'Following' },
@ -26,9 +26,10 @@ const Following: React.FC<IFollowing> = ({ params }) => {
const { account, isUnavailable } = useAccountLookup(params?.username);
const {
accounts,
data = [],
hasNextPage,
fetchNextPage,
isFetching,
isLoading,
} = useFollowing(account?.id);
@ -60,9 +61,13 @@ const Following: React.FC<IFollowing> = ({ params }) => {
onLoadMore={fetchNextPage}
emptyMessage={<FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />}
itemClassName='pb-4'
isLoading={isFetching}
>
{accounts.map((account) => (
<Account key={account.id} account={account} />
{data.map((accountId) => (
<AccountContainer
key={accountId}
id={accountId}
/>
))}
</ScrollableList>
</Column>

View File

@ -1,11 +1,12 @@
import clsx from 'clsx';
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { useBlocks } from 'pl-fe/api/hooks/accounts/use-account-list';
import Account from 'pl-fe/components/account';
import ScrollableList from 'pl-fe/components/scrollable-list';
import Column from 'pl-fe/components/ui/column';
import Spinner from 'pl-fe/components/ui/spinner';
import AccountContainer from 'pl-fe/containers/account-container';
import { useBlocks } from 'pl-fe/queries/account-lists/use-blocks';
const messages = defineMessages({
heading: { id: 'column.blocks', defaultMessage: 'Blocks' },
@ -15,10 +16,11 @@ const BlocksPage: React.FC = () => {
const intl = useIntl();
const {
accounts,
data = [],
hasNextPage,
fetchNextPage,
isLoading,
isFetching,
} = useBlocks();
if (isLoading) {
@ -39,10 +41,11 @@ const BlocksPage: React.FC = () => {
hasMore={hasNextPage}
emptyMessage={emptyMessage}
emptyMessageCard={false}
itemClassName='pb-4 last:pb-0'
itemClassName={clsx('pb-4', { 'last:pb-0': !hasNextPage })}
isLoading={isFetching}
>
{accounts.map((account) => (
<Account key={account.id} account={account} actionType='blocking' />
{data.map((accountId) => (
<AccountContainer key={accountId} id={accountId} actionType='blocking' />
))}
</ScrollableList>
</Column>

View File

@ -1,11 +1,12 @@
import clsx from 'clsx';
import React from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { useMutes } from 'pl-fe/api/hooks/accounts/use-account-list';
import ScrollableList from 'pl-fe/components/scrollable-list';
import Column from 'pl-fe/components/ui/column';
import Stack from 'pl-fe/components/ui/stack';
import AccountContainer from 'pl-fe/containers/account-container';
import { useMutes } from 'pl-fe/queries/account-lists/use-blocks';
const messages = defineMessages({
heading: { id: 'column.mutes', defaultMessage: 'Mutes' },
@ -15,32 +16,28 @@ const MutesPage: React.FC = () => {
const intl = useIntl();
const {
accounts,
hasNextPage: hasNextAccountsPage,
fetchNextPage: fetchNextAccounts,
isLoading: isLoadingAccounts,
data = [],
hasNextPage,
fetchNextPage,
isFetching,
} = useMutes();
const scrollableListProps = {
itemClassName: 'pb-4 last:pb-0',
scrollKey: 'mutes',
emptyMessageCard: false,
};
return (
<Column label={intl.formatMessage(messages.heading)}>
<Stack space={4}>
<ScrollableList
{...scrollableListProps}
isLoading={isLoadingAccounts}
onLoadMore={fetchNextAccounts}
hasMore={hasNextAccountsPage}
itemClassName={clsx('pb-4', { 'last:pb-0': !hasNextPage })}
scrollKey='mutes'
isLoading={isFetching}
onLoadMore={fetchNextPage}
hasMore={hasNextPage}
emptyMessage={
<FormattedMessage id='empty_column.mutes' defaultMessage="You haven't muted any users yet." />
}
emptyMessageCard={false}
>
{accounts.map((accounts) =>
<AccountContainer key={accounts.id} id={accounts.id} actionType='muting' />,
{data.map((accountId) =>
<AccountContainer key={accountId} id={accountId} actionType='muting' />,
)}
</ScrollableList>
</Stack>

View File

@ -0,0 +1,14 @@
import { makePaginatedResponseQuery } from '../utils/make-paginated-response-query';
import { minifyAccountList } from '../utils/minify-list';
const useBlocks = makePaginatedResponseQuery(
() => ['accountsLists', 'blocked'],
(client) => client.filtering.getBlocks({ with_relationships: true }).then(minifyAccountList),
);
const useMutes = makePaginatedResponseQuery(
() => ['accountsLists', 'muted'],
(client) => client.filtering.getMutes({ with_relationships: true }).then(minifyAccountList),
);
export { useBlocks, useMutes };

View File

@ -0,0 +1,25 @@
import { makePaginatedResponseQuery } from '../utils/make-paginated-response-query';
import { minifyAccountList } from '../utils/minify-list';
const useFollowers = makePaginatedResponseQuery(
(accountId?: string) => ['accountsLists', 'followers', accountId],
(client, [accountId]) => client.accounts.getAccountFollowers(accountId!, { with_relationships: true }).then(minifyAccountList),
undefined,
(accountId) => !!accountId,
);
const useFollowing = makePaginatedResponseQuery(
(accountId?: string) => ['accountsLists', 'following', accountId],
(client, [accountId]) => client.accounts.getAccountFollowing(accountId!, { with_relationships: true }).then(minifyAccountList),
undefined,
(accountId) => !!accountId,
);
const useSubscribers = makePaginatedResponseQuery(
(accountId?: string) => ['accountsLists', 'subscribers', accountId],
(client, [accountId]) => client.accounts.getAccountSubscribers(accountId!, { with_relationships: true }).then(minifyAccountList),
undefined,
(accountId) => !!accountId,
);
export { useFollowers, useFollowing, useSubscribers };