mirror of
https://github.com/mastodon/mastodon.git
synced 2025-10-05 00:22:42 +00:00
replace duplicated handler code
Some checks failed
Chromatic / Run Chromatic (push) Has been cancelled
Some checks failed
Chromatic / Run Chromatic (push) Has been cancelled
This commit is contained in:
parent
dd61fed777
commit
f04360c43e
|
@ -61,13 +61,19 @@ export const DisplayName: FC<Props & ComponentPropsWithoutRef<'span'>> = ({
|
|||
if (simple) {
|
||||
return (
|
||||
<bdi>
|
||||
<EmojiHTML {...props} htmlString={accountName} shallow as='span' />
|
||||
<EmojiHTML
|
||||
{...props}
|
||||
className={`animate-parent ${className}`}
|
||||
htmlString={accountName}
|
||||
shallow
|
||||
as='span'
|
||||
/>
|
||||
</bdi>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<span {...props} className={`display-name ${className}`}>
|
||||
<span {...props} className={`display-name animate-parent ${className}`}>
|
||||
<bdi>
|
||||
<EmojiHTML
|
||||
{...props}
|
||||
|
|
|
@ -13,8 +13,9 @@ 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 { languages as preloadedLanguages } from 'mastodon/initial_state';
|
||||
import { EmojiHTML } from '../features/emoji/emoji_html';
|
||||
import { handleAnimateEnter, handleAnimateLeave } from '../features/emoji/handlers';
|
||||
import { isModernEmojiEnabled } from '../utils/environment';
|
||||
|
||||
const MAX_HEIGHT = 706; // 22px * 32 (+ 2px padding at the top)
|
||||
|
@ -150,32 +151,6 @@ class StatusContent extends PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
handleMouseEnter = ({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = currentTarget.querySelectorAll('.custom-emoji');
|
||||
|
||||
for (var i = 0; i < emojis.length; i++) {
|
||||
let emoji = emojis[i];
|
||||
emoji.src = emoji.getAttribute('data-original');
|
||||
}
|
||||
};
|
||||
|
||||
handleMouseLeave = ({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = currentTarget.querySelectorAll('.custom-emoji');
|
||||
|
||||
for (var i = 0; i < emojis.length; i++) {
|
||||
let emoji = emojis[i];
|
||||
emoji.src = emoji.getAttribute('data-static');
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
this._updateStatusLinks();
|
||||
}
|
||||
|
@ -245,7 +220,7 @@ class StatusContent extends PureComponent {
|
|||
|
||||
const content = statusContent ?? getStatusContent(status);
|
||||
const language = status.getIn(['translation', 'language']) || status.get('language');
|
||||
const classNames = classnames('status__content', {
|
||||
const classNames = classnames('status__content animate-parent', {
|
||||
'status__content--with-action': this.props.onClick && this.props.history,
|
||||
'status__content--collapsed': renderReadMore,
|
||||
});
|
||||
|
@ -267,7 +242,15 @@ class StatusContent extends PureComponent {
|
|||
if (this.props.onClick) {
|
||||
return (
|
||||
<>
|
||||
<div className={classNames} ref={this.setRef} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} key='status-content' onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
||||
<div
|
||||
className={classNames}
|
||||
ref={this.setRef}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onMouseUp={this.handleMouseUp}
|
||||
key='status-content'
|
||||
onMouseEnter={handleAnimateEnter}
|
||||
onMouseLeave={handleAnimateLeave}
|
||||
>
|
||||
<EmojiHTML
|
||||
className='status__content__text status__content__text--visible translate'
|
||||
lang={language}
|
||||
|
@ -284,7 +267,7 @@ class StatusContent extends PureComponent {
|
|||
);
|
||||
} else {
|
||||
return (
|
||||
<div className={classNames} ref={this.setRef} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
||||
<div className={classNames} ref={this.setRef} onMouseEnter={handleAnimateEnter} onMouseLeave={handleAnimateLeave}>
|
||||
<EmojiHTML
|
||||
className='status__content__text status__content__text--visible translate'
|
||||
lang={language}
|
||||
|
|
|
@ -8,6 +8,10 @@ import { NavLink } from 'react-router-dom';
|
|||
|
||||
import { AccountBio } from '@/mastodon/components/account_bio';
|
||||
import { DisplayName } from '@/mastodon/components/display_name';
|
||||
import {
|
||||
handleAnimateEnter,
|
||||
handleAnimateLeave,
|
||||
} from '@/mastodon/features/emoji/handlers';
|
||||
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
||||
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
|
||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
|
@ -379,36 +383,6 @@ export const AccountHeader: React.FC<{
|
|||
});
|
||||
}, [account]);
|
||||
|
||||
const handleMouseEnter = useCallback(
|
||||
({ currentTarget }: React.MouseEvent) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentTarget
|
||||
.querySelectorAll<HTMLImageElement>('.custom-emoji')
|
||||
.forEach((emoji) => {
|
||||
emoji.src = emoji.getAttribute('data-original') ?? '';
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleMouseLeave = useCallback(
|
||||
({ currentTarget }: React.MouseEvent) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentTarget
|
||||
.querySelectorAll<HTMLImageElement>('.custom-emoji')
|
||||
.forEach((emoji) => {
|
||||
emoji.src = emoji.getAttribute('data-static') ?? '';
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const suspended = account?.suspended;
|
||||
const isRemote = account?.acct !== account?.username;
|
||||
const remoteDomain = isRemote ? account?.acct.split('@')[1] : null;
|
||||
|
@ -808,11 +782,11 @@ export const AccountHeader: React.FC<{
|
|||
)}
|
||||
|
||||
<div
|
||||
className={classNames('account__header', {
|
||||
className={classNames('account__header animate-parent', {
|
||||
inactive: !!account.moved,
|
||||
})}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
onMouseEnter={handleAnimateEnter}
|
||||
onMouseLeave={handleAnimateLeave}
|
||||
>
|
||||
{!(suspended || hidden || account.moved) &&
|
||||
relationship?.requested_by && (
|
||||
|
|
|
@ -23,9 +23,9 @@ import { IconButton } from 'mastodon/components/icon_button';
|
|||
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
|
||||
import StatusContent from 'mastodon/components/status_content';
|
||||
import { Dropdown } from 'mastodon/components/dropdown_menu';
|
||||
import { autoPlayGif } from 'mastodon/initial_state';
|
||||
import { makeGetStatus } from 'mastodon/selectors';
|
||||
import { LinkedDisplayName } from '@/mastodon/components/display_name';
|
||||
import { handleAnimateEnter, handleAnimateLeave } from '@/mastodon/features/emoji/handlers';
|
||||
|
||||
const messages = defineMessages({
|
||||
more: { id: 'status.more', defaultMessage: 'More' },
|
||||
|
@ -57,31 +57,8 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown })
|
|||
const lastStatus = useSelector(state => getStatus(state, { id: lastStatusId }));
|
||||
const accounts = useSelector(state => getAccounts(state, accountIds));
|
||||
|
||||
const handleMouseEnter = useCallback(({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = currentTarget.querySelectorAll('.custom-emoji');
|
||||
|
||||
for (var i = 0; i < emojis.length; i++) {
|
||||
let emoji = emojis[i];
|
||||
emoji.src = emoji.getAttribute('data-original');
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleMouseLeave = useCallback(({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = currentTarget.querySelectorAll('.custom-emoji');
|
||||
|
||||
for (var i = 0; i < emojis.length; i++) {
|
||||
let emoji = emojis[i];
|
||||
emoji.src = emoji.getAttribute('data-static');
|
||||
}
|
||||
}, []);
|
||||
const handleMouseEnter = useCallback(handleAnimateEnter, []);
|
||||
const handleMouseLeave = useCallback(handleAnimateLeave, []);
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
if (unread) {
|
||||
|
@ -173,7 +150,7 @@ export const Conversation = ({ conversation, scrollKey, onMoveUp, onMoveDown })
|
|||
{unread && <span className='conversation__unread' />} <RelativeTimestamp timestamp={lastStatus.get('created_at')} />
|
||||
</div>
|
||||
|
||||
<div className='conversation__content__names' onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
|
||||
<div className='conversation__content__names animate-parent' onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
|
||||
<FormattedMessage id='conversation.with' defaultMessage='With {names}' values={{ names: <span>{names}</span> }} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import type { MouseEventHandler } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||
|
@ -6,6 +5,10 @@ import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
|||
import classNames from 'classnames';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
handleAnimateEnter,
|
||||
handleAnimateLeave,
|
||||
} from '@/mastodon/features/emoji/handlers';
|
||||
import {
|
||||
followAccount,
|
||||
unblockAccount,
|
||||
|
@ -44,38 +47,8 @@ export const AccountCard: React.FC<{ accountId: string }> = ({ accountId }) => {
|
|||
const account = useAppSelector((s) => getAccount(s, accountId));
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const handleMouseEnter = useCallback<MouseEventHandler>(
|
||||
({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
const emojis =
|
||||
currentTarget.querySelectorAll<HTMLImageElement>('.custom-emoji');
|
||||
|
||||
emojis.forEach((emoji) => {
|
||||
const original = emoji.getAttribute('data-original');
|
||||
if (original) emoji.src = original;
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleMouseLeave = useCallback<MouseEventHandler>(
|
||||
({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis =
|
||||
currentTarget.querySelectorAll<HTMLImageElement>('.custom-emoji');
|
||||
|
||||
emojis.forEach((emoji) => {
|
||||
const staticUrl = emoji.getAttribute('data-static');
|
||||
if (staticUrl) emoji.src = staticUrl;
|
||||
});
|
||||
},
|
||||
[],
|
||||
);
|
||||
const handleMouseEnter = useCallback(handleAnimateEnter, []);
|
||||
const handleMouseLeave = useCallback(handleAnimateLeave, []);
|
||||
|
||||
const handleFollow = useCallback(() => {
|
||||
if (!account) return;
|
||||
|
@ -185,7 +158,7 @@ export const AccountCard: React.FC<{ accountId: string }> = ({ accountId }) => {
|
|||
|
||||
{account.get('note').length > 0 && (
|
||||
<div
|
||||
className='account-card__bio translate'
|
||||
className='account-card__bio translate animate-parent'
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
dangerouslySetInnerHTML={{ __html: account.get('note_emojified') }}
|
||||
|
|
|
@ -5,22 +5,23 @@ import type { CustomEmojiMapArg } from './types';
|
|||
|
||||
type EmojiHTMLProps<Element extends ElementType = 'div'> = Omit<
|
||||
ComponentPropsWithoutRef<Element>,
|
||||
'dangerouslySetInnerHTML'
|
||||
'dangerouslySetInnerHTML' | 'className'
|
||||
> & {
|
||||
htmlString: string;
|
||||
extraEmojis?: CustomEmojiMapArg;
|
||||
as?: Element;
|
||||
shallow?: boolean;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export const EmojiHTML = <Element extends ElementType>({
|
||||
export const EmojiHTML = ({
|
||||
extraEmojis,
|
||||
htmlString,
|
||||
as: asElement, // Rename for syntax highlighting
|
||||
as: Wrapper = 'div', // Rename for syntax highlighting
|
||||
shallow,
|
||||
className = '',
|
||||
...props
|
||||
}: EmojiHTMLProps<Element>) => {
|
||||
const Wrapper = asElement ?? 'div';
|
||||
}: EmojiHTMLProps<ElementType>) => {
|
||||
const emojifiedHtml = useEmojify({
|
||||
text: htmlString,
|
||||
extraEmojis,
|
||||
|
@ -32,6 +33,10 @@ export const EmojiHTML = <Element extends ElementType>({
|
|||
}
|
||||
|
||||
return (
|
||||
<Wrapper {...props} dangerouslySetInnerHTML={{ __html: emojifiedHtml }} />
|
||||
<Wrapper
|
||||
{...props}
|
||||
className={`${className} animate-parent`}
|
||||
dangerouslySetInnerHTML={{ __html: emojifiedHtml }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
|
78
app/javascript/mastodon/features/emoji/handlers.ts
Normal file
78
app/javascript/mastodon/features/emoji/handlers.ts
Normal file
|
@ -0,0 +1,78 @@
|
|||
import type { MouseEventHandler } from 'react';
|
||||
|
||||
import { autoPlayGif } from '@/mastodon/initial_state';
|
||||
import { isModernEmojiEnabled } from '@/mastodon/utils/environment';
|
||||
|
||||
export const handleAnimateEnter: MouseEventHandler = ({ currentTarget }) => {
|
||||
if (autoPlayGif || isModernEmojiEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentTarget
|
||||
.querySelectorAll<HTMLImageElement>('img.custom-emoji')
|
||||
.forEach((emoji) => {
|
||||
toggleAnimatedGif(emoji, true);
|
||||
});
|
||||
};
|
||||
|
||||
export const handleAnimateLeave: MouseEventHandler = ({ currentTarget }) => {
|
||||
if (autoPlayGif || isModernEmojiEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentTarget
|
||||
.querySelectorAll<HTMLImageElement>('img.custom-emoji')
|
||||
.forEach((emoji) => {
|
||||
toggleAnimatedGif(emoji, false);
|
||||
});
|
||||
};
|
||||
|
||||
const PARENT_MAX_DEPTH = 10;
|
||||
|
||||
export function handleAnimateGif(event: MouseEvent) {
|
||||
const { target, type } = event;
|
||||
const animate = type === 'mouseover';
|
||||
if (target instanceof HTMLImageElement) {
|
||||
toggleAnimatedGif(target, animate);
|
||||
} else if (!(target instanceof HTMLElement) || target === document.body) {
|
||||
return;
|
||||
}
|
||||
let parent: HTMLElement | null = null;
|
||||
let iter = 0;
|
||||
if (target.classList.contains('animate-parent')) {
|
||||
parent = target;
|
||||
} else {
|
||||
let current: HTMLElement | null = target;
|
||||
while (current) {
|
||||
if (iter >= PARENT_MAX_DEPTH) {
|
||||
return; // We can just exit right now.
|
||||
}
|
||||
current = current.parentElement;
|
||||
if (current?.classList.contains('animate-parent')) {
|
||||
parent = current;
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
const animatedChildren =
|
||||
parent.querySelectorAll<HTMLImageElement>('img.custom-emoji');
|
||||
for (const child of animatedChildren) {
|
||||
toggleAnimatedGif(child, animate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAnimatedGif(image: HTMLImageElement, animate: boolean) {
|
||||
const { classList, dataset } = image;
|
||||
if (
|
||||
!classList.contains('custom-emoji') ||
|
||||
!dataset.static ||
|
||||
!dataset.original
|
||||
) {
|
||||
return;
|
||||
}
|
||||
image.src = animate ? dataset.original : dataset.static;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import initialState from '@/mastodon/initial_state';
|
||||
import initialState, { autoPlayGif } from '@/mastodon/initial_state';
|
||||
import { loadWorker } from '@/mastodon/utils/workers';
|
||||
|
||||
import { handleAnimateGif } from './handlers';
|
||||
import { toSupportedLocale } from './locale';
|
||||
import { emojiLogger } from './utils';
|
||||
|
||||
|
@ -22,6 +23,11 @@ export function initializeEmoji() {
|
|||
}
|
||||
}
|
||||
|
||||
if (typeof document !== 'undefined' && !autoPlayGif) {
|
||||
document.addEventListener('mouseover', handleAnimateGif, { passive: true });
|
||||
document.addEventListener('mouseout', handleAnimateGif, { passive: true });
|
||||
}
|
||||
|
||||
if (worker) {
|
||||
// Assign worker to const to make TS happy inside the event listener.
|
||||
const thisWorker = worker;
|
||||
|
@ -51,16 +57,6 @@ export function initializeEmoji() {
|
|||
}
|
||||
}
|
||||
|
||||
async function fallbackLoad() {
|
||||
log('falling back to main thread for loading');
|
||||
const { importCustomEmojiData } = await import('./loader');
|
||||
await importCustomEmojiData();
|
||||
await loadEmojiLocale(userLocale);
|
||||
if (userLocale !== 'en') {
|
||||
await loadEmojiLocale('en');
|
||||
}
|
||||
}
|
||||
|
||||
export async function loadEmojiLocale(localeString: string) {
|
||||
const locale = toSupportedLocale(localeString);
|
||||
|
||||
|
@ -71,3 +67,13 @@ export async function loadEmojiLocale(localeString: string) {
|
|||
await importEmojiData(locale);
|
||||
}
|
||||
}
|
||||
|
||||
async function fallbackLoad() {
|
||||
log('falling back to main thread for loading');
|
||||
const { importCustomEmojiData } = await import('./loader');
|
||||
await importCustomEmojiData();
|
||||
await loadEmojiLocale(userLocale);
|
||||
if (userLocale !== 'en') {
|
||||
await loadEmojiLocale('en');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import { unicodeMapping } from 'mastodon/features/emoji/emoji_unicode_mapping_li
|
|||
import { autoPlayGif, reduceMotion, disableSwiping, mascot } from 'mastodon/initial_state';
|
||||
import { assetHost } from 'mastodon/utils/config';
|
||||
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||
import { handleAnimateEnter, handleAnimateLeave } from '../../emoji/handlers';
|
||||
|
||||
const messages = defineMessages({
|
||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||
|
@ -111,42 +112,16 @@ class ContentWithRouter extends ImmutablePureComponent {
|
|||
}
|
||||
};
|
||||
|
||||
handleMouseEnter = ({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = currentTarget.querySelectorAll('.custom-emoji');
|
||||
|
||||
for (var i = 0; i < emojis.length; i++) {
|
||||
let emoji = emojis[i];
|
||||
emoji.src = emoji.getAttribute('data-original');
|
||||
}
|
||||
};
|
||||
|
||||
handleMouseLeave = ({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = currentTarget.querySelectorAll('.custom-emoji');
|
||||
|
||||
for (var i = 0; i < emojis.length; i++) {
|
||||
let emoji = emojis[i];
|
||||
emoji.src = emoji.getAttribute('data-static');
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { announcement } = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className='announcements__item__content translate'
|
||||
className='announcements__item__content translate animate-parent'
|
||||
ref={this.setRef}
|
||||
dangerouslySetInnerHTML={{ __html: announcement.get('contentHtml') }}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
onMouseEnter={handleAnimateEnter}
|
||||
onMouseLeave={handleAnimateLeave}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -238,9 +213,20 @@ class Reaction extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
return (
|
||||
<animated.button className={classNames('reactions-bar__item', { active: reaction.get('me') })} onClick={this.handleClick} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} title={`:${shortCode}:`} style={this.props.style}>
|
||||
<span className='reactions-bar__item__emoji'><Emoji hovered={this.state.hovered} emoji={reaction.get('name')} emojiMap={this.props.emojiMap} /></span>
|
||||
<span className='reactions-bar__item__count'><AnimatedNumber value={reaction.get('count')} /></span>
|
||||
<animated.button
|
||||
className={classNames('reactions-bar__item', { active: reaction.get('me') })}
|
||||
onClick={this.handleClick}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
title={`:${shortCode}:`}
|
||||
style={this.props.style}
|
||||
>
|
||||
<span className='reactions-bar__item__emoji'>
|
||||
<Emoji hovered={this.state.hovered} emoji={reaction.get('name')} emojiMap={this.props.emojiMap} />
|
||||
</span>
|
||||
<span className='reactions-bar__item__count'>
|
||||
<AnimatedNumber value={reaction.get('count')} />
|
||||
</span>
|
||||
</animated.button>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ import { DisplayName } from 'mastodon/components/display_name';
|
|||
import { Icon } from 'mastodon/components/icon';
|
||||
import { useAppSelector, useAppDispatch } from 'mastodon/store';
|
||||
|
||||
import { handleAnimateEnter, handleAnimateLeave } from '../../emoji/handlers';
|
||||
|
||||
import { EmbeddedStatusContent } from './embedded_status_content';
|
||||
|
||||
export type Mention = RecordOf<{ url: string; acct: string }>;
|
||||
|
@ -76,31 +78,9 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({
|
|||
[clickCoordinatesRef, statusId, account, history],
|
||||
);
|
||||
|
||||
const handleMouseEnter = useCallback<React.MouseEventHandler<HTMLDivElement>>(
|
||||
({ currentTarget }) => {
|
||||
const emojis =
|
||||
currentTarget.querySelectorAll<HTMLImageElement>('.custom-emoji');
|
||||
const handleMouseEnter = useCallback(handleAnimateEnter, []);
|
||||
|
||||
for (const emoji of emojis) {
|
||||
const newSrc = emoji.getAttribute('data-original');
|
||||
if (newSrc) emoji.src = newSrc;
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const handleMouseLeave = useCallback<React.MouseEventHandler<HTMLDivElement>>(
|
||||
({ currentTarget }) => {
|
||||
const emojis =
|
||||
currentTarget.querySelectorAll<HTMLImageElement>('.custom-emoji');
|
||||
|
||||
for (const emoji of emojis) {
|
||||
const newSrc = emoji.getAttribute('data-static');
|
||||
if (newSrc) emoji.src = newSrc;
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
const handleMouseLeave = useCallback(handleAnimateLeave, []);
|
||||
|
||||
const handleContentWarningClick = useCallback(() => {
|
||||
dispatch(toggleStatusSpoilers(statusId));
|
||||
|
@ -123,7 +103,7 @@ export const EmbeddedStatus: React.FC<{ statusId: string }> = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className='notification-group__embedded-status'
|
||||
className='notification-group__embedded-status animate-parent'
|
||||
role='button'
|
||||
tabIndex={-1}
|
||||
onMouseDown={handleMouseDown}
|
||||
|
|
Loading…
Reference in New Issue
Block a user