diff --git a/src/assets/localization/fallback.strings b/src/assets/localization/fallback.strings
index 2b0f7a6dc..4a6a7be8e 100644
--- a/src/assets/localization/fallback.strings
+++ b/src/assets/localization/fallback.strings
@@ -1585,3 +1585,4 @@
"ViewButtonStickerset" = "VIEW STICKERS";
"ViewButtonGiftUnique" = "VIEW COLLECTIBLE";
"AuthContinueOnThisLanguage" = "Continue in English";
+"Share" = "Share";
diff --git a/src/components/modals/common/TableInfoModal.tsx b/src/components/modals/common/TableInfoModal.tsx
index c35fbeea7..47d473ec0 100644
--- a/src/components/modals/common/TableInfoModal.tsx
+++ b/src/components/modals/common/TableInfoModal.tsx
@@ -25,6 +25,7 @@ type OwnProps = {
tableData?: TableData;
headerAvatarPeer?: ApiPeer | CustomPeer;
header?: TeactNode;
+ modalHeader?: TeactNode;
footer?: TeactNode;
buttonText?: string;
className?: string;
@@ -39,6 +40,7 @@ const TableInfoModal = ({
tableData,
headerAvatarPeer,
header,
+ modalHeader,
footer,
buttonText,
className,
@@ -59,6 +61,7 @@ const TableInfoModal = ({
hasAbsoluteCloseButton={!title}
absoluteCloseButtonColor={hasBackdrop ? 'translucent-white' : undefined}
isSlim
+ header={modalHeader}
title={title}
className={className}
contentClassName={styles.content}
diff --git a/src/components/modals/gift/info/GiftInfoModal.module.scss b/src/components/modals/gift/info/GiftInfoModal.module.scss
index 97f8a9d4c..9fb17bf4a 100644
--- a/src/components/modals/gift/info/GiftInfoModal.module.scss
+++ b/src/components/modals/gift/info/GiftInfoModal.module.scss
@@ -61,6 +61,18 @@
margin-inline-start: 0 !important;
}
+.modalHeader {
+ z-index: 1;
+ width: 100%;
+ padding: 0.375rem;
+ position: absolute;
+ display: flex;
+
+ .modalCloseButton {
+ margin-right: auto;
+ }
+}
+
.ownerAddress {
font-family: var(--font-family-monospace);
font-size: 0.875rem;
diff --git a/src/components/modals/gift/info/GiftInfoModal.tsx b/src/components/modals/gift/info/GiftInfoModal.tsx
index 81786da05..b2c192efa 100644
--- a/src/components/modals/gift/info/GiftInfoModal.tsx
+++ b/src/components/modals/gift/info/GiftInfoModal.tsx
@@ -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 { getActions, getGlobal, withGlobal } from '../../../../global';
@@ -7,6 +7,7 @@ import type {
} 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';
@@ -32,7 +33,9 @@ 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';
@@ -68,6 +71,7 @@ const GiftInfoModal = ({
focusMessage,
openGiftUpgradeModal,
showNotification,
+ openChatWithDraft,
} = getActions();
const [isConvertConfirmOpen, openConvertConfirm, closeConvertConfirm] = useFlag();
@@ -103,6 +107,26 @@ const GiftInfoModal = ({
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;
@@ -132,6 +156,21 @@ const GiftInfoModal = ({
return gift && getGiftAttributes(gift);
}, [gift]);
+ const SettingsMenuButton: FC<{ onTrigger: () => void; isMenuOpen?: boolean }> = useMemo(() => {
+ return ({ onTrigger, isMenuOpen }) => (
+
+ );
+ }, [lang]);
+
const renderFooterButton = useLastCallback(() => {
if (canFocusUpgrade) {
return (
@@ -234,6 +273,45 @@ const GiftInfoModal = ({
const isUniqueGift = gift.type === 'starGiftUnique';
+ const contextMenu = (
+