From 4f7364b7984ef06125223264313e7c0f1732bfa5 Mon Sep 17 00:00:00 2001
From: 23rd <23rd@vivaldi.net>
Date: Sat, 10 Aug 2024 01:22:32 +0300
Subject: [PATCH] Added ability to cancel and renew subscription from settings
 section.

---
 Telegram/SourceFiles/api/api_chat_invite.cpp  |  6 +-
 Telegram/SourceFiles/api/api_chat_invite.h    |  3 +-
 .../settings/settings_credits_graphics.cpp    | 66 ++++++++++++++++++-
 3 files changed, 71 insertions(+), 4 deletions(-)

diff --git a/Telegram/SourceFiles/api/api_chat_invite.cpp b/Telegram/SourceFiles/api/api_chat_invite.cpp
index b7673c6ba..1f36a8b95 100644
--- a/Telegram/SourceFiles/api/api_chat_invite.cpp
+++ b/Telegram/SourceFiles/api/api_chat_invite.cpp
@@ -342,7 +342,8 @@ void ConfirmSubscriptionBox(
 void CheckChatInvite(
 		not_null<Window::SessionController*> controller,
 		const QString &hash,
-		ChannelData *invitePeekChannel) {
+		ChannelData *invitePeekChannel,
+		Fn<void()> loaded) {
 	const auto session = &controller->session();
 	const auto weak = base::make_weak(controller);
 	session->api().checkChatInvite(hash, [=](const MTPChatInvite &result) {
@@ -350,6 +351,9 @@ void CheckChatInvite(
 		if (!strong) {
 			return;
 		}
+		if (loaded) {
+			loaded();
+		}
 		Core::App().hideMediaView();
 		const auto show = [&](not_null<PeerData*> chat) {
 			const auto way = Window::SectionShow::Way::Forward;
diff --git a/Telegram/SourceFiles/api/api_chat_invite.h b/Telegram/SourceFiles/api/api_chat_invite.h
index c8d99548c..94eeab5e9 100644
--- a/Telegram/SourceFiles/api/api_chat_invite.h
+++ b/Telegram/SourceFiles/api/api_chat_invite.h
@@ -38,7 +38,8 @@ namespace Api {
 void CheckChatInvite(
 	not_null<Window::SessionController*> controller,
 	const QString &hash,
-	ChannelData *invitePeekChannel = nullptr);
+	ChannelData *invitePeekChannel = nullptr,
+	Fn<void()> loaded = nullptr);
 
 } // namespace Api
 
diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp
index ff39a28d0..07be46a92 100644
--- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp
+++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp
@@ -7,8 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 */
 #include "settings/settings_credits_graphics.h"
 
+#include "api/api_chat_invite.h"
 #include "api/api_credits.h"
 #include "api/api_earn.h"
+#include "apiwrap.h"
 #include "base/timer_rpl.h"
 #include "base/unixtime.h"
 #include "boxes/gift_premium_box.h"
@@ -29,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "history/history.h"
 #include "history/history_item.h"
 #include "history/history_item_components.h" // HistoryServicePaymentRefund.
+#include "info/channel_statistics/boosts/giveaway/boost_badge.h" // InfiniteRadialAnimationWidget.
 #include "info/settings/info_settings_widget.h" // SectionCustomTopBarData.
 #include "info/statistics/info_statistics_list_controllers.h"
 #include "lang/lang_keys.h"
@@ -783,9 +786,68 @@ void ReceiptCreditsBox(
 		}, widget->lifetime());
 	}
 
-	const auto button = box->addButton(tr::lng_box_ok(), [=] {
-		box->closeBox();
+	const auto toRenew = (s.cancelled || s.expired)
+		&& !s.inviteHash.isEmpty();
+	const auto toCancel = !toRenew && s;
+	struct State final {
+		rpl::variable<bool> confirmButtonBusy;
+	};
+	const auto state = box->lifetime().make_state<State>();
+	auto confirmText = rpl::conditional(
+		state->confirmButtonBusy.value(),
+		rpl::single(QString()),
+		toRenew
+			? tr::lng_credits_subscription_off_button()
+			: toCancel
+			? tr::lng_credits_subscription_on_button()
+			: tr::lng_box_ok());
+
+	using Flag = MTPpayments_ChangeStarsSubscription::Flag;
+	const auto send = [=, weak = Ui::MakeWeak(box)] {
+		if (toRenew && s.expired) {
+			Api::CheckChatInvite(controller, s.inviteHash, nullptr, [=] {
+				if (const auto strong = weak.get()) {
+					strong->closeBox();
+				}
+			});
+		} else {
+			session->api().request(
+				MTPpayments_ChangeStarsSubscription(
+					MTP_flags(Flag::f_canceled),
+					MTP_inputPeerSelf(),
+					MTP_string(s.id),
+					MTP_bool(toCancel)
+			)).done([=] {
+				state->confirmButtonBusy = false;
+				if (const auto strong = weak.get()) {
+					strong->closeBox();
+				}
+			}).fail([=, show = box->uiShow()](const MTP::Error &error) {
+				state->confirmButtonBusy = false;
+				show->showToast(error.type());
+			}).send();
+		}
+	};
+
+	const auto button = box->addButton(std::move(confirmText), [=] {
+		if (state->confirmButtonBusy.current()) {
+			return;
+		}
+		state->confirmButtonBusy = true;
+		if ((toRenew || toCancel) && peer) {
+			send();
+		} else {
+			box->closeBox();
+		}
 	});
+	{
+		using namespace Info::Statistics;
+		const auto loadingAnimation = InfiniteRadialAnimationWidget(
+			button,
+			button->height() / 2);
+		AddChildToWidgetCenter(button, loadingAnimation);
+		loadingAnimation->showOn(state->confirmButtonBusy.value());
+	}
 	const auto buttonWidth = st::boxWidth
 		- rect::m::sum::h(st::giveawayGiftCodeBox.buttonPadding);
 	button->widthValue() | rpl::filter([=] {