diff --git a/src/api/gramjs/apiBuilders/appConfig.ts b/src/api/gramjs/apiBuilders/appConfig.ts index 61c89b9b3..86f92a041 100644 --- a/src/api/gramjs/apiBuilders/appConfig.ts +++ b/src/api/gramjs/apiBuilders/appConfig.ts @@ -86,6 +86,7 @@ export interface GramJsAppConfig extends LimitsConfig { stargifts_message_length_max?: number; stargifts_convert_period_max?: number; starref_start_param_prefixes?: string[]; + ton_blockchain_explorer_url?: string; } function buildEmojiSounds(appConfig: GramJsAppConfig) { @@ -172,5 +173,6 @@ export function buildAppConfig(json: GramJs.TypeJSONValue, hash: number): ApiApp starGiftMaxMessageLength: appConfig.stargifts_message_length_max, starGiftMaxConvertPeriod: appConfig.stargifts_convert_period_max, starRefStartPrefixes: appConfig.starref_start_param_prefixes, + tonExplorerUrl: appConfig.ton_blockchain_explorer_url, }; } diff --git a/src/api/gramjs/apiBuilders/gifts.ts b/src/api/gramjs/apiBuilders/gifts.ts index cb0597dc2..13f7642e2 100644 --- a/src/api/gramjs/apiBuilders/gifts.ts +++ b/src/api/gramjs/apiBuilders/gifts.ts @@ -17,6 +17,7 @@ export function buildApiStarGift(starGift: GramJs.TypeStarGift): ApiStarGift { if (starGift instanceof GramJs.StarGiftUnique) { const { id, num, ownerId, ownerName, title, attributes, availabilityIssued, availabilityTotal, slug, ownerAddress, + giftAddress, } = starGift; return { @@ -31,6 +32,7 @@ export function buildApiStarGift(starGift: GramJs.TypeStarGift): ApiStarGift { totalCount: availabilityTotal, issuedCount: availabilityIssued, slug, + giftAddress, }; } diff --git a/src/api/types/misc.ts b/src/api/types/misc.ts index b57b8da4e..510b39b9f 100644 --- a/src/api/types/misc.ts +++ b/src/api/types/misc.ts @@ -241,6 +241,7 @@ export interface ApiAppConfig { starGiftMaxMessageLength?: number; starGiftMaxConvertPeriod?: number; starRefStartPrefixes?: string[]; + tonExplorerUrl?: string; } export interface ApiConfig { diff --git a/src/api/types/payments.ts b/src/api/types/payments.ts index 0313df5d1..0d55f53ba 100644 --- a/src/api/types/payments.ts +++ b/src/api/types/payments.ts @@ -218,6 +218,7 @@ export interface ApiStarGiftUnique { totalCount: number; attributes: ApiStarGiftAttribute[]; slug: string; + giftAddress?: string; } export type ApiStarGift = ApiStarGiftRegular | ApiStarGiftUnique; diff --git a/src/assets/localization/fallback.strings b/src/assets/localization/fallback.strings index e0edff25d..b59f34578 100644 --- a/src/assets/localization/fallback.strings +++ b/src/assets/localization/fallback.strings @@ -1405,6 +1405,8 @@ "GiftInfoChannelHidden" = "This gift is hidden from visitors of your channel. {link}"; "GiftInfoSavedHide" = "Hide >"; "GiftInfoSavedShow" = "Show >"; +"GiftInfoTonText" = "This gift is on the TON Blockchain. {link}"; +"GiftInfoTonLinkText" = "View >"; "GiftInfoAvailability" = "Availability"; "GiftInfoAvailabilityValue_one" = "{count} of {total} left"; "GiftInfoAvailabilityValue_other" = "{count} of {total} left"; @@ -1569,7 +1571,8 @@ "ActionUnsupportedDescription" = "Please use one of our apps to complete this action."; "LocationPermissionText" = "**{name}** requests access to set your **location**. You will be able to revoke this access in the profile page of **{name}**."; "UnlockMoreSimilarBots" = "Show More Apps"; -"MoreSimilarBotsText" = "Subscribe to **Telegram Premium** to unlock up to {count} similar apps."; +"MoreSimilarBotsDescription_one" = "Subscribe to **Telegram Premium** to unlock up to {count} similar bot."; +"MoreSimilarBotsDescription_other" = "Subscribe to **Telegram Premium** to unlock up to {count} similar bots."; "GiftWasNotFound" = "Gift was not found"; "ViewButtonRequestJoin" = "REQUEST TO JOIN"; "ViewButtonMessage" = "VIEW MESSAGE"; diff --git a/src/components/modals/gift/info/GiftInfoModal.tsx b/src/components/modals/gift/info/GiftInfoModal.tsx index 27471b0d4..099b9cf40 100644 --- a/src/components/modals/gift/info/GiftInfoModal.tsx +++ b/src/components/modals/gift/info/GiftInfoModal.tsx @@ -33,6 +33,7 @@ import AnimatedIconFromSticker from '../../../common/AnimatedIconFromSticker'; import Avatar from '../../../common/Avatar'; import BadgeButton from '../../../common/BadgeButton'; import Icon from '../../../common/icons/Icon'; +import SafeLink from '../../../common/SafeLink'; import Button from '../../../ui/Button'; import ConfirmDialog from '../../../ui/ConfirmDialog'; import DropdownMenu from '../../../ui/DropdownMenu'; @@ -55,6 +56,7 @@ type StateProps = { hasAdminRights?: boolean; currentUserEmojiStatus?: ApiEmojiStatusType; collectibleEmojiStatuses?: ApiEmojiStatusType[]; + tonExplorerUrl?: string; }; const STICKER_SIZE = 120; @@ -68,6 +70,7 @@ const GiftInfoModal = ({ hasAdminRights, currentUserEmojiStatus, collectibleEmojiStatuses, + tonExplorerUrl, }: OwnProps & StateProps) => { const { closeGiftInfoModal, @@ -599,21 +602,34 @@ const GiftInfoModal = ({ } } + const tonLink = tonExplorerUrl && isGiftUnique && gift.giftAddress && ( + `${tonExplorerUrl}${gift.giftAddress}` + ); + const footer = (
- {canUpdate && ( + {(canUpdate || tonLink) && (
-
- {lang(`GiftInfo${isTargetChat ? 'Channel' : ''}${isUnsaved ? 'Hidden' : 'Saved'}`, { - link: ( - - {lang(`GiftInfoSaved${isUnsaved ? 'Show' : 'Hide'}`)} - - ), - }, { - withNodes: true, - })} -
+ {tonLink && ( +
+ {lang('GiftInfoTonText', { + link: , + }, { withNodes: true })} +
+ )} + {canUpdate && ( +
+ {lang(`GiftInfo${isTargetChat ? 'Channel' : ''}${isUnsaved ? 'Hidden' : 'Saved'}`, { + link: ( + + {lang(`GiftInfoSaved${isUnsaved ? 'Show' : 'Hide'}`)} + + ), + }, { + withNodes: true, + })} +
+ )} {isVisibleForMe && (
{lang('GiftInfoSenderHidden')} @@ -633,7 +649,7 @@ const GiftInfoModal = ({ }; }, [ typeGift, savedGift, renderingTargetPeer, giftSticker, lang, - canUpdate, canConvertDifference, isSender, oldLang, + canUpdate, canConvertDifference, isSender, oldLang, tonExplorerUrl, gift, giftAttributes, renderFooterButton, isTargetChat, SettingsMenuButton, isOpen, isGiftUnique, canWear, canTakeOff, ]); @@ -703,6 +719,7 @@ export default memo(withGlobal( targetPeer, currentUserId: global.currentUserId, starGiftMaxConvertPeriod: global.appConfig?.starGiftMaxConvertPeriod, + tonExplorerUrl: global.appConfig?.tonExplorerUrl, hasAdminRights, currentUserEmojiStatus, collectibleEmojiStatuses, diff --git a/src/components/right/Profile.tsx b/src/components/right/Profile.tsx index a16faea0e..67f8bc1e4 100644 --- a/src/components/right/Profile.tsx +++ b/src/components/right/Profile.tsx @@ -807,9 +807,10 @@ const Profile: FC = ({
- {renderText(lang('MoreSimilarBotsText', { count: limitSimilarPeers }, { + {renderText(lang('MoreSimilarBotsDescription', { count: limitSimilarPeers }, { withNodes: true, withMarkdown: true, + pluralValue: limitSimilarPeers, }))}
diff --git a/src/types/language.d.ts b/src/types/language.d.ts index b8622b179..ff3cb8e2c 100644 --- a/src/types/language.d.ts +++ b/src/types/language.d.ts @@ -1178,6 +1178,7 @@ export interface LangPair { 'GiftInfoConvertDescription2': undefined; 'GiftInfoSavedHide': undefined; 'GiftInfoSavedShow': undefined; + 'GiftInfoTonLinkText': undefined; 'GiftInfoAvailability': undefined; 'GiftInfoFirstSale': undefined; 'GiftInfoLastSale': undefined; @@ -1768,6 +1769,9 @@ export interface LangPairWithVariables { 'GiftInfoChannelHidden': { 'link': V; }; + 'GiftInfoTonText': { + 'link': V; + }; 'GiftInfoIssued': { 'issued': V; 'total': V; @@ -1892,9 +1896,6 @@ export interface LangPairWithVariables { 'LocationPermissionText': { 'name': V; }; - 'MoreSimilarBotsText': { - 'count': V; - }; 'ActionPinnedText': { 'from': V; 'text': V; @@ -2424,6 +2425,9 @@ export interface LangPairPluralWithVariables { 'FolderLinkNotificationUpdatedSubtitle': { 'count': V; }; + 'MoreSimilarBotsDescription': { + 'count': V; + }; 'ActionGameScore': { 'from': V; 'count': V;