Gift unique: Support link menu (#5530)

This commit is contained in:
Alexander Zinchuk 2025-01-27 23:50:57 +01:00
parent 10009ce9ba
commit 495bd7e5d9
5 changed files with 99 additions and 2 deletions

View File

@ -1585,3 +1585,4 @@
"ViewButtonStickerset" = "VIEW STICKERS"; "ViewButtonStickerset" = "VIEW STICKERS";
"ViewButtonGiftUnique" = "VIEW COLLECTIBLE"; "ViewButtonGiftUnique" = "VIEW COLLECTIBLE";
"AuthContinueOnThisLanguage" = "Continue in English"; "AuthContinueOnThisLanguage" = "Continue in English";
"Share" = "Share";

View File

@ -25,6 +25,7 @@ type OwnProps = {
tableData?: TableData; tableData?: TableData;
headerAvatarPeer?: ApiPeer | CustomPeer; headerAvatarPeer?: ApiPeer | CustomPeer;
header?: TeactNode; header?: TeactNode;
modalHeader?: TeactNode;
footer?: TeactNode; footer?: TeactNode;
buttonText?: string; buttonText?: string;
className?: string; className?: string;
@ -39,6 +40,7 @@ const TableInfoModal = ({
tableData, tableData,
headerAvatarPeer, headerAvatarPeer,
header, header,
modalHeader,
footer, footer,
buttonText, buttonText,
className, className,
@ -59,6 +61,7 @@ const TableInfoModal = ({
hasAbsoluteCloseButton={!title} hasAbsoluteCloseButton={!title}
absoluteCloseButtonColor={hasBackdrop ? 'translucent-white' : undefined} absoluteCloseButtonColor={hasBackdrop ? 'translucent-white' : undefined}
isSlim isSlim
header={modalHeader}
title={title} title={title}
className={className} className={className}
contentClassName={styles.content} contentClassName={styles.content}

View File

@ -61,6 +61,18 @@
margin-inline-start: 0 !important; margin-inline-start: 0 !important;
} }
.modalHeader {
z-index: 1;
width: 100%;
padding: 0.375rem;
position: absolute;
display: flex;
.modalCloseButton {
margin-right: auto;
}
}
.ownerAddress { .ownerAddress {
font-family: var(--font-family-monospace); font-family: var(--font-family-monospace);
font-size: 0.875rem; font-size: 0.875rem;

View File

@ -1,4 +1,4 @@
import type { TeactNode } from '../../../../lib/teact/teact'; import type { FC, TeactNode } from '../../../../lib/teact/teact';
import React, { memo, useMemo } from '../../../../lib/teact/teact'; import React, { memo, useMemo } from '../../../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../../../global'; import { getActions, getGlobal, withGlobal } from '../../../../global';
@ -7,6 +7,7 @@ import type {
} from '../../../../api/types'; } from '../../../../api/types';
import type { TabState } from '../../../../global/types'; import type { TabState } from '../../../../global/types';
import { TME_LINK_PREFIX } from '../../../../config';
import { getHasAdminRight, getPeerTitle } from '../../../../global/helpers'; import { getHasAdminRight, getPeerTitle } from '../../../../global/helpers';
import { isApiPeerChat } from '../../../../global/helpers/peers'; import { isApiPeerChat } from '../../../../global/helpers/peers';
import { selectPeer } from '../../../../global/selectors'; import { selectPeer } from '../../../../global/selectors';
@ -32,7 +33,9 @@ import BadgeButton from '../../../common/BadgeButton';
import Icon from '../../../common/icons/Icon'; import Icon from '../../../common/icons/Icon';
import Button from '../../../ui/Button'; import Button from '../../../ui/Button';
import ConfirmDialog from '../../../ui/ConfirmDialog'; import ConfirmDialog from '../../../ui/ConfirmDialog';
import DropdownMenu from '../../../ui/DropdownMenu';
import Link from '../../../ui/Link'; import Link from '../../../ui/Link';
import MenuItem from '../../../ui/MenuItem';
import TableInfoModal, { type TableData } from '../../common/TableInfoModal'; import TableInfoModal, { type TableData } from '../../common/TableInfoModal';
import UniqueGiftHeader from '../UniqueGiftHeader'; import UniqueGiftHeader from '../UniqueGiftHeader';
@ -68,6 +71,7 @@ const GiftInfoModal = ({
focusMessage, focusMessage,
openGiftUpgradeModal, openGiftUpgradeModal,
showNotification, showNotification,
openChatWithDraft,
} = getActions(); } = getActions();
const [isConvertConfirmOpen, openConvertConfirm, closeConvertConfirm] = useFlag(); const [isConvertConfirmOpen, openConvertConfirm, closeConvertConfirm] = useFlag();
@ -103,6 +107,26 @@ const GiftInfoModal = ({
closeGiftInfoModal(); 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(() => { const handleFocusUpgraded = useLastCallback(() => {
if (!savedGift?.upgradeMsgId || !renderingTargetPeer) return; if (!savedGift?.upgradeMsgId || !renderingTargetPeer) return;
const { upgradeMsgId } = savedGift; const { upgradeMsgId } = savedGift;
@ -132,6 +156,21 @@ const GiftInfoModal = ({
return gift && getGiftAttributes(gift); return gift && getGiftAttributes(gift);
}, [gift]); }, [gift]);
const SettingsMenuButton: FC<{ onTrigger: () => void; isMenuOpen?: boolean }> = useMemo(() => {
return ({ onTrigger, isMenuOpen }) => (
<Button
round
size="smaller"
color="translucent-white"
className={isMenuOpen ? 'active' : ''}
onClick={onTrigger}
ariaLabel={lang('AriaMoreButton')}
>
<Icon name="more" />
</Button>
);
}, [lang]);
const renderFooterButton = useLastCallback(() => { const renderFooterButton = useLastCallback(() => {
if (canFocusUpgrade) { if (canFocusUpgrade) {
return ( return (
@ -234,6 +273,45 @@ const GiftInfoModal = ({
const isUniqueGift = gift.type === 'starGiftUnique'; const isUniqueGift = gift.type === 'starGiftUnique';
const contextMenu = (
<DropdownMenu
className="with-menu-transitions"
trigger={SettingsMenuButton}
positionX="right"
>
<MenuItem
icon="link-badge"
onClick={handleCopyLink}
>
{lang('CopyLink')}
</MenuItem>
<MenuItem
icon="forward"
onClick={handleLinkShare}
>
{lang('Share')}
</MenuItem>
</DropdownMenu>
);
const uniqueGiftModalHeader = (
<div
className={styles.modalHeader}
>
<Button
className={styles.modalCloseButton}
round
color="translucent-white"
size="smaller"
ariaLabel={lang('Close')}
onClick={handleClose}
>
<Icon name="close" />
</Button>
{contextMenu}
</div>
);
const uniqueGiftHeader = isUniqueGift && ( const uniqueGiftHeader = isUniqueGift && (
<div className={buildClassName(styles.header, styles.uniqueGift)}> <div className={buildClassName(styles.header, styles.uniqueGift)}>
<UniqueGiftHeader <UniqueGiftHeader
@ -501,19 +579,21 @@ const GiftInfoModal = ({
); );
return { return {
modalHeader: isUniqueGift ? uniqueGiftModalHeader : undefined,
header: isUniqueGift ? uniqueGiftHeader : regularHeader, header: isUniqueGift ? uniqueGiftHeader : regularHeader,
tableData, tableData,
footer, footer,
}; };
}, [ }, [
typeGift, savedGift, renderingTargetPeer, giftSticker, lang, canUpdate, canConvertDifference, isSender, oldLang, typeGift, savedGift, renderingTargetPeer, giftSticker, lang, canUpdate, canConvertDifference, isSender, oldLang,
gift, giftAttributes, renderFooterButton, isTargetChat, gift, giftAttributes, renderFooterButton, isTargetChat, SettingsMenuButton,
]); ]);
return ( return (
<> <>
<TableInfoModal <TableInfoModal
isOpen={isOpen} isOpen={isOpen}
modalHeader={modalData?.modalHeader}
header={modalData?.header} header={modalData?.header}
hasBackdrop={gift?.type === 'starGiftUnique'} hasBackdrop={gift?.type === 'starGiftUnique'}
tableData={modalData?.tableData} tableData={modalData?.tableData}

View File

@ -1295,6 +1295,7 @@ export interface LangPair {
'ViewButtonStickerset': undefined; 'ViewButtonStickerset': undefined;
'ViewButtonGiftUnique': undefined; 'ViewButtonGiftUnique': undefined;
'AuthContinueOnThisLanguage': undefined; 'AuthContinueOnThisLanguage': undefined;
'Share': undefined;
} }
export interface LangPairWithVariables<V extends unknown = LangVariable> { export interface LangPairWithVariables<V extends unknown = LangVariable> {