import React, { memo, useEffect, useMemo, useState, } from '../../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../../global'; import type { ApiPeer, ApiStarGiftAttribute, ApiStarGiftAttributeBackdrop, ApiStarGiftAttributeModel, ApiStarGiftAttributePattern, ApiStarGiftRegular, } from '../../../../api/types'; import type { TabState } from '../../../../global/types'; import { ApiMediaFormat } from '../../../../api/types'; import { getPeerTitle, getStickerMediaHash } from '../../../../global/helpers'; import { selectPeer } from '../../../../global/selectors'; import { formatStarsAsIcon } from '../../../../util/localization/format'; import { fetch } from '../../../../util/mediaLoader'; import useInterval from '../../../../hooks/schedulers/useInterval'; import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev'; import useLang from '../../../../hooks/useLang'; import useLastCallback from '../../../../hooks/useLastCallback'; import Button from '../../../ui/Button'; import Checkbox from '../../../ui/Checkbox'; import TableAboutModal, { type TableAboutData } from '../../common/TableAboutModal'; import UniqueGiftHeader from '../UniqueGiftHeader'; import styles from './GiftUpgradeModal.module.scss'; export type OwnProps = { modal: TabState['giftUpgradeModal']; }; type StateProps = { recipient?: ApiPeer; }; type Attributes = { model: ApiStarGiftAttributeModel; pattern: ApiStarGiftAttributePattern; backdrop: ApiStarGiftAttributeBackdrop; }; const PREVIEW_UPDATE_INTERVAL = 3000; const GiftUpgradeModal = ({ modal, recipient }: OwnProps & StateProps) => { const { closeGiftUpgradeModal, upgradeGift } = getActions(); const isOpen = Boolean(modal); const renderingModal = useCurrentOrPrev(modal); const renderingRecipient = useCurrentOrPrev(recipient); const [shouldKeepOriginalDetails, setShouldKeepOriginalDetails] = useState(false); const [previewAttributes, setPreviewAttributes] = useState(); const lang = useLang(); const handleClose = useLastCallback(() => closeGiftUpgradeModal()); const handleUpgrade = useLastCallback(() => { const gift = renderingModal?.gift; if (!gift?.inputGift) return; upgradeGift({ gift: gift.inputGift, shouldKeepOriginalDetails, upgradeStars: !gift.alreadyPaidUpgradeStars ? (gift.gift as ApiStarGiftRegular).upgradeStars : undefined, }); handleClose(); }); const updatePreviewAttributes = useLastCallback(() => { if (!renderingModal?.sampleAttributes) return; setPreviewAttributes(getRandomAttributes(renderingModal.sampleAttributes, previewAttributes)); }); useInterval(updatePreviewAttributes, isOpen ? PREVIEW_UPDATE_INTERVAL : undefined, true); useEffect(() => { if (isOpen && renderingModal?.sampleAttributes) { updatePreviewAttributes(); } }, [isOpen, renderingModal?.sampleAttributes]); // Preload stickers and patterns useEffect(() => { const attributes = renderingModal?.sampleAttributes; if (!attributes) return; const patternStickers = attributes.filter((attr): attr is ApiStarGiftAttributeModel => attr.type === 'pattern') .map((attr) => attr.sticker); const modelStickers = attributes.filter((attr): attr is ApiStarGiftAttributeModel => attr.type === 'model') .map((attr) => attr.sticker); const mediaHashes = [...patternStickers, ...modelStickers].map((sticker) => getStickerMediaHash(sticker, 'full')); mediaHashes.forEach((hash) => { fetch(hash, ApiMediaFormat.BlobUrl); }); }, [renderingModal?.sampleAttributes]); const modalData = useMemo(() => { if (!previewAttributes || !isOpen) { return undefined; } const gift = renderingModal?.gift; const listItemData = [ ['diamond', lang('GiftUpgradeUniqueTitle'), lang('GiftUpgradeUniqueDescription')], ['trade', lang('GiftUpgradeTransferableTitle'), lang('GiftUpgradeTransferableDescription')], ['auction', lang('GiftUpgradeTradeableTitle'), lang('GiftUpgradeTradeableDescription')], ] satisfies TableAboutData; const subtitle = renderingRecipient ? lang('GiftPeerUpgradeText', { peer: getPeerTitle(lang, renderingRecipient) }) : lang('GiftUpgradeTextOwn'); const header = ( ); const footer = (
{!gift && ( )} {gift && ( <> )}
); return { listItemData, header, footer, }; }, [previewAttributes, isOpen, lang, renderingRecipient, renderingModal?.gift, shouldKeepOriginalDetails]); return ( ); }; export default memo(withGlobal( (global, { modal }): StateProps => { const recipientId = modal?.recipientId; const recipient = recipientId ? selectPeer(global, recipientId) : undefined; return { recipient, }; }, )(GiftUpgradeModal)); function getRandomAttributes(list: ApiStarGiftAttribute[], previousSelection?: Attributes): Attributes { const models = list.filter((attr): attr is ApiStarGiftAttributeModel => ( attr.type === 'model' && attr.name !== previousSelection?.model.name )); const patterns = list.filter((attr): attr is ApiStarGiftAttributePattern => ( attr.type === 'pattern' && attr.name !== previousSelection?.pattern.name )); const backdrops = list.filter((attr): attr is ApiStarGiftAttributeBackdrop => ( attr.type === 'backdrop' && attr.name !== previousSelection?.backdrop.name )); const randomModel = models[Math.floor(Math.random() * models.length)]; const randomPattern = patterns[Math.floor(Math.random() * patterns.length)]; const randomBackdrop = backdrops[Math.floor(Math.random() * backdrops.length)]; return { model: randomModel, pattern: randomPattern, backdrop: randomBackdrop, }; }