From af7469fa1f8f56c892785c6cb00ae7632bb16758 Mon Sep 17 00:00:00 2001 From: Hampus Date: Mon, 24 Aug 2026 12:32:28 +0200 Subject: [PATCH] fix(app): request custom emoji at one canonical image size (#1857) --- .../bottomsheets/EmojiInfoBottomSheet.tsx | 12 ++++++---- .../features/expressions/models/GuildEmoji.ts | 7 ++---- .../expressions/utils/CustomEmojiImageUrl.ts | 23 +++++++++++++++++++ .../modals/CustomStatusBottomSheet.tsx | 4 ++-- .../components/modals/CustomStatusModal.tsx | 4 ++-- 5 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 fluxer_app/src/features/expressions/utils/CustomEmojiImageUrl.ts diff --git a/fluxer_app/src/features/emoji/components/bottomsheets/EmojiInfoBottomSheet.tsx b/fluxer_app/src/features/emoji/components/bottomsheets/EmojiInfoBottomSheet.tsx index a28cec6fe..cf87193d8 100644 --- a/fluxer_app/src/features/emoji/components/bottomsheets/EmojiInfoBottomSheet.tsx +++ b/fluxer_app/src/features/emoji/components/bottomsheets/EmojiInfoBottomSheet.tsx @@ -3,12 +3,14 @@ import {useShouldAnimate} from '@app/features/app/hooks/useShouldAnimate'; import styles from '@app/features/emoji/components/bottomsheets/EmojiInfoBottomSheet.module.css'; import Emoji from '@app/features/emoji/state/Emoji'; +import { + buildCustomEmojiURL, + CUSTOM_EMOJI_ENLARGED_IMAGE_RUNG, +} from '@app/features/expressions/utils/CustomEmojiImageUrl'; import * as EmojiUtils from '@app/features/expressions/utils/EmojiUtils'; import UnicodeEmojis from '@app/features/expressions/utils/UnicodeEmojis'; import Guilds from '@app/features/guild/state/Guilds'; -import {setUrlQueryParams} from '@app/features/messaging/utils/MessagingUrlUtils'; import {BottomSheet} from '@app/features/ui/bottom_sheet/BottomSheet'; -import * as AvatarUtils from '@app/features/user/utils/AvatarUtils'; import {Trans} from '@lingui/react/macro'; import {observer} from 'mobx-react-lite'; import type React from 'react'; @@ -46,19 +48,19 @@ interface EmojiInfoBottomSheetContentProps { } const EmojiInfoBottomSheetContent: React.FC = observer(({emoji, onClose}) => { - const shouldAnimateEmoji = useShouldAnimate({kind: 'emoji'}); const isCustomEmoji = emoji.id != null; + const shouldAnimateEmoji = useShouldAnimate({kind: 'emoji', isAnimated: Boolean(emoji.animated)}); const emojiRecord = isCustomEmoji ? Emoji.getEmojiById(emoji.id!) : null; const guildId = emojiRecord?.guildId; const guild = guildId ? Guilds.getGuild(guildId) : null; const defaultEmojiSurrogate = isCustomEmoji ? null : UnicodeEmojis.normalizeEmojiNameToSurrogate(emoji.name); const emojiUrl = useMemo(() => { if (isCustomEmoji) { - const url = AvatarUtils.getEmojiURL({ + return buildCustomEmojiURL({ id: emoji.id!, animated: Boolean(emoji.animated) && shouldAnimateEmoji, + size: CUSTOM_EMOJI_ENLARGED_IMAGE_RUNG, }); - return setUrlQueryParams(url, {size: 240, quality: 'lossless'}); } return EmojiUtils.getEmojiURL(defaultEmojiSurrogate ?? emoji.name); }, [emoji.id, emoji.name, emoji.animated, isCustomEmoji, defaultEmojiSurrogate, shouldAnimateEmoji]); diff --git a/fluxer_app/src/features/expressions/models/GuildEmoji.ts b/fluxer_app/src/features/expressions/models/GuildEmoji.ts index 97ebc46bd..9f99a08df 100644 --- a/fluxer_app/src/features/expressions/models/GuildEmoji.ts +++ b/fluxer_app/src/features/expressions/models/GuildEmoji.ts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0-or-later -import * as AvatarUtils from '@app/features/user/utils/AvatarUtils'; +import {buildCustomEmojiURL} from '@app/features/expressions/utils/CustomEmojiImageUrl'; import type {GuildEmoji as WireGuildEmoji} from '@fluxer/schema/src/domains/guild/GuildEmojiSchemas'; import type {UserPartial} from '@fluxer/schema/src/domains/user/UserResponseSchemas'; @@ -21,10 +21,7 @@ export class GuildEmoji { this.name = data.name; this.uniqueName = data.name; this.allNamesString = `:${data.name}:`; - this.url = AvatarUtils.getEmojiURL({ - id: data.id, - animated: data.animated, - }); + this.url = buildCustomEmojiURL({id: data.id, animated: data.animated}); this.animated = data.animated; this.nsfw = data.nsfw; this.user = data.user; diff --git a/fluxer_app/src/features/expressions/utils/CustomEmojiImageUrl.ts b/fluxer_app/src/features/expressions/utils/CustomEmojiImageUrl.ts new file mode 100644 index 000000000..e5055e72e --- /dev/null +++ b/fluxer_app/src/features/expressions/utils/CustomEmojiImageUrl.ts @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: AGPL-3.0-or-later + +import {setUrlQueryParams} from '@app/features/messaging/utils/MessagingUrlUtils'; +import * as AvatarUtils from '@app/features/user/utils/AvatarUtils'; + +export const CUSTOM_EMOJI_IMAGE_RUNG = 128; +export const CUSTOM_EMOJI_ENLARGED_IMAGE_RUNG = 240; + +export function buildCustomEmojiURL({ + id, + animated, + size = CUSTOM_EMOJI_IMAGE_RUNG, +}: { + id: string; + animated: boolean; + size?: number; +}): string { + const base = AvatarUtils.getEmojiURL({id, animated}); + if (!base) { + return base; + } + return setUrlQueryParams(base, {size}); +} diff --git a/fluxer_app/src/features/user/components/modals/CustomStatusBottomSheet.tsx b/fluxer_app/src/features/user/components/modals/CustomStatusBottomSheet.tsx index a9e2b0ccf..58a0b9fe4 100644 --- a/fluxer_app/src/features/user/components/modals/CustomStatusBottomSheet.tsx +++ b/fluxer_app/src/features/user/components/modals/CustomStatusBottomSheet.tsx @@ -13,6 +13,7 @@ import DeveloperMode from '@app/features/devtools/state/DeveloperMode'; import Emoji from '@app/features/emoji/state/Emoji'; import type {FlatEmoji} from '@app/features/emoji/types/EmojiTypes'; import {ExpressionPickerSheet} from '@app/features/expressions/components/modals/ExpressionPickerSheet'; +import {buildCustomEmojiURL} from '@app/features/expressions/utils/CustomEmojiImageUrl'; import {getEmojiURL} from '@app/features/expressions/utils/EmojiUtils'; import {getSkinTonedSurrogate} from '@app/features/expressions/utils/SkinToneUtils'; import Presence from '@app/features/presence/state/Presence'; @@ -24,7 +25,6 @@ import * as UserSettingsCommands from '@app/features/user/commands/UserSettingsC import styles from '@app/features/user/components/modals/CustomStatusBottomSheet.module.css'; import {type CustomStatus, normalizeCustomStatus} from '@app/features/user/state/CustomStatus'; import Users from '@app/features/user/state/Users'; -import * as AvatarUtils from '@app/features/user/utils/AvatarUtils'; import {msg} from '@lingui/core/macro'; import {Trans, useLingui} from '@lingui/react/macro'; import {SmileyIcon, XIcon} from '@phosphor-icons/react'; @@ -170,7 +170,7 @@ export const CustomStatusBottomSheet = observer(({isOpen, onClose}: CustomStatus if (emoji) { return ( { if (emoji) { return (