diff --git a/src/api/types/messages.ts b/src/api/types/messages.ts index 93d13c34d..9eda5107b 100644 --- a/src/api/types/messages.ts +++ b/src/api/types/messages.ts @@ -749,6 +749,7 @@ export interface ApiAvailableReaction { title: string; isInactive?: boolean; isPremium?: boolean; + isLocalCache?: true; } export interface ApiAvailableEffect { diff --git a/src/components/common/reactions/ReactionStaticEmoji.scss b/src/components/common/reactions/ReactionStaticEmoji.scss index 47d5677b9..bf3dafc7b 100644 --- a/src/components/common/reactions/ReactionStaticEmoji.scss +++ b/src/components/common/reactions/ReactionStaticEmoji.scss @@ -1,14 +1,28 @@ .ReactionStaticEmoji { + position: relative; display: block; + aspect-ratio: 1; width: 1rem; - // Unicorn reaction preview is too small - &.with-unicorn-fix { - transform: scale(2); - } - &.icon-heart { margin: 0 !important; color: var(--color-heart) !important; } + + .thumb, + .media { + position: absolute; + top: 0; + left: 0; + + width: 100%; + height: 100%; + } + + .media { + // Unicorn reaction preview is too small + &.with-unicorn-fix { + transform: scale(2); + } + } } diff --git a/src/components/common/reactions/ReactionStaticEmoji.tsx b/src/components/common/reactions/ReactionStaticEmoji.tsx index 00894bc92..de342d95b 100644 --- a/src/components/common/reactions/ReactionStaticEmoji.tsx +++ b/src/components/common/reactions/ReactionStaticEmoji.tsx @@ -7,8 +7,9 @@ import type { ObserveFn } from '../../../hooks/useIntersectionObserver'; import { isSameReaction } from '../../../global/helpers'; import buildClassName from '../../../util/buildClassName'; +import useThumbnail from '../../../hooks/media/useThumbnail'; import useMedia from '../../../hooks/useMedia'; -import useMediaTransitionDeprecated from '../../../hooks/useMediaTransitionDeprecated'; +import useMediaTransition from '../../../hooks/useMediaTransition'; import CustomEmoji from '../CustomEmoji'; import Icon from '../icons/Icon'; @@ -37,11 +38,19 @@ const ReactionStaticEmoji: FC = ({ const availableReaction = useMemo(() => ( availableReactions?.find((available) => isSameReaction(available.reaction, reaction)) ), [availableReactions, reaction]); - const staticIconId = availableReaction?.staticIcon?.id; + const staticIcon = availableReaction?.staticIcon; + const staticIconId = staticIcon?.id; const mediaHash = staticIconId ? `document${staticIconId}` : undefined; - const mediaData = useMedia(mediaHash); + const cacheBuster = availableReaction?.isLocalCache ? 0 : 1; + const mediaData = useMedia(mediaHash, false, undefined, undefined, cacheBuster); + const thumbDataUri = useThumbnail(staticIcon?.thumbnail); - const transitionClassNames = useMediaTransitionDeprecated(mediaData); + const { ref: thumbRef } = useMediaTransition({ + hasMediaData: Boolean(thumbDataUri && !mediaData), + }); + const { ref: mediaRef } = useMediaTransition({ + hasMediaData: Boolean(mediaData), + }); const shouldApplySizeFix = reaction.type === 'emoji' && reaction.emoticon === '🦄'; const shouldReplaceWithHeartIcon = withIconHeart && reaction.type === 'emoji' && reaction.emoticon === '❤'; @@ -64,18 +73,25 @@ const ReactionStaticEmoji: FC = ({ } return ( - {availableReaction?.title} + > + + {availableReaction?.title} + ); }; diff --git a/src/global/cache.ts b/src/global/cache.ts index 15d16a8b7..496b4794f 100644 --- a/src/global/cache.ts +++ b/src/global/cache.ts @@ -830,5 +830,5 @@ function reduceGroupCalls(global: T): GlobalState['groupC function reduceAvailableReactions(availableReactions?: ApiAvailableReaction[]): ApiAvailableReaction[] | undefined { return availableReactions - ?.map((r) => pick(r, ['reaction', 'staticIcon', 'title', 'isInactive'])); + ?.map((r) => ({ ...pick(r, ['reaction', 'staticIcon', 'title', 'isInactive']), isLocalCache: true })); } diff --git a/src/hooks/useMedia.ts b/src/hooks/useMedia.ts index a521e9e9a..43932870d 100644 --- a/src/hooks/useMedia.ts +++ b/src/hooks/useMedia.ts @@ -13,6 +13,7 @@ const useMedia = ( noLoad = false, mediaFormat = ApiMediaFormat.BlobUrl, delay?: number | false, + cacheBuster?: number, ) => { const isStreaming = IS_PROGRESSIVE_SUPPORTED && mediaFormat === ApiMediaFormat.Progressive; const mediaData = mediaHash @@ -35,7 +36,7 @@ const useMedia = ( } }); } - }, [noLoad, mediaHash, mediaData, mediaFormat, delay, isSynced]); + }, [noLoad, mediaHash, mediaData, mediaFormat, cacheBuster, delay, isSynced]); return mediaData; };