From a35092f0121617a4bed5e57c0ab74ad5ea4131aa Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 9 Sep 2024 13:29:00 +0400 Subject: [PATCH] Support second button in web apps. --- .../SourceFiles/payments/ui/payments.style | 6 +- .../ui/chat/attach/attach_bot_webview.cpp | 319 +++++++++++++----- .../ui/chat/attach/attach_bot_webview.h | 26 +- .../window/themes/window_theme.cpp | 1 + Telegram/lib_ui | 2 +- 5 files changed, 258 insertions(+), 96 deletions(-) diff --git a/Telegram/SourceFiles/payments/ui/payments.style b/Telegram/SourceFiles/payments/ui/payments.style index 86138bc7a..fd9e57bab 100644 --- a/Telegram/SourceFiles/payments/ui/payments.style +++ b/Telegram/SourceFiles/payments/ui/payments.style @@ -141,10 +141,12 @@ paymentsLoading: InfiniteRadialAnimation(defaultInfiniteRadialAnimation) { } botWebViewPanelSize: size(384px, 694px); +botWebViewBottomPadding: margins(12px, 12px, 12px, 12px); +botWebViewBottomSkip: point(12px, 8px); botWebViewBottomButton: RoundButton(paymentsPanelSubmit) { - height: 56px; + height: 40px; style: TextStyle(defaultTextStyle) { font: boxButtonFont; } - textTop: 19px; + textTop: 11px; } diff --git a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp index 9ff122833..3a39e23af 100644 --- a/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp +++ b/Telegram/SourceFiles/ui/chat/attach/attach_bot_webview.cpp @@ -48,6 +48,26 @@ constexpr auto kProgressOpacity = 0.3; constexpr auto kLightnessThreshold = 128; constexpr auto kLightnessDelta = 32; +struct ButtonArgs { + bool isActive = false; + bool isVisible = false; + bool isProgressVisible = false; + QString text; +}; + +[[nodiscard]] RectPart ParsePosition(const QString &position) { + if (position == u"left"_q) { + return RectPart::Left; + } else if (position == u"top"_q) { + return RectPart::Top; + } else if (position == u"right"_q) { + return RectPart::Right; + } else if (position == u"bottom"_q) { + return RectPart::Bottom; + } + return RectPart::Left; +} + [[nodiscard]] QJsonObject ParseMethodArgs(const QString &json) { if (json.isEmpty()) { return {}; @@ -99,6 +119,15 @@ constexpr auto kLightnessDelta = 32; alpha); } +[[nodiscard]] const style::color *LookupNamedColor(const QString &key) { + if (key == u"secondary_bg_color"_q) { + return &st::boxDividerBg; + } else if (key == u"bottom_bar_bg_color"_q) { + return &st::windowBg; + } + return nullptr; +} + } // namespace class Panel::Button final : public RippleButton { @@ -107,8 +136,11 @@ public: ~Button(); void updateBg(QColor bg); + void updateBg(not_null paletteBg); void updateFg(QColor fg); - void updateArgs(MainButtonArgs &&args); + void updateFg(not_null paletteFg); + + void updateArgs(ButtonArgs &&args); private: void paintEvent(QPaintEvent *e) override; @@ -128,6 +160,9 @@ private: style::owned_color _bg; RoundRect _roundRect; + rpl::lifetime _bgLifetime; + rpl::lifetime _fgLifetime; + }; struct Panel::Progress { @@ -171,15 +206,33 @@ Panel::Button::~Button() = default; void Panel::Button::updateBg(QColor bg) { _bg.update(bg); _roundRect.setColor(_bg.color()); + _bgLifetime.destroy(); update(); } +void Panel::Button::updateBg(not_null paletteBg) { + updateBg((*paletteBg)->c); + _bgLifetime = style::PaletteChanged( + ) | rpl::start_with_next([=] { + updateBg((*paletteBg)->c); + }); +} + void Panel::Button::updateFg(QColor fg) { _fg = fg; + _fgLifetime.destroy(); update(); } -void Panel::Button::updateArgs(MainButtonArgs &&args) { +void Panel::Button::updateFg(not_null paletteFg) { + updateFg((*paletteFg)->c); + _fgLifetime = style::PaletteChanged( + ) | rpl::start_with_next([=] { + updateFg((*paletteFg)->c); + }); +} + +void Panel::Button::updateArgs(ButtonArgs &&args) { _textFull = std::move(args.text); setDisabled(!args.isActive); setPointerCursor(false); @@ -266,10 +319,7 @@ void Panel::Button::setupProgressGeometry() { void Panel::Button::paintEvent(QPaintEvent *e) { Painter p(this); - _roundRect.paintSomeRounded( - p, - rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }), - RectPart::BottomLeft | RectPart::BottomRight); + _roundRect.paint(p, rect()); if (!isDisabled()) { const auto ripple = ResolveRipple(_bg.color()->c); @@ -292,12 +342,7 @@ void Panel::Button::paintEvent(QPaintEvent *e) { } QImage Panel::Button::prepareRippleMask() const { - return RippleAnimation::MaskByDrawer(size(), false, [&](QPainter &p) { - p.drawRoundedRect( - rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }), - st::callRadius, - st::callRadius); - }); + return RippleAnimation::RoundRectMask(size(), st::callRadius); } QPoint Panel::Button::prepareRippleStartPosition() const { @@ -599,7 +644,7 @@ void Panel::createWebviewBottom() { ) | rpl::start_with_next([=](QRect inner, int height) { bottom->move(inner.x(), inner.y() + inner.height() - height); bottom->resizeToWidth(inner.width()); - updateFooterHeight(); + layoutButtons(); }, bottom->lifetime()); } @@ -633,7 +678,9 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) { } if (_webviewBottom.get() == bottom) { _webviewBottom = nullptr; + _secondaryButton = nullptr; _mainButton = nullptr; + _bottomButtonsBg = nullptr; } }); if (!raw->widget()) { @@ -655,7 +702,6 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) { }); }); - updateFooterHeight(); rpl::combine( container->geometryValue(), _footerHeight.value() @@ -681,7 +727,9 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) { } else if (command == "web_app_switch_inline_query") { switchInlineQueryMessage(arguments); } else if (command == "web_app_setup_main_button") { - processMainButtonMessage(arguments); + processButtonMessage(_mainButton, arguments); + } else if (command == "web_app_setup_secondary_button") { + processButtonMessage(_secondaryButton, arguments); } else if (command == "web_app_setup_back_button") { processBackButtonMessage(arguments); } else if (command == "web_app_setup_settings_button") { @@ -714,6 +762,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_bottom_bar_color") { + processBottomBarColor(arguments); } else if (command == "share_score") { _delegate->botHandleMenuButton(MenuButton::ShareGame); } @@ -745,6 +795,7 @@ postEvent: function(eventType, eventData) { return false; } + layoutButtons(); setupProgressGeometry(); base::qt_signal_producer( @@ -1096,12 +1147,12 @@ void Panel::requestClipboardText(const QJsonObject &args) { } bool Panel::allowOpenLink() const { - const auto now = crl::now(); - if (_mainButtonLastClick - && _mainButtonLastClick + kProcessClickTimeout >= now) { - _mainButtonLastClick = 0; - return true; - } + //const auto now = crl::now(); + //if (_mainButtonLastClick + // && _mainButtonLastClick + kProcessClickTimeout >= now) { + // _mainButtonLastClick = 0; + // return true; + //} return true; } @@ -1109,12 +1160,12 @@ bool Panel::allowClipboardQuery() const { if (!_allowClipboardRead) { return false; } - const auto now = crl::now(); - if (_mainButtonLastClick - && _mainButtonLastClick + kProcessClickTimeout >= now) { - _mainButtonLastClick = 0; - return true; - } + //const auto now = crl::now(); + //if (_mainButtonLastClick + // && _mainButtonLastClick + kProcessClickTimeout >= now) { + // _mainButtonLastClick = 0; + // return true; + //} return true; } @@ -1157,14 +1208,16 @@ void Panel::setupClosingBehaviour(const QJsonObject &args) { _closeNeedConfirmation = args["need_confirmation"].toBool(); } -void Panel::processMainButtonMessage(const QJsonObject &args) { +void Panel::processButtonMessage( + std::unique_ptr