Gift Preview Modal: Fix animation (#6734)

This commit is contained in:
Alexander Zinchuk 2026-02-27 19:51:25 +01:00
parent 64c5b740d3
commit ca7d6eef8a
2 changed files with 16 additions and 5 deletions

View File

@ -44,6 +44,8 @@ type OwnProps = {
resellPrice?: ApiTypeCurrencyAmount; resellPrice?: ApiTypeCurrencyAmount;
showManageButtons?: boolean; showManageButtons?: boolean;
savedGift?: ApiSavedStarGift; savedGift?: ApiSavedStarGift;
noLoop?: boolean;
onStickerAnimationEnded?: (modelName: string) => void;
children?: React.ReactNode; children?: React.ReactNode;
}; };
@ -61,6 +63,8 @@ const UniqueGiftHeader = ({
resellPrice, resellPrice,
showManageButtons, showManageButtons,
savedGift, savedGift,
noLoop,
onStickerAnimationEnded,
children, children,
}: OwnProps) => { }: OwnProps) => {
const { const {
@ -74,6 +78,10 @@ const UniqueGiftHeader = ({
const activeKey = useTransitionActiveKey([modelAttribute, backdropAttribute, patternAttribute]); const activeKey = useTransitionActiveKey([modelAttribute, backdropAttribute, patternAttribute]);
const subtitleColor = backdropAttribute?.textColor; const subtitleColor = backdropAttribute?.textColor;
const handleStickerEnded = () => {
onStickerAnimationEnded?.(modelAttribute.name);
};
const radialPatternBackdrop = useMemo(() => { const radialPatternBackdrop = useMemo(() => {
const backdropColors = [backdropAttribute.centerColor, backdropAttribute.edgeColor]; const backdropColors = [backdropAttribute.centerColor, backdropAttribute.edgeColor];
@ -112,7 +120,8 @@ const UniqueGiftHeader = ({
className={styles.sticker} className={styles.sticker}
sticker={modelAttribute.sticker} sticker={modelAttribute.sticker}
size={STICKER_SIZE} size={STICKER_SIZE}
noLoop={!isGiftHover} noLoop={noLoop ?? !isGiftHover}
onEnded={handleStickerEnded}
onMouseEnter={!IS_TOUCH_ENV ? markGiftHover : undefined} onMouseEnter={!IS_TOUCH_ENV ? markGiftHover : undefined}
onMouseLeave={!IS_TOUCH_ENV ? unmarkGiftHover : undefined} onMouseLeave={!IS_TOUCH_ENV ? unmarkGiftHover : undefined}
/> />

View File

@ -15,7 +15,6 @@ import { getNextArrowReplacement } from '../../../../util/localization/format';
import { resolveTransitionName } from '../../../../util/resolveTransitionName'; import { resolveTransitionName } from '../../../../util/resolveTransitionName';
import { getGiftAttributes, getRandomGiftPreviewAttributes } from '../../../common/helpers/gifts'; import { getGiftAttributes, getRandomGiftPreviewAttributes } from '../../../common/helpers/gifts';
import useInterval from '../../../../hooks/schedulers/useInterval';
import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev'; import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev';
import useFlag from '../../../../hooks/useFlag'; import useFlag from '../../../../hooks/useFlag';
import { useIntersectionObserver } from '../../../../hooks/useIntersectionObserver'; import { useIntersectionObserver } from '../../../../hooks/useIntersectionObserver';
@ -45,7 +44,6 @@ type StateProps = {
const MODEL_STICKER_SIZE = 80; const MODEL_STICKER_SIZE = 80;
const PATTERN_STICKER_SIZE = 60; const PATTERN_STICKER_SIZE = 60;
const INTERSECTION_THROTTLE = 200; const INTERSECTION_THROTTLE = 200;
const PLAYBACK_INTERVAL = 5000;
enum AttributeTab { enum AttributeTab {
Model, Model,
@ -125,7 +123,9 @@ const GiftPreviewModal = ({ modal, animationLevel }: OwnProps & StateProps) => {
if (newModel && newModel.rarity.type !== 'regular') showCraftableModels(); if (newModel && newModel.rarity.type !== 'regular') showCraftableModels();
}, [initialAttributes, firstModel, firstPattern, firstBackdrop]); }, [initialAttributes, firstModel, firstPattern, firstBackdrop]);
useInterval(() => { const handleStickerAnimationEnded = useLastCallback((modelName: string) => {
if (modelName !== selectedModel?.name || !isPlayingRandomPreviews) return;
if (!originGift || !selectedModel || !selectedPattern || !selectedBackdrop) return; if (!originGift || !selectedModel || !selectedPattern || !selectedBackdrop) return;
const newAttributes = getRandomGiftPreviewAttributes(renderingModal?.attributes, { const newAttributes = getRandomGiftPreviewAttributes(renderingModal?.attributes, {
model: selectedModel, model: selectedModel,
@ -135,7 +135,7 @@ const GiftPreviewModal = ({ modal, animationLevel }: OwnProps & StateProps) => {
setSelectedModel(newAttributes.model); setSelectedModel(newAttributes.model);
setSelectedPattern(newAttributes.pattern); setSelectedPattern(newAttributes.pattern);
setSelectedBackdrop(newAttributes.backdrop); setSelectedBackdrop(newAttributes.backdrop);
}, isPlayingRandomPreviews ? PLAYBACK_INTERVAL : undefined, true); });
const { const {
observe: observeModelsIntersection, observe: observeModelsIntersection,
@ -273,6 +273,8 @@ const GiftPreviewModal = ({ modal, animationLevel }: OwnProps & StateProps) => {
patternAttribute={selectedPattern} patternAttribute={selectedPattern}
title={originGift?.title} title={originGift?.title}
subtitle={lang('GiftPreviewSelectedTraits')} subtitle={lang('GiftPreviewSelectedTraits')}
noLoop={isPlayingRandomPreviews}
onStickerAnimationEnded={handleStickerAnimationEnded}
> >
<div <div
className={styles.traitButtons} className={styles.traitButtons}