Add unique gift phrases.

This commit is contained in:
John Preston 2024-12-25 13:49:33 +04:00
parent 5f3db95cbd
commit e43ec6c4ea
9 changed files with 134 additions and 66 deletions

View file

@ -2024,7 +2024,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_proximity_distance_km#other" = "{count} km"; "lng_action_proximity_distance_km#other" = "{count} km";
"lng_action_webview_data_done" = "Data from the \"{text}\" button was transferred to the bot."; "lng_action_webview_data_done" = "Data from the \"{text}\" button was transferred to the bot.";
"lng_action_gift_received" = "{user} sent you a gift for {cost}"; "lng_action_gift_received" = "{user} sent you a gift for {cost}";
"lng_action_gift_unique_received" = "{user} sent you a unique collectible item";
"lng_action_gift_sent" = "You sent a gift for {cost}"; "lng_action_gift_sent" = "You sent a gift for {cost}";
"lng_action_gift_unique_sent" = "You sent a unique collectible item";
"lng_action_gift_received_anonymous" = "Unknown user sent you a gift for {cost}"; "lng_action_gift_received_anonymous" = "Unknown user sent you a gift for {cost}";
"lng_action_gift_for_stars#one" = "{count} Star"; "lng_action_gift_for_stars#one" = "{count} Star";
"lng_action_gift_for_stars#other" = "{count} Stars"; "lng_action_gift_for_stars#other" = "{count} Stars";
@ -3233,6 +3235,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_sent_about#other" = "You spent **{count}** Stars from your balance."; "lng_gift_sent_about#other" = "You spent **{count}** Stars from your balance.";
"lng_gift_limited_of_one" = "unique"; "lng_gift_limited_of_one" = "unique";
"lng_gift_limited_of_count" = "1 of {amount}"; "lng_gift_limited_of_count" = "1 of {amount}";
"lng_gift_price_unique" = "Unique";
"lng_gift_anonymous_hint" = "Only you can see the sender's name."; "lng_gift_anonymous_hint" = "Only you can see the sender's name.";
"lng_gift_hidden_hint" = "This gift is hidden. Only you can see it."; "lng_gift_hidden_hint" = "This gift is hidden. Only you can see it.";
"lng_gift_visible_hint" = "This gift is visible to visitors of your page."; "lng_gift_visible_hint" = "This gift is visible to visitors of your page.";
@ -3243,6 +3246,20 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_visibility_hidden" = "Not visible on your page"; "lng_gift_visibility_hidden" = "Not visible on your page";
"lng_gift_visibility_show" = "show"; "lng_gift_visibility_show" = "show";
"lng_gift_visibility_hide" = "hide"; "lng_gift_visibility_hide" = "hide";
"lng_gift_unique_owner" = "Owner";
"lng_gift_unique_owner_change" = "change";
"lng_gift_unique_status" = "Status";
"lng_gift_unique_status_non" = "Non-Unique";
"lng_gift_unique_status_upgrade" = "upgrade";
"lng_gift_unique_number" = "Collectible #{index}";
"lng_gift_unique_model" = "Model";
"lng_gift_unique_backdrop" = "Backdrop";
"lng_gift_unique_symbol" = "Symbol";
"lng_gift_unique_availability#one" = "{count} of {amount} issued";
"lng_gift_unique_availability#other" = "{count} of {amount} issued";
"lng_gift_unique_info" = "Gifted to {recipient} on {date}.";
"lng_gift_unique_info_sender" = "Gifted by {from} to {recipient} on {date}.";
"lng_gift_unique_info_comment" = "Gifted by {from} to {recipient} on {date} with the comment \"{text}\".";
"lng_gift_availability_left#one" = "{count} of {amount} left"; "lng_gift_availability_left#one" = "{count} of {amount} left";
"lng_gift_availability_left#other" = "{count} of {amount} left"; "lng_gift_availability_left#other" = "{count} of {amount} left";
"lng_gift_availability_none" = "None of {amount} left"; "lng_gift_availability_none" = "None of {amount} left";
@ -3265,6 +3282,37 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_send_small" = "send a gift"; "lng_gift_send_small" = "send a gift";
"lng_gift_sell_small#one" = "sell for {count} Star"; "lng_gift_sell_small#one" = "sell for {count} Star";
"lng_gift_sell_small#other" = "sell for {count} Stars"; "lng_gift_sell_small#other" = "sell for {count} Stars";
"lng_gift_upgrade_title" = "Upgrade Gift";
"lng_gift_upgrade_about" = "Turn your gift into a unique collectible that you can transfer or auction.";
"lng_gift_upgrade_unique_title" = "Unique";
"lng_gift_upgrade_unique_about" = "Get a unique number, model, backdrop and symbol for your gift.";
"lng_gift_upgrade_transferable_title" = "Transferable";
"lng_gift_upgrade_transferable_about" = "Send your upgraded gift to any of your friends on Telegram.";
"lng_gift_upgrade_tradable_title" = "Tradable";
"lng_gift_upgrade_tradable_about" = "Sell or auction your gift on third-party NFT marketplaces.";
"lng_gift_upgrade_button" = "Upgrade for {price}";
"lng_gift_upgrade_add_sender" = "Add sender's name";
"lng_gift_upgrade_add_comment" = "Add sender's name and comment";
"lng_gift_upgraded_title" = "Gift Upgraded";
"lng_gift_upgraded_about" = "Your gift {name} now has unique attributes and can be transferred to others";
"lng_gift_transfer_title" = "Transfer {name}";
"lng_gift_transfer_via_blockchain" = "Send via Blockchain";
"lng_gift_transfer_unlocks_days#one" = "unlocks in {count} day";
"lng_gift_transfer_unlocks_days#other" = "unlocks in {count} days";
"lng_gift_transfer_unlocks_hours#one" = "unlocks in {count} hour";
"lng_gift_transfer_unlocks_hours#other" = "unlocks in {count} hours";
"lng_gift_transfer_unlocks_title" = "Unlocking in progress";
"lng_gift_transfer_unlocks_about" = "{when}, you'll be able to send this collectible to any TON blockchain address outside Telegram for sale or auction.";
"lng_gift_transfer_unlocks_when_days#one" = "In {count} day";
"lng_gift_transfer_unlocks_when_days#other" = "In {count} days";
"lng_gift_transfer_unlocks_when_hours#one" = "In {count} hour";
"lng_gift_transfer_unlocks_when_hours#other" = "In {count} hours";
"lng_gift_transfer_unlocks_update_title" = "Update required";
"lng_gift_transfer_unlocks_update_about" = "Please update your Telegram application to the latest version.";
"lng_gift_transfer_sure" = "Do you want to transfer ownership of {name} to {recipient}?";
"lng_gift_transfer_sure_for" = "Do you want to transfer ownership of {name} to {recipient} for {price}?";
"lng_gift_transfer_button" = "Transfer";
"lng_gift_transfer_button_for" = "Transfer for {price}";
"lng_accounts_limit_title" = "Limit Reached"; "lng_accounts_limit_title" = "Limit Reached";
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account."; "lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account.";

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "api/api_credits.h" #include "api/api_credits.h"
#include "api/api_premium.h"
#include "api/api_statistics_data_deserialize.h" #include "api/api_statistics_data_deserialize.h"
#include "api/api_updates.h" #include "api/api_updates.h"
#include "apiwrap.h" #include "apiwrap.h"
@ -90,25 +91,10 @@ constexpr auto kTransactionsLimit = 100;
: 0; : 0;
const auto incoming = (amount >= StarsAmount()); const auto incoming = (amount >= StarsAmount());
const auto saveActorId = (reaction || !extended.empty()) && incoming; const auto saveActorId = (reaction || !extended.empty()) && incoming;
const auto giftStickerId = [&] { const auto parsedGift = stargift
if (!stargift) { ? FromTL(&peer->session(), *stargift)
return DocumentId(); : std::optional<Data::StarGift>();
} const auto giftStickerId = parsedGift ? parsedGift->stickerId : 0;
return stargift->match([&](const MTPDstarGift &data) {
return owner->processDocument(data.vsticker())->id;
}, [&](const MTPDstarGiftUnique &data) {
for (const auto &attribute : data.vattributes().v) {
const auto result = attribute.match([&](
const MTPDstarGiftAttributeModel &data) {
return DocumentId(data.vdocument_id().v);
}, [](const auto &) { return DocumentId(); });
if (result) {
return result;
}
}
return DocumentId();
});
}();
return Data::CreditsHistoryEntry{ return Data::CreditsHistoryEntry{
.id = qs(tl.data().vid()), .id = qs(tl.data().vid()),
.title = qs(tl.data().vtitle().value_or_empty()), .title = qs(tl.data().vtitle().value_or_empty()),
@ -123,6 +109,7 @@ constexpr auto kTransactionsLimit = 100;
tl.data().vgiveaway_post_id().value_or_empty()), tl.data().vgiveaway_post_id().value_or_empty()),
.bareGiftStickerId = giftStickerId, .bareGiftStickerId = giftStickerId,
.bareActorId = saveActorId ? barePeerId : uint64(0), .bareActorId = saveActorId ? barePeerId : uint64(0),
.uniqueGift = parsedGift ? parsedGift->unique : nullptr,
.starrefAmount = starrefAmount, .starrefAmount = starrefAmount,
.starrefCommission = starrefCommission, .starrefCommission = starrefCommission,
.starrefRecipientId = starrefBarePeerId, .starrefRecipientId = starrefBarePeerId,

View file

@ -371,17 +371,20 @@ void PreviewWrap::prepare(rpl::producer<GiftDetails> details) {
const auto cost = v::match(descriptor, [&](GiftTypePremium data) { const auto cost = v::match(descriptor, [&](GiftTypePremium data) {
return FillAmountAndCurrency(data.cost, data.currency, true); return FillAmountAndCurrency(data.cost, data.currency, true);
}, [&](GiftTypeStars data) { }, [&](GiftTypeStars data) {
return tr::lng_gift_stars_title( const auto stars = data.info.stars;
tr::now, return stars
lt_count, ? tr::lng_gift_stars_title(tr::now, lt_count, stars)
data.info.stars); : QString();
}); });
const auto text = tr::lng_action_gift_received( const auto name = _history->session().user()->shortName();
tr::now, const auto text = cost.isEmpty()
lt_user, ? tr::lng_action_gift_unique_received(tr::now, lt_user, name)
_history->session().user()->shortName(), : tr::lng_action_gift_received(
lt_cost, tr::now,
cost); lt_user,
name,
lt_cost,
cost);
const auto item = _history->makeMessage({ const auto item = _history->makeMessage({
.id = _history->nextNonHistoryEntryId(), .id = _history->nextNonHistoryEntryId(),
.flags = (MessageFlag::FakeAboutView .flags = (MessageFlag::FakeAboutView

View file

@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data { namespace Data {
struct UniqueGift;
struct CreditTopupOption final { struct CreditTopupOption final {
uint64 credits = 0; uint64 credits = 0;
QString product; QString product;
@ -63,6 +65,7 @@ struct CreditsHistoryEntry final {
uint64 bareGiveawayMsgId = 0; uint64 bareGiveawayMsgId = 0;
uint64 bareGiftStickerId = 0; uint64 bareGiftStickerId = 0;
uint64 bareActorId = 0; uint64 bareActorId = 0;
std::shared_ptr<UniqueGift> uniqueGift;
StarsAmount starrefAmount; StarsAmount starrefAmount;
int starrefCommission = 0; int starrefCommission = 0;
uint64 starrefRecipientId = 0; uint64 starrefRecipientId = 0;

View file

@ -39,6 +39,7 @@ namespace Data {
class CloudImage; class CloudImage;
class WallPaper; class WallPaper;
class Session; class Session;
struct UniqueGift;
enum class CallFinishReason : char { enum class CallFinishReason : char {
Missed, Missed,
@ -135,7 +136,8 @@ enum class GiftType : uchar {
struct GiftCode { struct GiftCode {
QString slug; QString slug;
DocumentData *document = nullptr; DocumentId stickerId = 0;
std::shared_ptr<UniqueGift> unique;
TextWithEntities message; TextWithEntities message;
ChannelData *channel = nullptr; ChannelData *channel = nullptr;
MsgId giveawayMsgId = 0; MsgId giveawayMsgId = 0;

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "history/history_item.h" #include "history/history_item.h"
#include "api/api_premium.h"
#include "api/api_sensitive_content.h" #include "api/api_sensitive_content.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwidget.h" #include "mainwidget.h"
@ -5410,6 +5411,20 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
}, [](const MTPDstarGiftUnique &) { }, [](const MTPDstarGiftUnique &) {
return uint64(); return uint64();
}); });
if (!stars) {
if (!isSelf) {
result.links.push_back(peer->createOpenLink());
}
result.text = isSelf
? tr::lng_action_gift_unique_sent(
tr::now,
Ui::Text::WithEntities)
: tr::lng_action_gift_unique_received(
tr::now,
lt_user,
Ui::Text::Link(peer->shortName(), 1), // Link 1.
Ui::Text::WithEntities);
}
const auto cost = TextWithEntities{ const auto cost = TextWithEntities{
tr::lng_action_gift_for_stars(tr::now, lt_count, stars), tr::lng_action_gift_for_stars(tr::now, lt_count, stars),
}; };
@ -5421,7 +5436,9 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
cost, cost,
Ui::Text::WithEntities); Ui::Text::WithEntities);
} else { } else {
result.links.push_back(peer->createOpenLink()); if (!isSelf) {
result.links.push_back(peer->createOpenLink());
}
result.text = isSelf result.text = isSelf
? tr::lng_action_gift_sent(tr::now, ? tr::lng_action_gift_sent(tr::now,
lt_cost, lt_cost,
@ -5611,32 +5628,29 @@ void HistoryItem::applyAction(const MTPMessageAction &action) {
.unclaimed = data.is_unclaimed(), .unclaimed = data.is_unclaimed(),
}); });
}, [&](const MTPDmessageActionStarGift &data) { }, [&](const MTPDmessageActionStarGift &data) {
data.vgift().match([&](const MTPDstarGift &gift) { using Fields = Data::GiftCode;
const auto document = history()->owner().processDocument( auto fields = Fields{
gift.vsticker()); .message = (data.vmessage()
using Fields = Data::GiftCode; ? TextWithEntities{
_media = std::make_unique<Data::MediaGiftBox>(this, _from, Fields{ .text = qs(data.vmessage()->data().vtext()),
.document = document->sticker() ? document.get() : nullptr, .entities = Api::EntitiesFromMTP(
.message = (data.vmessage() &history()->session(),
? TextWithEntities{ data.vmessage()->data().ventities().v),
.text = qs(data.vmessage()->data().vtext()), }
.entities = Api::EntitiesFromMTP( : TextWithEntities()),
&history()->session(), .starsConverted = int(data.vconvert_stars().value_or_empty()),
data.vmessage()->data().ventities().v), .type = Data::GiftType::StarGift,
} .anonymous = data.is_name_hidden(),
: TextWithEntities()), .converted = data.is_converted(),
.starsConverted = int(data.vconvert_stars().value_or_empty()), .saved = data.is_saved(),
.limitedCount = gift.vavailability_total().value_or_empty(), };
.limitedLeft = gift.vavailability_remains().value_or_empty(), if (auto gift = Api::FromTL(&history()->session(), data.vgift())) {
.count = int(gift.vstars().v), fields.stickerId = gift->stickerId;
.type = Data::GiftType::StarGift, fields.limitedCount = gift->limitedCount;
.anonymous = data.is_name_hidden(), fields.limitedLeft = gift->limitedLeft;
.converted = data.is_converted(), fields.count = gift->stars;
.saved = data.is_saved(), fields.unique = gift->unique;
}); }
}, [&](const MTPDstarGiftUnique &gift) {
});
}, [](const auto &) { }, [](const auto &) {
}); });
} }

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/gift_premium_box.h" // ResolveGiftCode #include "boxes/gift_premium_box.h" // ResolveGiftCode
#include "chat_helpers/stickers_gift_box_pack.h" #include "chat_helpers/stickers_gift_box_pack.h"
#include "core/click_handler_types.h" // ClickHandlerContext #include "core/click_handler_types.h" // ClickHandlerContext
#include "data/stickers/data_custom_emoji.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_credits.h" #include "data/data_credits.h"
#include "data/data_document.h" #include "data/data_document.h"
@ -221,7 +222,9 @@ void PremiumGift::draw(
} }
QString PremiumGift::cornerTagText() { QString PremiumGift::cornerTagText() {
if (const auto count = _data.limitedCount) { if (_data.unique) {
return tr::lng_gift_limited_of_one(tr::now);
} else if (const auto count = _data.limitedCount) {
return (count == 1) return (count == 1)
? tr::lng_gift_limited_of_one(tr::now) ? tr::lng_gift_limited_of_one(tr::now)
: tr::lng_gift_limited_of_count( : tr::lng_gift_limited_of_count(
@ -291,14 +294,21 @@ int PremiumGift::credits() const {
void PremiumGift::ensureStickerCreated() const { void PremiumGift::ensureStickerCreated() const {
if (_sticker) { if (_sticker) {
return; return;
} else if (const auto document = _data.document) { } else if (const auto stickerId = _data.stickerId) {
if (const auto sticker = document->sticker()) { if (!_lifetime) {
const auto skipPremiumEffect = false; const auto owner = &_parent->history()->owner();
_sticker.emplace(_parent, document, skipPremiumEffect, _parent); _lifetime = owner->customEmojiManager().resolve(
_sticker->setPlayingOnce(true); stickerId
_sticker->initSize(st::msgServiceGiftBoxStickerSize); ) | rpl::start_with_next([=](not_null<DocumentData*> document) {
return; const auto sticker = document->sticker();
Assert(sticker != nullptr);
_sticker.emplace(_parent, document, false, _parent);
_sticker->setPlayingOnce(true);
_sticker->initSize(st::msgServiceGiftBoxStickerSize);
_parent->repaint();
});
} }
return;
} }
const auto &session = _parent->history()->session(); const auto &session = _parent->history()->session();
auto &packs = session.giftBoxStickersPacks(); auto &packs = session.giftBoxStickersPacks();

View file

@ -60,6 +60,7 @@ private:
const not_null<Data::MediaGiftBox*> _gift; const not_null<Data::MediaGiftBox*> _gift;
const Data::GiftCode &_data; const Data::GiftCode &_data;
mutable std::optional<Sticker> _sticker; mutable std::optional<Sticker> _sticker;
mutable rpl::lifetime _lifetime;
}; };

View file

@ -1615,7 +1615,7 @@ void StarGiftViewBox(
.credits = StarsAmount(data.count), .credits = StarsAmount(data.count),
.bareMsgId = uint64(item->id.bare), .bareMsgId = uint64(item->id.bare),
.barePeerId = item->history()->peer->id.value, .barePeerId = item->history()->peer->id.value,
.bareGiftStickerId = data.document ? data.document->id : 0, .bareGiftStickerId = data.stickerId,
.peerType = Data::CreditsHistoryEntry::PeerType::Peer, .peerType = Data::CreditsHistoryEntry::PeerType::Peer,
.limitedCount = data.limitedCount, .limitedCount = data.limitedCount,
.limitedLeft = data.limitedLeft, .limitedLeft = data.limitedLeft,