Premium modal: Various fixes (#4045)
This commit is contained in:
parent
3ef2fa7680
commit
76629db59f
@ -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)}>
|
||||
|
||||
@ -372,6 +372,7 @@ const PremiumMainModal: FC<OwnProps & StateProps> = ({
|
||||
onClickSubscribe={handleClickWithStartParam}
|
||||
isPremium={isPremium}
|
||||
limits={limits}
|
||||
premiumPromoOrder={premiumPromoOrder}
|
||||
/>
|
||||
)}
|
||||
</Transition>
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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>
|
||||
)}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user