Add "Followers you know" to hovercard (#34769)
This commit is contained in:
parent
da60acced5
commit
12c8a6498c
6 changed files with 85 additions and 21 deletions
|
@ -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>,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
|
@ -9,11 +9,16 @@ import { fetchAccount } from 'mastodon/actions/accounts';
|
||||||
import { AccountBio } from 'mastodon/components/account_bio';
|
import { AccountBio } from 'mastodon/components/account_bio';
|
||||||
import { AccountFields } from 'mastodon/components/account_fields';
|
import { AccountFields } from 'mastodon/components/account_fields';
|
||||||
import { Avatar } from 'mastodon/components/avatar';
|
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 { DisplayName } from 'mastodon/components/display_name';
|
||||||
import { FollowButton } from 'mastodon/components/follow_button';
|
import { FollowButton } from 'mastodon/components/follow_button';
|
||||||
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
|
||||||
import { ShortNumber } from 'mastodon/components/short_number';
|
import { ShortNumber } from 'mastodon/components/short_number';
|
||||||
|
import { useFetchFamiliarFollowers } from 'mastodon/features/account_timeline/hooks/familiar_followers';
|
||||||
import { domain } from 'mastodon/initial_state';
|
import { domain } from 'mastodon/initial_state';
|
||||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||||
|
|
||||||
|
@ -38,6 +43,8 @@ export const HoverCardAccount = forwardRef<
|
||||||
}
|
}
|
||||||
}, [dispatch, accountId, account]);
|
}, [dispatch, accountId, account]);
|
||||||
|
|
||||||
|
const { familiarFollowers } = useFetchFamiliarFollowers({ accountId });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
@ -73,11 +80,27 @@ export const HoverCardAccount = forwardRef<
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='hover-card__number'>
|
<div className='hover-card__numbers'>
|
||||||
<ShortNumber
|
<ShortNumber
|
||||||
value={account.followers_count}
|
value={account.followers_count}
|
||||||
renderer={FollowersCounter}
|
renderer={FollowersCounter}
|
||||||
/>
|
/>
|
||||||
|
{familiarFollowers.length > 0 && (
|
||||||
|
<>
|
||||||
|
·
|
||||||
|
<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>
|
</div>
|
||||||
|
|
||||||
<FollowButton accountId={accountId} />
|
<FollowButton accountId={accountId} />
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { fetchAccountsFamiliarFollowers } from '@/mastodon/actions/accounts_familiar_followers';
|
|
||||||
import { Avatar } from '@/mastodon/components/avatar';
|
import { Avatar } from '@/mastodon/components/avatar';
|
||||||
import { AvatarGroup } from '@/mastodon/components/avatar_group';
|
import { AvatarGroup } from '@/mastodon/components/avatar_group';
|
||||||
import type { Account } from '@/mastodon/models/account';
|
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 }) => {
|
const AccountLink: React.FC<{ account?: Account }> = ({ account }) => {
|
||||||
if (!account) {
|
if (!account) {
|
||||||
|
@ -64,20 +61,11 @@ const FamiliarFollowersReadout: React.FC<{ familiarFollowers: Account[] }> = ({
|
||||||
export const FamiliarFollowers: React.FC<{ accountId: string }> = ({
|
export const FamiliarFollowers: React.FC<{ accountId: string }> = ({
|
||||||
accountId,
|
accountId,
|
||||||
}) => {
|
}) => {
|
||||||
const dispatch = useAppDispatch();
|
const { familiarFollowers, isLoading } = useFetchFamiliarFollowers({
|
||||||
const familiarFollowers = useAppSelector((state) =>
|
accountId,
|
||||||
getAccountFamiliarFollowers(state, accountId),
|
});
|
||||||
);
|
|
||||||
|
|
||||||
const hasNoData = familiarFollowers === null;
|
if (isLoading || familiarFollowers.length === 0) {
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (hasNoData) {
|
|
||||||
void dispatch(fetchAccountsFamiliarFollowers({ id: accountId }));
|
|
||||||
}
|
|
||||||
}, [dispatch, accountId, hasNoData]);
|
|
||||||
|
|
||||||
if (hasNoData || familiarFollowers.length === 0) {
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
};
|
||||||
|
};
|
|
@ -42,6 +42,7 @@
|
||||||
"account.followers": "Followers",
|
"account.followers": "Followers",
|
||||||
"account.followers.empty": "No one follows this user yet.",
|
"account.followers.empty": "No one follows this user yet.",
|
||||||
"account.followers_counter": "{count, plural, one {{counter} follower} other {{counter} followers}}",
|
"account.followers_counter": "{count, plural, one {{counter} follower} other {{counter} followers}}",
|
||||||
|
"account.followers_you_know_counter": "{counter} you know",
|
||||||
"account.following": "Following",
|
"account.following": "Following",
|
||||||
"account.following_counter": "{count, plural, one {{counter} following} other {{counter} following}}",
|
"account.following_counter": "{count, plural, one {{counter} following} other {{counter} following}}",
|
||||||
"account.follows.empty": "This user doesn't follow anyone yet.",
|
"account.follows.empty": "This user doesn't follow anyone yet.",
|
||||||
|
|
|
@ -10745,7 +10745,15 @@ noscript {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__number {
|
&__numbers,
|
||||||
|
&__familiar-followers {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__numbers {
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
color: $secondary-text-color;
|
color: $secondary-text-color;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue