mirror of
https://github.com/mastodon/mastodon.git
synced 2025-10-05 00:22:42 +00:00
Refactor: Replace all display name usage for new component (#36137)
This commit is contained in:
parent
ff03938808
commit
dfef7d9407
|
@ -1,27 +0,0 @@
|
||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
||||||
|
|
||||||
exports[`<DisplayName /> > renders display name + account name 1`] = `
|
|
||||||
<span
|
|
||||||
className="display-name"
|
|
||||||
onMouseEnter={[Function]}
|
|
||||||
onMouseLeave={[Function]}
|
|
||||||
>
|
|
||||||
<bdi>
|
|
||||||
<strong
|
|
||||||
className="display-name__html"
|
|
||||||
dangerouslySetInnerHTML={
|
|
||||||
{
|
|
||||||
"__html": "<p>Foo</p>",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</bdi>
|
|
||||||
|
|
||||||
<span
|
|
||||||
className="display-name__account"
|
|
||||||
>
|
|
||||||
@
|
|
||||||
bar@baz
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
`;
|
|
|
@ -1,19 +0,0 @@
|
||||||
import { fromJS } from 'immutable';
|
|
||||||
|
|
||||||
import renderer from 'react-test-renderer';
|
|
||||||
|
|
||||||
import { DisplayName } from '../display_name';
|
|
||||||
|
|
||||||
describe('<DisplayName />', () => {
|
|
||||||
it('renders display name + account name', () => {
|
|
||||||
const account = fromJS({
|
|
||||||
username: 'bar',
|
|
||||||
acct: 'bar@baz',
|
|
||||||
display_name_html: '<p>Foo</p>',
|
|
||||||
});
|
|
||||||
const component = renderer.create(<DisplayName account={account} />);
|
|
||||||
const tree = component.toJSON();
|
|
||||||
|
|
||||||
expect(tree).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,122 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import type { List } from 'immutable';
|
|
||||||
|
|
||||||
import type { Account } from 'mastodon/models/account';
|
|
||||||
|
|
||||||
import { autoPlayGif } from '../initial_state';
|
|
||||||
|
|
||||||
import { Skeleton } from './skeleton';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
account?: Account;
|
|
||||||
others?: List<Account>;
|
|
||||||
localDomain?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DisplayName extends React.PureComponent<Props> {
|
|
||||||
handleMouseEnter: React.ReactEventHandler<HTMLSpanElement> = ({
|
|
||||||
currentTarget,
|
|
||||||
}) => {
|
|
||||||
if (autoPlayGif) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emojis =
|
|
||||||
currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
|
|
||||||
|
|
||||||
emojis.forEach((emoji) => {
|
|
||||||
const originalSrc = emoji.getAttribute('data-original');
|
|
||||||
if (originalSrc != null) emoji.src = originalSrc;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
handleMouseLeave: React.ReactEventHandler<HTMLSpanElement> = ({
|
|
||||||
currentTarget,
|
|
||||||
}) => {
|
|
||||||
if (autoPlayGif) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const emojis =
|
|
||||||
currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
|
|
||||||
|
|
||||||
emojis.forEach((emoji) => {
|
|
||||||
const staticSrc = emoji.getAttribute('data-static');
|
|
||||||
if (staticSrc != null) emoji.src = staticSrc;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { others, localDomain } = this.props;
|
|
||||||
|
|
||||||
let displayName: React.ReactNode,
|
|
||||||
suffix: React.ReactNode,
|
|
||||||
account: Account | undefined;
|
|
||||||
|
|
||||||
if (others && others.size > 0) {
|
|
||||||
account = others.first();
|
|
||||||
} else if (this.props.account) {
|
|
||||||
account = this.props.account;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (others && others.size > 1) {
|
|
||||||
displayName = others
|
|
||||||
.take(2)
|
|
||||||
.map((a) => (
|
|
||||||
<bdi key={a.get('id')}>
|
|
||||||
<strong
|
|
||||||
className='display-name__html'
|
|
||||||
dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }}
|
|
||||||
/>
|
|
||||||
</bdi>
|
|
||||||
))
|
|
||||||
.reduce((prev, cur) => [prev, ', ', cur]);
|
|
||||||
|
|
||||||
if (others.size - 2 > 0) {
|
|
||||||
suffix = `+${others.size - 2}`;
|
|
||||||
}
|
|
||||||
} else if (account) {
|
|
||||||
let acct = account.get('acct');
|
|
||||||
|
|
||||||
if (!acct.includes('@') && localDomain) {
|
|
||||||
acct = `${acct}@${localDomain}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
displayName = (
|
|
||||||
<bdi>
|
|
||||||
<strong
|
|
||||||
className='display-name__html'
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: account.get('display_name_html'),
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</bdi>
|
|
||||||
);
|
|
||||||
suffix = <span className='display-name__account'>@{acct}</span>;
|
|
||||||
} else {
|
|
||||||
displayName = (
|
|
||||||
<bdi>
|
|
||||||
<strong className='display-name__html'>
|
|
||||||
<Skeleton width='10ch' />
|
|
||||||
</strong>
|
|
||||||
</bdi>
|
|
||||||
);
|
|
||||||
suffix = (
|
|
||||||
<span className='display-name__account'>
|
|
||||||
<Skeleton width='7ch' />
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span
|
|
||||||
className='display-name'
|
|
||||||
onMouseEnter={this.handleMouseEnter}
|
|
||||||
onMouseLeave={this.handleMouseLeave}
|
|
||||||
>
|
|
||||||
{displayName} {suffix}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
36
app/javascript/mastodon/components/display_name/default.tsx
Normal file
36
app/javascript/mastodon/components/display_name/default.tsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import type { ComponentPropsWithoutRef, FC } from 'react';
|
||||||
|
|
||||||
|
import { Skeleton } from '../skeleton';
|
||||||
|
|
||||||
|
import type { DisplayNameProps } from './index';
|
||||||
|
import { DisplayNameWithoutDomain } from './no-domain';
|
||||||
|
|
||||||
|
export const DisplayNameDefault: FC<
|
||||||
|
Omit<DisplayNameProps, 'variant'> & ComponentPropsWithoutRef<'span'>
|
||||||
|
> = ({ account, localDomain, className, ...props }) => {
|
||||||
|
const username = useMemo(() => {
|
||||||
|
if (!account) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let acct = account.get('acct');
|
||||||
|
|
||||||
|
if (!acct.includes('@') && localDomain) {
|
||||||
|
acct = `${acct}@${localDomain}`;
|
||||||
|
}
|
||||||
|
return `@${acct}`;
|
||||||
|
}, [account, localDomain]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DisplayNameWithoutDomain
|
||||||
|
account={account}
|
||||||
|
className={className}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{' '}
|
||||||
|
<span className='display-name__account'>
|
||||||
|
{username ?? <Skeleton width='7ch' />}
|
||||||
|
</span>
|
||||||
|
</DisplayNameWithoutDomain>
|
||||||
|
);
|
||||||
|
};
|
|
@ -18,8 +18,6 @@ const meta = {
|
||||||
username: 'mastodon@mastodon.social',
|
username: 'mastodon@mastodon.social',
|
||||||
name: 'Test User 🧪',
|
name: 'Test User 🧪',
|
||||||
loading: false,
|
loading: false,
|
||||||
simple: false,
|
|
||||||
noDomain: false,
|
|
||||||
localDomain: 'mastodon.social',
|
localDomain: 'mastodon.social',
|
||||||
},
|
},
|
||||||
tags: [],
|
tags: [],
|
||||||
|
@ -50,13 +48,13 @@ export const Loading: Story = {
|
||||||
|
|
||||||
export const NoDomain: Story = {
|
export const NoDomain: Story = {
|
||||||
args: {
|
args: {
|
||||||
noDomain: true,
|
variant: 'noDomain',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Simple: Story = {
|
export const Simple: Story = {
|
||||||
args: {
|
args: {
|
||||||
simple: true,
|
variant: 'simple',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,6 +74,6 @@ export const Linked: Story = {
|
||||||
acct: username,
|
acct: username,
|
||||||
})
|
})
|
||||||
: undefined;
|
: undefined;
|
||||||
return <LinkedDisplayName {...args} account={account} />;
|
return <LinkedDisplayName {...args} displayProps={{ account }} />;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,110 +1,37 @@
|
||||||
import type { ComponentPropsWithoutRef, FC } from 'react';
|
import type { ComponentPropsWithoutRef, FC } from 'react';
|
||||||
import { useMemo } from 'react';
|
|
||||||
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import type { LinkProps } from 'react-router-dom';
|
import type { LinkProps } from 'react-router-dom';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { EmojiHTML } from '@/mastodon/features/emoji/emoji_html';
|
|
||||||
import type { Account } from '@/mastodon/models/account';
|
import type { Account } from '@/mastodon/models/account';
|
||||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
|
||||||
|
|
||||||
import { Skeleton } from '../skeleton';
|
import { DisplayNameDefault } from './default';
|
||||||
|
import { DisplayNameWithoutDomain } from './no-domain';
|
||||||
|
import { DisplayNameSimple } from './simple';
|
||||||
|
|
||||||
interface Props {
|
export interface DisplayNameProps {
|
||||||
account?: Account;
|
account?: Account;
|
||||||
localDomain?: string;
|
localDomain?: string;
|
||||||
simple?: boolean;
|
variant?: 'default' | 'simple' | 'noDomain';
|
||||||
noDomain?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DisplayName: FC<Props & ComponentPropsWithoutRef<'span'>> = ({
|
export const DisplayName: FC<
|
||||||
account,
|
DisplayNameProps & ComponentPropsWithoutRef<'span'>
|
||||||
localDomain,
|
> = ({ variant = 'default', ...props }) => {
|
||||||
simple = false,
|
if (variant === 'simple') {
|
||||||
noDomain = false,
|
return <DisplayNameSimple {...props} />;
|
||||||
className,
|
} else if (variant === 'noDomain') {
|
||||||
...props
|
return <DisplayNameWithoutDomain {...props} />;
|
||||||
}) => {
|
|
||||||
const username = useMemo(() => {
|
|
||||||
if (!account || noDomain) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let acct = account.get('acct');
|
|
||||||
|
|
||||||
if (!acct.includes('@') && localDomain) {
|
|
||||||
acct = `${acct}@${localDomain}`;
|
|
||||||
}
|
|
||||||
return `@${acct}`;
|
|
||||||
}, [account, localDomain, noDomain]);
|
|
||||||
|
|
||||||
if (!account) {
|
|
||||||
if (simple) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<span {...props} className={classNames('display-name', className)}>
|
|
||||||
<bdi>
|
|
||||||
<strong className='display-name__html'>
|
|
||||||
<Skeleton width='10ch' />
|
|
||||||
</strong>
|
|
||||||
</bdi>
|
|
||||||
{!noDomain && (
|
|
||||||
<span className='display-name__account'>
|
|
||||||
|
|
||||||
<Skeleton width='7ch' />
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const accountName = isModernEmojiEnabled()
|
return <DisplayNameDefault {...props} />;
|
||||||
? account.get('display_name')
|
|
||||||
: account.get('display_name_html');
|
|
||||||
if (simple) {
|
|
||||||
return (
|
|
||||||
<bdi>
|
|
||||||
<EmojiHTML {...props} htmlString={accountName} shallow as='span' />
|
|
||||||
</bdi>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span {...props} className={classNames('display-name', className)}>
|
|
||||||
<bdi>
|
|
||||||
<EmojiHTML
|
|
||||||
className='display-name__html'
|
|
||||||
htmlString={accountName}
|
|
||||||
shallow
|
|
||||||
as='strong'
|
|
||||||
/>
|
|
||||||
</bdi>
|
|
||||||
{username && (
|
|
||||||
<span className='display-name__account'> {username}</span>
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const LinkedDisplayName: FC<
|
export const LinkedDisplayName: FC<
|
||||||
Props & { asProps?: ComponentPropsWithoutRef<'span'> } & Partial<LinkProps>
|
Omit<LinkProps, 'to'> & {
|
||||||
> = ({
|
displayProps: DisplayNameProps & ComponentPropsWithoutRef<'span'>;
|
||||||
account,
|
}
|
||||||
asProps = {},
|
> = ({ displayProps, children, ...linkProps }) => {
|
||||||
className,
|
const { account } = displayProps;
|
||||||
localDomain,
|
|
||||||
simple,
|
|
||||||
noDomain,
|
|
||||||
...linkProps
|
|
||||||
}) => {
|
|
||||||
const displayProps = {
|
|
||||||
account,
|
|
||||||
className,
|
|
||||||
localDomain,
|
|
||||||
simple,
|
|
||||||
noDomain,
|
|
||||||
...asProps,
|
|
||||||
};
|
|
||||||
if (!account) {
|
if (!account) {
|
||||||
return <DisplayName {...displayProps} />;
|
return <DisplayName {...displayProps} />;
|
||||||
}
|
}
|
||||||
|
@ -113,9 +40,11 @@ export const LinkedDisplayName: FC<
|
||||||
<Link
|
<Link
|
||||||
to={`/@${account.acct}`}
|
to={`/@${account.acct}`}
|
||||||
title={`@${account.acct}`}
|
title={`@${account.acct}`}
|
||||||
|
data-id={account.id}
|
||||||
data-hover-card-account={account.id}
|
data-hover-card-account={account.id}
|
||||||
{...linkProps}
|
{...linkProps}
|
||||||
>
|
>
|
||||||
|
{children}
|
||||||
<DisplayName {...displayProps} />
|
<DisplayName {...displayProps} />
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
import type { ComponentPropsWithoutRef, FC } from 'react';
|
||||||
|
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { EmojiHTML } from '@/mastodon/features/emoji/emoji_html';
|
||||||
|
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||||
|
|
||||||
|
import { Skeleton } from '../skeleton';
|
||||||
|
|
||||||
|
import type { DisplayNameProps } from './index';
|
||||||
|
|
||||||
|
export const DisplayNameWithoutDomain: FC<
|
||||||
|
Omit<DisplayNameProps, 'variant' | 'localDomain'> &
|
||||||
|
ComponentPropsWithoutRef<'span'>
|
||||||
|
> = ({ account, className, children, ...props }) => {
|
||||||
|
return (
|
||||||
|
<span {...props} className={classNames('display-name', className)}>
|
||||||
|
<bdi>
|
||||||
|
{account ? (
|
||||||
|
<EmojiHTML
|
||||||
|
className='display-name__html'
|
||||||
|
htmlString={
|
||||||
|
isModernEmojiEnabled()
|
||||||
|
? account.get('display_name')
|
||||||
|
: account.get('display_name_html')
|
||||||
|
}
|
||||||
|
shallow
|
||||||
|
as='strong'
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<strong className='display-name__html'>
|
||||||
|
<Skeleton width='10ch' />
|
||||||
|
</strong>
|
||||||
|
)}
|
||||||
|
</bdi>
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
23
app/javascript/mastodon/components/display_name/simple.tsx
Normal file
23
app/javascript/mastodon/components/display_name/simple.tsx
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import type { ComponentPropsWithoutRef, FC } from 'react';
|
||||||
|
|
||||||
|
import { EmojiHTML } from '@/mastodon/features/emoji/emoji_html';
|
||||||
|
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||||
|
|
||||||
|
import type { DisplayNameProps } from './index';
|
||||||
|
|
||||||
|
export const DisplayNameSimple: FC<
|
||||||
|
Omit<DisplayNameProps, 'variant' | 'localDomain'> &
|
||||||
|
ComponentPropsWithoutRef<'span'>
|
||||||
|
> = ({ account, ...props }) => {
|
||||||
|
if (!account) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const accountName = isModernEmojiEnabled()
|
||||||
|
? account.get('display_name')
|
||||||
|
: account.get('display_name_html');
|
||||||
|
return (
|
||||||
|
<bdi>
|
||||||
|
<EmojiHTML {...props} htmlString={accountName} shallow as='span' />
|
||||||
|
</bdi>
|
||||||
|
);
|
||||||
|
};
|
|
@ -28,7 +28,7 @@ import { displayMedia } from '../initial_state';
|
||||||
|
|
||||||
import { Avatar } from './avatar';
|
import { Avatar } from './avatar';
|
||||||
import { AvatarOverlay } from './avatar_overlay';
|
import { AvatarOverlay } from './avatar_overlay';
|
||||||
import { DisplayName } from './display_name';
|
import { LinkedDisplayName } from './display_name';
|
||||||
import { getHashtagBarForStatus } from './hashtag_bar';
|
import { getHashtagBarForStatus } from './hashtag_bar';
|
||||||
import { RelativeTimestamp } from './relative_timestamp';
|
import { RelativeTimestamp } from './relative_timestamp';
|
||||||
import StatusActionBar from './status_action_bar';
|
import StatusActionBar from './status_action_bar';
|
||||||
|
@ -409,12 +409,20 @@ class Status extends ImmutablePureComponent {
|
||||||
const matchedFilters = status.get('matched_filters');
|
const matchedFilters = status.get('matched_filters');
|
||||||
|
|
||||||
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
|
if (status.get('reblog', null) !== null && typeof status.get('reblog') === 'object') {
|
||||||
const display_name_html = { __html: status.getIn(['account', 'display_name_html']) };
|
const name = (
|
||||||
|
<LinkedDisplayName
|
||||||
|
displayProps={{
|
||||||
|
account: status.get('account'),
|
||||||
|
variant: 'simple'
|
||||||
|
}}
|
||||||
|
className='status__display-name muted'
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
|
||||||
prepend = (
|
prepend = (
|
||||||
<div className='status__prepend'>
|
<div className='status__prepend'>
|
||||||
<div className='status__prepend__icon'><Icon id='retweet' icon={RepeatIcon} /></div>
|
<div className='status__prepend__icon'><Icon id='retweet' icon={RepeatIcon} /></div>
|
||||||
<FormattedMessage id='status.reblogged_by' defaultMessage='{name} boosted' values={{ name: <Link data-id={status.getIn(['account', 'id'])} data-hover-card-account={status.getIn(['account', 'id'])} to={`/@${status.getIn(['account', 'acct'])}`} className='status__display-name muted'><bdi><strong dangerouslySetInnerHTML={display_name_html} /></bdi></Link> }} />
|
<FormattedMessage id='status.reblogged_by' defaultMessage='{name} boosted' values={{ name }} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -570,13 +578,11 @@ class Status extends ImmutablePureComponent {
|
||||||
<RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
|
<RelativeTimestamp timestamp={status.get('created_at')} />{status.get('edited_at') && <abbr title={intl.formatMessage(messages.edited, { date: intl.formatDate(status.get('edited_at'), { year: 'numeric', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }) })}> *</abbr>}
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link to={`/@${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])} data-hover-card-account={status.getIn(['account', 'id'])} className='status__display-name'>
|
<LinkedDisplayName displayProps={{account: status.get('account')}} className='status__display-name'>
|
||||||
<div className='status__avatar'>
|
<div className='status__avatar'>
|
||||||
{statusAvatar}
|
{statusAvatar}
|
||||||
</div>
|
</div>
|
||||||
|
</LinkedDisplayName>
|
||||||
<DisplayName account={status.get('account')} />
|
|
||||||
</Link>
|
|
||||||
|
|
||||||
{isQuotedPost && !!this.props.onQuoteCancel && (
|
{isQuotedPost && !!this.props.onQuoteCancel && (
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|
|
@ -2,9 +2,10 @@ import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
|
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { DisplayedName } from 'mastodon/features/notifications_v2/components/displayed_name';
|
|
||||||
import { useAppSelector } from 'mastodon/store';
|
import { useAppSelector } from 'mastodon/store';
|
||||||
|
|
||||||
|
import { LinkedDisplayName } from './display_name';
|
||||||
|
|
||||||
export const StatusThreadLabel: React.FC<{
|
export const StatusThreadLabel: React.FC<{
|
||||||
accountId: string;
|
accountId: string;
|
||||||
inReplyToAccountId: string;
|
inReplyToAccountId: string;
|
||||||
|
@ -27,7 +28,13 @@ export const StatusThreadLabel: React.FC<{
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='status.replied_to'
|
id='status.replied_to'
|
||||||
defaultMessage='Replied to {name}'
|
defaultMessage='Replied to {name}'
|
||||||
values={{ name: <DisplayedName accountIds={[inReplyToAccountId]} /> }}
|
values={{
|
||||||
|
name: (
|
||||||
|
<LinkedDisplayName
|
||||||
|
displayProps={{ account: inReplyToAccount, variant: 'simple' }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
||||||
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
import { DisplayName } from '@/mastodon/components/display_name';
|
||||||
|
|
||||||
export default class FollowRequestNote extends ImmutablePureComponent {
|
export default class FollowRequestNote extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ export default class FollowRequestNote extends ImmutablePureComponent {
|
||||||
return (
|
return (
|
||||||
<div className='follow-request-banner'>
|
<div className='follow-request-banner'>
|
||||||
<div className='follow-request-banner__message'>
|
<div className='follow-request-banner__message'>
|
||||||
<FormattedMessage id='account.requested_follow' defaultMessage='{name} has requested to follow you' values={{ name: <bdi><strong dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /></bdi> }} />
|
<FormattedMessage id='account.requested_follow' defaultMessage='{name} has requested to follow you' values={{ name: <DisplayName account={account} variant='simple' /> }} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='follow-request-banner__action'>
|
<div className='follow-request-banner__action'>
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Helmet } from 'react-helmet';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
|
|
||||||
import { AccountBio } from '@/mastodon/components/account_bio';
|
import { AccountBio } from '@/mastodon/components/account_bio';
|
||||||
|
import { DisplayName } from '@/mastodon/components/display_name';
|
||||||
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
||||||
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
|
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
|
||||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||||
|
@ -774,7 +775,6 @@ export const AccountHeader: React.FC<{
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const displayNameHtml = { __html: account.display_name_html };
|
|
||||||
const fields = account.fields;
|
const fields = account.fields;
|
||||||
const isLocal = !account.acct.includes('@');
|
const isLocal = !account.acct.includes('@');
|
||||||
const username = account.acct.split('@')[0];
|
const username = account.acct.split('@')[0];
|
||||||
|
@ -863,7 +863,7 @@ export const AccountHeader: React.FC<{
|
||||||
|
|
||||||
<div className='account__header__tabs__name'>
|
<div className='account__header__tabs__name'>
|
||||||
<h1>
|
<h1>
|
||||||
<span dangerouslySetInnerHTML={displayNameHtml} />
|
<DisplayName account={account} variant='simple' />
|
||||||
<small>
|
<small>
|
||||||
<span>
|
<span>
|
||||||
@{username}
|
@{username}
|
||||||
|
|
|
@ -1,33 +1,26 @@
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
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 { LinkedDisplayName } from '@/mastodon/components/display_name';
|
||||||
import type { Account } from '@/mastodon/models/account';
|
import type { Account } from '@/mastodon/models/account';
|
||||||
|
|
||||||
import { useFetchFamiliarFollowers } from '../hooks/familiar_followers';
|
import { useFetchFamiliarFollowers } from '../hooks/familiar_followers';
|
||||||
|
|
||||||
const AccountLink: React.FC<{ account?: Account }> = ({ account }) => {
|
|
||||||
if (!account) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
to={`/@${account.acct}`}
|
|
||||||
data-hover-card-account={account.id}
|
|
||||||
dangerouslySetInnerHTML={{ __html: account.display_name_html }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const FamiliarFollowersReadout: React.FC<{ familiarFollowers: Account[] }> = ({
|
const FamiliarFollowersReadout: React.FC<{ familiarFollowers: Account[] }> = ({
|
||||||
familiarFollowers,
|
familiarFollowers,
|
||||||
}) => {
|
}) => {
|
||||||
const messageData = {
|
const messageData = {
|
||||||
name1: <AccountLink account={familiarFollowers.at(0)} />,
|
name1: (
|
||||||
name2: <AccountLink account={familiarFollowers.at(1)} />,
|
<LinkedDisplayName
|
||||||
|
displayProps={{ account: familiarFollowers.at(0), variant: 'simple' }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
name2: (
|
||||||
|
<LinkedDisplayName
|
||||||
|
displayProps={{ account: familiarFollowers.at(1), variant: 'simple' }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
othersCount: familiarFollowers.length - 2,
|
othersCount: familiarFollowers.length - 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { DisplayName } from '@/mastodon/components/display_name';
|
||||||
import { AvatarOverlay } from 'mastodon/components/avatar_overlay';
|
import { AvatarOverlay } from 'mastodon/components/avatar_overlay';
|
||||||
import { DisplayName } from 'mastodon/components/display_name';
|
|
||||||
import { useAppSelector } from 'mastodon/store';
|
import { useAppSelector } from 'mastodon/store';
|
||||||
|
|
||||||
export const MovedNote: React.FC<{
|
export const MovedNote: React.FC<{
|
||||||
|
@ -20,15 +20,7 @@ export const MovedNote: React.FC<{
|
||||||
id='account.moved_to'
|
id='account.moved_to'
|
||||||
defaultMessage='{name} has indicated that their new account is now:'
|
defaultMessage='{name} has indicated that their new account is now:'
|
||||||
values={{
|
values={{
|
||||||
name: (
|
name: <DisplayName account={from} variant='simple' />,
|
||||||
<bdi>
|
|
||||||
<strong
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: from?.display_name_html ?? '',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</bdi>
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { useCallback } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { DisplayName } from '@/mastodon/components/display_name';
|
||||||
import { toggleStatusSpoilers } from 'mastodon/actions/statuses';
|
import { toggleStatusSpoilers } from 'mastodon/actions/statuses';
|
||||||
import { DetailedStatus } from 'mastodon/features/status/components/detailed_status';
|
import { DetailedStatus } from 'mastodon/features/status/components/detailed_status';
|
||||||
import { me } from 'mastodon/initial_state';
|
import { me } from 'mastodon/initial_state';
|
||||||
|
@ -79,11 +80,7 @@ export const HighlightedPost: React.FC<{
|
||||||
id='annual_report.summary.highlighted_post.possessive'
|
id='annual_report.summary.highlighted_post.possessive'
|
||||||
defaultMessage="{name}'s"
|
defaultMessage="{name}'s"
|
||||||
values={{
|
values={{
|
||||||
name: account && (
|
name: <DisplayName account={account} variant='simple' />,
|
||||||
<bdi
|
|
||||||
dangerouslySetInnerHTML={{ __html: account.display_name_html }}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</strong>
|
</strong>
|
||||||
|
|
|
@ -25,6 +25,7 @@ import StatusContent from 'mastodon/components/status_content';
|
||||||
import { Dropdown } from 'mastodon/components/dropdown_menu';
|
import { Dropdown } from 'mastodon/components/dropdown_menu';
|
||||||
import { autoPlayGif } from 'mastodon/initial_state';
|
import { autoPlayGif } from 'mastodon/initial_state';
|
||||||
import { makeGetStatus } from 'mastodon/selectors';
|
import { makeGetStatus } from 'mastodon/selectors';
|
||||||
|
import { LinkedDisplayName } from '@/mastodon/components/display_name';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
more: { id: 'status.more', defaultMessage: 'More' },
|
more: { id: 'status.more', defaultMessage: 'More' },
|
||||||
|
@ -139,15 +140,8 @@ export const Conversation = ({ conversation, scrollKey }) => {
|
||||||
|
|
||||||
menu.push({ text: intl.formatMessage(messages.delete), action: handleDelete });
|
menu.push({ text: intl.formatMessage(messages.delete), action: handleDelete });
|
||||||
|
|
||||||
const names = accounts.map(a => (
|
const names = accounts.map((account) => (
|
||||||
<Link to={`/@${a.get('acct')}`} key={a.get('id')} data-hover-card-account={a.get('id')}>
|
<LinkedDisplayName displayProps={{account, variant: 'simple'}} key={account.get('id')} />
|
||||||
<bdi>
|
|
||||||
<strong
|
|
||||||
className='display-name__html'
|
|
||||||
dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }}
|
|
||||||
/>
|
|
||||||
</bdi>
|
|
||||||
</Link>
|
|
||||||
)).reduce((prev, cur) => [prev, ', ', cur]);
|
)).reduce((prev, cur) => [prev, ', ', cur]);
|
||||||
|
|
||||||
const handlers = {
|
const handlers = {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { Avatar } from 'mastodon/components/avatar';
|
import { Avatar } from 'mastodon/components/avatar';
|
||||||
import { useAppSelector } from 'mastodon/store';
|
import { useAppSelector } from 'mastodon/store';
|
||||||
|
import { LinkedDisplayName } from '@/mastodon/components/display_name';
|
||||||
|
|
||||||
export const AuthorLink = ({ accountId }) => {
|
export const AuthorLink = ({ accountId }) => {
|
||||||
const account = useAppSelector(state => state.getIn(['accounts', accountId]));
|
const account = useAppSelector(state => state.getIn(['accounts', accountId]));
|
||||||
|
@ -13,10 +12,9 @@ export const AuthorLink = ({ accountId }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={`/@${account.get('acct')}`} className='story__details__shared__author-link' data-hover-card-account={accountId}>
|
<LinkedDisplayName displayProps={{account}} className='story__details__shared__author-link'>
|
||||||
<Avatar account={account} size={16} />
|
<Avatar account={account} size={16} />
|
||||||
<bdi dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} />
|
</LinkedDisplayName>
|
||||||
</Link>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import classNames from 'classnames';
|
||||||
import { escapeRegExp } from 'lodash';
|
import { escapeRegExp } from 'lodash';
|
||||||
import { useDebouncedCallback } from 'use-debounce';
|
import { useDebouncedCallback } from 'use-debounce';
|
||||||
|
|
||||||
|
import { DisplayName } from '@/mastodon/components/display_name';
|
||||||
import { openModal, closeModal } from 'mastodon/actions/modal';
|
import { openModal, closeModal } from 'mastodon/actions/modal';
|
||||||
import { apiRequest } from 'mastodon/api';
|
import { apiRequest } from 'mastodon/api';
|
||||||
import { Button } from 'mastodon/components/button';
|
import { Button } from 'mastodon/components/button';
|
||||||
|
@ -404,15 +405,13 @@ const InteractionModal: React.FC<{
|
||||||
url: string;
|
url: string;
|
||||||
}> = ({ accountId, url }) => {
|
}> = ({ accountId, url }) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const displayNameHtml = useAppSelector(
|
|
||||||
(state) => state.accounts.get(accountId)?.display_name_html ?? '',
|
|
||||||
);
|
|
||||||
const signupUrl = useAppSelector(
|
const signupUrl = useAppSelector(
|
||||||
(state) =>
|
(state) =>
|
||||||
(state.server.getIn(['server', 'registrations', 'url'], null) ||
|
(state.server.getIn(['server', 'registrations', 'url'], null) ||
|
||||||
'/auth/sign_up') as string,
|
'/auth/sign_up') as string,
|
||||||
);
|
);
|
||||||
const name = <bdi dangerouslySetInnerHTML={{ __html: displayNameHtml }} />;
|
const account = useAppSelector((state) => state.accounts.get(accountId));
|
||||||
|
const name = <DisplayName account={account} variant='simple' />;
|
||||||
|
|
||||||
const handleSignupClick = useCallback(() => {
|
const handleSignupClick = useCallback(() => {
|
||||||
dispatch(
|
dispatch(
|
||||||
|
|
|
@ -18,6 +18,7 @@ import PersonAddIcon from '@/material-icons/400-24px/person_add-fill.svg?react';
|
||||||
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
import RepeatIcon from '@/material-icons/400-24px/repeat.svg?react';
|
||||||
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
|
import StarIcon from '@/material-icons/400-24px/star-fill.svg?react';
|
||||||
import { Account } from 'mastodon/components/account';
|
import { Account } from 'mastodon/components/account';
|
||||||
|
import { LinkedDisplayName } from '@/mastodon/components/display_name';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { Hotkeys } from 'mastodon/components/hotkeys';
|
import { Hotkeys } from 'mastodon/components/hotkeys';
|
||||||
import { StatusQuoteManager } from 'mastodon/components/status_quoted';
|
import { StatusQuoteManager } from 'mastodon/components/status_quoted';
|
||||||
|
@ -485,8 +486,10 @@ class Notification extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetAccount = report.get('target_account');
|
const targetAccount = report.get('target_account');
|
||||||
const targetDisplayNameHtml = { __html: targetAccount.get('display_name_html') };
|
const targetLink = <LinkedDisplayName
|
||||||
const targetLink = <bdi><Link className='notification__display-name' title={targetAccount.get('acct')} data-hover-card-account={targetAccount.get('id')} to={`/@${targetAccount.get('acct')}`} dangerouslySetInnerHTML={targetDisplayNameHtml} /></bdi>;
|
className='notification__display-name'
|
||||||
|
displayProps={{account:targetAccount, variant: 'simple'}}
|
||||||
|
/>;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Hotkeys handlers={this.getHandlers()}>
|
<Hotkeys handlers={this.getHandlers()}>
|
||||||
|
@ -508,8 +511,7 @@ class Notification extends ImmutablePureComponent {
|
||||||
render () {
|
render () {
|
||||||
const { notification } = this.props;
|
const { notification } = this.props;
|
||||||
const account = notification.get('account');
|
const account = notification.get('account');
|
||||||
const displayNameHtml = { __html: account.get('display_name_html') };
|
const link = <LinkedDisplayName className='notification__display-name' displayProps={{account, variant: 'simple'}} />;
|
||||||
const link = <bdi><Link className='notification__display-name' href={`/@${account.get('acct')}`} title={account.get('acct')} data-hover-card-account={account.get('id')} to={`/@${account.get('acct')}`} dangerouslySetInnerHTML={displayNameHtml} /></bdi>;
|
|
||||||
|
|
||||||
switch(notification.get('type')) {
|
switch(notification.get('type')) {
|
||||||
case 'follow':
|
case 'follow':
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { acceptNotificationRequest, dismissNotificationRequest } from 'mastodon/
|
||||||
import { initReport } from 'mastodon/actions/reports';
|
import { initReport } from 'mastodon/actions/reports';
|
||||||
import { Avatar } from 'mastodon/components/avatar';
|
import { Avatar } from 'mastodon/components/avatar';
|
||||||
import { CheckBox } from 'mastodon/components/check_box';
|
import { CheckBox } from 'mastodon/components/check_box';
|
||||||
|
import { DisplayName } from '@/mastodon/components/display_name';
|
||||||
import { IconButton } from 'mastodon/components/icon_button';
|
import { IconButton } from 'mastodon/components/icon_button';
|
||||||
import { Dropdown } from 'mastodon/components/dropdown_menu';
|
import { Dropdown } from 'mastodon/components/dropdown_menu';
|
||||||
import { makeGetAccount } from 'mastodon/selectors';
|
import { makeGetAccount } from 'mastodon/selectors';
|
||||||
|
@ -96,7 +97,7 @@ export const NotificationRequest = ({ id, accountId, notificationsCount, checked
|
||||||
|
|
||||||
<div className='notification-request__name'>
|
<div className='notification-request__name'>
|
||||||
<div className='notification-request__name__display-name'>
|
<div className='notification-request__name__display-name'>
|
||||||
<bdi><strong dangerouslySetInnerHTML={{ __html: account?.get('display_name_html') }} /></bdi>
|
<DisplayName account={account} variant='simple' />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<span>@{account?.get('acct')}</span>
|
<span>@{account?.get('acct')}</span>
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import { useAppSelector } from 'mastodon/store';
|
|
||||||
|
|
||||||
export const DisplayedName: React.FC<{
|
|
||||||
accountIds: string[];
|
|
||||||
}> = ({ accountIds }) => {
|
|
||||||
const lastAccountId = accountIds[0] ?? '0';
|
|
||||||
const account = useAppSelector((state) => state.accounts.get(lastAccountId));
|
|
||||||
|
|
||||||
if (!account) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Link
|
|
||||||
to={`/@${account.acct}`}
|
|
||||||
title={`@${account.acct}`}
|
|
||||||
data-hover-card-account={account.id}
|
|
||||||
>
|
|
||||||
<bdi dangerouslySetInnerHTML={{ __html: account.display_name_html }} />
|
|
||||||
</Link>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -2,6 +2,7 @@ import { FormattedMessage, useIntl, defineMessages } from 'react-intl';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { DisplayName } from '@/mastodon/components/display_name';
|
||||||
import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react';
|
import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react';
|
||||||
import { Icon } from 'mastodon/components/icon';
|
import { Icon } from 'mastodon/components/icon';
|
||||||
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
|
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
|
||||||
|
@ -42,11 +43,9 @@ export const NotificationAdminReport: React.FC<{
|
||||||
|
|
||||||
if (!account || !targetAccount) return null;
|
if (!account || !targetAccount) return null;
|
||||||
|
|
||||||
const domain = account.acct.split('@')[1];
|
|
||||||
|
|
||||||
const values = {
|
const values = {
|
||||||
name: <bdi>{domain ?? `@${account.acct}`}</bdi>,
|
name: <DisplayName account={account} variant='simple' />,
|
||||||
target: <bdi>@{targetAccount.acct}</bdi>,
|
target: <DisplayName account={targetAccount} variant='simple' />,
|
||||||
category: intl.formatMessage(messages[report.category]),
|
category: intl.formatMessage(messages[report.category]),
|
||||||
count: report.status_ids.length,
|
count: report.status_ids.length,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@ import type { JSX } from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { LinkedDisplayName } from '@/mastodon/components/display_name';
|
||||||
import { replyComposeById } from 'mastodon/actions/compose';
|
import { replyComposeById } from 'mastodon/actions/compose';
|
||||||
import { navigateToStatus } from 'mastodon/actions/statuses';
|
import { navigateToStatus } from 'mastodon/actions/statuses';
|
||||||
import { Avatar } from 'mastodon/components/avatar';
|
import { Avatar } from 'mastodon/components/avatar';
|
||||||
|
@ -14,7 +15,6 @@ import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
|
||||||
import { NOTIFICATIONS_GROUP_MAX_AVATARS } from 'mastodon/models/notification_group';
|
import { NOTIFICATIONS_GROUP_MAX_AVATARS } from 'mastodon/models/notification_group';
|
||||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||||
|
|
||||||
import { DisplayedName } from './displayed_name';
|
|
||||||
import { EmbeddedStatus } from './embedded_status';
|
import { EmbeddedStatus } from './embedded_status';
|
||||||
|
|
||||||
const AVATAR_SIZE = 28;
|
const AVATAR_SIZE = 28;
|
||||||
|
@ -61,15 +61,18 @@ export const NotificationGroupWithStatus: React.FC<{
|
||||||
additionalContent,
|
additionalContent,
|
||||||
}) => {
|
}) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
const account = useAppSelector((state) =>
|
||||||
|
state.accounts.get(accountIds.at(0) ?? ''),
|
||||||
|
);
|
||||||
|
|
||||||
const label = useMemo(
|
const label = useMemo(
|
||||||
() =>
|
() =>
|
||||||
labelRenderer(
|
labelRenderer(
|
||||||
<DisplayedName accountIds={accountIds} />,
|
<LinkedDisplayName displayProps={{ account, variant: 'simple' }} />,
|
||||||
count,
|
count,
|
||||||
labelSeeMoreHref,
|
labelSeeMoreHref,
|
||||||
),
|
),
|
||||||
[labelRenderer, accountIds, count, labelSeeMoreHref],
|
[labelRenderer, account, count, labelSeeMoreHref],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isPrivateMention = useAppSelector(
|
const isPrivateMention = useAppSelector(
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { useMemo } from 'react';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
import { LinkedDisplayName } from '@/mastodon/components/display_name';
|
||||||
import { replyComposeById } from 'mastodon/actions/compose';
|
import { replyComposeById } from 'mastodon/actions/compose';
|
||||||
import { toggleReblog, toggleFavourite } from 'mastodon/actions/interactions';
|
import { toggleReblog, toggleFavourite } from 'mastodon/actions/interactions';
|
||||||
import {
|
import {
|
||||||
|
@ -15,7 +16,6 @@ import { StatusQuoteManager } from 'mastodon/components/status_quoted';
|
||||||
import { getStatusHidden } from 'mastodon/selectors/filters';
|
import { getStatusHidden } from 'mastodon/selectors/filters';
|
||||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||||
|
|
||||||
import { DisplayedName } from './displayed_name';
|
|
||||||
import type { LabelRenderer } from './notification_group_with_status';
|
import type { LabelRenderer } from './notification_group_with_status';
|
||||||
|
|
||||||
export const NotificationWithStatus: React.FC<{
|
export const NotificationWithStatus: React.FC<{
|
||||||
|
@ -39,9 +39,16 @@ export const NotificationWithStatus: React.FC<{
|
||||||
}) => {
|
}) => {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const account = useAppSelector((state) =>
|
||||||
|
state.accounts.get(accountIds.at(0) ?? ''),
|
||||||
|
);
|
||||||
const label = useMemo(
|
const label = useMemo(
|
||||||
() => labelRenderer(<DisplayedName accountIds={accountIds} />, count),
|
() =>
|
||||||
[labelRenderer, accountIds, count],
|
labelRenderer(
|
||||||
|
<LinkedDisplayName displayProps={{ account, variant: 'simple' }} />,
|
||||||
|
count,
|
||||||
|
),
|
||||||
|
[labelRenderer, account, count],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isPrivateMention = useAppSelector(
|
const isPrivateMention = useAppSelector(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user