import { memo, useMemo, useRef } from '../../../lib/teact/teact'; import { getActions, withGlobal } from '../../../global'; import type { ApiEmojiStatusType, ApiPeer, ApiSavedStarGift } from '../../../api/types'; import { STARS_CURRENCY_CODE, TON_CURRENCY_CODE } from '../../../config'; import { getHasAdminRight } from '../../../global/helpers'; import { selectChat, selectPeer, selectUser } from '../../../global/selectors'; import { IS_TOUCH_ENV } from '../../../util/browser/windowEnvironment'; import buildClassName from '../../../util/buildClassName'; import { formatStarsAsIcon, formatTonAsIcon } from '../../../util/localization/format'; import { CUSTOM_PEER_HIDDEN } from '../../../util/objects/customPeer'; import { formatIntegerCompact } from '../../../util/textFormat'; import { getGiftAttributes, getStickerFromGift, getTotalGiftAvailability } from '../helpers/gifts'; import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers'; import useFlag from '../../../hooks/useFlag'; import { type ObserveFn } from '../../../hooks/useIntersectionObserver'; import useLang from '../../../hooks/useLang'; import useLastCallback from '../../../hooks/useLastCallback'; import StickerView from '../../common/StickerView'; import Button from '../../ui/Button'; import Menu from '../../ui/Menu'; import Avatar from '../Avatar'; import Icon from '../icons/Icon'; import RadialPatternBackground from '../profile/RadialPatternBackground'; import GiftMenuItems from './GiftMenuItems'; import GiftRibbon from './GiftRibbon'; import styles from './SavedGift.module.scss'; type OwnProps = { peerId: string; gift: ApiSavedStarGift; style?: string; className?: string; observeIntersection?: ObserveFn; }; type StateProps = { fromPeer?: ApiPeer; currentUserId?: string; hasAdminRights?: boolean; currentUserEmojiStatus?: ApiEmojiStatusType; collectibleEmojiStatuses?: ApiEmojiStatusType[]; }; const GIFT_STICKER_SIZE = 90; const SavedGift = ({ peerId, gift, style, fromPeer, currentUserId, hasAdminRights, collectibleEmojiStatuses, currentUserEmojiStatus, className, observeIntersection, }: OwnProps & StateProps) => { const { openGiftInfoModal } = getActions(); const ref = useRef(); const stickerRef = useRef(); const lang = useLang(); const [isHover, markHover, unmarkHover] = useFlag(); const canManage = peerId === currentUserId || hasAdminRights; const totalIssued = getTotalGiftAvailability(gift.gift); const starGift = gift.gift; const starGiftUnique = starGift.type === 'starGiftUnique' ? starGift : undefined; const resellPrice = useMemo(() => { if (!starGiftUnique?.resellPrice) return undefined; if (starGiftUnique.resaleTonOnly) { return starGiftUnique.resellPrice.find((amount) => amount.currency === TON_CURRENCY_CODE); } return starGiftUnique.resellPrice.find((amount) => amount.currency === STARS_CURRENCY_CODE); }, [starGiftUnique]); const ribbonText = (() => { if (starGiftUnique?.resellPrice) { return lang('GiftRibbonSale'); } if (gift.isPinned && starGiftUnique) { return lang('GiftSavedNumber', { number: starGiftUnique.number }); } if (totalIssued) { return lang('ActionStarGiftLimitedRibbon', { total: formatIntegerCompact(lang, totalIssued) }); } return undefined; })(); const ribbonColor = starGiftUnique?.resellPrice ? 'green' : 'blue'; const { isContextMenuOpen, contextMenuAnchor, handleBeforeContextMenu, handleContextMenu, handleContextMenuClose, handleContextMenuHide, } = useContextMenuHandlers(ref); const getTriggerElement = useLastCallback(() => ref.current); const getRootElement = useLastCallback(() => ref.current!.closest('.custom-scroll')); const getMenuElement = useLastCallback(() => ( document.querySelector('#portals')?.querySelector('.saved-gift-context-menu .bubble') )); const getLayout = useLastCallback(() => ({ withPortal: true })); const handleClick = useLastCallback(() => { openGiftInfoModal({ peerId, gift, }); }); const avatarPeer = (gift.isNameHidden && !fromPeer) ? CUSTOM_PEER_HIDDEN : fromPeer; const sticker = getStickerFromGift(gift.gift); const giftAttributes = useMemo(() => getGiftAttributes(gift.gift), [gift.gift]); const { backdrop, pattern } = giftAttributes || {}; const radialPatternBackdrop = useMemo(() => { if (!backdrop || !pattern) { return undefined; } const backdropColors = [backdrop.centerColor, backdrop.edgeColor]; const patternColor = backdrop.patternColor; return ( ); }, [backdrop, pattern]); if (!sticker) return undefined; return (
{radialPatternBackdrop} {!radialPatternBackdrop && } {gift.isPinned && }
{sticker && ( )}
{gift.isUnsaved && (
)} {resellPrice && ( )} {ribbonText && ( )} {contextMenuAnchor !== undefined && ( )}
); }; export default memo(withGlobal( (global, { peerId, gift }): Complete => { const fromPeer = gift.fromId ? selectPeer(global, gift.fromId) : undefined; const chat = selectChat(global, peerId); const hasAdminRights = chat && getHasAdminRight(chat, 'postMessages'); const currentUserId = global.currentUserId; const currentUser = currentUserId ? selectUser(global, currentUserId) : undefined; const currentUserEmojiStatus = currentUser?.emojiStatus; const collectibleEmojiStatuses = global.collectibleEmojiStatuses?.statuses; return { fromPeer, hasAdminRights, currentUserId, currentUserEmojiStatus, collectibleEmojiStatuses, }; }, )(SavedGift));