Emoji: Remove final flag (#36409)

This commit is contained in:
Echo 2025-10-28 12:33:27 +01:00 committed by GitHub
commit 85d0cdb5f7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
37 changed files with 112 additions and 1103 deletions

View file

@ -1,11 +1,6 @@
import { useCallback } from 'react';
import classNames from 'classnames';
import { useLinks } from 'mastodon/hooks/useLinks';
import { useAppSelector } from '../store';
import { isModernEmojiEnabled } from '../utils/environment';
import { EmojiHTML } from './emoji/html';
import { useElementHandledLink } from './status/handled_link';
@ -21,22 +16,6 @@ export const AccountBio: React.FC<AccountBioProps> = ({
accountId,
showDropdown = false,
}) => {
const handleClick = useLinks(showDropdown);
const handleNodeChange = useCallback(
(node: HTMLDivElement | null) => {
if (
!showDropdown ||
!node ||
node.childNodes.length === 0 ||
isModernEmojiEnabled()
) {
return;
}
addDropdownToHashtags(node, accountId);
},
[showDropdown, accountId],
);
const htmlHandlers = useElementHandledLink({
hashtagAccountId: showDropdown ? accountId : undefined,
});
@ -62,30 +41,7 @@ export const AccountBio: React.FC<AccountBioProps> = ({
htmlString={note}
extraEmojis={extraEmojis}
className={classNames(className, 'translate')}
onClickCapture={handleClick}
ref={handleNodeChange}
{...htmlHandlers}
/>
);
};
function addDropdownToHashtags(node: HTMLElement | null, accountId: string) {
if (!node) {
return;
}
for (const childNode of node.childNodes) {
if (!(childNode instanceof HTMLElement)) {
continue;
}
if (
childNode instanceof HTMLAnchorElement &&
(childNode.classList.contains('hashtag') ||
childNode.innerText.startsWith('#')) &&
!childNode.dataset.menuHashtag
) {
childNode.dataset.menuHashtag = accountId;
} else if (childNode.childNodes.length > 0) {
addDropdownToHashtags(childNode, accountId);
}
}
}

View file

@ -7,8 +7,6 @@ import {
useState,
} from 'react';
import classNames from 'classnames';
import { cleanExtraEmojis } from '@/mastodon/features/emoji/normalize';
import { autoPlayGif } from '@/mastodon/initial_state';
import { polymorphicForwardRef } from '@/types/polymorphic';
@ -65,11 +63,7 @@ export const AnimateEmojiProvider = polymorphicForwardRef<
const parentContext = useContext(AnimateEmojiContext);
if (parentContext !== null) {
return (
<Wrapper
{...props}
className={classNames(className, 'animate-parent')}
ref={ref}
>
<Wrapper {...props} className={className} ref={ref}>
{children}
</Wrapper>
);
@ -78,7 +72,7 @@ export const AnimateEmojiProvider = polymorphicForwardRef<
return (
<Wrapper
{...props}
className={classNames(className, 'animate-parent')}
className={className}
onMouseEnter={handleEnter}
onMouseLeave={handleLeave}
ref={ref}

View file

@ -1,9 +1,6 @@
import { useMemo } from 'react';
import classNames from 'classnames';
import type { CustomEmojiMapArg } from '@/mastodon/features/emoji/types';
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
import type {
OnAttributeHandler,
OnElementHandler,
@ -22,7 +19,7 @@ export interface EmojiHTMLProps {
onAttribute?: OnAttributeHandler;
}
export const ModernEmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>(
export const EmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>(
(
{
extraEmojis,
@ -59,32 +56,4 @@ export const ModernEmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>(
);
},
);
ModernEmojiHTML.displayName = 'ModernEmojiHTML';
export const LegacyEmojiHTML = polymorphicForwardRef<'div', EmojiHTMLProps>(
(props, ref) => {
const {
as: asElement,
htmlString,
extraEmojis,
className,
onElement,
onAttribute,
...rest
} = props;
const Wrapper = asElement ?? 'div';
return (
<Wrapper
{...rest}
ref={ref}
dangerouslySetInnerHTML={{ __html: htmlString }}
className={classNames(className, 'animate-parent')}
/>
);
},
);
LegacyEmojiHTML.displayName = 'LegacyEmojiHTML';
export const EmojiHTML = isModernEmojiEnabled()
? ModernEmojiHTML
: LegacyEmojiHTML;
EmojiHTML.displayName = 'EmojiHTML';

View file

@ -23,8 +23,6 @@ import { domain } from 'mastodon/initial_state';
import { getAccountHidden } from 'mastodon/selectors/accounts';
import { useAppSelector, useAppDispatch } from 'mastodon/store';
import { useLinks } from '../hooks/useLinks';
export const HoverCardAccount = forwardRef<
HTMLDivElement,
{ accountId?: string }
@ -66,8 +64,6 @@ export const HoverCardAccount = forwardRef<
!isMutual &&
!isFollower;
const handleClick = useLinks();
return (
<div
ref={ref}
@ -110,7 +106,7 @@ export const HoverCardAccount = forwardRef<
className='hover-card__bio'
/>
<div className='account-fields' onClickCapture={handleClick}>
<div className='account-fields'>
<AccountFields
fields={account.fields.take(2)}
emojis={account.emojis}

View file

@ -4,7 +4,7 @@ import type { OnElementHandler } from '@/mastodon/utils/html';
import { polymorphicForwardRef } from '@/types/polymorphic';
import type { EmojiHTMLProps } from '../emoji/html';
import { ModernEmojiHTML } from '../emoji/html';
import { EmojiHTML } from '../emoji/html';
import { useElementHandledLink } from '../status/handled_link';
export const HTMLBlock = polymorphicForwardRef<
@ -25,6 +25,6 @@ export const HTMLBlock = polymorphicForwardRef<
(...args) => onParentElement?.(...args) ?? onLinkElement(...args),
[onLinkElement, onParentElement],
);
return <ModernEmojiHTML {...props} onElement={onElement} />;
return <EmojiHTML {...props} onElement={onElement} />;
},
);

View file

@ -13,9 +13,7 @@ import CheckIcon from '@/material-icons/400-24px/check.svg?react';
import { openModal } from 'mastodon/actions/modal';
import { fetchPoll, vote } from 'mastodon/actions/polls';
import { Icon } from 'mastodon/components/icon';
import emojify from 'mastodon/features/emoji/emoji';
import { useIdentity } from 'mastodon/identity_context';
import { makeEmojiMap } from 'mastodon/models/custom_emoji';
import type * as Model from 'mastodon/models/poll';
import type { Status } from 'mastodon/models/status';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
@ -235,12 +233,11 @@ const PollOption: React.FC<PollOptionProps> = (props) => {
let titleHtml = option.translation?.titleHtml ?? option.titleHtml;
if (!titleHtml) {
const emojiMap = makeEmojiMap(poll.emojis);
titleHtml = emojify(escapeTextContentForBrowser(title), emojiMap);
titleHtml = escapeTextContentForBrowser(title);
}
return titleHtml;
}, [option, poll, title]);
}, [option, title]);
// Handlers
const handleOptionChange = useCallback(() => {

View file

@ -15,8 +15,6 @@ import { Poll } from 'mastodon/components/poll';
import { identityContextPropShape, withIdentity } from 'mastodon/identity_context';
import { languages as preloadedLanguages } from 'mastodon/initial_state';
import { isModernEmojiEnabled } from '../utils/environment';
import { EmojiHTML } from './emoji/html';
import { HandledLink } from './status/handled_link';
@ -119,41 +117,6 @@ class StatusContent extends PureComponent {
onCollapsedToggle(collapsed);
}
// Exit if modern emoji is enabled, as it handles links using the HandledLink component.
if (isModernEmojiEnabled()) {
return;
}
const links = node.querySelectorAll('a');
let link, mention;
for (var i = 0; i < links.length; ++i) {
link = links[i];
if (link.classList.contains('status-link')) {
continue;
}
link.classList.add('status-link');
mention = this.props.status.get('mentions').find(item => compareUrls(link, item.get('url')));
if (mention) {
link.addEventListener('click', this.onMentionClick.bind(this, mention), false);
link.setAttribute('title', `@${mention.get('acct')}`);
link.setAttribute('href', `/@${mention.get('acct')}`);
link.setAttribute('data-hover-card-account', mention.get('id'));
} else if (link.textContent[0] === '#' || (link.previousSibling && link.previousSibling.textContent && link.previousSibling.textContent[link.previousSibling.textContent.length - 1] === '#')) {
link.addEventListener('click', this.onHashtagClick.bind(this, link.text), false);
link.setAttribute('href', `/tags/${link.text.replace(/^#/, '')}`);
link.setAttribute('data-menu-hashtag', this.props.status.getIn(['account', 'id']));
} else {
link.setAttribute('title', link.href);
link.classList.add('unhandled-link');
}
}
}
componentDidMount () {
@ -164,22 +127,6 @@ class StatusContent extends PureComponent {
this._updateStatusLinks();
}
onMentionClick = (mention, e) => {
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.props.history.push(`/@${mention.get('acct')}`);
}
};
onHashtagClick = (hashtag, e) => {
hashtag = hashtag.replace(/^#/, '');
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
e.preventDefault();
this.props.history.push(`/tags/${hashtag}`);
}
};
handleMouseDown = (e) => {
this.startXY = [e.clientX, e.clientY];
};

View file

@ -1,30 +1,10 @@
import { EmojiHTML } from '@/mastodon/components/emoji/html';
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
import { isModernEmojiEnabled } from '../utils/environment';
import type { OnAttributeHandler } from '../utils/html';
import { Icon } from './icon';
const domParser = new DOMParser();
const stripRelMe = (html: string) => {
if (isModernEmojiEnabled()) {
return html;
}
const document = domParser.parseFromString(html, 'text/html').documentElement;
document.querySelectorAll<HTMLAnchorElement>('a[rel]').forEach((link) => {
link.rel = link.rel
.split(' ')
.filter((x: string) => x !== 'me')
.join(' ');
});
const body = document.querySelector('body');
return body?.innerHTML ?? '';
};
const onAttribute: OnAttributeHandler = (name, value, tagName) => {
if (name === 'rel' && tagName === 'a') {
if (value === 'me') {
@ -47,10 +27,6 @@ interface Props {
export const VerifiedBadge: React.FC<Props> = ({ link }) => (
<span className='verified-badge'>
<Icon id='check' icon={CheckIcon} className='verified-badge__mark' />
<EmojiHTML
as='span'
htmlString={stripRelMe(link)}
onAttribute={onAttribute}
/>
<EmojiHTML as='span' htmlString={link} onAttribute={onAttribute} />
</span>
);