mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 13:35:42 +09:00
perf(app): preload reaction menu emoji at the size they render (#1882)
This commit is contained in:
1 parent
76ce060d13
commit
19264d7f81
2 files changed
+40
-9
No files matched your search
@@ -4,15 +4,14 @@ import styles from '@app/features/channel/components/MessageActionBottomSheet.mo
|
|||||||
import {useMessageActionMenuData} from '@app/features/channel/components/MessageActionMenu';
|
import {useMessageActionMenuData} from '@app/features/channel/components/MessageActionMenu';
|
||||||
import {MessageReactionsSheet} from '@app/features/channel/components/MessageReactionsSheet';
|
import {MessageReactionsSheet} from '@app/features/channel/components/MessageReactionsSheet';
|
||||||
import {
|
import {
|
||||||
getQuickReactionEmojiSrc,
|
|
||||||
REACT_WITH_EMOJI_DESCRIPTOR,
|
REACT_WITH_EMOJI_DESCRIPTOR,
|
||||||
renderQuickReactionEmoji,
|
renderQuickReactionEmoji,
|
||||||
|
useReactionMenuImagePreload,
|
||||||
} from '@app/features/channel/components/QuickReactionsRow';
|
} from '@app/features/channel/components/QuickReactionsRow';
|
||||||
import quickReactionStyles from '@app/features/channel/components/QuickReactionsRow.module.css';
|
import quickReactionStyles from '@app/features/channel/components/QuickReactionsRow.module.css';
|
||||||
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 {ExpressionPickerSheet} from '@app/features/expressions/components/modals/ExpressionPickerSheet';
|
import {ExpressionPickerSheet} from '@app/features/expressions/components/modals/ExpressionPickerSheet';
|
||||||
import {useExpressionImagesPreload} from '@app/features/expressions/utils/ExpressionImageCache';
|
|
||||||
import {COPY_LINK_DESCRIPTOR, OPEN_LINK_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
import {COPY_LINK_DESCRIPTOR, OPEN_LINK_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
||||||
import {useMessageReactions as useMessageReactionsSnapshot} from '@app/features/messaging/hooks/useMessageReactionStore';
|
import {useMessageReactions as useMessageReactionsSnapshot} from '@app/features/messaging/hooks/useMessageReactionStore';
|
||||||
import type {Message} from '@app/features/messaging/models/MessagingMessage';
|
import type {Message} from '@app/features/messaging/models/MessagingMessage';
|
||||||
@@ -109,11 +108,7 @@ export const MessageActionBottomSheet: React.FC<MessageActionBottomSheetProps> =
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
}, [handleCopyLink, handleOpenLink, i18n.locale, linkUrl]);
|
}, [handleCopyLink, handleOpenLink, i18n.locale, linkUrl]);
|
||||||
const quickReactionImageUrls = useMemo(
|
useReactionMenuImagePreload(quickReactionEmojis);
|
||||||
() => quickReactionEmojis.map((emoji) => getQuickReactionEmojiSrc(emoji)),
|
|
||||||
[quickReactionEmojis],
|
|
||||||
);
|
|
||||||
useExpressionImagesPreload(quickReactionImageUrls);
|
|
||||||
const visibleGroups = useMemo(
|
const visibleGroups = useMemo(
|
||||||
() => [...linkGroups, ...groups].filter((group) => group.items.length > 0),
|
() => [...linkGroups, ...groups].filter((group) => group.items.length > 0),
|
||||||
[groups, linkGroups],
|
[groups, linkGroups],
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
import {useShouldAnimate} from '@app/features/app/hooks/useShouldAnimate';
|
||||||
import styles from '@app/features/channel/components/QuickReactionsRow.module.css';
|
import styles from '@app/features/channel/components/QuickReactionsRow.module.css';
|
||||||
import type {FlatEmoji} from '@app/features/emoji/types/EmojiTypes';
|
import type {FlatEmoji} from '@app/features/emoji/types/EmojiTypes';
|
||||||
|
import {buildCustomEmojiURL} from '@app/features/expressions/utils/CustomEmojiImageUrl';
|
||||||
|
import {useExpressionImagesPreload} from '@app/features/expressions/utils/ExpressionImageCache';
|
||||||
import {getEmojiDisplayData} from '@app/features/expressions/utils/SkinToneUtils';
|
import {getEmojiDisplayData} from '@app/features/expressions/utils/SkinToneUtils';
|
||||||
import {ReactionImage} from '@app/features/messaging/components/ReactionImage';
|
import {ReactionImage} from '@app/features/messaging/components/ReactionImage';
|
||||||
import * as AvatarUtils from '@app/features/user/utils/AvatarUtils';
|
|
||||||
import {msg} from '@lingui/core/macro';
|
import {msg} from '@lingui/core/macro';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
|
import {useMemo} from 'react';
|
||||||
|
|
||||||
export const REACT_WITH_EMOJI_DESCRIPTOR = msg({
|
export const REACT_WITH_EMOJI_DESCRIPTOR = msg({
|
||||||
message: 'React with {emojiShortcode}',
|
message: 'React with {emojiShortcode}',
|
||||||
@@ -16,7 +19,7 @@ export const REACT_WITH_EMOJI_DESCRIPTOR = msg({
|
|||||||
|
|
||||||
export function getQuickReactionEmojiSrc(emoji: FlatEmoji): string {
|
export function getQuickReactionEmojiSrc(emoji: FlatEmoji): string {
|
||||||
const {url: displayUrl} = getEmojiDisplayData(emoji);
|
const {url: displayUrl} = getEmojiDisplayData(emoji);
|
||||||
return emoji.id ? AvatarUtils.getEmojiURL({id: emoji.id, animated: false}) : (displayUrl ?? '');
|
return emoji.id ? buildCustomEmojiURL({id: emoji.id, animated: emoji.animated === true}) : (displayUrl ?? '');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderQuickReactionEmoji(emoji: FlatEmoji): React.ReactNode {
|
export function renderQuickReactionEmoji(emoji: FlatEmoji): React.ReactNode {
|
||||||
@@ -25,9 +28,42 @@ export function renderQuickReactionEmoji(emoji: FlatEmoji): React.ReactNode {
|
|||||||
<ReactionImage
|
<ReactionImage
|
||||||
src={emojiSrc}
|
src={emojiSrc}
|
||||||
alt={emoji.name}
|
alt={emoji.name}
|
||||||
|
aria-hidden={true}
|
||||||
draggable={false}
|
draggable={false}
|
||||||
className={styles.emojiImg}
|
className={styles.emojiImg}
|
||||||
data-flx="channel.quick-reactions-row.render-quick-reaction-emoji.emoji-img"
|
data-flx="channel.quick-reactions-row.render-quick-reaction-emoji.emoji-img"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getReactionSubmenuEmojiSrc(emoji: FlatEmoji, animationAllowed: boolean): string {
|
||||||
|
const {url: displayUrl} = getEmojiDisplayData(emoji);
|
||||||
|
return emoji.id
|
||||||
|
? buildCustomEmojiURL({id: emoji.id, animated: emoji.animated === true && animationAllowed})
|
||||||
|
: (displayUrl ?? '');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useReactionSubmenuEmojiSrc(emoji: FlatEmoji): string {
|
||||||
|
const animationAllowed = useShouldAnimate({kind: 'emoji', isAnimated: emoji.animated === true});
|
||||||
|
return getReactionSubmenuEmojiSrc(emoji, animationAllowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
const NO_SUBMENU_EMOJIS: ReadonlyArray<FlatEmoji> = [];
|
||||||
|
|
||||||
|
export function useReactionMenuImagePreload(
|
||||||
|
quickReactionEmojis: ReadonlyArray<FlatEmoji>,
|
||||||
|
submenuReactionEmojis: ReadonlyArray<FlatEmoji> = NO_SUBMENU_EMOJIS,
|
||||||
|
): void {
|
||||||
|
const animationAllowed = useShouldAnimate({kind: 'emoji', isAnimated: true});
|
||||||
|
const urls = useMemo(
|
||||||
|
() =>
|
||||||
|
Array.from(
|
||||||
|
new Set([
|
||||||
|
...quickReactionEmojis.map(getQuickReactionEmojiSrc),
|
||||||
|
...submenuReactionEmojis.map((emoji) => getReactionSubmenuEmojiSrc(emoji, animationAllowed)),
|
||||||
|
]),
|
||||||
|
).filter(Boolean),
|
||||||
|
[quickReactionEmojis, submenuReactionEmojis, animationAllowed],
|
||||||
|
);
|
||||||
|
useExpressionImagesPreload(urls);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user