import React, { memo, useEffect, useMemo, useState, } from '../../../lib/teact/teact'; import { getActions, getGlobal, withGlobal } from '../../../global'; import type { ApiStarTopupOption } from '../../../api/types'; import type { GlobalState, TabState } from '../../../global/types'; import { getChatTitle, getUserFullName } from '../../../global/helpers'; import { selectChat, selectIsPremiumPurchaseBlocked, selectUser } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; 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 Icon from '../../common/icons/Icon'; import StarIcon from '../../common/icons/StarIcon'; import SafeLink from '../../common/SafeLink'; import Button from '../../ui/Button'; import InfiniteScroll from '../../ui/InfiniteScroll'; import Modal from '../../ui/Modal'; import TabList, { type TabWithProperties } from '../../ui/TabList'; import Transition from '../../ui/Transition'; import BalanceBlock from './BalanceBlock'; import StarTopupOptionList from './StarTopupOptionList'; import StarsSubscriptionItem from './subscription/StarsSubscriptionItem'; import StarsTransactionItem from './transaction/StarsTransactionItem'; import styles from './StarsBalanceModal.module.scss'; import StarLogo from '../../../assets/icons/StarLogo.svg'; import StarsBackground from '../../../assets/stars-bg.png'; const TRANSACTION_TYPES = ['all', 'inbound', 'outbound'] as const; const TRANSACTION_TABS: TabWithProperties[] = [ { title: 'StarsTransactionsAll' }, { title: 'StarsTransactionsIncoming' }, { title: 'StarsTransactionsOutgoing' }, ]; const TRANSACTION_ITEM_CLASS = 'StarsTransactionItem'; const SUBSCRIPTION_PURPOSE = 'subs'; export type OwnProps = { modal: TabState['starsBalanceModal']; }; type StateProps = { starsBalanceState?: GlobalState['stars']; canBuyPremium?: boolean; }; const StarsBalanceModal = ({ modal, starsBalanceState, canBuyPremium, }: OwnProps & StateProps) => { const { closeStarsBalanceModal, loadStarsTransactions, loadStarsSubscriptions, openStarsGiftingPickerModal, openInvoice, } = getActions(); const { balance, history, subscriptions } = starsBalanceState || {}; const oldLang = useOldLang(); const lang = useLang(); const [isHeaderHidden, setHeaderHidden] = useState(true); const [selectedTabIndex, setSelectedTabIndex] = useState(0); const [areBuyOptionsShown, showBuyOptions, hideBuyOptions] = useFlag(); const isOpen = Boolean(modal && starsBalanceState); const { originStarsPayment, originReaction, originGift, topup, } = modal || {}; const shouldOpenOnBuy = originStarsPayment || originReaction || originGift || topup; const ongoingTransactionAmount = originStarsPayment?.form?.invoice?.totalAmount || originStarsPayment?.subscriptionInfo?.subscriptionPricing?.amount || originReaction?.amount || originGift?.gift.stars || topup?.balanceNeeded; const starsNeeded = ongoingTransactionAmount ? ongoingTransactionAmount - (balance || 0) : undefined; const starsNeededText = useMemo(() => { const global = getGlobal(); if (originReaction) { const channel = selectChat(global, originReaction.chatId); if (!channel) return undefined; return oldLang('StarsNeededTextReactions', getChatTitle(oldLang, channel)); } if (originStarsPayment) { const bot = originStarsPayment.form?.botId ? selectUser(global, originStarsPayment.form.botId) : undefined; if (!bot) return undefined; return oldLang('StarsNeededText', getUserFullName(bot)); } if (originGift) { const user = selectUser(global, originGift.userId); if (!user) return undefined; return oldLang('StarsNeededTextGift', getUserFullName(user)); } if (topup?.purpose === SUBSCRIPTION_PURPOSE) { return oldLang('StarsNeededTextLink'); } return undefined; }, [originReaction, originStarsPayment, originGift, topup?.purpose, oldLang]); const shouldShowItems = Boolean(history?.all?.transactions.length && !shouldOpenOnBuy); const shouldSuggestGifting = !shouldOpenOnBuy; useEffect(() => { if (!isOpen) { setHeaderHidden(true); setSelectedTabIndex(0); hideBuyOptions(); } }, [isOpen]); useEffect(() => { if (shouldOpenOnBuy) { showBuyOptions(); return; } hideBuyOptions(); }, [shouldOpenOnBuy]); const tosText = useMemo(() => { if (!isOpen) return undefined; const text = oldLang('lng_credits_summary_options_about'); const parts = text.split('{link}'); return [ parts[0], , parts[1], ]; }, [isOpen, oldLang]); function handleScroll(e: React.UIEvent) { const { scrollTop } = e.currentTarget; setHeaderHidden(scrollTop <= 150); } const handleLoadMoreTransactions = useLastCallback(() => { loadStarsTransactions({ type: TRANSACTION_TYPES[selectedTabIndex], }); }); const handleLoadMoreSubscriptions = useLastCallback(() => { loadStarsSubscriptions(); }); const openStarsGiftingPickerModalHandler = useLastCallback(() => { openStarsGiftingPickerModal({}); }); const handleBuyStars = useLastCallback((option: ApiStarTopupOption) => { openInvoice({ type: 'stars', stars: option.stars, currency: option.currency, amount: option.amount, }); }); return (

{oldLang('TelegramStars')}

{starsNeeded ? oldLang('StarsNeededTitle', ongoingTransactionAmount) : oldLang('TelegramStars')}

{renderText( starsNeededText || oldLang('TelegramStarsInfo'), ['simple_markdown', 'emoji'], )}
{canBuyPremium && !areBuyOptionsShown && ( )} {canBuyPremium && !areBuyOptionsShown && shouldSuggestGifting && ( )} {areBuyOptionsShown && starsBalanceState?.topupOptions && ( )}
{areBuyOptionsShown && (
{tosText}
)} {shouldShowItems && Boolean(subscriptions?.list.length) && (

{oldLang('StarMySubscriptions')}

{subscriptions?.list.map((subscription) => ( ))} {subscriptions?.nextOffset && ( )}
)} {shouldShowItems && (
{history?.[TRANSACTION_TYPES[selectedTabIndex]]?.transactions.map((transaction) => ( ))}
)}
); }; export default memo(withGlobal( (global): StateProps => { return { starsBalanceState: global.stars, canBuyPremium: !selectIsPremiumPurchaseBlocked(global), }; }, )(StarsBalanceModal));