[Glitch] Refactor: Replace all display name usage for new component

Port dfef7d9407 to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
Echo authored and Claire committed 2025-09-17 19:36:18 +02:00
1 parent 210786efd8
commit 0a6895f8b9
21 files changed
+188 -338

No files matched your search

@@ -1,122 +0,0 @@
import React from 'react';
import type { List } from 'immutable';
import type { Account } from 'flavours/glitch/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>
);
}
}
@@ -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>
);
};
@@ -1,122 +1,52 @@
import type { ComponentPropsWithoutRef, FC } from 'react';
import { useMemo } from 'react';
import classNames from 'classnames';
import type { LinkProps } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { EmojiHTML } from '@/flavours/glitch/features/emoji/emoji_html';
import type { Account } from '@/flavours/glitch/models/account';
import { isModernEmojiEnabled } from '@/flavours/glitch/utils/environment';
import { Permalink } from 'flavours/glitch/components/permalink';
import { Skeleton } from '../skeleton';
import { DisplayNameDefault } from './default';
import { DisplayNameWithoutDomain } from './no-domain';
import { DisplayNameSimple } from './simple';
interface Props {
export interface DisplayNameProps {
account?: Account;
localDomain?: string;
simple?: boolean;
noDomain?: boolean;
variant?: 'default' | 'simple' | 'noDomain';
}
export const DisplayName: FC<Props & ComponentPropsWithoutRef<'span'>> = ({
account,
localDomain,
simple = false,
noDomain = false,
className,
...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'>
&nbsp;
<Skeleton width='7ch' />
</span>
)}
</span>
);
export const DisplayName: FC<
DisplayNameProps & ComponentPropsWithoutRef<'span'>
> = ({ variant = 'default', ...props }) => {
if (variant === 'simple') {
return <DisplayNameSimple {...props} />;
} else if (variant === 'noDomain') {
return <DisplayNameWithoutDomain {...props} />;
}
const accountName = isModernEmojiEnabled()
? 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'>&nbsp;{username}</span>
)}
</span>
);
return <DisplayNameDefault {...props} />;
};
export const LinkedDisplayName: FC<
Props & { asProps?: ComponentPropsWithoutRef<'span'> } & Partial<LinkProps>
> = ({
account,
asProps = {},
className,
localDomain,
simple,
noDomain,
...linkProps
}) => {
const displayProps = {
account,
className,
localDomain,
simple,
noDomain,
...asProps,
};
Omit<LinkProps, 'to'> & {
displayProps: DisplayNameProps & ComponentPropsWithoutRef<'span'>;
}
> = ({ displayProps, children, ...linkProps }) => {
const { account } = displayProps;
if (!account) {
return <DisplayName {...displayProps} />;
}
return (
<Link
<Permalink
href={account.url}
to={`/@${account.acct}`}
title={`@${account.acct}`}
data-id={account.id}
data-hover-card-account={account.id}
{...linkProps}
>
{children}
<DisplayName {...displayProps} />
</Link>
</Permalink>
);
};
@@ -0,0 +1,39 @@
import type { ComponentPropsWithoutRef, FC } from 'react';
import classNames from 'classnames';
import { EmojiHTML } from '@/flavours/glitch/features/emoji/emoji_html';
import { isModernEmojiEnabled } from '@/flavours/glitch/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>
);
};
@@ -0,0 +1,23 @@
import type { ComponentPropsWithoutRef, FC } from 'react';
import { EmojiHTML } from '@/flavours/glitch/features/emoji/emoji_html';
import { isModernEmojiEnabled } from '@/flavours/glitch/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>
);
};
@@ -25,10 +25,9 @@ import { displayMedia } from '../initial_state';
import AttachmentList from './attachment_list';
import { Avatar } from './avatar';
import { AvatarOverlay } from './avatar_overlay';
import { DisplayName } from './display_name';
import { LinkedDisplayName } from './display_name';
import { getHashtagBarForStatus } from './hashtag_bar';
import { MentionsPlaceholder } from './mentions_placeholder';
import { Permalink } from './permalink';
import StatusActionBar from './status_action_bar';
import StatusContent from './status_content';
import StatusIcons from './status_icons';
@@ -713,14 +712,11 @@ class Status extends ImmutablePureComponent {
{(!muted) && (
<header onClick={this.handleHeaderClick} onAuxClick={this.handleHeaderClick} className='status__info'>
<Permalink href={status.getIn(['account', 'url'])} 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'>
{statusAvatar}
</div>
<DisplayName account={status.get('account')} />
</Permalink>
</LinkedDisplayName>
{isQuotedPost && !!this.props.onQuoteCancel ? (
<IconButton
@@ -2,9 +2,10 @@ import { FormattedMessage } from 'react-intl';
import ReplyIcon from '@/material-icons/400-24px/reply.svg?react';
import { Icon } from 'flavours/glitch/components/icon';
import { DisplayedName } from 'flavours/glitch/features/notifications_v2/components/displayed_name';
import { useAppSelector } from 'flavours/glitch/store';
import { LinkedDisplayName } from './display_name';
export const StatusThreadLabel: React.FC<{
accountId: string;
inReplyToAccountId: string;
@@ -27,7 +28,13 @@ export const StatusThreadLabel: React.FC<{
<FormattedMessage
id='status.replied_to'
defaultMessage='Replied to {name}'
values={{ name: <DisplayedName accountIds={[inReplyToAccountId]} /> }}
values={{
name: (
<LinkedDisplayName
displayProps={{ account: inReplyToAccount, variant: 'simple' }}
/>
),
}}
/>
);
} else {