Gifts: Small fixes (#5671)

This commit is contained in:
zubiden 2025-03-01 17:59:30 +01:00 committed by Alexander Zinchuk
parent 10f5e628f4
commit e54989c791
11 changed files with 109 additions and 77 deletions

View File

@ -1378,10 +1378,13 @@
"GiftInfoTitle" = "Gift";
"GiftInfoDescription_one" = "You can keep this gift in your Profile or convert it to **{amount}** Star.";
"GiftInfoDescription_other" = "You can keep this gift in your Profile or convert it to **{amount}** Stars.";
"GiftInfoDescriptionRegular" = "You can add this gift to your profile or hide it";
"GiftInfoPeerDescriptionOut_one" = "{peer} can keep this gift in profile or convert it to **{amount}** Star.";
"GiftInfoPeerDescriptionOut_other" = "{peer} can keep this gift in profile or convert it to **{amount}** Stars.";
"GiftInfoPeerDescriptionOutRegular" = "{peer} can add this gift to their profile or hide it";
"GiftInfoDescriptionUpgrade_one" = "You can keep this gift, upgrade it, or sell it for **{amount}** Star.";
"GiftInfoDescriptionUpgrade_other" = "You can keep this gift, upgrade it, or sell it for **{amount}** Stars.";
"GiftInfoDescriptionUpgradeRegular" = "You can add this gift to your profile or turn it into a unique transferable collectible.";
"GiftInfoDescriptionConverted_one" = "You converted this gift to **{amount}** Star.";
"GiftInfoDescriptionConverted_other" = "You converted this gift to **{amount}** Stars.";
"GiftInfoPeerDescriptionOutConverted_one" = "{peer} converted this gift to **{amount}** Star.";

View File

@ -19,6 +19,7 @@ type OwnProps = {
className?: string;
children?: TeactNode;
isRtl?: boolean;
shouldSkipModal?: boolean;
};
const SafeLink = ({
@ -27,6 +28,7 @@ const SafeLink = ({
className,
children,
isRtl,
shouldSkipModal,
}: OwnProps) => {
const { openUrl } = getActions();
@ -37,7 +39,7 @@ const SafeLink = ({
if (!url) return true;
e.preventDefault();
openUrl({ url, shouldSkipModal: isRegularLink });
openUrl({ url, shouldSkipModal: shouldSkipModal || isRegularLink });
return false;
});

View File

@ -59,7 +59,7 @@ const SavedGift = ({
if (entry.isIntersecting) play();
});
const avatarPeer = (gift.isNameHidden || !fromPeer) ? CUSTOM_PEER_HIDDEN : fromPeer;
const avatarPeer = (gift.isNameHidden && !fromPeer) ? CUSTOM_PEER_HIDDEN : fromPeer;
const sticker = getStickerFromGift(gift.gift);

View File

@ -9,7 +9,7 @@
:global(.star-amount-icon) {
vertical-align: text-bottom;
margin-inline: 0;
margin-inline: 0 !important;
}
}

View File

@ -28,7 +28,7 @@ import {
getPinnedMediaValue,
renderMessageLink,
renderPeerLink,
translateWithOutgoing,
translateWithYou,
} from './helpers/messageActions';
import useLang from '../../../hooks/useLang';
@ -114,7 +114,7 @@ const ActionMessageText = ({
asPreview,
);
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionPinnedText', isOutgoing, { text: textLink, from: senderLink },
);
}
@ -122,13 +122,13 @@ const ActionMessageText = ({
const mediaValue = getPinnedMediaValue(lang, replyMessage);
if (mediaValue) {
const messageLink = renderMessageLink(replyMessage, mediaValue, asPreview);
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionPinnedMedia', isOutgoing, { from: senderLink, media: messageLink },
);
}
}
return translateWithOutgoing(
return translateWithYou(
lang,
'ActionPinnedNotFound',
isOutgoing,
@ -143,7 +143,7 @@ const ActionMessageText = ({
const gameLink = gameTitle && renderMessageLink(replyMessage, renderText(gameTitle), asPreview);
if (gameLink) {
return translateWithOutgoing(
return translateWithYou(
lang,
'ActionGameScore',
isOutgoing,
@ -152,7 +152,7 @@ const ActionMessageText = ({
);
}
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionGameScoreNoGame', isOutgoing, { from: senderLink, count: score }, { pluralValue: score },
);
}
@ -161,7 +161,7 @@ const ActionMessageText = ({
return lang('ActionUserJoinedByLink', { from: senderLink }, { withNodes: true });
case 'chatJoinedByRequest':
return translateWithOutgoing(lang, 'ActionJoinedByRequest', isOutgoing, { from: senderLink });
return translateWithYou(lang, 'ActionJoinedByRequest', isOutgoing, { from: senderLink });
case 'channelJoined': {
const { isViaRequest, inviterId } = action;
@ -177,16 +177,16 @@ const ActionMessageText = ({
case 'chatEditTitle': {
const { title } = action;
if (isChannel) return lang('ActionChangedTitleChannel', { title });
return translateWithOutgoing(lang, 'ActionChangedTitle', isOutgoing, { title, from: senderLink });
return translateWithYou(lang, 'ActionChangedTitle', isOutgoing, { title, from: senderLink });
}
case 'chatDeletePhoto':
return isChannel ? lang('ActionRemovedPhotoChannel')
: translateWithOutgoing(lang, 'ActionRemovedPhoto', isOutgoing, { from: senderLink });
: translateWithYou(lang, 'ActionRemovedPhoto', isOutgoing, { from: senderLink });
case 'chatEditPhoto':
return isChannel ? lang('ActionChangedPhotoChannel')
: translateWithOutgoing(lang, 'ActionChangedPhoto', isOutgoing, { from: senderLink });
: translateWithYou(lang, 'ActionChangedPhoto', isOutgoing, { from: senderLink });
case 'chatCreate': {
const { title } = action;
@ -196,7 +196,7 @@ const ActionMessageText = ({
case 'channelCreate': {
const { title } = action;
return isChannel ? lang('ActionCreatedChannel')
: translateWithOutgoing(lang, 'ActionCreatedChat', isOutgoing, { title, from: senderLink });
: translateWithYou(lang, 'ActionCreatedChat', isOutgoing, { title, from: senderLink });
}
case 'chatMigrateTo': {
@ -325,7 +325,7 @@ const ActionMessageText = ({
}
case 'boostApply':
return translateWithOutgoing(
return translateWithYou(
lang,
'ActionBoostApply',
isOutgoing,
@ -337,27 +337,27 @@ const ActionMessageText = ({
const { userIds } = action;
if (sender?.id === userIds[0]) {
return translateWithOutgoing(lang, 'ActionUserJoined', isOutgoing, { from: senderLink });
return translateWithYou(lang, 'ActionUserJoined', isOutgoing, { from: senderLink });
}
if (userIds.length === 1) {
const user = selectPeer(global, userIds[0]);
const userTitle = (user && getPeerTitle(lang, user)) || userFallbackText;
const userLink = renderPeerLink(user?.id, userTitle, asPreview);
return translateWithOutgoing(lang, 'ActionAddUser', isOutgoing, { from: senderLink, user: userLink });
return translateWithYou(lang, 'ActionAddUser', isOutgoing, { from: senderLink, user: userLink });
}
const users = userIds.map((userId) => selectPeer(global, userId)).filter(Boolean);
if (!users.length) {
return translateWithOutgoing(lang, 'ActionAddUser', isOutgoing, { from: senderLink, user: userFallbackText });
return translateWithYou(lang, 'ActionAddUser', isOutgoing, { from: senderLink, user: userFallbackText });
}
const userLinks = users.map((user) => (
renderPeerLink(user.id, getPeerTitle(lang, user) || userFallbackText, asPreview)
));
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionAddUsersMany', isOutgoing, { from: senderLink, users: conjuctionWithNodes(lang, userLinks) },
);
}
@ -365,13 +365,13 @@ const ActionMessageText = ({
case 'chatDeleteUser': {
const { userId } = action;
if (sender?.id === userId) {
return translateWithOutgoing(lang, 'ActionUserLeft', isOutgoing, { from: senderLink });
return translateWithYou(lang, 'ActionUserLeft', isOutgoing, { from: senderLink });
}
const user = selectPeer(global, userId);
const userTitle = (user && getPeerTitle(lang, user)) || userFallbackText;
const userLink = renderPeerLink(user?.id, userTitle, asPreview);
return translateWithOutgoing(lang, 'ActionKickUser', isOutgoing, { from: senderLink, user: userLink });
return translateWithYou(lang, 'ActionKickUser', isOutgoing, { from: senderLink, user: userLink });
}
case 'botAllowed': {
@ -444,7 +444,7 @@ const ActionMessageText = ({
if (isServiceNotificationsChat) {
return lang('ActionGiftTextCostAnonymous', { cost }, { withNodes: true });
}
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionGiftTextCost', isOutgoing, { from: senderLink, cost: renderStrong(cost) },
);
}
@ -485,13 +485,13 @@ const ActionMessageText = ({
const user = selectPeer(global, userIds[0]);
const userTitle = (user && getPeerTitle(lang, user)) || userFallbackText;
const userLink = renderPeerLink(user?.id, userTitle, asPreview);
return translateWithOutgoing(lang, 'ActionVideoInvited', isOutgoing, { from: senderLink, user: userLink });
return translateWithYou(lang, 'ActionVideoInvited', isOutgoing, { from: senderLink, user: userLink });
}
const users = userIds.map((userId) => selectPeer(global, userId)).filter(Boolean);
if (!users.length) {
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionVideoInvited', isOutgoing, { from: senderLink, user: userFallbackText },
);
}
@ -500,7 +500,7 @@ const ActionMessageText = ({
renderPeerLink(user.id, getPeerTitle(lang, user) || userFallbackText, asPreview)
));
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionVideoInvitedMany', isOutgoing, { from: senderLink, users: conjuctionWithNodes(lang, userLinks) },
);
}
@ -570,7 +570,7 @@ const ActionMessageText = ({
const channelTitle = (channelPeer && getPeerTitle(lang, channelPeer)) || channelFallbackText;
const channelLink = renderPeerLink(peerId, channelTitle, asPreview);
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionStarGiftSentChannel', isYou, { user: fromLink, channel: channelLink, cost },
);
}
@ -610,7 +610,7 @@ const ActionMessageText = ({
const channelLink = renderPeerLink(peerId, channelTitle, asPreview);
if (isUpgrade) {
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionStarGiftUpgradedChannel', isYou, { user: fromLink, channel: channelLink },
);
}
@ -620,7 +620,7 @@ const ActionMessageText = ({
return lang('ActionStarGiftTransferredUnknownChannel', { channel: channelLink }, { withNodes: true });
}
return translateWithOutgoing(
return translateWithYou(
lang, 'ActionStarGiftTransferredChannel', isYou, { user: fromLink, channel: channelLink },
);
}
@ -670,7 +670,7 @@ const ActionMessageText = ({
const actionPeer = (isOutgoing ? chat : sender)!;
const actionPeerLink = renderPeerLink(actionPeer.id, getPeerTitle(lang, actionPeer) || userFallbackText);
return translateWithOutgoing(lang, 'ActionSuggestedPhoto', isOutgoing, { user: actionPeerLink });
return translateWithYou(lang, 'ActionSuggestedPhoto', isOutgoing, { user: actionPeerLink });
}
case 'webViewDataSent':
@ -688,7 +688,7 @@ const ActionMessageText = ({
return lang('ActionHistoryCleared');
case 'screenshotTaken':
return translateWithOutgoing(lang, 'ActionScreenshotTaken', isOutgoing, { from: senderLink });
return translateWithYou(lang, 'ActionScreenshotTaken', isOutgoing, { from: senderLink });
case 'contactSignUp':
return lang('ActionUserRegistered', { from: senderLink }, { withNodes: true });

View File

@ -17,7 +17,7 @@ import { getServerTime } from '../../../../util/serverTime';
import { formatIntegerCompact } from '../../../../util/textFormat';
import { getStickerFromGift } from '../../../common/helpers/gifts';
import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities';
import { renderPeerLink, translateWithOutgoing } from '../helpers/messageActions';
import { renderPeerLink, translateWithYou } from '../helpers/messageActions';
import useDynamicColorListener from '../../../../hooks/stickers/useDynamicColorListener';
import { type ObserveFn } from '../../../../hooks/useIntersectionObserver';
@ -86,20 +86,20 @@ const StarGiftAction = ({
}
if (action.alreadyPaidUpgradeStars) {
return translateWithOutgoing(
lang, 'ActionStarGiftUpgradeText', !isOutgoing, { peer: peerLink },
return translateWithYou(
lang, 'ActionStarGiftUpgradeText', !isOutgoing || isSelf, { peer: peerLink },
);
}
if (action.isConverted) {
return translateWithOutgoing(
lang, 'ActionStarGiftConvertedText', !isOutgoing, { peer: peerLink, amount: starsAmount },
return translateWithYou(
lang, 'ActionStarGiftConvertedText', !isOutgoing || isSelf, { peer: peerLink, amount: starsAmount },
);
}
if (starGiftMaxConvertPeriod && getServerTime() < message.date + starGiftMaxConvertPeriod) {
return translateWithOutgoing(
lang, 'ActionStarGiftConvertText', !isOutgoing, { peer: peerLink, amount: starsAmount },
return translateWithYou(
lang, 'ActionStarGiftConvertText', !isOutgoing || isSelf, { peer: peerLink, amount: starsAmount },
);
}
@ -109,11 +109,12 @@ const StarGiftAction = ({
);
}
return translateWithOutgoing(
lang, 'ActionStarGiftNoConvertText', !isOutgoing, { peer: peerLink },
return translateWithYou(
lang, 'ActionStarGiftNoConvertText', !isOutgoing || isSelf, { peer: peerLink },
);
}, [
action, fallbackPeerTitle, isChannel, isOutgoing, lang, message.date, peer?.id, peerTitle, starGiftMaxConvertPeriod,
isSelf,
]);
return (

View File

@ -30,15 +30,15 @@ type VariablesForKey<K extends LangKey> =
? LangPairPluralWithVariables<TeactNode | undefined>[K] | SuffixKey<LangPairPluralWithVariables, K>
: undefined;
export function translateWithOutgoing<K extends LangKey>(
export function translateWithYou<K extends LangKey>(
lang: LangFn,
key: K,
isOutgoing: boolean,
isYou: boolean,
variables: VariablesForKey<K>,
options?: { pluralValue?: number; asText?: boolean; isMarkdown?: boolean },
): TeactNode {
const { pluralValue, asText, isMarkdown } = options || {};
const translationKey = isOutgoing ? (`${key}You` as LangKey) : key;
const translationKey = isYou ? (`${key}You` as LangKey) : key;
return lang(
// @ts-ignore -- I have no idea if this even possible to type correctly

View File

@ -81,7 +81,7 @@ function GiftComposer({
return {
id: -1,
chatId: '0',
isOutgoing: true,
isOutgoing: false,
senderId: currentUserId,
date: Math.floor(Date.now() / 1000),
content: {
@ -99,7 +99,7 @@ function GiftComposer({
return {
id: -1,
chatId: currentUserId!,
chatId: '0',
isOutgoing: false,
senderId: currentUserId,
date: Math.floor(Date.now() / 1000),

View File

@ -19,7 +19,7 @@ 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 { formatPercent } from '../../../../util/textFormat';
import { getGiftAttributes, getStickerFromGift } from '../../../common/helpers/gifts';
import { renderTextWithEntities } from '../../../common/helpers/renderTextWithEntities';
@ -109,6 +109,7 @@ const GiftInfoModal = ({
const gift = isSavedGift ? typeGift.gift : typeGift;
const giftSticker = gift && getStickerFromGift(gift);
const hasConvertOption = canConvertDifference > 0 && Boolean(savedGift?.starsToConvert);
const currenUniqueEmojiStatusSlug = currentUserEmojiStatus?.type === 'collectible'
? currentUserEmojiStatus.slug : undefined;
@ -244,8 +245,9 @@ const GiftInfoModal = ({
}
const {
fromId, isNameHidden, starsToConvert, isUnsaved, isConverted,
fromId, isNameHidden, starsToConvert, isUnsaved, isConverted, upgradeMsgId,
} = savedGift || {};
const canConvert = hasConvertOption && Boolean(starsToConvert);
const isVisibleForMe = isNameHidden && renderingTargetPeer;
@ -260,17 +262,17 @@ const GiftInfoModal = ({
: lang('GiftInfoPeerDescriptionFreeUpgradeOut', { peer: getPeerTitle(lang, renderingTargetPeer!)! });
}
if (!canUpdate && !isSender) return undefined;
if (isConverted && starsToConvert) {
if (isConverted && canConvert) {
return canUpdate
? lang('GiftInfoDescriptionConverted', {
amount: formatInteger(starsToConvert!),
amount: starsToConvert,
}, {
pluralValue: starsToConvert,
withNodes: true,
withMarkdown: true,
})
: lang('GiftInfoPeerDescriptionOutConverted', {
amount: formatInteger(starsToConvert!),
amount: starsToConvert,
peer: getPeerTitle(lang, renderingTargetPeer!)!,
}, {
pluralValue: starsToConvert,
@ -280,31 +282,45 @@ const GiftInfoModal = ({
}
if (savedGift.canUpgrade && canUpdate) {
return lang('GiftInfoDescriptionUpgrade', {
amount: formatInteger(starsToConvert!),
}, {
pluralValue: starsToConvert!,
withNodes: true,
withMarkdown: true,
});
if (canConvert) {
return lang('GiftInfoDescriptionUpgrade', {
amount: starsToConvert,
}, {
pluralValue: starsToConvert,
withNodes: true,
withMarkdown: true,
});
}
return lang('GiftInfoDescriptionUpgradeRegular');
}
return canUpdate
? lang('GiftInfoDescription', {
amount: starsToConvert,
}, {
withNodes: true,
withMarkdown: true,
pluralValue: starsToConvert || 0,
})
: lang('GiftInfoPeerDescriptionOut', {
if (canUpdate) {
if (canConvert) {
return lang('GiftInfoDescription', {
amount: starsToConvert,
}, {
withNodes: true,
withMarkdown: true,
pluralValue: starsToConvert,
});
}
return lang('GiftInfoDescriptionRegular');
}
if (canConvert) {
return lang('GiftInfoPeerDescriptionOut', {
amount: starsToConvert,
peer: getPeerTitle(lang, renderingTargetPeer!)!,
}, {
withNodes: true,
withMarkdown: true,
pluralValue: starsToConvert || 0,
pluralValue: starsToConvert,
});
}
return lang('GiftInfoPeerDescriptionOutRegular', { peer: getPeerTitle(lang, renderingTargetPeer!)! });
})();
function getTitle() {
@ -394,15 +410,17 @@ const GiftInfoModal = ({
const tableData: TableData = [];
if (gift.type === 'starGift') {
if ((fromId || isNameHidden)) {
const hasFrom = fromId || isNameHidden;
if (hasFrom) {
tableData.push([
lang('GiftInfoFrom'),
fromId ? { chatId: fromId } : (
!fromId ? (
<>
<Avatar size="small" peer={CUSTOM_PEER_HIDDEN} />
<span className={styles.unknown}>{oldLang(CUSTOM_PEER_HIDDEN.titleKey!)}</span>
</>
),
) : { chatId: fromId },
]);
}
@ -433,7 +451,7 @@ const GiftInfoModal = ({
lang('GiftInfoValue'),
<div className={styles.giftValue}>
{formatStarsAsIcon(lang, starsValue, { className: styles.starAmountIcon })}
{canUpdate && canConvertDifference > 0 && Boolean(starsToConvert) && (
{canUpdate && hasConvertOption && Boolean(starsToConvert) && (
<BadgeButton onClick={openConvertConfirm}>
{lang('GiftInfoConvert', { amount: starsToConvert }, { pluralValue: starsToConvert })}
</BadgeButton>
@ -453,7 +471,7 @@ const GiftInfoModal = ({
]);
}
if (gift.upgradeStars && !savedGift?.upgradeMsgId) {
if (gift.upgradeStars && !upgradeMsgId) {
tableData.push([
lang('GiftInfoStatus'),
<div className={styles.giftValue}>
@ -613,7 +631,7 @@ const GiftInfoModal = ({
{tonLink && (
<div>
{lang('GiftInfoTonText', {
link: <SafeLink url={tonLink} text={lang('GiftInfoTonLinkText')} />,
link: <SafeLink url={tonLink} shouldSkipModal text={lang('GiftInfoTonLinkText')} />,
}, { withNodes: true })}
</div>
)}
@ -649,7 +667,7 @@ const GiftInfoModal = ({
};
}, [
typeGift, savedGift, renderingTargetPeer, giftSticker, lang,
canUpdate, canConvertDifference, isSender, oldLang, tonExplorerUrl,
canUpdate, hasConvertOption, isSender, oldLang, tonExplorerUrl,
gift, giftAttributes, renderFooterButton, isTargetChat,
SettingsMenuButton, isOpen, isGiftUnique, canWear, canTakeOff,
]);
@ -682,7 +700,7 @@ const GiftInfoModal = ({
withMarkdown: true,
})}
</div>
{canConvertDifference > 0 && (
{hasConvertOption && (
<div>
{lang('GiftInfoConvertDescriptionPeriod', {
count: conversionLeft,
@ -704,20 +722,21 @@ export default memo(withGlobal<OwnProps>(
(global, { modal }): StateProps => {
const typeGift = modal?.gift;
const isSavedGift = typeGift && 'gift' in typeGift;
const currentUserId = global.currentUserId;
const fromId = isSavedGift && typeGift.fromId;
const fromPeer = fromId ? selectPeer(global, fromId) : undefined;
const targetPeer = modal?.peerId ? selectPeer(global, modal.peerId) : undefined;
const chat = targetPeer && isApiPeerChat(targetPeer) ? targetPeer : undefined;
const hasAdminRights = chat && getHasAdminRight(chat, 'postMessages');
const currentUser = global.currentUserId ? selectUser(global, global.currentUserId) : undefined;
const currentUser = selectUser(global, currentUserId!);
const currentUserEmojiStatus = currentUser?.emojiStatus;
const collectibleEmojiStatuses = global.collectibleEmojiStatuses?.statuses;
return {
fromPeer,
targetPeer,
currentUserId: global.currentUserId,
currentUserId,
starGiftMaxConvertPeriod: global.appConfig?.starGiftMaxConvertPeriod,
tonExplorerUrl: global.appConfig?.tonExplorerUrl,
hasAdminRights,

View File

@ -219,6 +219,8 @@ addActionHandler('openGiftInfoModalFromMessage', (global, actions, payload): Act
? { type: 'chat', chatId, savedId: action.savedId }
: { type: 'user', messageId };
const fromId = action.fromId || (message.isOutgoing ? global.currentUserId! : message.chatId);
const gift: ApiSavedStarGift = {
date: message.date,
gift: action.gift,
@ -226,7 +228,7 @@ addActionHandler('openGiftInfoModalFromMessage', (global, actions, payload): Act
starsToConvert: starGift?.starsToConvert,
isNameHidden: starGift?.isNameHidden,
isUnsaved: !action.isSaved,
fromId: action.fromId,
fromId,
messageId: message.id,
isConverted: starGift?.isConverted,
upgradeMsgId: starGift?.upgradeMsgId,

View File

@ -1169,6 +1169,8 @@ export interface LangPair {
'GiftInfoSent': undefined;
'GiftInfoReceived': undefined;
'GiftInfoTitle': undefined;
'GiftInfoDescriptionRegular': undefined;
'GiftInfoDescriptionUpgradeRegular': undefined;
'GiftInfoDescriptionFreeUpgrade': undefined;
'GiftInfoDescriptionUpgraded': undefined;
'GiftInfoFrom': undefined;
@ -1750,6 +1752,9 @@ export interface LangPairWithVariables<V extends unknown = LangVariable> {
'title': V;
'number': V;
};
'GiftInfoPeerDescriptionOutRegular': {
'peer': V;
};
'GiftInfoPeerDescriptionFreeUpgradeOut': {
'peer': V;
};