From aed1904b4c207647b0961b286d8e11f2ad62b402 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 29 Mar 2022 00:14:10 +0400 Subject: [PATCH] Support theming for webview-s (payments, attach). --- Telegram/SourceFiles/api/api_updates.cpp | 13 ++++++++ Telegram/SourceFiles/data/data_session.cpp | 8 +++++ Telegram/SourceFiles/data/data_session.h | 10 +++++++ .../history/history_item_components.cpp | 12 ++++++-- .../payments/payments_checkout_process.cpp | 12 ++++++++ .../payments/payments_checkout_process.h | 1 + .../SourceFiles/payments/payments_form.cpp | 24 ++------------- .../payments/ui/payments_panel.cpp | 13 ++++++++ .../SourceFiles/payments/ui/payments_panel.h | 1 + .../ui/chat/attach/attach_bot_webview.cpp | 30 +++++++++++++++++-- .../ui/chat/attach/attach_bot_webview.h | 8 +++-- .../window/themes/window_theme.cpp | 28 +++++++++++++++++ .../SourceFiles/window/themes/window_theme.h | 2 ++ .../window/window_session_controller.cpp | 16 ++++++++-- 14 files changed, 147 insertions(+), 31 deletions(-) diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index e2370360e..49d755305 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -1997,6 +1997,19 @@ void Updates::feedUpdate(const MTPUpdate &update) { } } break; + case mtpc_updateAttachMenuBots: { + + } break; + + case mtpc_updateWebViewResultSent: { + const auto &d = update.c_updateWebViewResultSent(); + session().data().webViewResultSent({ + .peerId = peerFromMTP(d.vpeer()), + .botId = UserId(d.vbot_id()), + .queryId = d.vquery_id().v, + }); + } break; + case mtpc_updatePendingJoinRequests: { const auto &d = update.c_updatePendingJoinRequests(); if (const auto peer = session().data().peerLoaded(peerFromMTP(d.vpeer()))) { diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index ded68526a..80d83a537 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -4225,6 +4225,14 @@ uint64 Session::wallpapersHash() const { return _wallpapersHash; } +void Session::webViewResultSent(WebViewResultSent &&sent) { + return _webViewResultSent.fire(std::move(sent)); +} + +auto Session::webViewResultSent() const -> rpl::producer { + return _webViewResultSent.events(); +} + void Session::clearLocalStorage() { _cache->close(); _cache->clear(); diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 941e457bd..89223bd6f 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -698,6 +698,14 @@ public: const std::vector &wallpapers() const; uint64 wallpapersHash() const; + struct WebViewResultSent { + PeerId peerId = 0; + UserId botId = 0; + uint64 queryId = 0; + }; + void webViewResultSent(WebViewResultSent &&sent); + [[nodiscard]] rpl::producer webViewResultSent() const; + void clearLocalStorage(); private: @@ -984,6 +992,8 @@ private: std::vector _wallpapers; uint64 _wallpapersHash = 0; + rpl::event_stream _webViewResultSent; + Groups _groups; const std::unique_ptr _chatsFilters; std::unique_ptr _scheduledMessages; diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index 292f5d65a..71def1223 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -54,11 +54,17 @@ void HistoryMessageVia::create( tr::lng_inline_bot_via(tr::now, lt_inline_bot, '@' + bot->username)); link = std::make_shared([bot = this->bot]( ClickContext context) { - if (base::IsCtrlPressed()) { - if (const auto window = App::wnd()) { - if (const auto controller = window->sessionController()) { + if (const auto window = App::wnd()) { + if (const auto controller = window->sessionController()) { + if (base::IsCtrlPressed()) { controller->showPeerInfo(bot); return; + } else if (!bot->isBot() + || bot->botInfo->inlinePlaceholder.isEmpty()) { + controller->showPeerHistory( + bot->id, + Window::SectionShow::Way::Forward); + return; } } } diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.cpp b/Telegram/SourceFiles/payments/payments_checkout_process.cpp index 861bf2d5d..6dc9f461c 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.cpp +++ b/Telegram/SourceFiles/payments/payments_checkout_process.cpp @@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" #include "apiwrap.h" #include "api/api_cloud_password.h" +#include "window/themes/window_theme.h" #include #include @@ -161,6 +162,17 @@ CheckoutProcess::CheckoutProcess( showForm(); _panel->toggleProgress(true); + style::PaletteChanged( + ) | rpl::filter([=] { + return !_themeUpdateScheduled; + }) | rpl::start_with_next([=] { + _themeUpdateScheduled = true; + crl::on_main(this, [=] { + _themeUpdateScheduled = false; + _panel->updateThemeParams(Window::Theme::WebViewParams()); + }); + }, _panel->lifetime()); + if (mode == Mode::Payment) { _session->api().cloudPassword().state( ) | rpl::start_with_next([=](const Core::CloudPasswordState &state) { diff --git a/Telegram/SourceFiles/payments/payments_checkout_process.h b/Telegram/SourceFiles/payments/payments_checkout_process.h index 8dceffd2c..65efb2426 100644 --- a/Telegram/SourceFiles/payments/payments_checkout_process.h +++ b/Telegram/SourceFiles/payments/payments_checkout_process.h @@ -137,6 +137,7 @@ private: SubmitState _submitState = SubmitState::None; bool _initialSilentValidation = false; + bool _themeUpdateScheduled = false; rpl::lifetime _gettingPasswordState; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/payments/payments_form.cpp b/Telegram/SourceFiles/payments/payments_form.cpp index 7bd866915..c1ff50882 100644 --- a/Telegram/SourceFiles/payments/payments_form.cpp +++ b/Telegram/SourceFiles/payments/payments_form.cpp @@ -28,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "apiwrap.h" #include "core/core_cloud_password.h" +#include "window/themes/window_theme.h" #include "styles/style_payments.h" // paymentsThumbnailSize. #include @@ -106,27 +107,6 @@ constexpr auto kPasswordPeriod = 15 * TimeId(60); + SmartGlocal::Last4(card); } -[[nodiscard]] QByteArray ThemeParams() { - const auto colors = std::vector>{ - { "bg_color", st::windowBg }, - { "text_color", st::windowFg }, - { "hint_color", st::windowSubTextFg }, - { "link_color", st::windowActiveTextFg }, - { "button_color", st::windowBgActive }, - { "button_text_color", st::windowFgActive }, - }; - auto object = QJsonObject(); - for (const auto &[name, color] : colors) { - const auto value = uint32(0xFF000000U) - | (uint32(color->c.red()) << 16) - | (uint32(color->c.green()) << 8) - | (uint32(color->c.blue())); - const auto int32value = *reinterpret_cast(&value); - object.insert(name, int32value); - } - return QJsonDocument(object).toJson(QJsonDocument::Compact); -} - } // namespace Form::Form(not_null peer, MsgId itemId, bool receipt) @@ -262,7 +242,7 @@ void Form::requestForm() { MTP_flags(MTPpayments_GetPaymentForm::Flag::f_theme_params), _peer->input, MTP_int(_msgId), - MTP_dataJSON(MTP_bytes(ThemeParams())) + MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams())) )).done([=](const MTPpayments_PaymentForm &result) { hideProgress(); result.match([&](const auto &data) { diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.cpp b/Telegram/SourceFiles/payments/ui/payments_panel.cpp index 26e6977f2..0aa5e85b3 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_panel.cpp @@ -781,6 +781,19 @@ void Panel::showWebviewError( showCriticalError(rich); } +void Panel::updateThemeParams(const QByteArray &json) { + if (!_webview || !_webview->window.widget()) { + return; + } + _webview->window.eval(R"( +if (window.TelegramGameProxy) { + window.TelegramGameProxy.receiveEvent( + "theme_changed", + { "theme_params": )" + json + R"( }); +} +)"); +} + rpl::lifetime &Panel::lifetime() { return _widget->lifetime(); } diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.h b/Telegram/SourceFiles/payments/ui/payments_panel.h index c977fe7a4..3fb3e26e2 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.h +++ b/Telegram/SourceFiles/payments/ui/payments_panel.h @@ -76,6 +76,7 @@ public: const QString &url, bool allowBack, rpl::producer bottomText); + void updateThemeParams(const QByteArray &json); [[nodiscard]] rpl::producer<> backRequests() const; diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp index eae6b3b89..8238bf005 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp @@ -69,7 +69,8 @@ Panel::Progress::Progress(QWidget *parent, Fn rect) Panel::Panel( const QString &userDataPath, Fn sendData, - Fn close) + Fn close, + Fn themeParams) : _userDataPath(userDataPath) , _sendData(std::move(sendData)) , _close(std::move(close)) @@ -83,6 +84,17 @@ Panel::Panel( _widget->closeEvents( ) | rpl::start_with_next(_close, _widget->lifetime()); + style::PaletteChanged( + ) | rpl::filter([=] { + return !_themeUpdateScheduled; + }) | rpl::start_with_next([=] { + _themeUpdateScheduled = true; + crl::on_main(_widget.get(), [=] { + _themeUpdateScheduled = false; + updateThemeParams(themeParams()); + }); + }, _widget->lifetime()); + setTitle(rpl::single(u"Title"_q)); } @@ -392,6 +404,19 @@ void Panel::showCriticalError(const TextWithEntities &text) { _widget->showInner(std::move(error)); } +void Panel::updateThemeParams(const QByteArray &json) { + if (!_webview || !_webview->window.widget()) { + return; + } + _webview->window.eval(R"( +if (window.TelegramGameProxy) { + window.TelegramGameProxy.receiveEvent( + "theme_changed", + { "theme_params": )" + json + R"( }); +} +)"); +} + void Panel::showWebviewError( const QString &text, const Webview::Available &information) { @@ -438,7 +463,8 @@ std::unique_ptr Show(Args &&args) { auto result = std::make_unique( args.userDataPath, std::move(args.sendData), - std::move(args.close)); + std::move(args.close), + std::move(args.themeParams)); result->showWebview(args.url, rpl::single(u"smth"_q)); return result; } diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h index 01e351fac..a5fe8e039 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h @@ -26,7 +26,8 @@ public: Panel( const QString &userDataPath, Fn sendData, - Fn close); + Fn close, + Fn themeParams); ~Panel(); void requestActivate(); @@ -40,6 +41,8 @@ public: void showToast(const TextWithEntities &text); void showCriticalError(const TextWithEntities &text); + void updateThemeParams(const QByteArray &json); + [[nodiscard]] rpl::lifetime &lifetime(); private: @@ -66,6 +69,7 @@ private: std::unique_ptr _webviewBottom; std::unique_ptr _progress; bool _webviewProgress = false; + bool _themeUpdateScheduled = false; }; @@ -74,7 +78,7 @@ struct Args { QString userDataPath; Fn sendData; Fn close; - bool simple = false; + Fn themeParams; }; [[nodiscard]] std::unique_ptr Show(Args &&args); diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 7214bffd8..716cbad9f 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -38,6 +38,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_chat.h" #include +#include +#include namespace Window { namespace Theme { @@ -1489,5 +1491,31 @@ bool ReadPaletteValues(const QByteArray &content, Fn>{ + { "bg_color", st::windowBg }, + { "text_color", st::windowFg }, + { "hint_color", st::windowSubTextFg }, + { "link_color", st::windowActiveTextFg }, + { "button_color", st::windowBgActive }, + { "button_text_color", st::windowFgActive }, + }; + auto object = QJsonObject(); + for (const auto &[name, color] : colors) { + auto r = 0; + auto g = 0; + auto b = 0; + color->c.getRgb(&r, &g, &b); + const auto hex = [](int component) { + const auto digit = [](int c) { + return QChar((c < 10) ? ('0' + c) : ('a' + c - 10)); + }; + return QString() + digit(component / 16) + digit(component % 16); + }; + object.insert(name, '#' + hex(r) + hex(g) + hex(b)); + } + return QJsonDocument(object).toJson(QJsonDocument::Compact); +} + } // namespace Theme } // namespace Window diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index 22cd32f97..385880c12 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -293,5 +293,7 @@ bool ReadPaletteValues( const QByteArray &content, Fn callback); +[[nodiscard]] QByteArray WebViewParams(); + } // namespace Theme } // namespace Window diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 7c824e4b4..e6e048886 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -432,12 +432,14 @@ void SessionNavigation::requestAttachWebview( not_null bot, const WebViewButton &button) { using Flag = MTPmessages_RequestWebView::Flag; + const auto flags = Flag::f_theme_params + | (button.url.isEmpty() ? Flag(0) : Flag::f_url); _api.request(MTPmessages_RequestWebView( - MTP_flags(button.url.isEmpty() ? Flag(0) : Flag::f_url), + MTP_flags(flags), peer->input, bot->inputUser, MTP_bytes(button.url), - MTPDataJSON(), // theme_params + MTP_dataJSON(MTP_bytes(Theme::WebViewParams())), MTPint() // reply_to_msg_id )).done([=](const MTPWebViewResult &result) { result.match([&](const MTPDwebViewResultUrl &data) { @@ -509,7 +511,17 @@ void SessionNavigation::showAttachWebview( .userDataPath = session().domain().local().webviewDataPath(), .sendData = sendData, .close = close, + .themeParams = [] { return Window::Theme::WebViewParams(); }, }); + + session().data().webViewResultSent( + ) | rpl::filter([=](const Data::Session::WebViewResultSent &sent) { + return (sent.peerId == peer->id) + && (sent.botId == bot->id) + && (sent.queryId == queryId); + }) | rpl::start_with_next([=] { + _botWebView = nullptr; + }, _botWebView->lifetime()); } void SessionNavigation::requestAddToMenu(