fix(app): only track hover on reactions that have an animated emoji (#1899)

This commit is contained in:
Hampus authored and GitHub committed 2026-08-24 12:41:58 +02:00
1 parent 670a3a970e
commit 94bbbd1021
2 files changed
+11 -15

No files matched your search

@@ -4,6 +4,7 @@ import {LongPressable} from '@app/features/app/components/LongPressable';
import styles from '@app/features/app/components/shared/MessageReactionsContent.module.css'; import styles from '@app/features/app/components/shared/MessageReactionsContent.module.css';
import {useHover} from '@app/features/app/hooks/useHover'; import {useHover} from '@app/features/app/hooks/useHover';
import reactionStyles from '@app/features/channel/components/MessageReactions.module.css'; import reactionStyles from '@app/features/channel/components/MessageReactions.module.css';
import {ReactionImage} from '@app/features/messaging/components/ReactionImage';
import { import {
emojiEquals, emojiEquals,
getEmojiName, getEmojiName,
@@ -49,6 +50,7 @@ const ReactionFilterButton = observer(
({reaction, isSelected, onSelect, onContextMenu, showTooltip}: ReactionFilterButtonProps) => { ({reaction, isSelected, onSelect, onContextMenu, showTooltip}: ReactionFilterButtonProps) => {
const {i18n} = useLingui(); const {i18n} = useLingui();
const [hoverRef, isHovering] = useHover(); const [hoverRef, isHovering] = useHover();
const emojiHasAnimatedVariant = reaction.emoji.animated === true;
const emojiName = getEmojiName(reaction.emoji); const emojiName = getEmojiName(reaction.emoji);
const emojiUrl = useEmojiURL({emoji: reaction.emoji, isHovering}); const emojiUrl = useEmojiURL({emoji: reaction.emoji, isHovering});
const reactionCountText = plural( const reactionCountText = plural(
@@ -67,7 +69,7 @@ const ReactionFilterButton = observer(
aria-pressed={isSelected} aria-pressed={isSelected}
onClick={onSelect} onClick={onSelect}
onContextMenu={onContextMenu} onContextMenu={onContextMenu}
ref={hoverRef} ref={emojiHasAnimatedVariant ? hoverRef : undefined}
className={clsx( className={clsx(
reactionStyles.reactionButton, reactionStyles.reactionButton,
styles.filterButton, styles.filterButton,
@@ -80,10 +82,11 @@ const ReactionFilterButton = observer(
data-flx="app.message-reactions-content.reaction-filter-button.div" data-flx="app.message-reactions-content.reaction-filter-button.div"
> >
{emojiUrl ? ( {emojiUrl ? (
<img <ReactionImage
className={clsx('emoji', reactionStyles.emoji)} className={clsx('emoji', reactionStyles.emoji)}
src={emojiUrl} src={emojiUrl}
alt={emojiName} alt={emojiName}
aria-hidden={true}
draggable={false} draggable={false}
data-flx="app.message-reactions-content.reaction-filter-button.emoji" data-flx="app.message-reactions-content.reaction-filter-button.emoji"
/> />
@@ -4,14 +4,14 @@ import Accessibility from '@app/features/accessibility/state/Accessibility';
import {messageActionMenuItemIds, useMessageActionMenuData} from '@app/features/channel/components/MessageActionMenu'; import {messageActionMenuItemIds, useMessageActionMenuData} from '@app/features/channel/components/MessageActionMenu';
import {getEffectiveContent, triggerAddReaction} from '@app/features/channel/components/MessageActionUtils'; import {getEffectiveContent, triggerAddReaction} from '@app/features/channel/components/MessageActionUtils';
import { import {
getQuickReactionEmojiSrc,
REACT_WITH_EMOJI_DESCRIPTOR, REACT_WITH_EMOJI_DESCRIPTOR,
renderQuickReactionEmoji, renderQuickReactionEmoji,
useReactionMenuImagePreload,
useReactionSubmenuEmojiSrc,
} from '@app/features/channel/components/QuickReactionsRow'; } from '@app/features/channel/components/QuickReactionsRow';
import type {Channel} from '@app/features/channel/models/Channel'; import type {Channel} from '@app/features/channel/models/Channel';
import EmojiPicker from '@app/features/emoji/state/EmojiPicker'; import EmojiPicker from '@app/features/emoji/state/EmojiPicker';
import type {FlatEmoji} from '@app/features/emoji/types/EmojiTypes'; import type {FlatEmoji} from '@app/features/emoji/types/EmojiTypes';
import {useExpressionImagesPreload} from '@app/features/expressions/utils/ExpressionImageCache';
import { import {
COPY_LINK_DESCRIPTOR, COPY_LINK_DESCRIPTOR,
COPY_TEXT_DESCRIPTOR, COPY_TEXT_DESCRIPTOR,
@@ -126,7 +126,7 @@ interface RemoveReactionsSubmenuProps {
const RemoveReactionsSubmenuItem = observer( const RemoveReactionsSubmenuItem = observer(
({reaction, channelId, messageId}: {reaction: MessageReaction; channelId: string; messageId: string}) => { ({reaction, channelId, messageId}: {reaction: MessageReaction; channelId: string; messageId: string}) => {
const {i18n} = useLingui(); const {i18n} = useLingui();
const emojiUrl = useEmojiURL({emoji: reaction.emoji, size: 32}); const emojiUrl = useEmojiURL({emoji: reaction.emoji});
const label = getEmojiNameWithColons(reaction.emoji); const label = getEmojiNameWithColons(reaction.emoji);
if (reaction.count <= 0) { if (reaction.count <= 0) {
return null; return null;
@@ -188,10 +188,10 @@ const RemoveReactionsSubmenu = observer(({reactions, channelId, messageId}: Remo
RemoveReactionsSubmenu.displayName = 'RemoveReactionsSubmenu'; RemoveReactionsSubmenu.displayName = 'RemoveReactionsSubmenu';
const AddReactionSubmenuItem = observer( export const AddReactionSubmenuItem = observer(
({emoji, onSelect}: {emoji: FlatEmoji; onSelect: (emoji: FlatEmoji) => void}) => { ({emoji, onSelect}: {emoji: FlatEmoji; onSelect: (emoji: FlatEmoji) => void}) => {
const reactionEmoji = useMemo(() => toReactionEmoji(emoji), [emoji]); const reactionEmoji = useMemo(() => toReactionEmoji(emoji), [emoji]);
const emojiUrl = useEmojiURL({emoji: reactionEmoji, size: 32}); const emojiUrl = useReactionSubmenuEmojiSrc(emoji);
const label = getEmojiNameWithColons(reactionEmoji); const label = getEmojiNameWithColons(reactionEmoji);
const renderEmojiPreview = () => { const renderEmojiPreview = () => {
if (emojiUrl) { if (emojiUrl) {
@@ -427,14 +427,7 @@ export const MessageContextMenu: React.FC<MessageContextMenuProps> = observer(
quickReactionCount: 4, quickReactionCount: 4,
submenuReactionCount: 16, submenuReactionCount: 16,
}); });
const preloadedReactionImageUrls = useMemo( useReactionMenuImagePreload(quickReactionEmojis, submenuReactionEmojis);
() =>
Array.from(
new Set([...quickReactionEmojis, ...submenuReactionEmojis].map((emoji) => getQuickReactionEmojiSrc(emoji))),
),
[quickReactionEmojis, submenuReactionEmojis],
);
useExpressionImagesPreload(preloadedReactionImageUrls);
const handleQuickReact = useCallback( const handleQuickReact = useCallback(
(emoji: FlatEmoji) => { (emoji: FlatEmoji) => {
EmojiPicker.trackEmoji(emoji); EmojiPicker.trackEmoji(emoji);