diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 7433dbd9a..c8e5466b9 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -345,6 +345,24 @@ void UserData::setBotInfo(const MTPBotInfo &info) { const auto privacyChanged = (botInfo->privacyPolicyUrl != privacy); botInfo->privacyPolicyUrl = privacy; + if (const auto settings = d.vapp_settings()) { + const auto &data = settings->data(); + botInfo->botAppColorTitleDay = Ui::MaybeColorFromSerialized( + data.vheader_color()).value_or(QColor(0, 0, 0, 0)); + botInfo->botAppColorTitleNight = Ui::MaybeColorFromSerialized( + data.vheader_dark_color()).value_or(QColor(0, 0, 0, 0)); + botInfo->botAppColorBodyDay = Ui::MaybeColorFromSerialized( + data.vbackground_color()).value_or(QColor(0, 0, 0, 0)); + botInfo->botAppColorBodyNight = Ui::MaybeColorFromSerialized( + data.vbackground_dark_color()).value_or(QColor(0, 0, 0, 0)); + } else { + botInfo->botAppColorTitleDay + = botInfo->botAppColorTitleNight + = botInfo->botAppColorBodyDay + = botInfo->botAppColorBodyNight + = QColor(0, 0, 0, 0); + } + if (changedCommands || changedButton || privacyChanged) { owner().botCommandsChanged(this); } diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index 8dfc2b4f7..63f03549a 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -33,6 +33,11 @@ struct BotInfo { QString botMenuButtonUrl; QString privacyPolicyUrl; + QColor botAppColorTitleDay = QColor(0, 0, 0, 0); + QColor botAppColorTitleNight = QColor(0, 0, 0, 0); + QColor botAppColorBodyDay = QColor(0, 0, 0, 0); + QColor botAppColorBodyNight = QColor(0, 0, 0, 0); + QString startToken; Dialogs::EntryState inlineReturnTo; diff --git a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp index 17983983f..93fa4d389 100644 --- a/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp +++ b/Telegram/SourceFiles/inline_bots/bot_attach_web_view.cpp @@ -1423,7 +1423,23 @@ void WebViewInstance::started(uint64 queryId) { } Webview::ThemeParams WebViewInstance::botThemeParams() { - return Window::Theme::WebViewParams(); + auto result = Window::Theme::WebViewParams(); + if (const auto info = _bot->botInfo.get()) { + const auto night = Window::Theme::IsNightMode(); + const auto &title = night + ? info->botAppColorTitleNight + : info->botAppColorTitleDay; + const auto &body = night + ? info->botAppColorBodyNight + : info->botAppColorBodyDay; + if (title.alpha() == 255) { + result.titleBg = title; + } + if (body.alpha() == 255) { + result.bodyBg = body; + } + } + return result; } bool WebViewInstance::botHandleLocalUri(QString uri, bool keepOpen) { diff --git a/Telegram/SourceFiles/payments/ui/payments_panel.cpp b/Telegram/SourceFiles/payments/ui/payments_panel.cpp index 2bc023e8c..b0e1bcc0c 100644 --- a/Telegram/SourceFiles/payments/ui/payments_panel.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_panel.cpp @@ -550,7 +550,7 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) { _webview = std::make_unique( container, Webview::WindowConfig{ - .opaqueBg = params.opaqueBg, + .opaqueBg = params.bodyBg, .storageId = _delegate->panelWebviewStorageId(), }); @@ -919,7 +919,7 @@ void Panel::updateThemeParams(const Webview::ThemeParams ¶ms) { return; } _webview->window.updateTheme( - params.opaqueBg, + params.bodyBg, params.scrollBg, params.scrollBgOver, params.scrollBarBg, diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp index 9da6c01eb..7158f1e9f 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp @@ -366,23 +366,19 @@ Panel::Progress::Progress(QWidget *parent, Fn rect) st::paymentsLoading) { } -Panel::Panel( - const Webview::StorageId &storageId, - rpl::producer title, - object_ptr titleBadge, - not_null delegate, - MenuButtons menuButtons, - bool fullscreen, - bool allowClipboardRead) -: _storageId(storageId) -, _delegate(delegate) -, _menuButtons(menuButtons) +Panel::Panel(Args &&args) +: _storageId(args.storageId) +, _delegate(args.delegate) +, _menuButtons(args.menuButtons) , _widget(std::make_unique()) -, _fullscreen(fullscreen) -, _allowClipboardRead(allowClipboardRead) { +, _fullscreen(args.fullscreen) +, _allowClipboardRead(args.allowClipboardRead) { _widget->setWindowFlag(Qt::WindowStaysOnTopHint, false); _widget->setInnerSize(st::botWebViewPanelSize, true); + const auto params = _delegate->botThemeParams(); + updateColorOverrides(params); + _fullscreen.value( ) | rpl::start_with_next([=](bool fullscreen) { _widget->toggleFullScreen(fullscreen); @@ -426,8 +422,17 @@ Panel::Panel( }); }, _widget->lifetime()); - setTitle(std::move(title)); - _widget->setTitleBadge(std::move(titleBadge)); + setTitle(std::move(args.title)); + _widget->setTitleBadge(std::move(args.titleBadge)); + + if (!showWebview(args.url, params, std::move(args.bottom))) { + const auto available = Webview::Availability(); + if (available.error != Webview::Available::Error::None) { + showWebviewError(tr::lng_bot_no_webview(tr::now), available); + } else { + showCriticalError({ "Error: Could not initialize WebView." }); + } + } } Panel::~Panel() { @@ -679,13 +684,17 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) { _widget->showInner(std::move(outer)); _webviewParent = container; + _headerColorReceived = false; + _bodyColorReceived = false; + _bottomColorReceived = false; + updateColorOverrides(params); createWebviewBottom(); container->show(); _webview = std::make_unique( container, Webview::WindowConfig{ - .opaqueBg = params.opaqueBg, + .opaqueBg = params.bodyBg, .storageId = _storageId, }); const auto raw = &_webview->window; @@ -823,6 +832,8 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) { requestClipboardText(arguments); } else if (command == "web_app_set_header_color") { processHeaderColor(arguments); + } else if (command == "web_app_set_background_color") { + processBackgroundColor(arguments); } else if (command == "web_app_set_bottom_bar_color") { processBottomBarColor(arguments); } else if (command == "web_app_send_prepared_message") { @@ -1437,6 +1448,7 @@ void Panel::processSettingsButtonMessage(const QJsonObject &args) { } void Panel::processHeaderColor(const QJsonObject &args) { + _headerColorReceived = true; if (const auto color = ParseColor(args["color"].toString())) { _widget->overrideTitleColor(color); _headerColorLifetime.destroy(); @@ -1453,7 +1465,32 @@ void Panel::processHeaderColor(const QJsonObject &args) { } } +void Panel::processBackgroundColor(const QJsonObject &args) { + _bodyColorReceived = true; + if (const auto color = ParseColor(args["color"].toString())) { + _widget->overrideBodyColor(color); + _bodyColorLifetime.destroy(); + } else if (const auto color = LookupNamedColor( + args["color_key"].toString())) { + _widget->overrideBodyColor((*color)->c); + _bodyColorLifetime = style::PaletteChanged( + ) | rpl::start_with_next([=] { + _widget->overrideBodyColor((*color)->c); + }); + } else { + _widget->overrideBodyColor(std::nullopt); + _bodyColorLifetime.destroy(); + } + if (const auto raw = _bottomButtonsBg.get()) { + raw->update(); + } + if (const auto raw = _webviewBottom.get()) { + raw->update(); + } +} + void Panel::processBottomBarColor(const QJsonObject &args) { + _bottomColorReceived = true; if (const auto color = ParseColor(args["color"].toString())) { _widget->overrideBottomBarColor(color); _bottomBarColor = color; @@ -1462,7 +1499,7 @@ void Panel::processBottomBarColor(const QJsonObject &args) { args["color_key"].toString())) { _widget->overrideBottomBarColor((*color)->c); _bottomBarColor = (*color)->c; - _headerColorLifetime = style::PaletteChanged( + _bottomBarColorLifetime = style::PaletteChanged( ) | rpl::start_with_next([=] { _widget->overrideBottomBarColor((*color)->c); _bottomBarColor = (*color)->c; @@ -1470,7 +1507,7 @@ void Panel::processBottomBarColor(const QJsonObject &args) { } else { _widget->overrideBottomBarColor(std::nullopt); _bottomBarColor = std::nullopt; - _headerColorLifetime.destroy(); + _bottomBarColorLifetime.destroy(); } if (const auto raw = _bottomButtonsBg.get()) { raw->update(); @@ -1596,13 +1633,15 @@ void Panel::layoutButtons() { } else if (_bottomButtonsBg) { _bottomButtonsBg->hide(); } - _footerHeight = _layerShown + const auto footer = _layerShown ? 0 : any ? _bottomButtonsBg->height() : _fullscreen.current() ? 0 : _webviewBottom->height(); + _widget->setBottomBarHeight((!_layerShown && any) ? footer : 0); + _footerHeight = footer; } void Panel::showBox(object_ptr box) { @@ -1707,11 +1746,12 @@ void Panel::showCriticalError(const TextWithEntities &text) { } void Panel::updateThemeParams(const Webview::ThemeParams ¶ms) { + updateColorOverrides(params); if (!_webview || !_webview->window.widget()) { return; } _webview->window.updateTheme( - params.opaqueBg, + params.bodyBg, params.scrollBg, params.scrollBgOver, params.scrollBarBg, @@ -1719,6 +1759,15 @@ void Panel::updateThemeParams(const Webview::ThemeParams ¶ms) { postEvent("theme_changed", "{\"theme_params\": " + params.json + "}"); } +void Panel::updateColorOverrides(const Webview::ThemeParams ¶ms) { + if (!_headerColorReceived && params.titleBg.alpha() == 255) { + _widget->overrideTitleColor(params.titleBg); + } + if (!_bodyColorReceived && params.bodyBg.alpha() == 255) { + _widget->overrideBodyColor(params.bodyBg); + } +} + void Panel::invoiceClosed(const QString &slug, const QString &status) { if (!_webview || !_webview->window.widget()) { return; @@ -1802,27 +1851,7 @@ rpl::lifetime &Panel::lifetime() { } std::unique_ptr Show(Args &&args) { - auto result = std::make_unique( - args.storageId, - std::move(args.title), - std::move(args.titleBadge), - args.delegate, - args.menuButtons, - args.fullscreen, - args.allowClipboardRead); - const auto params = args.delegate->botThemeParams(); - if (!result->showWebview(args.url, params, std::move(args.bottom))) { - const auto available = Webview::Availability(); - if (available.error != Webview::Available::Error::None) { - result->showWebviewError( - tr::lng_bot_no_webview(tr::now), - available); - } else { - result->showCriticalError({ - "Error: Could not initialize WebView." }); - } - } - return result; + return std::make_unique(std::move(args)); } } // namespace Ui::BotWebView diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h index 1f15dac3c..bff1175ce 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.h @@ -87,16 +87,21 @@ public: virtual void botClose() = 0; }; +struct Args { + QString url; + Webview::StorageId storageId; + rpl::producer title; + object_ptr titleBadge = { nullptr }; + rpl::producer bottom; + not_null delegate; + MenuButtons menuButtons; + bool fullscreen = false; + bool allowClipboardRead = false; +}; + class Panel final : public base::has_weak_ptr { public: - Panel( - const Webview::StorageId &storageId, - rpl::producer title, - object_ptr titleBadge, - not_null delegate, - MenuButtons menuButtons, - bool fullscreen, - bool allowClipboardRead); + explicit Panel(Args &&args); ~Panel(); void requestActivate(); @@ -148,6 +153,7 @@ private: void processBackButtonMessage(const QJsonObject &args); void processSettingsButtonMessage(const QJsonObject &args); void processHeaderColor(const QJsonObject &args); + void processBackgroundColor(const QJsonObject &args); void processBottomBarColor(const QJsonObject &args); void openTgLink(const QJsonObject &args); void openExternalLink(const QJsonObject &args); @@ -171,6 +177,8 @@ private: void sendContentSafeArea(); void sendFullScreen(); + void updateColorOverrides(const Webview::ThemeParams ¶ms); + using EventData = std::variant; void postEvent(const QString &event); void postEvent(const QString &event, EventData data); @@ -201,29 +209,22 @@ private: rpl::event_stream<> _themeUpdateForced; std::optional _bottomBarColor; rpl::lifetime _headerColorLifetime; + rpl::lifetime _bodyColorLifetime; rpl::lifetime _bottomBarColorLifetime; rpl::variable _fullscreen = false; - bool _layerShown = false; - bool _webviewProgress = false; - bool _themeUpdateScheduled = false; - bool _hiddenForPayment = false; - bool _closeWithConfirmationScheduled = false; - bool _allowClipboardRead = false; - bool _inBlockingRequest = false; + bool _layerShown : 1 = false; + bool _webviewProgress : 1 = false; + bool _themeUpdateScheduled : 1 = false; + bool _hiddenForPayment : 1 = false; + bool _closeWithConfirmationScheduled : 1 = false; + bool _allowClipboardRead : 1 = false; + bool _inBlockingRequest : 1 = false; + bool _headerColorReceived : 1 = false; + bool _bodyColorReceived : 1 = false; + bool _bottomColorReceived : 1 = false; }; -struct Args { - QString url; - Webview::StorageId storageId; - rpl::producer title; - object_ptr titleBadge = { nullptr }; - rpl::producer bottom; - not_null delegate; - MenuButtons menuButtons; - bool fullscreen = false; - bool allowClipboardRead = false; -}; [[nodiscard]] std::unique_ptr Show(Args &&args); } // namespace Ui::BotWebView diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 899534d9e..dcdbfcccd 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -1539,7 +1539,8 @@ bool ReadPaletteValues(const QByteArray &content, Fnc, + .bodyBg = st::windowBg->c, + .titleBg = QColor(0, 0, 0, 0), .scrollBg = st::scrollBg->c, .scrollBgOver = st::scrollBgOver->c, .scrollBarBg = st::scrollBarBg->c, diff --git a/Telegram/lib_webview b/Telegram/lib_webview index efc48237b..095babf23 160000 --- a/Telegram/lib_webview +++ b/Telegram/lib_webview @@ -1 +1 @@ -Subproject commit efc48237bcaf269b57c8a37539e11e1887e1f3cf +Subproject commit 095babf234736e053bdbbc3dc15bc042a40c45b4