Emoji Rendering (#35424)

This commit is contained in:
Echo authored and GitHub committed 2025-07-22 14:43:15 +00:00
1 parent 0af2c4829f
commit 760d00b7f7
25 files changed
+1064 -70

No files matched your search

@@ -2,27 +2,44 @@ import { useCallback } from 'react';
import { useLinks } from 'mastodon/hooks/useLinks';
import { EmojiHTML } from '../features/emoji/emoji_html';
import { isFeatureEnabled } from '../initial_state';
import { useAppSelector } from '../store';
interface AccountBioProps {
note: string;
className: string;
dropdownAccountId?: string;
accountId: string;
showDropdown?: boolean;
}
export const AccountBio: React.FC<AccountBioProps> = ({
note,
className,
dropdownAccountId,
accountId,
showDropdown = false,
}) => {
const handleClick = useLinks(!!dropdownAccountId);
const handleClick = useLinks(showDropdown);
const handleNodeChange = useCallback(
(node: HTMLDivElement | null) => {
if (!dropdownAccountId || !node || node.childNodes.length === 0) {
if (!showDropdown || !node || node.childNodes.length === 0) {
return;
}
addDropdownToHashtags(node, dropdownAccountId);
addDropdownToHashtags(node, accountId);
},
[dropdownAccountId],
[showDropdown, accountId],
);
const note = useAppSelector((state) => {
const account = state.accounts.get(accountId);
if (!account) {
return '';
}
return isFeatureEnabled('modern_emojis')
? account.note
: account.note_emojified;
});
const extraEmojis = useAppSelector((state) => {
const account = state.accounts.get(accountId);
return account?.emojis;
});
if (note.length === 0) {
return null;
@@ -31,10 +48,11 @@ export const AccountBio: React.FC<AccountBioProps> = ({
return (
<div
className={`${className} translate`}
dangerouslySetInnerHTML={{ __html: note }}
onClickCapture={handleClick}
ref={handleNodeChange}
/>
>
<EmojiHTML htmlString={note} extraEmojis={extraEmojis} />
</div>
);
};
@@ -102,7 +102,7 @@ export const HoverCardAccount = forwardRef<
<>
<div className='hover-card__text-row'>
<AccountBio
note={account.note_emojified}
accountId={account.id}
className='hover-card__bio'
/>
<AccountFields fields={account.fields} limit={2} />
@@ -13,7 +13,8 @@ import ChevronRightIcon from '@/material-icons/400-24px/chevron_right.svg?react'
import { Icon } from 'mastodon/components/icon';
import { Poll } from 'mastodon/components/poll';
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
import { autoPlayGif, languages as preloadedLanguages } from 'mastodon/initial_state';
import { autoPlayGif, isFeatureEnabled, languages as preloadedLanguages } from 'mastodon/initial_state';
import { EmojiHTML } from '../features/emoji/emoji_html';
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
@@ -23,6 +24,9 @@ const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
* @returns {string}
*/
export function getStatusContent(status) {
if (isFeatureEnabled('modern_emojis')) {
return status.getIn(['translation', 'content']) || status.get('content');
}
return status.getIn(['translation', 'contentHtml']) || status.get('contentHtml');
}
@@ -228,7 +232,7 @@ class StatusContent extends PureComponent {
const targetLanguages = this.props.languages?.get(status.get('language') || 'und');
const renderTranslate = this.props.onTranslate && this.props.identity.signedIn && ['public', 'unlisted'].includes(status.get('visibility')) && status.get('search_index').trim().length > 0 && targetLanguages?.includes(contentLocale);
const content = { __html: statusContent ?? getStatusContent(status) };
const content = statusContent ?? getStatusContent(status);
const language = status.getIn(['translation', 'language']) || status.get('language');
const classNames = classnames('status__content', {
'status__content--with-action': this.props.onClick && this.props.history,
@@ -253,7 +257,12 @@ class StatusContent extends PureComponent {
return (
<>
<div className={classNames} ref={this.setRef} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} key='status-content' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
<div className='status__content__text status__content__text--visible translate' lang={language} dangerouslySetInnerHTML={content} />
<EmojiHTML
className='status__content__text status__content__text--visible translate'
lang={language}
htmlString={content}
extraEmojis={status.get('emojis')}
/>
{poll}
{translateButton}
@@ -265,7 +274,12 @@ class StatusContent extends PureComponent {
} else {
return (
<div className={classNames} ref={this.setRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
<div className='status__content__text status__content__text--visible translate' lang={language} dangerouslySetInnerHTML={content} />
<EmojiHTML
className='status__content__text status__content__text--visible translate'
lang={language}
htmlString={content}
extraEmojis={status.get('emojis')}
/>
{poll}
{translateButton}