From eec9c8a46b5b77922c0ece18322f69ae2bcf597d Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 14 Aug 2024 16:47:39 +0200 Subject: [PATCH] Support tg://stars_topup links. --- Telegram/Resources/langs/cloud_lang.strings | 2 + Telegram/Resources/langs/lang.strings | 3 + Telegram/SourceFiles/api/api_chat_invite.cpp | 3 +- .../SourceFiles/core/local_url_handlers.cpp | 62 +++++++++++++++++++ .../view/media/history_view_web_page.cpp | 5 +- .../payments/payments_reaction_process.cpp | 3 +- .../settings/settings_credits_graphics.cpp | 18 +++++- .../settings/settings_credits_graphics.h | 7 ++- 8 files changed, 97 insertions(+), 6 deletions(-) diff --git a/Telegram/Resources/langs/cloud_lang.strings b/Telegram/Resources/langs/cloud_lang.strings index c9d4af958..16e9ea357 100644 --- a/Telegram/Resources/langs/cloud_lang.strings +++ b/Telegram/Resources/langs/cloud_lang.strings @@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "cloud_lng_forwarded_psa_covid" = "COVID-19 Notification from {channel}"; "cloud_lng_tooltip_psa_covid" = "This message provides you with a public service announcement in relation to the ongoing COVID-19 pandemic. Learn more about this initiative at https://telegram.org/blog/coronavirus"; +"cloud_lng_topup_purpose_subs" = "Buy **Stars** to keep your channel subscriptions."; + "cloud_lng_passport_in_ar" = "Arabic"; "cloud_lng_passport_in_az" = "Azerbaijani"; "cloud_lng_passport_in_bg" = "Bulgarian"; diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 013244b04..0f97e1451 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2453,7 +2453,10 @@ 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_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 ({balance}). {link}"; +"lng_credits_enough_link" = "Topup anyway"; "lng_credits_gift_title" = "Gift Telegram Stars"; diff --git a/Telegram/SourceFiles/api/api_chat_invite.cpp b/Telegram/SourceFiles/api/api_chat_invite.cpp index 1f36a8b95..49baf3425 100644 --- a/Telegram/SourceFiles/api/api_chat_invite.cpp +++ b/Telegram/SourceFiles/api/api_chat_invite.cpp @@ -310,7 +310,8 @@ void ConfirmSubscriptionBox( state->loading.force_assign(true); const auto done = [=](Settings::SmallBalanceResult result) { - if (result == Settings::SmallBalanceResult::Success) { + if (result == Settings::SmallBalanceResult::Success + || result == Settings::SmallBalanceResult::Already) { sendCredits(); } else { state->api = std::nullopt; diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 28aa99822..229b46a80 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/qthelp_url.h" #include "lang/lang_cloud_manager.h" #include "lang/lang_keys.h" +#include "core/ui_integration.h" // MarkedTextContext. #include "core/update_checker.h" #include "core/application.h" #include "core/click_handler_types.h" @@ -46,6 +47,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_peer_menu.h" #include "window/themes/window_theme_editor_box.h" // GenerateSlug. #include "payments/payments_checkout_process.h" +#include "settings/settings_credits.h" +#include "settings/settings_credits_graphics.h" #include "settings/settings_information.h" #include "settings/settings_global_ttl.h" #include "settings/settings_folders.h" @@ -1170,6 +1173,61 @@ bool ResolveBoost( return true; } +bool ResolveTopUp( + Window::SessionController *controller, + const Match &match, + const QVariant &context) { + if (!controller) { + return false; + } + const auto params = url_parse_params( + match->captured(1), + qthelp::UrlParamNameTransform::ToLower); + const auto amount = std::clamp( + params.value(u"balance"_q).toULongLong(), + qulonglong(1), + qulonglong(1'000'000)); + const auto purpose = params.value(u"purpose"_q); + const auto weak = base::make_weak(controller); + const auto done = [=](::Settings::SmallBalanceResult result) { + if (result == ::Settings::SmallBalanceResult::Already) { + if (const auto strong = weak.get()) { + auto balance = TextWithEntities{ u"hello"_q }; + const auto context = [=](not_null toast) { + return Core::MarkedTextContext{ + .session = &strong->session(), + .customEmojiRepaint = [=] { toast->update(); }, + }; + }; + const auto filter = [=](const auto &...) { + strong->showSettings(::Settings::CreditsId()); + return false; + }; + strong->showToast(Ui::Toast::Config{ + .text = tr::lng_credits_enough( + tr::now, + lt_balance, + balance, + lt_link, + Ui::Text::Link( + Ui::Text::Bold( + tr::lng_credits_enough_link(tr::now))), + Ui::Text::RichLangValue), + .textContext = context, + .filter = filter, + }); + } + } + }; + ::Settings::MaybeRequestBalanceIncrease( + controller->uiShow(), + amount, + ::Settings::SmallBalanceDeepLink{ .purpose = purpose }, + [](auto) {}); + return true; +} + + bool ResolveChatLink( Window::SessionController *controller, const Match &match, @@ -1276,6 +1334,10 @@ const std::vector &LocalUrlHandlers() { u"^message/?\\?slug=([a-zA-Z0-9\\.\\_\\-]+)(&|$)"_q, ResolveChatLink }, + { + u"^stars_topup/?\\?(.+)(#|$)"_q, + ResolveTopUp + }, { u"^([^\\?]+)(\\?|#|$)"_q, HandleUnknown diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp index 8b2c18839..611827081 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp @@ -310,10 +310,11 @@ void WebPage::setupAdditionalData() { : 0; if (!_attach) { const auto maybePhoto = details.mediaPhotoId - ? _data->session().data().photo(details.mediaPhotoId) + ? _data->session().data().photo(details.mediaPhotoId).get() : nullptr; const auto maybeDocument = details.mediaDocumentId - ? _data->session().data().document(details.mediaDocumentId) + ? _data->session().data().document( + details.mediaDocumentId).get() : nullptr; _attach = CreateAttach( _parent, diff --git a/Telegram/SourceFiles/payments/payments_reaction_process.cpp b/Telegram/SourceFiles/payments/payments_reaction_process.cpp index b18339a84..57c769f12 100644 --- a/Telegram/SourceFiles/payments/payments_reaction_process.cpp +++ b/Telegram/SourceFiles/payments/payments_reaction_process.cpp @@ -60,7 +60,8 @@ void TryAddingPaidReaction( return; } const auto done = [=](Settings::SmallBalanceResult result) { - if (result == Settings::SmallBalanceResult::Success) { + if (result == Settings::SmallBalanceResult::Success + || result == Settings::SmallBalanceResult::Already) { if (const auto item = checkItem()) { item->addPaidReaction(count, anonymous); if (const auto view = count ? weakView.get() : nullptr) { diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index fe9630bf9..4f3e986e1 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -82,6 +82,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Settings { namespace { +const auto kTopUpPrefix = "cloud_lng_topup_purpose_"; + [[nodiscard]] uint64 UniqueIdFromOption( const Data::CreditTopupOption &d) { const auto string = QString::number(d.credits) @@ -97,6 +99,15 @@ namespace { return session->appConfig().get(key, 1000); } +[[nodiscard]] rpl::producer DeepLinkBalanceAbout( + const QString &purpose) { + const auto phrase = Lang::GetNonDefaultValue( + kTopUpPrefix + purpose.toUtf8()); + return phrase.isEmpty() + ? tr::lng_credits_small_balance_fallback(Ui::Text::RichLangValue) + : rpl::single(Ui::Text::RichLangValue(phrase)); +} + class Balance final : public Ui::RpWidget , public Ui::AbstractTooltipShower { @@ -1025,6 +1036,8 @@ void SmallBalanceBox( return owner->peer(peerFromChannel(value.channelId))->name(); }, [](SmallBalanceSubscription value) { return value.name; + }, [](SmallBalanceDeepLink value) { + return QString(); }); auto needed = show->session().credits().balanceValue( @@ -1051,6 +1064,9 @@ void SmallBalanceBox( lt_channel, rpl::single(Ui::Text::Bold(name)), Ui::Text::RichLangValue) + : v::is(source) + ? DeepLinkBalanceAbout( + v::get(source).purpose) : tr::lng_credits_small_balance_about( lt_bot, rpl::single(TextWithEntities{ name }), @@ -1424,7 +1440,7 @@ void MaybeRequestBalanceIncrease( const auto balance = session->credits().balance(); if (credits <= balance) { if (const auto onstack = done) { - onstack(SmallBalanceResult::Success); + onstack(SmallBalanceResult::Already); } } else if (show->session().premiumPossible()) { const auto success = [=] { diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.h b/Telegram/SourceFiles/settings/settings_credits_graphics.h index 2978a87aa..15b2f0ff8 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.h +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.h @@ -111,10 +111,14 @@ struct SmallBalanceReaction { struct SmallBalanceSubscription { QString name; }; +struct SmallBalanceDeepLink { + QString purpose; +}; struct SmallBalanceSource : std::variant< SmallBalanceBot, SmallBalanceReaction, - SmallBalanceSubscription> { + SmallBalanceSubscription, + SmallBalanceDeepLink> { using variant::variant; }; @@ -126,6 +130,7 @@ void SmallBalanceBox( Fn paid); enum class SmallBalanceResult { + Already, Success, Blocked, Cancelled,