import type { FC } from '../../../lib/teact/teact'; import React, { memo, useEffect, useMemo, useRef, useState, } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { ApiPremiumPromo, ApiPremiumSubscriptionOption, ApiSticker, ApiStickerSet, ApiUser, } from '../../../api/types'; import type { ApiPremiumSection, GlobalState } from '../../../global/types'; import { PREMIUM_FEATURE_SECTIONS, TME_LINK_PREFIX } from '../../../config'; import { getUserFullName } from '../../../global/helpers'; import { selectIsCurrentUserPremium, selectStickerSet, selectTabState, selectUser, } from '../../../global/selectors'; import { selectPremiumLimit } from '../../../global/selectors/limits'; import buildClassName from '../../../util/buildClassName'; import { formatCurrency } from '../../../util/formatCurrency'; import { REM } from '../../common/helpers/mediaDimensions'; import renderText from '../../common/helpers/renderText'; import { renderTextWithEntities } from '../../common/helpers/renderTextWithEntities'; import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; import useSyncEffect from '../../../hooks/useSyncEffect'; import CustomEmoji from '../../common/CustomEmoji'; import Button from '../../ui/Button'; import Modal from '../../ui/Modal'; import Transition from '../../ui/Transition'; import PremiumFeatureItem from './PremiumFeatureItem'; import PremiumFeatureModal, { PREMIUM_FEATURE_DESCRIPTIONS, PREMIUM_FEATURE_TITLES, } from './PremiumFeatureModal'; import PremiumSubscriptionOption from './PremiumSubscriptionOption'; import styles from './PremiumMainModal.module.scss'; import PremiumAds from '../../../assets/premium/PremiumAds.svg'; import PremiumBadge from '../../../assets/premium/PremiumBadge.svg'; import PremiumChats from '../../../assets/premium/PremiumChats.svg'; import PremiumEmoji from '../../../assets/premium/PremiumEmoji.svg'; import PremiumFile from '../../../assets/premium/PremiumFile.svg'; import PremiumLastSeen from '../../../assets/premium/PremiumLastSeen.svg'; import PremiumLimits from '../../../assets/premium/PremiumLimits.svg'; import PremiumLogo from '../../../assets/premium/PremiumLogo.svg'; import PremiumMessagePrivacy from '../../../assets/premium/PremiumMessagePrivacy.svg'; import PremiumReactions from '../../../assets/premium/PremiumReactions.svg'; import PremiumSpeed from '../../../assets/premium/PremiumSpeed.svg'; import PremiumStatus from '../../../assets/premium/PremiumStatus.svg'; import PremiumStickers from '../../../assets/premium/PremiumStickers.svg'; import PremiumTags from '../../../assets/premium/PremiumTags.svg'; import PremiumTranslate from '../../../assets/premium/PremiumTranslate.svg'; import PremiumVideo from '../../../assets/premium/PremiumVideo.svg'; import PremiumVoice from '../../../assets/premium/PremiumVoice.svg'; const LIMIT_ACCOUNTS = 4; const STATUS_EMOJI_SIZE = 8 * REM; const PREMIUM_FEATURE_COLOR_ICONS: Record = { stories: PremiumStatus, double_limits: PremiumLimits, infinite_reactions: PremiumReactions, premium_stickers: PremiumStickers, animated_emoji: PremiumEmoji, no_ads: PremiumAds, voice_to_text: PremiumVoice, profile_badge: PremiumBadge, faster_download: PremiumSpeed, more_upload: PremiumFile, advanced_chat_management: PremiumChats, animated_userpics: PremiumVideo, emoji_status: PremiumStatus, translations: PremiumTranslate, saved_tags: PremiumTags, last_seen: PremiumLastSeen, message_privacy: PremiumMessagePrivacy, }; export type OwnProps = { isOpen?: boolean; }; type StateProps = { currentUserId?: string; promo?: ApiPremiumPromo; fromUser?: ApiUser; fromUserStatusEmoji?: ApiSticker; fromUserStatusSet?: ApiStickerSet; toUser?: ApiUser; initialSection?: ApiPremiumSection; isPremium?: boolean; isSuccess?: boolean; isGift?: boolean; monthsAmount?: number; limitChannels: number; limitPins: number; limitLinks: number; limitFolders: number; limits?: NonNullable['limits']; premiumSlug?: string; premiumBotUsername?: string; premiumPromoOrder?: ApiPremiumSection[]; }; const PremiumMainModal: FC = ({ isOpen, currentUserId, fromUser, fromUserStatusEmoji, fromUserStatusSet, promo, initialSection, isPremium, limitChannels, limitLinks, limitFolders, limitPins, limits, premiumSlug, premiumBotUsername, isSuccess, isGift, toUser, monthsAmount, premiumPromoOrder, }) => { // eslint-disable-next-line no-null/no-null const dialogRef = useRef(null); const { closePremiumModal, openInvoice, requestConfetti, openTelegramLink, loadStickers, openStickerSet, } = getActions(); const lang = useLang(); const [isHeaderHidden, setHeaderHidden] = useState(true); const [currentSection, setCurrentSection] = useState(initialSection); const [selectedSubscriptionOption, setSubscriptionOption] = useState(); useEffect(() => { if (!isOpen) { setHeaderHidden(true); setCurrentSection(undefined); } }, [isOpen]); const handleOpenSection = useLastCallback((section: ApiPremiumSection) => { setCurrentSection(section); }); const handleResetSection = useLastCallback(() => { setCurrentSection(undefined); }); function handleScroll(e: React.UIEvent) { const { scrollTop } = e.currentTarget; setHeaderHidden(scrollTop <= 150); } const handleClickWithStartParam = useLastCallback((startParam?: string) => { const dialog = dialogRef.current; if (!dialog) return; if (premiumSlug) { openInvoice({ slug: premiumSlug, }); } else if (premiumBotUsername) { openTelegramLink({ url: `${TME_LINK_PREFIX}${premiumBotUsername}?start=${startParam || 'promo'}`, }); closePremiumModal(); } }); const handleClick = useLastCallback(() => { if (selectedSubscriptionOption) { handleClickWithStartParam(String(selectedSubscriptionOption.months)); } else { handleClickWithStartParam(); } }); const handleChangeSubscriptionOption = useLastCallback((months: number) => { const foundOption = promo?.options.find((option) => option.months === months); setSubscriptionOption(foundOption); }); const showConfetti = useLastCallback(() => { const dialog = dialogRef.current; if (!dialog) return; if (isOpen) { const { top, left, width, height, } = dialog.querySelector('.modal-content')!.getBoundingClientRect(); requestConfetti({ top, left, width, height, }); } }); useEffect(() => { if (isSuccess) { showConfetti(); } }, [isSuccess, showConfetti]); useSyncEffect(([prevIsPremium]) => { if (prevIsPremium === isPremium) return; showConfetti(); }, [isPremium, showConfetti]); const filteredSections = useMemo(() => { if (!premiumPromoOrder) return PREMIUM_FEATURE_SECTIONS; return premiumPromoOrder.filter((section) => PREMIUM_FEATURE_SECTIONS.includes(section)); }, [premiumPromoOrder]); useEffect(() => { if (!fromUserStatusEmoji || fromUserStatusSet) return; loadStickers({ stickerSetInfo: fromUserStatusEmoji.stickerSetInfo, }); }, [loadStickers, fromUserStatusEmoji, fromUserStatusSet]); useEffect(() => { const [defaultOption] = promo?.options ?? []; setSubscriptionOption(defaultOption); }, [promo]); const handleOpenStatusSet = useLastCallback(() => { if (!fromUserStatusSet) return; openStickerSet({ stickerSetInfo: fromUserStatusSet, }); }); const stickerSetTitle = useMemo(() => { if (!fromUserStatusSet || !fromUser) return undefined; const template = lang('lng_premium_emoji_status_title').replace('{user}', getUserFullName(fromUser)!); const [first, second] = template.split('{link}'); const emoji = fromUserStatusSet.thumbCustomEmojiId ? ( ) : undefined; const link = ( {emoji}{renderText(fromUserStatusSet.title)} ); return [renderText(first), link, renderText(second)]; }, [fromUser, fromUserStatusSet, lang]); const fullMonthlyAmount = useMemo(() => { const monthOption = promo?.options.find((option) => option.months === 1); if (!monthOption) { return undefined; } return Number(monthOption.amount); }, [promo]); const subscribeButtonText = useMemo(() => { if (!selectedSubscriptionOption) { return undefined; } const { amount, months, currency } = selectedSubscriptionOption; const perMonthPrice = Math.floor(amount / months); return formatCurrency( perMonthPrice, currency, lang.code, ); }, [selectedSubscriptionOption, lang.code]); if (!promo || (fromUserStatusEmoji && !fromUserStatusSet)) return undefined; function getHeaderText() { if (isGift) { return fromUser?.id === currentUserId ? lang('TelegramPremiumUserGiftedPremiumOutboundDialogTitle', [getUserFullName(toUser), monthsAmount]) : lang('TelegramPremiumUserGiftedPremiumDialogTitle', [getUserFullName(fromUser), monthsAmount]); } return fromUser ? lang('TelegramPremiumUserDialogTitle', getUserFullName(fromUser)) : lang(isPremium ? 'TelegramPremiumSubscribedTitle' : 'TelegramPremium'); } function getHeaderDescription() { if (isGift) { return fromUser?.id === currentUserId ? lang('TelegramPremiumUserGiftedPremiumOutboundDialogSubtitle', getUserFullName(toUser)) : lang('TelegramPremiumUserGiftedPremiumDialogSubtitle'); } if (fromUserStatusSet) { return lang('TelegramPremiumUserStatusDialogSubtitle'); } return fromUser ? lang('TelegramPremiumUserDialogSubtitle') : lang(isPremium ? 'TelegramPremiumSubscribedSubtitle' : 'TelegramPremiumSubtitle'); } function renderFooterText() { if (!promo || (isGift && fromUser?.id === currentUserId)) { return undefined; } return (
{renderTextWithEntities({ text: promo.statusText, entities: promo.statusEntities, })}
); } function renderSubscriptionOptions() { return (
{promo?.options .map((option) => ( ))}
); } return ( {!currentSection ? (
{fromUserStatusEmoji ? ( ) : ( )}

{fromUserStatusSet ? stickerSetTitle : renderText(getHeaderText(), ['simple_markdown', 'emoji'])}

{renderText(getHeaderDescription(), ['simple_markdown', 'emoji'])}
{!isPremium && renderSubscriptionOptions()}

{lang('TelegramPremium')}

{filteredSections.map((section, index) => { return ( ); })}

{renderText(lang('AboutPremiumDescription'), ['simple_markdown'])}

{renderText(lang('AboutPremiumDescription2'), ['simple_markdown'])}

{renderFooterText()}
{!isPremium && selectedSubscriptionOption && (
)}
) : ( )}
); }; export default memo(withGlobal((global): StateProps => { const { premiumModal, } = selectTabState(global); const fromUser = premiumModal?.fromUserId ? selectUser(global, premiumModal.fromUserId) : undefined; const fromUserStatusEmoji = fromUser?.emojiStatus ? global.customEmojis.byId[fromUser.emojiStatus.documentId] : undefined; const fromUserStatusSet = fromUserStatusEmoji ? selectStickerSet(global, fromUserStatusEmoji.stickerSetInfo) : undefined; return { currentUserId: global.currentUserId, promo: premiumModal?.promo, isSuccess: premiumModal?.isSuccess, isGift: premiumModal?.isGift, monthsAmount: premiumModal?.monthsAmount, fromUser, fromUserStatusEmoji, fromUserStatusSet, toUser: premiumModal?.toUserId ? selectUser(global, premiumModal.toUserId) : undefined, initialSection: premiumModal?.initialSection, isPremium: selectIsCurrentUserPremium(global), limitChannels: selectPremiumLimit(global, 'channels'), limitFolders: selectPremiumLimit(global, 'dialogFilters'), limitPins: selectPremiumLimit(global, 'dialogFolderPinned'), limitLinks: selectPremiumLimit(global, 'channelsPublic'), limits: global.appConfig?.limits, premiumSlug: global.appConfig?.premiumInvoiceSlug, premiumBotUsername: global.appConfig?.premiumBotUsername, premiumPromoOrder: global.appConfig?.premiumPromoOrder, }; })(PremiumMainModal));