fix(app): retry emoji picker images that fail to load (#3151)

This commit is contained in:
Hampus
2026-10-03 02:14:28 +02:00
committed by GitHub
parent eb0e8366bc
commit 79d7c85832
@@ -11,6 +11,7 @@ import type {FlatEmoji} from '@app/features/emoji/types/EmojiTypes';
import {checkEmojiAvailability} from '@app/features/expressions/utils/ExpressionPermissionUtils';
import {getEmojiDisplayDataWithSkinTone} from '@app/features/expressions/utils/SkinToneUtils';
import UnicodeEmojis, {EMOJI_SPRITES} from '@app/features/expressions/utils/UnicodeEmojis';
import {loadImage} from '@app/features/messaging/utils/ImageCacheUtils';
import {getEmojiRenderUrl} from '@app/features/messaging/utils/markdown/EmojiDetector';
import {EmojiContextMenuItems} from '@app/features/ui/action_menu/items/EmojiContextMenuItems';
import * as ContextMenuCommands from '@app/features/ui/commands/ContextMenuCommands';
@@ -25,9 +26,34 @@ type PickerEmojiImageProps = React.ImgHTMLAttributes<HTMLImageElement> & {
alt: string;
};
const PICKER_IMAGE_RETRY_LIMIT = 3;
const PickerEmojiImage = ({src, alt, ...props}: PickerEmojiImageProps) => {
const imageRef = useRef<HTMLImageElement | null>(null);
const hasLoadedRef = useRef(false);
const retriesRef = useRef(0);
const cancelRetryRef = useRef<(() => void) | null>(null);
useEffect(() => {
retriesRef.current = 0;
return () => {
cancelRetryRef.current?.();
cancelRetryRef.current = null;
};
}, [src]);
const handleError = () => {
if (retriesRef.current >= PICKER_IMAGE_RETRY_LIMIT) {
return;
}
retriesRef.current += 1;
cancelRetryRef.current?.();
cancelRetryRef.current = loadImage(src, () => {
cancelRetryRef.current = null;
const image = imageRef.current;
if (image != null && image.getAttribute('src') === src) {
image.src = src;
}
});
};
const handleLoad = (event: React.SyntheticEvent<HTMLImageElement>) => {
const view = event.currentTarget?.ownerDocument?.defaultView ?? window;
view.requestAnimationFrame(() => {
@@ -47,6 +73,7 @@ const PickerEmojiImage = ({src, alt, ...props}: PickerEmojiImageProps) => {
alt={alt}
className={hasLoadedRef.current ? styles.emojiImage : clsx(styles.emojiImage, styles.emojiImageLoading)}
onLoad={hasLoadedRef.current ? undefined : handleLoad}
onError={hasLoadedRef.current ? undefined : handleError}
/>
);
};