From dd4fbc256ccb6f3f7d0327e65188148afb3eaaa5 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Mon, 7 Oct 2024 14:47:08 +0400
Subject: [PATCH] Version 5.6.1: Support sold out gifts better.

---
 Telegram/Resources/langs/lang.strings              |  5 +++++
 Telegram/SourceFiles/boxes/star_gift_box.cpp       | 10 ++++++++++
 .../info/peer_gifts/info_peer_gifts_common.cpp     | 11 ++++++++---
 .../info/peer_gifts/info_peer_gifts_common.h       |  1 +
 .../payments/payments_non_panel_process.cpp        | 13 ++++++++-----
 .../settings/settings_credits_graphics.cpp         | 14 +++++++++++++-
 .../settings/settings_credits_graphics.h           |  6 +++++-
 7 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index 60cdcc65c..a57fc8b1b 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -2486,6 +2486,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_credits_small_balance_about" = "Buy **Stars** and use them on **{bot}** and other miniapps.";
 "lng_credits_small_balance_reaction" = "Buy **Stars** and send them to {channel} to support their posts.";
 "lng_credits_small_balance_subscribe" = "Buy **Stars** and subscribe to **{channel}** and other channels.";
+"lng_credits_small_balance_star_gift" = "Buy **Stars** to send gifts to {user} and other contacts.";
 "lng_credits_small_balance_fallback" = "Buy **Stars** to unlock content and services on Telegram.";
 "lng_credits_purchase_blocked" = "Sorry, you can't purchase this item with Telegram Stars.";
 "lng_credits_enough" = "You have enough stars at the moment. {link}";
@@ -3014,6 +3015,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_gift_stars_about" = "Give {name} gifts that can be kept on your profile or converted to Stars. {link}";
 "lng_gift_stars_link" = "What are Stars >";
 "lng_gift_stars_limited" = "limited";
+"lng_gift_stars_sold_out" = "sold out";
 "lng_gift_stars_tabs_all" = "All Gifts";
 "lng_gift_stars_tabs_limited" = "Limited";
 "lng_gift_send_title" = "Send a Gift";
@@ -3047,6 +3049,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_gift_display_done_hide" = "The gift is now hidden from your profile page.";
 "lng_gift_got_stars#one" = "You got **{count} Star** for this gift.";
 "lng_gift_got_stars#other" = "You got **{count} Stars** for this gift.";
+"lng_gift_sold_out_title" = "Sold Out!";
+"lng_gift_sold_out_text#one" = "All {count} gift was already sold.";
+"lng_gift_sold_out_text#other" = "All {count} gifts were already sold.";
 
 "lng_accounts_limit_title" = "Limit Reached";
 "lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account.";
diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp
index ce239e247..306c00dfb 100644
--- a/Telegram/SourceFiles/boxes/star_gift_box.cpp
+++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp
@@ -514,6 +514,7 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
 					.convertStars = gift.convertStars,
 					.document = gift.document,
 					.limitedCount = gift.limitedCount,
+					.limitedLeft = gift.limitedLeft,
 				});
 			}
 			auto &map = Map[session];
@@ -1081,6 +1082,7 @@ void SendGiftBox(
 				}
 			};
 			button->setClickedCallback([=] {
+				const auto star = std::get_if<GiftTypeStars>(&descriptor);
 				if (v::is<GiftTypePremium>(descriptor)) {
 					if (state->sending) {
 						return;
@@ -1093,6 +1095,14 @@ void SendGiftBox(
 						api,
 						GiftDetails{ descriptor },
 						premiumSent);
+				} else if (star && star->limitedCount && !star->limitedLeft) {
+					window->showToast({
+						.title = tr::lng_gift_sold_out_title(tr::now),
+						.text = tr::lng_gift_sold_out_text(
+							tr::now,
+							lt_count_decimal,
+							star->limitedCount),
+					});
 				} else {
 					window->show(
 						Box(SendGiftBox, window, peer, api, descriptor));
diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp
index 45b26cd35..83649bf5a 100644
--- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp
+++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp
@@ -253,15 +253,20 @@ void GiftButton::paintEvent(QPaintEvent *e) {
 	p.setFont(font);
 	const auto text = v::match(_descriptor, [&](GiftTypePremium data) {
 		if (data.discountPercent > 0) {
-			p.setBrush(st::attentionBoxButton.textFg);
+			p.setBrush(st::attentionButtonFg);
 			const auto kMinus = QChar(0x2212);
 			return kMinus + QString::number(data.discountPercent) + '%';
 		}
 		return QString();
 	}, [&](const GiftTypeStars &data) {
 		if (const auto count = data.limitedCount) {
-			p.setBrush(st::windowActiveTextFg);
-			return !data.userpic
+			const auto soldOut = !data.userpic && !data.limitedLeft;
+			p.setBrush(soldOut
+				? st::attentionButtonFg
+				: st::windowActiveTextFg);
+			return soldOut
+				? tr::lng_gift_stars_sold_out(tr::now)
+				: !data.userpic
 				? tr::lng_gift_stars_limited(tr::now)
 				: (count == 1)
 				? tr::lng_gift_limited_of_one(tr::now)
diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h
index 5c63e8885..6fd2b7413 100644
--- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h
+++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h
@@ -48,6 +48,7 @@ struct GiftTypeStars {
 	DocumentData *document = nullptr;
 	PeerData *from = nullptr;
 	int limitedCount = 0;
+	int limitedLeft = 0;
 	bool userpic = false;
 	bool hidden = false;
 	bool mine = false;
diff --git a/Telegram/SourceFiles/payments/payments_non_panel_process.cpp b/Telegram/SourceFiles/payments/payments_non_panel_process.cpp
index 3f269a534..baa019072 100644
--- a/Telegram/SourceFiles/payments/payments_non_panel_process.cpp
+++ b/Telegram/SourceFiles/payments/payments_non_panel_process.cpp
@@ -93,11 +93,14 @@ void ProcessCreditsPayment(
 			});
 		}, box->lifetime());
 	};
-	Settings::MaybeRequestBalanceIncrease(
-		show,
-		form->invoice.credits,
-		Settings::SmallBalanceBot{ .botId = form->botId },
-		done);
+	using namespace Settings;
+	const auto starGift = std::get_if<InvoiceStarGift>(&form->id.value);
+	auto source = !starGift
+		? SmallBalanceSource(SmallBalanceBot{ .botId = form->botId })
+		: SmallBalanceSource(SmallBalanceStarGift{
+			.userId = peerToUser(starGift->user->id)
+		});
+	MaybeRequestBalanceIncrease(show, form->invoice.credits, source, done);
 }
 
 void ProcessCreditsReceipt(
diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp
index 407f22d16..01ffb1aff 100644
--- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp
+++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp
@@ -1555,13 +1555,17 @@ void SmallBalanceBox(
 
 	const auto owner = &show->session().data();
 	const auto name = v::match(source, [&](SmallBalanceBot value) {
-		return owner->peer(peerFromUser(value.botId))->name();
+		return value.botId
+			? owner->peer(peerFromUser(value.botId))->name()
+			: QString();
 	}, [&](SmallBalanceReaction value) {
 		return owner->peer(peerFromChannel(value.channelId))->name();
 	}, [](SmallBalanceSubscription value) {
 		return value.name;
 	}, [](SmallBalanceDeepLink value) {
 		return QString();
+	}, [&](SmallBalanceStarGift value) {
+		return owner->peer(peerFromUser(value.userId))->shortName();
 	});
 
 	auto needed = show->session().credits().balanceValue(
@@ -1591,6 +1595,14 @@ void SmallBalanceBox(
 					: v::is<SmallBalanceDeepLink>(source)
 					? DeepLinkBalanceAbout(
 						v::get<SmallBalanceDeepLink>(source).purpose)
+					: v::is<SmallBalanceStarGift>(source)
+					? tr::lng_credits_small_balance_star_gift(
+						lt_user,
+						rpl::single(Ui::Text::Bold(name)),
+						Ui::Text::RichLangValue)
+					: name.isEmpty()
+					? tr::lng_credits_small_balance_fallback(
+						Ui::Text::RichLangValue)
 					: tr::lng_credits_small_balance_about(
 						lt_bot,
 						rpl::single(TextWithEntities{ name }),
diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.h b/Telegram/SourceFiles/settings/settings_credits_graphics.h
index 37b14c949..bfc266e3e 100644
--- a/Telegram/SourceFiles/settings/settings_credits_graphics.h
+++ b/Telegram/SourceFiles/settings/settings_credits_graphics.h
@@ -138,11 +138,15 @@ struct SmallBalanceSubscription {
 struct SmallBalanceDeepLink {
 	QString purpose;
 };
+struct SmallBalanceStarGift {
+	UserId userId = 0;
+};
 struct SmallBalanceSource : std::variant<
 	SmallBalanceBot,
 	SmallBalanceReaction,
 	SmallBalanceSubscription,
-	SmallBalanceDeepLink> {
+	SmallBalanceDeepLink,
+	SmallBalanceStarGift> {
 	using variant::variant;
 };