import type { FC, TeactNode } from '../../../../lib/teact/teact';
import React, { memo, useMemo } from '../../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../../global';
import type {
ApiPeer,
} from '../../../../api/types';
import type { TabState } from '../../../../global/types';
import { TME_LINK_PREFIX } from '../../../../config';
import { getHasAdminRight, getPeerTitle } from '../../../../global/helpers';
import { isApiPeerChat } from '../../../../global/helpers/peers';
import { selectPeer } from '../../../../global/selectors';
import buildClassName from '../../../../util/buildClassName';
import { copyTextToClipboard } from '../../../../util/clipboard';
import { formatDateTimeToString } from '../../../../util/dates/dateFormat';
import { formatStarsAsIcon, formatStarsAsText } from '../../../../util/localization/format';
import { CUSTOM_PEER_HIDDEN } from '../../../../util/objects/customPeer';
import { getServerTime } from '../../../../util/serverTime';
import { formatInteger, formatPercent } from '../../../../util/textFormat';
import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts';
import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities';
import useCurrentOrPrev from '../../../../hooks/useCurrentOrPrev';
import useFlag from '../../../../hooks/useFlag';
import useLang from '../../../../hooks/useLang';
import useLastCallback from '../../../../hooks/useLastCallback';
import useOldLang from '../../../../hooks/useOldLang';
import AnimatedIconFromSticker from '../../../common/AnimatedIconFromSticker';
import Avatar from '../../../common/Avatar';
import BadgeButton from '../../../common/BadgeButton';
import Icon from '../../../common/icons/Icon';
import Button from '../../../ui/Button';
import ConfirmDialog from '../../../ui/ConfirmDialog';
import DropdownMenu from '../../../ui/DropdownMenu';
import Link from '../../../ui/Link';
import MenuItem from '../../../ui/MenuItem';
import TableInfoModal, { type TableData } from '../../common/TableInfoModal';
import UniqueGiftHeader from '../UniqueGiftHeader';
import styles from './GiftInfoModal.module.scss';
export type OwnProps = {
modal: TabState['giftInfoModal'];
};
type StateProps = {
fromPeer?: ApiPeer;
targetPeer?: ApiPeer;
currentUserId?: string;
starGiftMaxConvertPeriod?: number;
hasAdminRights?: boolean;
};
const STICKER_SIZE = 120;
const GiftInfoModal = ({
modal,
fromPeer,
targetPeer,
currentUserId,
starGiftMaxConvertPeriod,
hasAdminRights,
}: OwnProps & StateProps) => {
const {
closeGiftInfoModal,
changeGiftVisibility,
convertGiftToStars,
openChatWithInfo,
focusMessage,
openGiftUpgradeModal,
showNotification,
openChatWithDraft,
} = getActions();
const [isConvertConfirmOpen, openConvertConfirm, closeConvertConfirm] = useFlag();
const lang = useLang();
const oldLang = useOldLang();
const isOpen = Boolean(modal);
const renderingModal = useCurrentOrPrev(modal);
const renderingFromPeer = useCurrentOrPrev(fromPeer);
const renderingTargetPeer = useCurrentOrPrev(targetPeer);
const isTargetChat = renderingTargetPeer && isApiPeerChat(renderingTargetPeer);
const { gift: typeGift } = renderingModal || {};
const isSavedGift = typeGift && 'gift' in typeGift;
const savedGift = isSavedGift ? typeGift : undefined;
const isSender = savedGift?.fromId === currentUserId;
const canConvertDifference = (savedGift && starGiftMaxConvertPeriod && (
savedGift.date + starGiftMaxConvertPeriod - getServerTime()
)) || 0;
const conversionLeft = Math.ceil(canConvertDifference / 60 / 60 / 24);
const gift = isSavedGift ? typeGift.gift : typeGift;
const giftSticker = gift && getStickerFromGift(gift);
const canFocusUpgrade = Boolean(savedGift?.upgradeMsgId);
const canUpdate = !canFocusUpgrade && savedGift?.inputGift && (
isTargetChat ? hasAdminRights : renderingTargetPeer?.id === currentUserId
);
const handleClose = useLastCallback(() => {
closeGiftInfoModal();
});
const starGiftUniqueLink = useMemo(() => {
const slug = gift?.type === 'starGiftUnique' ? gift.slug : undefined;
if (!slug) return undefined;
return `${TME_LINK_PREFIX}nft/${slug}`;
}, [gift]);
const handleCopyLink = useLastCallback(() => {
if (!starGiftUniqueLink) return;
copyTextToClipboard(starGiftUniqueLink);
showNotification({
message: lang('LinkCopied'),
});
});
const handleLinkShare = useLastCallback(() => {
if (!starGiftUniqueLink) return;
openChatWithDraft({ text: { text: starGiftUniqueLink } });
handleClose();
});
const handleFocusUpgraded = useLastCallback(() => {
if (!savedGift?.upgradeMsgId || !renderingTargetPeer) return;
const { upgradeMsgId } = savedGift;
focusMessage({ chatId: renderingTargetPeer.id, messageId: upgradeMsgId! });
handleClose();
});
const handleTriggerVisibility = useLastCallback(() => {
const { inputGift, isUnsaved } = savedGift!;
changeGiftVisibility({ gift: inputGift!, shouldUnsave: !isUnsaved });
handleClose();
});
const handleConvertToStars = useLastCallback(() => {
const { inputGift } = savedGift!;
convertGiftToStars({ gift: inputGift! });
closeConvertConfirm();
handleClose();
});
const handleOpenUpgradeModal = useLastCallback(() => {
if (!savedGift) return;
openGiftUpgradeModal({ giftId: savedGift.gift.id, gift: savedGift });
});
const giftAttributes = useMemo(() => {
return gift && getGiftAttributes(gift);
}, [gift]);
const SettingsMenuButton: FC<{ onTrigger: () => void; isMenuOpen?: boolean }> = useMemo(() => {
return ({ onTrigger, isMenuOpen }) => (
);
}, [lang]);
const renderFooterButton = useLastCallback(() => {
if (canFocusUpgrade) {
return (
);
}
if (canUpdate && savedGift?.alreadyPaidUpgradeStars && !savedGift.upgradeMsgId) {
return (
);
}
return (
);
});
const modalData = useMemo(() => {
if (!typeGift || !gift) {
return undefined;
}
const {
fromId, isNameHidden, starsToConvert, isUnsaved, isConverted,
} = savedGift || {};
const isVisibleForMe = isNameHidden && renderingTargetPeer;
const description = (() => {
if (!savedGift) return lang('GiftInfoSoldOutDescription');
if (isTargetChat) return undefined;
if (savedGift.upgradeMsgId) return lang('GiftInfoDescriptionUpgraded');
if (savedGift.canUpgrade && savedGift.alreadyPaidUpgradeStars) {
return canUpdate
? lang('GiftInfoDescriptionFreeUpgrade')
: lang('GiftInfoPeerDescriptionFreeUpgradeOut', { peer: getPeerTitle(lang, renderingTargetPeer!)! });
}
if (!canUpdate && !isSender) return undefined;
if (isConverted && starsToConvert) {
return canUpdate
? lang('GiftInfoDescriptionConverted', {
amount: formatInteger(starsToConvert!),
}, {
pluralValue: starsToConvert,
withNodes: true,
withMarkdown: true,
})
: lang('GiftInfoPeerDescriptionOutConverted', {
amount: formatInteger(starsToConvert!),
peer: getPeerTitle(lang, renderingTargetPeer!)!,
}, {
pluralValue: starsToConvert,
withNodes: true,
withMarkdown: true,
});
}
if (savedGift.canUpgrade && canUpdate) {
return lang('GiftInfoDescriptionUpgrade', {
amount: formatInteger(starsToConvert!),
}, {
pluralValue: starsToConvert!,
withNodes: true,
withMarkdown: true,
});
}
return canUpdate
? lang('GiftInfoDescription', {
amount: starsToConvert,
}, {
withNodes: true,
withMarkdown: true,
pluralValue: starsToConvert || 0,
})
: lang('GiftInfoPeerDescriptionOut', {
amount: starsToConvert,
peer: getPeerTitle(lang, renderingTargetPeer!)!,
}, {
withNodes: true,
withMarkdown: true,
pluralValue: starsToConvert || 0,
});
})();
function getTitle() {
if (gift?.type === 'starGiftUnique') return gift.title;
if (!savedGift) return lang('GiftInfoSoldOutTitle');
return canUpdate ? lang('GiftInfoReceived') : lang('GiftInfoTitle');
}
const isUniqueGift = gift.type === 'starGiftUnique';
const contextMenu = (
{description}
)}