Action Message: Fix premium gift text (#5959)

Co-authored-by: zubiden <19638254+zubiden@users.noreply.github.com>
This commit is contained in:
Alexander Zinchuk 2025-06-18 17:41:00 +02:00
parent 9b82953426
commit 2da7c72c44
7 changed files with 84 additions and 27 deletions

View File

@ -1779,6 +1779,7 @@
"ActionBotAllowedFromApp" = "You allowed this bot to message you when you opened {app}.";
"ActionBotAppPlaceholder" = "App";
"ActionGiftTextUnknown" = "You've received a gift";
"ActionGiftTextUnknownYou" = "You sent a gift";
"ActionGiftTextCost" = "{from} sent you a gift for {cost}";
"ActionGiftTextCostYou" = "You've sent a gift for {cost}";
"ActionGiftTextCostAnonymous" = "Someone sent you a gift for {cost}";
@ -1868,6 +1869,10 @@
"ActionGiftCodePremiumText_other" = "You've received a gift from {channel}.\n\nYour gift is a **Telegram Premium** subscription for {months} months.";
"ActionGiveawayResultStarsText_one" = "You won a prize in a giveaway organized by {channel}.\n\nYour prize is **{amount}** Star.";
"ActionGiveawayResultStarsText_other" = "You won a prize in a giveaway organized by {channel}.\n\nYour prize is **{amount}** Stars.";
"ActionGiftCodeSubscriptionText_one" = "You've received a gift from {peer}.\n\nYour gift is a Telegram Premium subscription for {months} month.";
"ActionGiftCodeSubscriptionText_other" = "You've received a gift from {peer}.\n\nYour gift is a Telegram Premium subscription for {months} months.";
"ActionGiftCodeSubscriptionTextYou_one" = "You've sent a gift to {peer}.\n\nTelegram Premium subscription giftcode for {months} month.";
"ActionGiftCodeSubscriptionTextYou_other" = "You've sent a gift to {peer}.\n\nTelegram Premium subscription giftcode for {months} months.";
"ActionGiftPremiumTitle_one" = "{months} Month Premium";
"ActionGiftPremiumTitle_other" = "{months} Months Premium";
"ActionGiftPremiumText" = "Subscription for exclusive Telegram features.";
@ -1996,7 +2001,6 @@
"GiftSortByPrice" = "Sort by Price";
"GiftSortByNumber" = "Sort by Number";
"ContextMenuItemSelectAll" = "Select All";
"ButtonSort" = "Sort";
"GiftAttributeModelPlural_one" = "{count} Model";
"GiftAttributeModelPlural_other" = "{count} Models";
"GiftAttributeBackdropPlural_one" = "{count} Backdrop";

View File

@ -49,7 +49,7 @@ import useFocusMessage from './hooks/useFocusMessage';
import ActionMessageText from './ActionMessageText';
import ChannelPhoto from './actions/ChannelPhoto';
import Gift from './actions/Gift';
import PremiumGiftCode from './actions/GiveawayPrize';
import GiveawayPrize from './actions/GiveawayPrize';
import StarGift from './actions/StarGift';
import StarGiftUnique from './actions/StarGiftUnique';
import SuggestedPhoto from './actions/SuggestedPhoto';
@ -336,8 +336,9 @@ const ActionMessage = ({
case 'prizeStars':
case 'giftCode':
return (
<PremiumGiftCode
<GiveawayPrize
action={action}
sender={sender}
observeIntersectionForLoading={observeIntersectionForLoading}
observeIntersectionForPlaying={observeIntersectionForPlaying}
onClick={handleClick}
@ -387,7 +388,7 @@ const ActionMessage = ({
default:
return undefined;
}
}, [action, observeIntersectionForLoading, message, observeIntersectionForPlaying]);
}, [action, message, observeIntersectionForLoading, sender, observeIntersectionForPlaying]);
if ((isInsideTopic && action.type === 'topicCreate') || action.type === 'phoneCall') {
return undefined;

View File

@ -456,7 +456,7 @@ const ActionMessageText = ({
case 'prizeStars':
case 'giftCode': {
return lang('ActionGiftTextUnknown');
return translateWithYou(lang, 'ActionGiftTextUnknown', isOutgoing, undefined);
}
case 'groupCall': {

View File

@ -1,7 +1,7 @@
import { memo, useMemo, useRef } from '../../../../lib/teact/teact';
import { withGlobal } from '../../../../global';
import type { ApiChat, ApiSticker } from '../../../../api/types';
import type { ApiChat, ApiPeer, ApiSticker } from '../../../../api/types';
import type { ApiMessageActionGiftCode, ApiMessageActionPrizeStars } from '../../../../api/types/messageActions';
import { getPeerTitle } from '../../../../global/helpers/peers';
@ -11,7 +11,7 @@ import {
selectGiftStickerForDuration,
selectGiftStickerForStars,
} from '../../../../global/selectors';
import { renderPeerLink } from '../helpers/messageActions';
import { renderPeerLink, translateWithYou } from '../helpers/messageActions';
import { type ObserveFn } from '../../../../hooks/useIntersectionObserver';
import useLang from '../../../../hooks/useLang';
@ -23,12 +23,14 @@ import styles from '../ActionMessage.module.scss';
type OwnProps = {
action: ApiMessageActionGiftCode | ApiMessageActionPrizeStars;
sender?: ApiPeer;
observeIntersectionForLoading?: ObserveFn;
observeIntersectionForPlaying?: ObserveFn;
onClick?: NoneToVoidFunction;
};
type StateProps = {
currentUserId: string;
channel?: ApiChat;
sticker?: ApiSticker;
canPlayAnimatedEmojis: boolean;
@ -37,7 +39,9 @@ type StateProps = {
const STICKER_SIZE = 150;
const GiveawayPrizeAction = ({
currentUserId,
action,
sender,
sticker,
canPlayAnimatedEmojis,
channel,
@ -55,6 +59,14 @@ const GiveawayPrizeAction = ({
return renderPeerLink(channel?.id, channelTitle || channelFallbackText);
}, [channel, lang]);
const peerLink = useMemo(() => {
const peer = channel || sender;
const peerTitle = peer && getPeerTitle(lang, peer);
const peerFallbackText = lang('ActionFallbackChat');
return renderPeerLink(peer?.id, peerTitle || peerFallbackText);
}, [channel, sender, lang]);
return (
<div className={styles.contentBox} tabIndex={0} role="button" onClick={onClick}>
<div
@ -74,19 +86,30 @@ const GiveawayPrizeAction = ({
)}
</div>
<div>
<h3 className={styles.title}>{lang('ActionGiveawayResultTitle')}</h3>
<h3 className={styles.title}>
{lang(action.type !== 'giftCode' || action.isViaGiveaway
? 'ActionGiveawayResultTitle' : 'GiftInfoTitle')}
</h3>
<div>
{action.type === 'giftCode' && (
lang(
action.isViaGiveaway ? 'ActionGiveawayResultPremiumText' : 'ActionGiftCodePremiumText',
{ months: action.months, channel: channelLink },
action.isViaGiveaway ? lang(
'ActionGiveawayResultPremiumText',
{ channel: channelLink, months: action.months },
{
withNodes: true,
withMarkdown: true,
pluralValue: action.months,
renderTextFilters: ['br'],
},
)
})
: translateWithYou(
lang,
'ActionGiftCodeSubscriptionText',
sender?.id === currentUserId,
{ peer: peerLink, months: action.months },
{
pluralValue: action.months,
renderTextFilters: ['br'],
})
)}
{action.type === 'prizeStars' && (
lang(
@ -112,14 +135,16 @@ const GiveawayPrizeAction = ({
export default memo(withGlobal<OwnProps>(
(global, { action }): StateProps => {
const currentUserId = global.currentUserId!;
const sticker = action.type === 'giftCode'
? selectGiftStickerForDuration(global, action.months)
: selectGiftStickerForStars(global, action.stars);
const canPlayAnimatedEmojis = selectCanPlayAnimatedEmojis(global);
const channel = selectChat(global, action.boostPeerId!);
const channel = action.boostPeerId ? selectChat(global, action.boostPeerId) : undefined;
return {
currentUserId,
sticker,
canPlayAnimatedEmojis,
channel,

View File

@ -35,16 +35,23 @@ export function translateWithYou<K extends LangKey>(
key: K,
isYou: boolean,
variables: VariablesForKey<K>,
options?: { pluralValue?: number; asText?: boolean; isMarkdown?: boolean },
options?: {
pluralValue?: number;
asText?: boolean;
isMarkdown?: boolean;
renderTextFilters?: string[];
},
): TeactNode {
const { pluralValue, asText, isMarkdown } = options || {};
const { pluralValue, asText, isMarkdown, renderTextFilters } = options || {};
const translationKey = isYou ? (`${key}You` as LangKey) : key;
return lang(
// @ts-ignore -- I have no idea if this even possible to type correctly
translationKey,
variables,
{ withNodes: !asText, isMarkdown, pluralValue },
{
withNodes: !asText, isMarkdown, pluralValue, renderTextFilters,
},
);
}

View File

@ -75,18 +75,30 @@ const GiftCodeModal = ({
</>
);
const tableData = [
const tableData: TableData = [
[lang('BoostingFrom'), fromId ? { chatId: fromId } : lang('BoostingNoRecipient')],
[lang('BoostingTo'), info.toId ? { chatId: info.toId } : lang('BoostingNoRecipient')],
[lang('BoostingGift'), lang('BoostingTelegramPremiumFor', lang('Months', info.months, 'i'))],
[lang('BoostingReason'), (
<span className={buildClassName(info.giveawayMessageId && styles.clickable)} onClick={handleOpenGiveaway}>
{info.isFromGiveaway && !info.toId ? lang('BoostingIncompleteGiveaway')
: lang(info.isFromGiveaway ? 'BoostingGiveaway' : 'BoostingYouWereSelected')}
</span>
)],
[lang('BoostingDate'), formatDateTimeToString(info.date * 1000, lang.code, true)],
] satisfies TableData;
];
if (info.isFromGiveaway) {
tableData.push([
lang('BoostingReason'),
(
<span
className={buildClassName(info.giveawayMessageId && styles.clickable)}
onClick={handleOpenGiveaway}
>
{info.isFromGiveaway && !info.toId
? lang('BoostingIncompleteGiveaway')
: lang('BoostingGiveaway')}
</span>
),
]);
}
tableData.push([
lang('BoostingDate'),
formatDateTimeToString(info.date * 1000, lang.code, true),
]);
const footer = (
<span className={styles.centered}>

View File

@ -1419,6 +1419,7 @@ export interface LangPair {
'ActionScreenshotTakenYou': undefined;
'ActionBotAppPlaceholder': undefined;
'ActionGiftTextUnknown': undefined;
'ActionGiftTextUnknownYou': undefined;
'ActionGiftUniqueSent': undefined;
'ActionStarGiftUpgradedSelf': undefined;
'ActionStarGiftTransferredSelf': undefined;
@ -1524,7 +1525,6 @@ export interface LangPair {
'GiftSortByPrice': undefined;
'GiftSortByNumber': undefined;
'ContextMenuItemSelectAll': undefined;
'ButtonSort': undefined;
'ValueGiftSortByDate': undefined;
'ValueGiftSortByPrice': undefined;
'ValueGiftSortByNumber': undefined;
@ -2759,6 +2759,14 @@ export interface LangPairPluralWithVariables<V = LangVariable> {
'channel': V;
'amount': V;
};
'ActionGiftCodeSubscriptionText': {
'peer': V;
'months': V;
};
'ActionGiftCodeSubscriptionTextYou': {
'peer': V;
'months': V;
};
'ActionGiftPremiumTitle': {
'months': V;
};