import React, { memo, useEffect, useMemo } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { ApiChat, ApiMediaExtendedPreview, ApiMessage, ApiUser, } from '../../../api/types'; import type { GlobalState, TabState } from '../../../global/types'; import { getChatTitle, getCustomPeerFromInvite, getUserFullName } from '../../../global/helpers'; import { selectChat, selectChatMessage, selectUser, } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import { formatStarsAsIcon } from '../../../util/localization/format'; import { formatInteger } from '../../../util/textFormat'; import renderText from '../../common/helpers/renderText'; import useFlag from '../../../hooks/useFlag'; import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import usePrevious from '../../../hooks/usePrevious'; import Avatar from '../../common/Avatar'; import StarIcon from '../../common/icons/StarIcon'; import PeerBadge from '../../common/PeerBadge'; import PeerChip from '../../common/PeerChip'; import SafeLink from '../../common/SafeLink'; import Button from '../../ui/Button'; import Modal from '../../ui/Modal'; import BalanceBlock from './BalanceBlock'; import PaidMediaThumb from './transaction/PaidMediaThumb'; import styles from './StarsBalanceModal.module.scss'; import StarsBackground from '../../../assets/stars-bg.png'; export type OwnProps = { modal: TabState['starsPayment']; }; type StateProps = { starsBalanceState?: GlobalState['stars']; bot?: ApiUser; paidMediaMessage?: ApiMessage; paidMediaChat?: ApiChat; }; const StarPaymentModal = ({ modal, bot, starsBalanceState, paidMediaMessage, paidMediaChat, }: OwnProps & StateProps) => { const { closeStarsPaymentModal, openStarsBalanceModal, sendStarPaymentForm } = getActions(); const [isLoading, markLoading, unmarkLoading] = useFlag(); const isOpen = Boolean(modal?.inputInvoice && starsBalanceState); const prevModal = usePrevious(modal); const renderingModal = modal || prevModal; const { form, subscriptionInfo } = renderingModal || {}; const amount = form?.invoice?.totalAmount || subscriptionInfo?.subscriptionPricing?.amount; const isBotSubscription = Boolean(form?.invoice.subscriptionPeriod); const canShowPeerItem = !subscriptionInfo?.subscriptionPricing; const photo = form?.photo; const oldLang = useOldLang(); const lang = useLang(); useEffect(() => { if (!isOpen) { unmarkLoading(); } }, [isOpen]); const descriptionText = useMemo(() => { if (!renderingModal?.inputInvoice) { return ''; } const botName = getUserFullName(bot); const starsText = oldLang('Stars.Intro.PurchasedText.Stars', amount); if (paidMediaMessage) { const extendedMedia = paidMediaMessage.content.paidMedia!.extendedMedia as ApiMediaExtendedPreview[]; const areAllPhotos = extendedMedia.every((media) => !media.duration); const areAllVideos = extendedMedia.every((media) => !!media.duration); const mediaText = areAllPhotos ? oldLang('Stars.Transfer.Photos', extendedMedia.length) : areAllVideos ? oldLang('Stars.Transfer.Videos', extendedMedia.length) : oldLang('Media', extendedMedia.length); const channelTitle = getChatTitle(oldLang, paidMediaChat!); return oldLang('Stars.Transfer.UnlockInfo', [mediaText, channelTitle, starsText]); } if (subscriptionInfo) { return lang('StarsSubscribeText', { chat: subscriptionInfo.title, amount, }, { withNodes: true, withMarkdown: true, pluralValue: amount!, }); } if (isBotSubscription) { return lang('StarsSubscribeBotText', { name: form.title, amount, bot: botName, }, { pluralValue: amount!, }); } return oldLang('Stars.Transfer.Info', [form!.title, botName, starsText]); }, [ renderingModal?.inputInvoice, bot, oldLang, amount, paidMediaMessage, subscriptionInfo, isBotSubscription, form, paidMediaChat, lang, ]); const disclaimerText = useMemo(() => { if (subscriptionInfo) { return lang('StarsSubscribeInfo', { link: , }, { withNodes: true, }); } return undefined; }, [subscriptionInfo, lang]); const inviteCustomPeer = useMemo(() => { if (!subscriptionInfo) { return undefined; } return getCustomPeerFromInvite(subscriptionInfo); }, [subscriptionInfo]); const handlePayment = useLastCallback(() => { const balance = starsBalanceState?.balance; if (amount === undefined || balance === undefined) { return; } if (amount > balance.amount) { openStarsBalanceModal({ originStarsPayment: modal, }); return; } sendStarPaymentForm({}); markLoading(); }); return ( {paidMediaMessage ? ( ) : inviteCustomPeer ? ( <> > ) : ( )} {inviteCustomPeer ? oldLang('StarsSubscribeTitle') : oldLang('StarsConfirmPurchaseTitle')} {canShowPeerItem && } {renderText(descriptionText, ['simple_markdown', 'emoji'])} {lang(isBotSubscription ? 'StarsSubscribeBotButtonMonth' : 'StarsPay', { amount: formatStarsAsIcon(lang, amount!, true), }, { withNodes: true, })} {disclaimerText && ( {disclaimerText} )} ); }; export default memo(withGlobal( (global, { modal }): StateProps => { const bot = modal?.form?.botId ? selectUser(global, modal.form.botId) : undefined; const messageInputInvoice = modal?.inputInvoice?.type === 'message' ? modal.inputInvoice : undefined; const message = messageInputInvoice ? selectChatMessage(global, messageInputInvoice.chatId, messageInputInvoice.messageId) : undefined; const chat = messageInputInvoice ? selectChat(global, messageInputInvoice.chatId) : undefined; const isPaidMedia = message?.content.paidMedia; return { bot, starsBalanceState: global.stars, paidMediaMessage: isPaidMedia ? message : undefined, paidMediaChat: isPaidMedia ? chat : undefined, }; }, )(StarPaymentModal));