import React, { memo, useEffect, useMemo, useState, } from '../../../lib/teact/teact'; import { getActions, getGlobal, withGlobal } from '../../../global'; import type { ApiChat, ApiMessage, ApiStarsAmount, ApiUser, } from '../../../api/types'; import type { TabState } from '../../../global/types'; import type { CustomPeer } from '../../../types'; import { STARS_ICON_PLACEHOLDER } from '../../../config'; import { getChatTitle, getUserFullName } from '../../../global/helpers'; import { selectChat, selectChatMessage, selectUser } from '../../../global/selectors'; 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 Icon from '../../common/icons/Icon'; import PeerBadge from '../../common/PeerBadge'; import SafeLink from '../../common/SafeLink'; import Button from '../../ui/Button'; import Checkbox from '../../ui/Checkbox'; import Modal from '../../ui/Modal'; import Separator from '../../ui/Separator'; import BalanceBlock from '../stars/BalanceBlock'; import StarSlider from './StarSlider'; import styles from './PaidReactionModal.module.scss'; export type OwnProps = { modal: TabState['paidReactionModal']; }; type StateProps = { message?: ApiMessage; chat?: ApiChat; maxAmount: number; starBalance?: ApiStarsAmount; defaultPrivacy?: boolean; }; type ReactorData = { amount: number; localAmount: number; isMe?: boolean; isAnonymous?: boolean; user?: ApiUser; }; const MAX_TOP_REACTORS = 3; const DEFAULT_STARS_AMOUNT = 50; const MAX_REACTION_AMOUNT = 2500; const ANONYMOUS_PEER: CustomPeer = { avatarIcon: 'author-hidden', customPeerAvatarColor: '#9eaab5', isCustomPeer: true, titleKey: 'StarsReactionAnonymous', }; const PaidReactionModal = ({ modal, chat, message, maxAmount, starBalance, defaultPrivacy, }: OwnProps & StateProps) => { const { closePaidReactionModal, addLocalPaidReaction } = getActions(); const [starsAmount, setStarsAmount] = useState(DEFAULT_STARS_AMOUNT); const [isTouched, markTouched, unmarkTouched] = useFlag(); const [shouldShowUp, setShouldShowUp] = useState(true); const oldLang = useOldLang(); const lang = useLang(); const handleAnonimityChange = useLastCallback((e: React.ChangeEvent) => { setShouldShowUp(e.target.checked); }); const handleAmountChange = useLastCallback((value: number) => { setStarsAmount(value); markTouched(); }); useEffect(() => { if (!modal) { unmarkTouched(); } }, [modal]); useEffect(() => { const currentReactor = message?.reactions?.topReactors?.find((reactor) => reactor.isMe); if (currentReactor) { setShouldShowUp(!currentReactor.isAnonymous); return; } setShouldShowUp(defaultPrivacy || true); }, [defaultPrivacy, message?.reactions?.topReactors]); const handleSend = useLastCallback(() => { if (!modal) return; addLocalPaidReaction({ chatId: modal.chatId, messageId: modal.messageId, count: starsAmount, isPrivate: !shouldShowUp, }); closePaidReactionModal(); }); const topReactors = useMemo(() => { const global = getGlobal(); const all = message?.reactions?.topReactors; if (!all) { return undefined; } const result: ReactorData[] = []; let hasMe = false; all.forEach((reactor) => { const user = reactor.peerId ? selectUser(global, reactor.peerId) : undefined; if (!user && !reactor.isAnonymous && !reactor.isMe) return; if (reactor.isMe) { hasMe = true; } result.push({ amount: reactor.count, localAmount: reactor.isMe && isTouched ? starsAmount : 0, isMe: reactor.isMe, isAnonymous: reactor.isAnonymous, user, }); }); if (!hasMe && isTouched) { const me = selectUser(global, global.currentUserId!); result.push({ amount: 0, localAmount: starsAmount, isMe: true, user: me, }); } result.sort((a, b) => (b.amount + b.localAmount) - (a.amount + a.localAmount)); return result.slice(0, MAX_TOP_REACTORS); }, [isTouched, message?.reactions?.topReactors, starsAmount]); const chatTitle = chat && getChatTitle(oldLang, chat); return (

{oldLang('StarsReactionTitle')}

{renderText(oldLang('StarsReactionText', chatTitle), ['simple_markdown', 'emoji'])}
{topReactors &&
{oldLang('StarsReactionTopSenders')}
}
{topReactors && (
{topReactors.map((reactor) => { const countText = formatInteger(reactor.amount + reactor.localAmount); const peer = (reactor.isAnonymous || !reactor.user || (reactor.isMe && !shouldShowUp)) ? ANONYMOUS_PEER : reactor.user; const text = 'isCustomPeer' in peer ? oldLang(peer.titleKey) : getUserFullName(peer); return ( ); })}
)}

{lang('StarsReactionTerms', { link: , }, { withNodes: true, })}

); }; export default memo(withGlobal( (global, { modal }): StateProps => { const chat = modal && selectChat(global, modal.chatId); const message = modal && selectChatMessage(global, modal.chatId, modal.messageId); const starBalance = global.stars?.balance; const maxAmount = global.appConfig?.paidReactionMaxAmount || MAX_REACTION_AMOUNT; const defaultPrivacy = global.settings.paidReactionPrivacy; return { chat, message, starBalance, maxAmount, defaultPrivacy, }; }, )(PaidReactionModal));