import { memo, useEffect, useState, } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { ApiDraft, ApiPeer, ApiStarsAmount, ApiTypeCurrencyAmount } from '../../../api/types'; import type { TabState } from '../../../global/types'; import { MAIN_THREAD_ID } from '../../../api/types'; import { STARS_CURRENCY_CODE, TON_CURRENCY_CODE, } from '../../../config'; import { selectIsMonoforumAdmin, selectPeer } from '../../../global/selectors'; import { selectDraft } from '../../../global/selectors/threads'; import buildClassName from '../../../util/buildClassName'; import { formatScheduledDateTime, formatShortDuration } from '../../../util/dates/oldDateFormat'; import { convertTonFromNanos, convertTonToNanos } from '../../../util/formatCurrency'; import { formatStarsAsIcon, formatStarsAsText, formatTonAsIcon, formatTonAsText } from '../../../util/localization/format'; import { getServerTime } from '../../../util/serverTime'; import useFlag from '../../../hooks/useFlag'; import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; import useOldLang from '../../../hooks/useOldLang'; import CalendarModal from '../../common/CalendarModal'; import Icon from '../../common/icons/Icon'; import Button from '../../ui/Button'; import InputText from '../../ui/InputText'; import Modal from '../../ui/Modal'; import styles from './SuggestMessageModal.module.scss'; export type OwnProps = { modal: TabState['suggestMessageModal']; }; type StateProps = { starBalance?: ApiStarsAmount; tonBalance?: number; peer?: ApiPeer; currentDraft?: ApiDraft; maxStarsAmount: number; minStarsAmount: number; tonMaxAmount: number; tonMinAmount: number; ageMinSeconds: number; futureMin: number; futureMax: number; isMonoforumAdmin?: boolean; }; // Add 1 minute if time is less than server min, to allow user to send the message const FUTURE_TIME_ADJUSTMENT = 1 * 60; const SuggestMessageModal = ({ modal, starBalance, tonBalance, peer, currentDraft, maxStarsAmount, minStarsAmount, tonMaxAmount, tonMinAmount, ageMinSeconds, futureMin, futureMax, isMonoforumAdmin, }: OwnProps & StateProps) => { const { closeSuggestMessageModal, updateDraftSuggestedPostInfo, openStarsBalanceModal } = getActions(); const [isCalendarOpened, openCalendar, closeCalendar] = useFlag(); const currentSuggestedPostInfo = currentDraft?.suggestedPostInfo; const currentReplyInfo = currentDraft?.replyInfo; const isInSuggestChangesMode = Boolean(currentReplyInfo); const [currencyAmount, setCurrencyAmount] = useState( currentSuggestedPostInfo?.price?.amount || undefined, ); const [selectedCurrency, setSelectedCurrency] = useState( currentSuggestedPostInfo?.price?.currency || STARS_CURRENCY_CODE, ); const [scheduleDate, setScheduleDate] = useState( currentSuggestedPostInfo?.scheduleDate ? currentSuggestedPostInfo.scheduleDate * 1000 : undefined, ); useEffect(() => { const price = currentSuggestedPostInfo?.price; const amount = price?.currency === TON_CURRENCY_CODE ? convertTonFromNanos(price.amount) : price?.amount; setCurrencyAmount(amount); setSelectedCurrency(currentSuggestedPostInfo?.price?.currency || STARS_CURRENCY_CODE); setScheduleDate(currentSuggestedPostInfo?.scheduleDate ? currentSuggestedPostInfo.scheduleDate * 1000 : undefined); }, [currentSuggestedPostInfo]); const lang = useLang(); const oldLang = useOldLang(); const isCurrencyStars = selectedCurrency === STARS_CURRENCY_CODE; const now = getServerTime(); const minAt = (now + futureMin) * 1000; const maxAt = (now + futureMax) * 1000; const defaultSelectedTime = (now + futureMin * 2) * 1000; const handleAmountChange = useLastCallback((e: React.ChangeEvent) => { const value = e.target.value; const number = parseFloat(value); const result = value === '' || Number.isNaN(number) ? undefined : Math.min(Math.max(number, 0), currentMaxAmount); setCurrencyAmount(result); }); const handleExpireDateChange = useLastCallback((date: Date) => { setScheduleDate(date.getTime()); closeCalendar(); }); const handleAnytimeClick = useLastCallback(() => { setScheduleDate(undefined); closeCalendar(); }); const currentMinAmount = isCurrencyStars ? minStarsAmount : convertTonFromNanos(tonMinAmount); const currentMaxAmount = isCurrencyStars ? maxStarsAmount : convertTonFromNanos(tonMaxAmount); const isDisabled = Boolean(currencyAmount) && currencyAmount < currentMinAmount; const handleOffer = useLastCallback(() => { const neededAmount = currencyAmount ? (isCurrencyStars ? currencyAmount : convertTonToNanos(currencyAmount)) : 0; if (isDisabled) { return; } if (!isMonoforumAdmin) { if (isCurrencyStars) { const currentBalance = starBalance?.amount || 0; if (neededAmount > currentBalance) { openStarsBalanceModal({ topup: { balanceNeeded: neededAmount, }, }); return; } } else { const currentTonBalance = tonBalance || 0; if (neededAmount > currentTonBalance) { openStarsBalanceModal({ currency: TON_CURRENCY_CODE, }); return; } } } updateDraftSuggestedPostInfo({ price: { currency: selectedCurrency, amount: neededAmount, nanos: 0 }, scheduleDate: scheduleDate ? Math.max(scheduleDate / 1000, getServerTime() + futureMin + FUTURE_TIME_ADJUSTMENT) : undefined, }); closeSuggestMessageModal(); }); return (
{currencyAmount !== undefined && currencyAmount > 0 && currencyAmount < currentMinAmount ? lang('DescriptionSuggestedPostMinimumOffer', { amount: isCurrencyStars ? formatStarsAsText(lang, currentMinAmount) : formatTonAsText(lang, currentMinAmount) }, { withNodes: true, withMarkdown: true }) : isCurrencyStars ? lang('SuggestMessagePriceDescriptionStars') : lang('SuggestMessagePriceDescriptionTon')}
{lang('SuggestMessageTimeDescription', { hint: lang('SuggestMessageDateTimeHint'), duration: formatShortDuration(lang, ageMinSeconds, true), })}
); }; export default memo(withGlobal( (global, { modal }): Complete => { const starBalance = global.stars?.balance; const peer = modal ? selectPeer(global, modal.chatId) : undefined; const currentDraft = modal ? selectDraft(global, modal.chatId, MAIN_THREAD_ID) : undefined; const { appConfig } = global; const maxStarsAmount = appConfig.starsSuggestedPostAmountMax; const minStarsAmount = appConfig.starsSuggestedPostAmountMin; const ageMinSeconds = appConfig.starsSuggestedPostAgeMin; const futureMin = appConfig.starsSuggestedPostFutureMin; const futureMax = appConfig.starsSuggestedPostFutureMax; const tonMaxAmount = appConfig.tonSuggestedPostAmountMax; const tonMinAmount = appConfig.tonSuggestedPostAmountMin; const isMonoforumAdmin = modal ? selectIsMonoforumAdmin(global, modal.chatId) : false; return { peer, starBalance, tonBalance: global.ton?.balance?.amount, currentDraft, maxStarsAmount, minStarsAmount, tonMaxAmount, tonMinAmount, ageMinSeconds, futureMin, futureMax, isMonoforumAdmin, }; }, )(SuggestMessageModal));