Files
mastodon/app/javascript/flavours/glitch/features/following/index.tsx
2026-03-24 17:22:59 +01:00

113 lines
3.2 KiB
TypeScript

import { useEffect } from 'react';
import type { FC } from 'react';
import { defineMessage, FormattedMessage } from 'react-intl';
import { useDebouncedCallback } from 'use-debounce';
import {
expandFollowing,
fetchFollowing,
} from '@/flavours/glitch/actions/accounts';
import { useAccount } from '@/flavours/glitch/hooks/useAccount';
import { useAccountId } from '@/flavours/glitch/hooks/useAccountId';
import { useRelationship } from '@/flavours/glitch/hooks/useRelationship';
import { selectUserListWithoutMe } from '@/flavours/glitch/selectors/user_lists';
import { useAppDispatch, useAppSelector } from '@/flavours/glitch/store';
import type { EmptyMessageProps } from '../followers/components/empty';
import { BaseEmptyMessage } from '../followers/components/empty';
import { AccountListHeader } from '../followers/components/header';
import { AccountList } from '../followers/components/list';
import { RemoteHint } from './components/remote';
const titleText = defineMessage({
id: 'following.title',
defaultMessage: 'Followed by {name}',
});
const Followers: FC = () => {
const accountId = useAccountId();
const account = useAccount(accountId);
const currentAccountId = useAppSelector(
(state) => (state.meta.get('me') as string | null) ?? null,
);
const followingList = useAppSelector((state) =>
selectUserListWithoutMe(state, 'following', accountId),
);
const dispatch = useAppDispatch();
useEffect(() => {
if (!followingList && accountId) {
dispatch(fetchFollowing(accountId));
}
}, [accountId, dispatch, followingList]);
const loadMore = useDebouncedCallback(
() => {
if (accountId) {
dispatch(expandFollowing(accountId));
}
},
300,
{ leading: true },
);
const relationship = useRelationship(accountId);
const followedId = relationship?.followed_by ? currentAccountId : null;
const followingExceptMeHidden = !!(
account?.hide_collections &&
followingList?.items.length === 0 &&
followedId
);
const footer = followingExceptMeHidden && (
<div className='empty-column-indicator'>
<FormattedMessage
id='following.hide_other_following'
defaultMessage='This user has chosen to not make the rest of who they follow visible'
/>
</div>
);
const domain = account?.acct.split('@')[1];
return (
<AccountList
accountId={accountId}
append={domain && <RemoteHint domain={domain} url={account.url} />}
emptyMessage={<EmptyMessage account={account} />}
header={
accountId && (
<AccountListHeader
accountId={accountId}
titleText={titleText}
total={account?.following_count}
/>
)
}
footer={footer}
list={followingList}
loadMore={loadMore}
prependAccountId={followedId}
scrollKey='following'
/>
);
};
const EmptyMessage: FC<EmptyMessageProps> = (props) => (
<BaseEmptyMessage
{...props}
defaultMessage={
<FormattedMessage
id='account.follows.empty'
defaultMessage="This user doesn't follow anyone yet."
/>
}
/>
);
// eslint-disable-next-line import/no-default-export -- Used by async components.
export default Followers;