import React, { memo, useEffect, useMemo, useRef, useState, } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { ApiChannelMonetizationStatistics, StatisticsGraph } from '../../../api/types'; import { selectChat, selectChatFullInfo, selectTabState } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; import renderText from '../../common/helpers/renderText'; import useFlag from '../../../hooks/useFlag'; import useForceUpdate from '../../../hooks/useForceUpdate'; import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import AboutMonetizationModal from '../../common/AboutMonetizationModal.async'; import Icon from '../../common/icons/Icon'; import SafeLink from '../../common/SafeLink'; import VerificationMonetizationModal from '../../common/VerificationMonetizationModal.async'; import Button from '../../ui/Button'; import ConfirmDialog from '../../ui/ConfirmDialog'; import Link from '../../ui/Link'; import Loading from '../../ui/Loading'; import StatisticsOverview from './StatisticsOverview'; import styles from './MonetizationStatistics.module.scss'; type ILovelyChart = { create: Function }; let lovelyChartPromise: Promise; let LovelyChart: ILovelyChart; async function ensureLovelyChart() { if (!lovelyChartPromise) { lovelyChartPromise = import('../../../lib/lovely-chart/LovelyChart') as Promise; LovelyChart = await lovelyChartPromise; } return lovelyChartPromise; } const MONETIZATION_GRAPHS_TITLES = { topHoursGraph: 'ChannelStats.Graph.ViewsByHours', revenueGraph: 'lng_channel_earn_chart_revenue', }; const MONETIZATION_GRAPHS = Object.keys(MONETIZATION_GRAPHS_TITLES) as (keyof ApiChannelMonetizationStatistics)[]; type StateProps = { chatId: string; dcId?: number; statistics?: ApiChannelMonetizationStatistics; isCreator?: boolean; isChannelRevenueWithdrawalEnabled?: boolean; hasPassword?: boolean; passwordHint?: string; error?: string; isLoading?: boolean; }; const MonetizationStatistics = ({ chatId, dcId, statistics, isCreator, isChannelRevenueWithdrawalEnabled, hasPassword, passwordHint, error, isLoading, }: StateProps) => { const { loadChannelMonetizationStatistics, loadPasswordInfo } = getActions(); const oldLang = useOldLang(); const lang = useLang(); // eslint-disable-next-line no-null/no-null const containerRef = useRef(null); const [isReady, setIsReady] = useState(false); const loadedCharts = useRef([]); const forceUpdate = useForceUpdate(); const [isAboutMonetizationModalOpen, openAboutMonetizationModal, closeAboutMonetizationModal] = useFlag(false); const [ isVerificationMonetizationModalOpen, openVerificationMonetizationModal, closeVerificationMonetizationModal, ] = useFlag(false); const [isConfirmPasswordDialogOpen, openConfirmPasswordDialogOpen, closeConfirmPasswordDialogOpen] = useFlag(); const availableBalance = statistics?.balances?.availableBalance; const isWithdrawalEnabled = statistics?.balances?.isWithdrawalEnabled; const canWithdraw = isCreator && isChannelRevenueWithdrawalEnabled && Boolean(availableBalance) && isWithdrawalEnabled; useEffect(() => { if (chatId) { loadChannelMonetizationStatistics({ chatId }); loadPasswordInfo(); } }, [chatId, loadChannelMonetizationStatistics]); useEffect(() => { (async () => { await ensureLovelyChart(); if (!isReady) { setIsReady(true); return; } if (containerRef.current) { Array.from(containerRef.current.children).forEach((child) => { child.innerHTML = ''; child.classList.add(styles.hidden); }); } loadedCharts.current = []; if (!statistics || !containerRef.current) { return; } MONETIZATION_GRAPHS.forEach((name, index: number) => { const graph = statistics[name as keyof typeof statistics]; const isAsync = typeof graph === 'string'; if (isAsync || loadedCharts.current.includes(name)) { return; } if (!graph) { loadedCharts.current.push(name); return; } LovelyChart.create(containerRef.current!.children[index], { title: oldLang((MONETIZATION_GRAPHS_TITLES as Record)[name]), ...graph as StatisticsGraph, }); loadedCharts.current.push(name); containerRef.current!.children[index].classList.remove(styles.hidden); }); forceUpdate(); })(); }, [isReady, statistics, oldLang, chatId, dcId, forceUpdate]); function renderAvailableReward() { const [integerTonPart, decimalTonPart] = availableBalance ? availableBalance.toFixed(4).split('.') : [0]; const [integerUsdPart, decimalUsdPart] = availableBalance && statistics?.usdRate ? (availableBalance * statistics.usdRate).toFixed(2).split('.') : [0]; return (
{integerTonPart} {decimalTonPart ? .{decimalTonPart} : undefined}
{' '} ≈ ${integerUsdPart} {decimalUsdPart ? .{decimalUsdPart} : undefined}
); } const topText = useMemo(() => { const linkText = oldLang('LearnMore'); return lang( 'ChannelEarnAbout', { link: ( {linkText} ), }, { withNodes: true, }, ); }, [lang, oldLang]); const rewardsText = useMemo(() => { const linkText = oldLang('LearnMore'); return lang( 'MonetizationBalanceZeroInfo', { link: ( {linkText} ), }, { withNodes: true, }, ); }, [lang, oldLang]); const verificationMonetizationHandler = useLastCallback(() => { if (hasPassword) { openVerificationMonetizationModal(); } else { openConfirmPasswordDialogOpen(); } }); if (!isReady || !statistics) { return ; } return (
{topText}
{oldLang('MonetizationProceedsTONInfo')}
} /> {!loadedCharts.current.length && }
{MONETIZATION_GRAPHS.filter(Boolean).map((graph) => (
))}
{oldLang('lng_channel_earn_balance_title')} {renderAvailableReward()}
{rewardsText}

{renderText(oldLang('Monetization.Withdraw.Error.Text'), ['br'])}

); }; export default memo(withGlobal( (global): StateProps => { const tabState = selectTabState(global); const { settings: { byKey: { hasPassword, }, }, twoFaSettings: { hint: passwordHint, }, } = global; const isLoading = global.monetizationInfo?.isLoading; const error = global.monetizationInfo?.error; const monetizationStatistics = tabState.monetizationStatistics; const chatId = monetizationStatistics && monetizationStatistics.chatId; const chat = chatId ? selectChat(global, chatId) : undefined; const dcId = selectChatFullInfo(global, chatId!)?.statisticsDcId; const isCreator = Boolean(chat?.isCreator); const statistics = tabState.statistics.monetization; const isChannelRevenueWithdrawalEnabled = global.appConfig?.isChannelRevenueWithdrawalEnabled; return { chatId: chatId!, dcId, statistics, isCreator, isChannelRevenueWithdrawalEnabled, hasPassword, passwordHint, error, isLoading, }; }, )(MonetizationStatistics));