Premium modal: Various fixes (#4045)

This commit is contained in:
Alexander Zinchuk 2023-12-04 14:39:22 +01:00
parent 3ef2fa7680
commit 76629db59f
5 changed files with 50 additions and 33 deletions

View File

@ -1,6 +1,6 @@
import type { FC } from '../../../lib/teact/teact';
import React, {
memo, useCallback, useEffect, useRef, useState,
memo, useCallback, useEffect, useMemo, useRef, useState,
} from '../../../lib/teact/teact';
import type { ApiPremiumPromo } from '../../../api/types';
@ -127,21 +127,23 @@ const LIMITS_DESCRIPTIONS: Record<ApiLimitTypeWithoutUpload, string> = {
const BORDER_THRESHOLD = 20;
type OwnProps = {
onBack: VoidFunction;
initialSection: string;
promo: ApiPremiumPromo;
onClickSubscribe: (startParam?: string) => void;
isPremium?: boolean;
limits?: NonNullable<GlobalState['appConfig']>['limits'];
premiumPromoOrder?: string[];
onBack: VoidFunction;
onClickSubscribe: (startParam?: string) => void;
};
const PremiumFeatureModal: FC<OwnProps> = ({
promo,
initialSection,
onBack,
onClickSubscribe,
isPremium,
limits,
premiumPromoOrder,
onBack,
onClickSubscribe,
}) => {
const lang = useLang();
// eslint-disable-next-line no-null/no-null
@ -155,6 +157,11 @@ const PremiumFeatureModal: FC<OwnProps> = ({
const prevInitialSection = usePrevious(initialSection);
const filteredSections = useMemo(() => {
if (!premiumPromoOrder) return PREMIUM_FEATURE_SECTIONS;
return premiumPromoOrder.filter((section) => PREMIUM_FEATURE_SECTIONS.includes(section));
}, [premiumPromoOrder]);
function handleClick() {
onClickSubscribe(initialSection);
}
@ -192,12 +199,12 @@ const PremiumFeatureModal: FC<OwnProps> = ({
const scrollContainer = scrollContainerRef.current;
if (!scrollContainer || (prevInitialSection === initialSection)) return;
const index = PREMIUM_FEATURE_SECTIONS.indexOf(initialSection);
const index = filteredSections.indexOf(initialSection);
setCurrentSlideIndex(index);
startScrolling();
animateHorizontalScroll(scrollContainer, scrollContainer.clientWidth * index, 0)
.then(stopScrolling);
}, [currentSlideIndex, initialSection, prevInitialSection, startScrolling, stopScrolling]);
}, [currentSlideIndex, filteredSections, initialSection, prevInitialSection]);
const handleSelectSlide = useCallback(async (index: number) => {
const scrollContainer = scrollContainerRef.current;
@ -208,7 +215,7 @@ const PremiumFeatureModal: FC<OwnProps> = ({
startScrolling();
await animateHorizontalScroll(scrollContainer, scrollContainer.clientWidth * index, 800);
stopScrolling();
}, [startScrolling, stopScrolling]);
}, []);
// TODO Support all subscription options
const month = promo.options.find((option) => option.months === 1)!;
@ -230,7 +237,7 @@ const PremiumFeatureModal: FC<OwnProps> = ({
<div className={buildClassName(styles.content, 'no-scrollbar')} onScroll={handleScroll} ref={scrollContainerRef}>
{PREMIUM_FEATURE_SECTIONS.map((section, index) => {
{filteredSections.map((section, index) => {
if (section === 'double_limits') {
return (
<div className={buildClassName(styles.slide, styles.limits)}>

View File

@ -372,6 +372,7 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
onClickSubscribe={handleClickWithStartParam}
isPremium={isPremium}
limits={limits}
premiumPromoOrder={premiumPromoOrder}
/>
)}
</Transition>

View File

@ -1,6 +1,6 @@
import type { FC } from '../../../../lib/teact/teact';
import React, {
memo, useCallback, useEffect, useRef, useState,
memo, useEffect, useRef, useState,
} from '../../../../lib/teact/teact';
import { withGlobal } from '../../../../global';
@ -10,6 +10,7 @@ import type { GlobalState } from '../../../../global/types';
import cycleRestrict from '../../../../util/cycleRestrict';
import useFlag from '../../../../hooks/useFlag';
import useLastCallback from '../../../../hooks/useLastCallback';
import useMedia from '../../../../hooks/useMedia';
import AnimatedSticker from '../../../common/AnimatedSticker';
@ -36,7 +37,7 @@ const AnimatedCircleSticker: FC<{
index: number;
maxLength: number;
onClick: (index: number) => void;
onEnded: NoneToVoidFunction;
onEnded: (index: number) => void;
canPlay: boolean;
}> = ({
size, realIndex, canPlay,
@ -60,14 +61,14 @@ const AnimatedCircleSticker: FC<{
const x = Math.cos(angle) * width - circleSize * 2.8;
const y = Math.sin(angle) * height;
const handleClick = useCallback(() => {
const handleClick = useLastCallback(() => {
onClick(realIndex);
}, [onClick, realIndex]);
});
const handleEnded = useCallback(() => {
const handleEnded = useLastCallback(() => {
inanimate();
onEnded();
}, [inanimate, onEnded]);
onEnded(realIndex);
});
useEffect(() => {
if (isActivated) {
@ -112,15 +113,20 @@ const PremiumFeaturePreviewStickers: FC<OwnProps & StateProps> = ({
const renderedStickers = stickers?.slice(0, MAX_EMOJIS);
const handleClick = useCallback((i: number) => {
const handleClick = useLastCallback((i: number) => {
setOffset(-i);
}, []);
});
const handleEnded = useLastCallback((i: number) => {
const displayIndex = cycleRestrict(renderedStickers.length, i + offset);
if (displayIndex !== 0) return;
const handleEnded = useCallback(() => {
setTimeout(() => {
setOffset((current) => cycleRestrict(renderedStickers.length, current + 1));
setOffset((current) => {
return cycleRestrict(renderedStickers.length, current + 1);
});
}, ENDED_DELAY);
}, [renderedStickers.length]);
});
useEffect(() => {
const container = containerRef.current;
@ -134,11 +140,11 @@ const PremiumFeaturePreviewStickers: FC<OwnProps & StateProps> = ({
className={styles.root}
ref={containerRef}
>
{Boolean(size) && renderedStickers?.map((l, i) => {
{Boolean(size) && renderedStickers?.map((sticker, i) => {
return (
<AnimatedCircleSticker
size={size}
sticker={l}
sticker={sticker}
realIndex={i}
index={(i + offset + renderedStickers.length) % renderedStickers.length}
maxLength={renderedStickers.length}

View File

@ -30,10 +30,11 @@
overflow-y: scroll;
border-top: 0.0625rem solid transparent;
transition: 0.2s ease-in-out border-color;
margin-inline: 1rem;
}
.mobile {
padding: 1rem 1rem 1rem 2rem;
padding: 1rem 0rem 1rem 1rem;
color: var(--color-text-secondary);
font-size: 0.875rem;
}

View File

@ -88,15 +88,17 @@ const MediaAreaSuggestedReaction = ({
<div
className={buildClassName(styles.background, isFlipped && styles.flipped)}
/>
<ReactionAnimatedEmoji
className={buildClassName(styles.reaction, shouldDisplayCount && styles.withCount)}
reaction={reaction}
containerId={containerId}
size={customEmojiSize}
effectSize={customEmojiSize * EFFECT_SIZE_MULTIPLIER}
shouldPause={isPreview}
shouldLoop={!isPreview}
/>
{Boolean(customEmojiSize) && (
<ReactionAnimatedEmoji
className={buildClassName(styles.reaction, shouldDisplayCount && styles.withCount)}
reaction={reaction}
containerId={containerId}
size={customEmojiSize}
effectSize={customEmojiSize * EFFECT_SIZE_MULTIPLIER}
shouldPause={isPreview}
shouldLoop={!isPreview}
/>
)}
{shouldDisplayCount && (
<span className={styles.reactionCount}>{reactionCount}</span>
)}