Profile redesign: Account featured tab (#38529)

Co-authored-by: diondiondion <mail@diondiondion.com>
This commit is contained in:
Echoanddiondiondion authored and GitHub committed 2026-04-02 12:33:32 +00:00
1 parent 8a5d6dab5f
commit 8da2fae6cc
10 files changed
+158 -135

No files matched your search

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 334 353"><ellipse cx="162.778" cy="327.222" fill="#181820" rx="113.889" ry="25"/><g clip-path="url(#a)"><path fill="#3a3a50" d="M181.219 292.602s.546 21.402 1.091 27.288 1.636 8.561 10.909 9.096 22.365-1.071 27.274-2.141 8.727-3.21 7.636-15.516-2.182-27.288-2.182-27.288"/><path stroke="#21212c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M181.219 292.602s.546 21.402 1.091 27.288 1.636 8.561 10.909 9.096 22.365-1.071 27.274-2.141 8.727-3.21 7.636-15.516-2.182-27.288-2.182-27.288"/><path fill="#67678e" stroke="#21212c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="m227.584 320.851-.054-.321c-.818-3.05-2.455-3.746-4.364-3.371-2.618.535-3.327 4.12-3.764 8.935 0 .214-.054.428-.054.696l.382.16c.218-.053.49-.107.709-.16 3.218-.642 5.945-1.819 7.145-5.939"/><path fill="#44445f" d="M231.184 121.917c25.092-2.676 43.092-14.982 45.82-17.122 0 0-7.637-6.42-1.637-10.701 6-4.28 9.819 1.07 9.819 1.07s12.818-15.999 23.728-7.438c10.909 8.561 15 17.604 11.182 26.165-3.819 8.561-28.365 38.524-80.184 45.48"/><path stroke="#21212c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M231.184 121.917c25.092-2.676 43.092-14.982 45.82-17.122 0 0-7.637-6.42-1.637-10.701 6-4.28 9.819 1.07 9.819 1.07s12.818-15.999 23.728-7.438c10.909 8.561 15 17.604 11.182 26.165-3.819 8.561-28.365 38.524-80.184 45.48"/><path fill="#3a3a50" d="M83.363 281.364c-8.728 8.026-22.364 12.307-29.455 2.676-7.092-9.632-2.182-13.912-3.819-16.052-1.636-2.14-11.454 4.28-7.09 16.587 4.363 12.306 29.454 25.682 52.91 7.49"/><path fill="#44445f" d="M225.403 101.638s18.873 37.935 23.51 93.849c3.927 47.62 8.182 74.373-25.092 89.89s-77.456 12.841-98.184 13.376-42.546-2.14-48.001-25.148.273-40.932.273-40.932.763-38.096-1.146-44.249c-1.91-6.153-5.018-15.356-5.018-15.356s-3.11 21.456-19.364 28.679c-16.255 7.277-30.601.428-29.401-19.53 0 0-13.91-22.793-20.51-42.751s10.8-39.54 42.71-31.461c1.091-37.99 34.692-69.932 81.33-73.678 46.583-3.799 57.983 20.707 82.856 21.777 24.001 1.07 40.91-6.42 53.456-18.727 12.546-12.306 38.183-28.358 58.365-15.517 0 0 9.818-3.21 10.909 5.351s-3.818 8.56-6.545 10.166c0 0 3.818 11.771-3.819 13.377-7.636 1.605-6.545-9.631-6.545-9.631s-12.546-1.606-22.91 14.446-25.746 37.561-66.874 46.069c-8.782.749-16.091-2.087-16.091-2.087z"/><path stroke="#21212c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M225.403 101.638s18.873 37.935 23.51 93.849c3.927 47.62 8.182 74.373-25.092 89.89s-77.456 12.841-98.184 13.376-42.546-2.14-48.001-25.148.273-40.932.273-40.932.763-38.096-1.146-44.249c-1.91-6.153-5.018-15.356-5.018-15.356s-3.11 21.456-19.364 28.679c-16.255 7.277-30.601.428-29.401-19.53 0 0-13.91-22.793-20.51-42.751s10.8-39.54 42.71-31.461c1.091-37.99 34.692-69.932 81.33-73.678 46.583-3.799 57.983 20.707 82.856 21.777 24.001 1.07 40.91-6.42 53.456-18.727 12.546-12.306 38.183-28.358 58.365-15.517 0 0 9.818-3.21 10.909 5.351s-3.818 8.56-6.545 10.166c0 0 3.818 11.771-3.819 13.377-7.636 1.605-6.545-9.631-6.545-9.631s-12.546-1.606-22.91 14.446-25.746 37.561-66.874 46.069m0 0c-8.782.749-16.091-2.087-16.091-2.087"/><path fill="#3a3a50" d="M94.272 285.11c0 12.306-2.182 28.358-2.728 34.244C91 325.239 93.182 331.339 103 331.66c15.273.535 44.729 2.675 47.456-6.421 3.436-11.557 2.727-31.033 0-37.454"/><path stroke="#21212c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M94.272 285.11c0 12.306-2.182 28.358-2.728 34.244C91 325.239 93.182 331.339 103 331.66c15.273.535 44.729 2.675 47.456-6.421 3.436-11.557 2.727-31.033 0-37.454"/><path fill="#67678e" d="M113.471 332.035c.437-5.19.982-8.401 3.71-8.936s4.8 1.659 4.854 9.15"/><path stroke="#21212c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M113.471 332.035c.437-5.19.982-8.401 3.71-8.936s4.8 1.659 4.854 9.15"/><path fill="#67678e" d="M122.199 332.035c.437-5.19.982-8.401 3.709-8.936s4.801 1.659 4.855 9.15"/><path stroke="#21212c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M122.199 332.035c.437-5.19.982-8.401 3.709-8.936s4.801 1.659 4.855 9.15"/><path fill="#67678e" d="M130.818 332.195c.437-5.19 1.091-9.096 3.818-9.631s4.855 1.124 4.91 8.561"/><path stroke="#21212c" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M130.818 332.195c.437-5.19 1.091-9.096 3.818-9.631s4.855 1.124 4.91 8.561"/><path fill="#3a3a50" d="M21.835 140.216c3.982 4.869 11.237 20.439 10.8 32.639-.49 12.252 12.982 17.549 20.073 6.955s9.055-31.247 4.146-41.306c-4.91-10.113-7.582-13.912-7.582-13.912s-2.673 4.816-9.546 5.779-7.09-1.659-9.436-5.244c0 0 .327 3.96-5.782 6.153-6.11 2.248-8.073-2.675-8.073-2.675s1.473 6.795 5.4 11.611m99.438 157.521c-11.619 0-20.074-1.444-26.674-4.494-8.4-3.906-13.636-10.38-15.873-19.904-5.345Line truncated

After

Width:  |  Height:  |  Size: 11 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 334 353"><ellipse cx="162.778" cy="327.222" fill="#f2f2f7" rx="113.889" ry="25"/><g clip-path="url(#a)"><path fill="#d7d6e1" d="M181.219 292.602s.546 21.402 1.091 27.288 1.636 8.561 10.909 9.096 22.365-1.071 27.274-2.141 8.727-3.21 7.636-15.516-2.182-27.288-2.182-27.288"/><path stroke="#b2b1c8" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M181.219 292.602s.546 21.402 1.091 27.288 1.636 8.561 10.909 9.096 22.365-1.071 27.274-2.141 8.727-3.21 7.636-15.516-2.182-27.288-2.182-27.288"/><path fill="#f6f6f9" stroke="#b2b1c8" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="m227.584 320.851-.054-.321c-.818-3.05-2.455-3.746-4.364-3.371-2.618.535-3.327 4.12-3.764 8.935 0 .214-.054.428-.054.696l.382.16c.218-.053.49-.107.709-.16 3.218-.642 5.945-1.819 7.145-5.939"/><path fill="#eeedf3" d="M231.184 121.917c25.092-2.676 43.092-14.982 45.82-17.122 0 0-7.637-6.42-1.637-10.701 6-4.28 9.819 1.07 9.819 1.07s12.818-15.999 23.728-7.438c10.909 8.561 15 17.604 11.182 26.165-3.819 8.561-28.365 38.524-80.184 45.48"/><path stroke="#b2b1c8" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M231.184 121.917c25.092-2.676 43.092-14.982 45.82-17.122 0 0-7.637-6.42-1.637-10.701 6-4.28 9.819 1.07 9.819 1.07s12.818-15.999 23.728-7.438c10.909 8.561 15 17.604 11.182 26.165-3.819 8.561-28.365 38.524-80.184 45.48"/><path fill="#d7d6e1" d="M83.363 281.364c-8.728 8.026-22.364 12.307-29.455 2.676-7.092-9.632-2.182-13.912-3.819-16.052-1.636-2.14-11.454 4.28-7.09 16.587 4.363 12.306 29.455 25.682 52.91 7.49"/><path fill="#eeedf3" d="M225.403 101.638s18.873 37.935 23.51 93.849c3.927 47.62 8.182 74.373-25.092 89.89s-77.456 12.841-98.184 13.376-42.546-2.14-48.001-25.148.273-40.932.273-40.932.763-38.096-1.146-44.249c-1.91-6.153-5.018-15.356-5.018-15.356s-3.11 21.456-19.364 28.679c-16.255 7.277-30.601.428-29.401-19.53 0 0-13.91-22.793-20.51-42.751s10.8-39.54 42.71-31.461c1.091-37.99 34.692-69.932 81.33-73.678 46.583-3.799 57.983 20.707 82.856 21.777 24.001 1.07 40.91-6.42 53.456-18.727 12.546-12.306 38.183-28.358 58.365-15.517 0 0 9.818-3.21 10.909 5.351s-3.818 8.56-6.545 10.166c0 0 3.818 11.771-3.819 13.377-7.636 1.605-6.545-9.631-6.545-9.631s-12.546-1.606-22.91 14.446-25.746 37.561-66.874 46.069c-8.782.749-16.091-2.087-16.091-2.087z"/><path stroke="#b2b1c8" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M225.403 101.638s18.873 37.935 23.51 93.849c3.927 47.62 8.182 74.373-25.092 89.89s-77.456 12.841-98.184 13.376-42.546-2.14-48.001-25.148.273-40.932.273-40.932.763-38.096-1.146-44.249c-1.91-6.153-5.018-15.356-5.018-15.356s-3.11 21.456-19.364 28.679c-16.255 7.277-30.601.428-29.401-19.53 0 0-13.91-22.793-20.51-42.751s10.8-39.54 42.71-31.461c1.091-37.99 34.692-69.932 81.33-73.678 46.583-3.799 57.983 20.707 82.856 21.777 24.001 1.07 40.91-6.42 53.456-18.727 12.546-12.306 38.183-28.358 58.365-15.517 0 0 9.818-3.21 10.909 5.351s-3.818 8.56-6.545 10.166c0 0 3.818 11.771-3.819 13.377-7.636 1.605-6.545-9.631-6.545-9.631s-12.546-1.606-22.91 14.446-25.746 37.561-66.874 46.069m0 0c-8.782.749-16.091-2.087-16.091-2.087"/><path fill="#d7d6e1" d="M94.272 285.11c0 12.306-2.182 28.358-2.727 34.244-.546 5.885 1.636 11.985 11.454 12.306 15.273.535 44.729 2.675 47.456-6.421 3.436-11.557 2.727-31.033 0-37.454"/><path stroke="#b2b1c8" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M94.272 285.11c0 12.306-2.182 28.358-2.727 34.244-.546 5.885 1.636 11.985 11.454 12.306 15.273.535 44.729 2.675 47.456-6.421 3.436-11.557 2.727-31.033 0-37.454"/><path fill="#f6f6f9" d="M113.471 332.035c.437-5.19.982-8.401 3.71-8.936s4.8 1.659 4.854 9.15"/><path stroke="#b2b1c8" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M113.471 332.035c.437-5.19.982-8.401 3.71-8.936s4.8 1.659 4.854 9.15"/><path fill="#f6f6f9" d="M122.199 332.035c.437-5.19.982-8.401 3.709-8.936s4.801 1.659 4.855 9.15"/><path stroke="#b2b1c8" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M122.199 332.035c.437-5.19.982-8.401 3.709-8.936s4.801 1.659 4.855 9.15"/><path fill="#f6f6f9" d="M130.818 332.195c.437-5.19 1.091-9.096 3.818-9.631s4.855 1.124 4.91 8.561"/><path stroke="#b2b1c8" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="1.826" d="M130.818 332.195c.437-5.19 1.091-9.096 3.818-9.631s4.855 1.124 4.91 8.561"/><path fill="#d7d6e1" d="M21.835 140.216c3.982 4.869 11.237 20.439 10.8 32.639-.49 12.252 12.982 17.549 20.073 6.955s9.055-31.247 4.146-41.306c-4.91-10.113-7.582-13.912-7.582-13.912s-2.673 4.816-9.546 5.779-7.09-1.659-9.436-5.244c0 0 .327 3.96-5.782 6.153-6.11 2.248-8.073-2.675-8.073-2.675s1.473 6.795 5.4 11.611m99.438 157.521c-11.619 0-20.074-1.444-26.674-4.494-8.4-3.906-13.636-10.38-15.873-19.904-5.3Line truncated

After

Width:  |  Height:  |  Size: 11 KiB

@@ -10,6 +10,13 @@
}
.content {
svg,
img {
width: 240px;
max-width: 100%;
margin-bottom: 16px;
}
h3 {
font-size: 17px;
font-weight: 500;
@@ -9,10 +9,12 @@ import classes from './empty_state.module.scss';
*/
export const EmptyState: React.FC<{
title?: string | React.ReactElement;
message?: string | React.ReactElement;
image?: React.ReactNode;
title?: React.ReactNode;
message?: React.ReactNode;
children?: React.ReactNode;
}> = ({
image,
title = (
<FormattedMessage id='empty_state.no_results' defaultMessage='No results' />
),
@@ -21,10 +23,13 @@ export const EmptyState: React.FC<{
}) => {
return (
<div className={classes.wrapper}>
<div className={classes.content}>
<h3>{title}</h3>
{!!message && <p>{message}</p>}
</div>
{(title || message || image) && (
<div className={classes.content}>
{image}
{!!title && <h3>{title}</h3>}
{!!message && <p>{message}</p>}
</div>
)}
{children}
</div>
@@ -1,9 +1,15 @@
import { FormattedMessage } from 'react-intl';
import { useParams } from 'react-router';
import { Link } from 'react-router-dom';
import { LimitedAccountHint } from 'mastodon/features/account_timeline/components/limited_account_hint';
import { me } from 'mastodon/initial_state';
import ElephantDarkImage from '@/images/elephant_ui_dark.svg?react';
import ElephantLightImage from '@/images/elephant_ui_light.svg?react';
import { EmptyState } from '@/mastodon/components/empty_state';
import { LimitedAccountHint } from '@/mastodon/features/account_timeline/components/limited_account_hint';
import { areCollectionsEnabled } from '@/mastodon/features/collections/utils';
import { useCurrentAccountId } from '@/mastodon/hooks/useAccountId';
import { useTheme } from '@/mastodon/hooks/useTheme';
interface EmptyMessageProps {
suspended: boolean;
@@ -19,21 +25,59 @@ export const EmptyMessage: React.FC<EmptyMessageProps> = ({
blockedBy,
}) => {
const { acct } = useParams<{ acct?: string }>();
const me = useCurrentAccountId();
const theme = useTheme();
const ElephantImage =
theme === 'dark' ? ElephantDarkImage : ElephantLightImage;
if (!accountId) {
return null;
}
let title: React.ReactNode = null;
let message: React.ReactNode = null;
const hasCollections = areCollectionsEnabled();
const image = <ElephantImage />;
if (me === accountId) {
message = (
<FormattedMessage
id='empty_column.account_featured.me'
defaultMessage='You have not featured anything yet. Did you know that you can feature your hashtags you use the most, and even your friend’s accounts on your profile?'
/>
);
if (hasCollections) {
// Return only here to insert the "Create a collection" button as the action for the empty state.
return (
<EmptyState
image={image}
title={
<FormattedMessage
id='empty_column.account_featured_self.no_collections'
defaultMessage='No collections yet'
/>
}
>
<Link to='/collections/new' className='button'>
<FormattedMessage
id='empty_column.account_featured_self.no_collections_button'
defaultMessage='Create a collection'
/>
</Link>
</EmptyState>
);
} else {
title = (
<FormattedMessage
id='empty_column.account_featured_self.pre_collections'
defaultMessage='Stay tuned for Collections'
/>
);
message = (
<FormattedMessage
id='empty_column.account_featured_self.pre_collections_desc'
defaultMessage='Collections (coming in Mastodon 4.6) allows you to create your own curated lists of accounts to recommend to others.'
/>
);
}
} else if (suspended) {
message = (
title = (
<FormattedMessage
id='empty_column.account_suspended'
defaultMessage='Account suspended'
@@ -42,32 +86,56 @@ export const EmptyMessage: React.FC<EmptyMessageProps> = ({
} else if (hidden) {
message = <LimitedAccountHint accountId={accountId} />;
} else if (blockedBy) {
message = (
title = (
<FormattedMessage
id='empty_column.account_unavailable'
defaultMessage='Profile unavailable'
/>
);
} else if (acct) {
message = (
<FormattedMessage
id='empty_column.account_featured.other'
defaultMessage='{acct} has not featured anything yet. Did you know that you can feature your hashtags you use the most, and even your friend’s accounts on your profile?'
values={{ acct }}
/>
);
} else {
message = (
// Standard other account empty state.
title = (
<FormattedMessage
id='empty_column.account_featured_other.unknown'
defaultMessage='This account has not featured anything yet.'
id='empty_column.account_featured_other.title'
defaultMessage='Nothing to see here'
/>
);
if (hasCollections) {
if (acct) {
message = (
<FormattedMessage
id='empty_column.account_featured_other.no_collections_desc'
defaultMessage='{acct} hasn’t created any collections yet.'
values={{ acct }}
/>
);
} else {
message = (
<FormattedMessage
id='empty_column.account_featured_unknown.no_collections_desc'
defaultMessage='This account hasn’t created any collections yet.'
/>
);
}
} else {
if (acct) {
message = (
<FormattedMessage
id='empty_column.account_featured.other'
defaultMessage='{acct} hasn’t featured anything yet.'
values={{ acct }}
/>
);
} else {
message = (
<FormattedMessage
id='empty_column.account_featured_unknown.other'
defaultMessage='This account hasn’t featured anything yet.'
/>
);
}
}
}
return (
<div className='empty-column-indicator'>
<span>{message}</span>
</div>
);
return <EmptyState title={title} message={message} image={image} />;
};
@@ -1,52 +0,0 @@
import { defineMessages, useIntl } from 'react-intl';
import type { Map as ImmutableMap } from 'immutable';
import { Hashtag } from 'mastodon/components/hashtag';
export type TagMap = ImmutableMap<
'id' | 'name' | 'url' | 'statuses_count' | 'last_status_at' | 'accountId',
string | null
>;
interface FeaturedTagProps {
tag: TagMap;
account: string;
}
const messages = defineMessages({
lastStatusAt: {
id: 'account.featured_tags.last_status_at',
defaultMessage: 'Last post on {date}',
},
empty: {
id: 'account.featured_tags.last_status_never',
defaultMessage: 'No posts',
},
});
export const FeaturedTag: React.FC<FeaturedTagProps> = ({ tag, account }) => {
const intl = useIntl();
const name = tag.get('name') ?? '';
const count = Number.parseInt(tag.get('statuses_count') ?? '');
return (
<Hashtag
key={name}
name={name}
to={`/@${account}/tagged/${name}`}
uses={count}
withGraph={false}
description={
count > 0
? intl.formatMessage(messages.lastStatusAt, {
date: intl.formatDate(tag.get('last_status_at') ?? '', {
month: 'short',
day: '2-digit',
year: 'numeric',
}),
})
: intl.formatMessage(messages.empty)
}
/>
);
};
@@ -8,7 +8,6 @@ import { List as ImmutableList } from 'immutable';
import { useAccount } from '@/mastodon/hooks/useAccount';
import { fetchEndorsedAccounts } from 'mastodon/actions/accounts';
import { fetchFeaturedTags } from 'mastodon/actions/featured_tags';
import { Account } from 'mastodon/components/account';
import { ColumnBackButton } from 'mastodon/components/column_back_button';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
@@ -33,8 +32,6 @@ import { CollectionListItem } from '../collections/detail/collection_list_item';
import { areCollectionsEnabled } from '../collections/utils';
import { EmptyMessage } from './components/empty_message';
import { FeaturedTag } from './components/featured_tag';
import type { TagMap } from './components/featured_tag';
const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
multiColumn,
@@ -55,26 +52,15 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
useEffect(() => {
if (accountId) {
void dispatch(fetchFeaturedTags({ accountId }));
void dispatch(fetchEndorsedAccounts({ accountId }));
if (areCollectionsEnabled()) {
void dispatch(fetchAccountCollections({ accountId }));
}
}
}, [accountId, dispatch]);
const isLoading = useAppSelector(
(state) =>
!accountId ||
!!state.user_lists.getIn(['featured_tags', accountId, 'isLoading']),
);
const featuredTags = useAppSelector(
(state) =>
state.user_lists.getIn(
['featured_tags', accountId, 'items'],
ImmutableList(),
) as ImmutableList<TagMap>,
);
const isLoading = !accountId;
const featuredAccountIds = useAppSelector(
(state) =>
state.user_lists.getIn(
@@ -106,13 +92,7 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
);
}
const noTags = featuredTags.isEmpty();
if (
noTags &&
featuredAccountIds.isEmpty() &&
listedCollections.length === 0
) {
if (featuredAccountIds.isEmpty() && listedCollections.length === 0) {
return (
<AccountFeaturedWrapper accountId={accountId}>
<EmptyMessage
@@ -156,28 +136,6 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
</ItemList>
</>
)}
{!noTags && (
<>
<h4 className='column-subheading'>
<FormattedMessage
id='account.featured.hashtags'
defaultMessage='Hashtags'
/>
</h4>
<ItemList>
{featuredTags.map((tag, index) => (
<Article
focusable
key={tag.get('id')}
aria-posinset={index + 1}
aria-setsize={featuredTags.size}
>
<FeaturedTag tag={tag} account={account?.acct ?? ''} />
</Article>
))}
</ItemList>
</>
)}
{!featuredAccountIds.isEmpty() && (
<>
<h4 className='column-subheading'>
@@ -8,6 +8,8 @@ import { NavLink } from 'react-router-dom';
import { useAccount } from '@/mastodon/hooks/useAccount';
import { useAccountId } from '@/mastodon/hooks/useAccountId';
import { areCollectionsEnabled } from '../../collections/utils';
import classes from './redesign.module.scss';
const isActive: Required<NavLinkProps>['isActive'] = (match, location) =>
@@ -39,7 +41,14 @@ export const AccountTabs: FC = () => {
)}
{show_featured && (
<NavLink exact to={`/@${acct}/featured`}>
<FormattedMessage id='account.featured' defaultMessage='Featured' />
{areCollectionsEnabled() ? (
<FormattedMessage
id='account.featured.collections'
defaultMessage='Collections'
/>
) : (
<FormattedMessage id='account.featured' defaultMessage='Featured' />
)}
</NavLink>
)}
</div>
+23
View File
@@ -0,0 +1,23 @@
import { useEffect, useState } from 'react';
import { isDarkMode } from '../utils/theme';
export function useTheme() {
const [darkMode, setDarkMode] = useState(() => isDarkMode());
useEffect(() => {
const mutationObserver = new MutationObserver(() => {
setDarkMode(isDarkMode());
});
mutationObserver.observe(document.documentElement, {
attributes: true,
attributeFilter: ['data-color-scheme'],
});
return () => {
mutationObserver.disconnect();
};
}, []);
return darkMode ? 'dark' : 'light';
}
+8 -5
View File
@@ -45,9 +45,6 @@
"account.featured": "Featured",
"account.featured.accounts": "Profiles",
"account.featured.collections": "Collections",
"account.featured.hashtags": "Hashtags",
"account.featured_tags.last_status_at": "Last post on {date}",
"account.featured_tags.last_status_never": "No posts",
"account.field_overflow": "Show full content",
"account.filters.all": "All activity",
"account.filters.boosts_toggle": "Show boosts",
@@ -606,9 +603,15 @@
"emoji_button.search_results": "Search results",
"emoji_button.symbols": "Symbols",
"emoji_button.travel": "Travel & Places",
"empty_column.account_featured.me": "You have not featured anything yet. Did you know that you can feature your hashtags you use the most, and even your friend’s accounts on your profile?",
"empty_column.account_featured.other": "{acct} has not featured anything yet. Did you know that you can feature your hashtags you use the most, and even your friend’s accounts on your profile?",
"empty_column.account_featured_other.unknown": "This account has not featured anything yet.",
"empty_column.account_featured_other.no_collections_desc": "{acct} hasn’t created any collections yet.",
"empty_column.account_featured_other.title": "Nothing to see here",
"empty_column.account_featured_self.no_collections": "No collections yet",
"empty_column.account_featured_self.no_collections_button": "Create a collection",
"empty_column.account_featured_self.pre_collections": "Stay tuned for Collections",
"empty_column.account_featured_self.pre_collections_desc": "Collections (coming in Mastodon 4.6) allows you to create your own curated lists of accounts to recommend to others.",
"empty_column.account_featured_unknown.no_collections_desc": "This account hasn’t created any collections yet.",
"empty_column.account_featured_unknown.other": "This account hasn’t featured anything yet.",
"empty_column.account_hides_collections": "This user has chosen to not make this information available",
"empty_column.account_suspended": "Account suspended",
"empty_column.account_timeline": "No posts here!",