Add "Followers you know" to hovercard (#34769)

This commit is contained in:
diondiondion 2025-05-22 14:46:14 +02:00 committed by GitHub
parent da60acced5
commit 12c8a6498c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 85 additions and 21 deletions

View file

@ -43,3 +43,17 @@ export const FollowersCounter = (
}}
/>
);
export const FollowersYouKnowCounter = (
displayNumber: React.ReactNode,
pluralReady: number,
) => (
<FormattedMessage
id='account.followers_you_know_counter'
defaultMessage='{counter} you know'
values={{
count: pluralReady,
counter: <strong>{displayNumber}</strong>,
}}
/>
);

View file

@ -9,11 +9,16 @@ import { fetchAccount } from 'mastodon/actions/accounts';
import { AccountBio } from 'mastodon/components/account_bio';
import { AccountFields } from 'mastodon/components/account_fields';
import { Avatar } from 'mastodon/components/avatar';
import { FollowersCounter } from 'mastodon/components/counters';
import { AvatarGroup } from 'mastodon/components/avatar_group';
import {
FollowersCounter,
FollowersYouKnowCounter,
} from 'mastodon/components/counters';
import { DisplayName } from 'mastodon/components/display_name';
import { FollowButton } from 'mastodon/components/follow_button';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { ShortNumber } from 'mastodon/components/short_number';
import { useFetchFamiliarFollowers } from 'mastodon/features/account_timeline/hooks/familiar_followers';
import { domain } from 'mastodon/initial_state';
import { useAppSelector, useAppDispatch } from 'mastodon/store';
@ -38,6 +43,8 @@ export const HoverCardAccount = forwardRef<
}
}, [dispatch, accountId, account]);
const { familiarFollowers } = useFetchFamiliarFollowers({ accountId });
return (
<div
ref={ref}
@ -73,11 +80,27 @@ export const HoverCardAccount = forwardRef<
)}
</div>
<div className='hover-card__number'>
<div className='hover-card__numbers'>
<ShortNumber
value={account.followers_count}
renderer={FollowersCounter}
/>
{familiarFollowers.length > 0 && (
<>
&middot;
<div className='hover-card__familiar-followers'>
<ShortNumber
value={familiarFollowers.length}
renderer={FollowersYouKnowCounter}
/>
<AvatarGroup compact>
{familiarFollowers.slice(0, 3).map((account) => (
<Avatar key={account.id} account={account} size={22} />
))}
</AvatarGroup>
</div>
</>
)}
</div>
<FollowButton accountId={accountId} />

View file

@ -1,15 +1,12 @@
import { useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { Link } from 'react-router-dom';
import { fetchAccountsFamiliarFollowers } from '@/mastodon/actions/accounts_familiar_followers';
import { Avatar } from '@/mastodon/components/avatar';
import { AvatarGroup } from '@/mastodon/components/avatar_group';
import type { Account } from '@/mastodon/models/account';
import { getAccountFamiliarFollowers } from '@/mastodon/selectors/accounts';
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
import { useFetchFamiliarFollowers } from '../hooks/familiar_followers';
const AccountLink: React.FC<{ account?: Account }> = ({ account }) => {
if (!account) {
@ -64,20 +61,11 @@ const FamiliarFollowersReadout: React.FC<{ familiarFollowers: Account[] }> = ({
export const FamiliarFollowers: React.FC<{ accountId: string }> = ({
accountId,
}) => {
const dispatch = useAppDispatch();
const familiarFollowers = useAppSelector((state) =>
getAccountFamiliarFollowers(state, accountId),
);
const { familiarFollowers, isLoading } = useFetchFamiliarFollowers({
accountId,
});
const hasNoData = familiarFollowers === null;
useEffect(() => {
if (hasNoData) {
void dispatch(fetchAccountsFamiliarFollowers({ id: accountId }));
}
}, [dispatch, accountId, hasNoData]);
if (hasNoData || familiarFollowers.length === 0) {
if (isLoading || familiarFollowers.length === 0) {
return null;
}

View file

@ -0,0 +1,30 @@
import { useEffect } from 'react';
import { fetchAccountsFamiliarFollowers } from '@/mastodon/actions/accounts_familiar_followers';
import { getAccountFamiliarFollowers } from '@/mastodon/selectors/accounts';
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
import { me } from 'mastodon/initial_state';
export const useFetchFamiliarFollowers = ({
accountId,
}: {
accountId?: string;
}) => {
const dispatch = useAppDispatch();
const familiarFollowers = useAppSelector((state) =>
accountId ? getAccountFamiliarFollowers(state, accountId) : null,
);
const hasNoData = familiarFollowers === null;
useEffect(() => {
if (hasNoData && accountId && accountId !== me) {
void dispatch(fetchAccountsFamiliarFollowers({ id: accountId }));
}
}, [dispatch, accountId, hasNoData]);
return {
familiarFollowers: hasNoData ? [] : familiarFollowers,
isLoading: hasNoData,
};
};

View file

@ -42,6 +42,7 @@
"account.followers": "Followers",
"account.followers.empty": "No one follows this user yet.",
"account.followers_counter": "{count, plural, one {{counter} follower} other {{counter} followers}}",
"account.followers_you_know_counter": "{counter} you know",
"account.following": "Following",
"account.following_counter": "{count, plural, one {{counter} following} other {{counter} following}}",
"account.follows.empty": "This user doesn't follow anyone yet.",

View file

@ -10745,7 +10745,15 @@ noscript {
color: inherit;
}
&__number {
&__numbers,
&__familiar-followers {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 10px;
}
&__numbers {
font-size: 15px;
line-height: 22px;
color: $secondary-text-color;