mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Support second button in web apps.
This commit is contained in:
parent
49ee7ee52b
commit
a35092f012
5 changed files with 258 additions and 96 deletions
|
@ -141,10 +141,12 @@ paymentsLoading: InfiniteRadialAnimation(defaultInfiniteRadialAnimation) {
|
||||||
}
|
}
|
||||||
|
|
||||||
botWebViewPanelSize: size(384px, 694px);
|
botWebViewPanelSize: size(384px, 694px);
|
||||||
|
botWebViewBottomPadding: margins(12px, 12px, 12px, 12px);
|
||||||
|
botWebViewBottomSkip: point(12px, 8px);
|
||||||
botWebViewBottomButton: RoundButton(paymentsPanelSubmit) {
|
botWebViewBottomButton: RoundButton(paymentsPanelSubmit) {
|
||||||
height: 56px;
|
height: 40px;
|
||||||
style: TextStyle(defaultTextStyle) {
|
style: TextStyle(defaultTextStyle) {
|
||||||
font: boxButtonFont;
|
font: boxButtonFont;
|
||||||
}
|
}
|
||||||
textTop: 19px;
|
textTop: 11px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,26 @@ constexpr auto kProgressOpacity = 0.3;
|
||||||
constexpr auto kLightnessThreshold = 128;
|
constexpr auto kLightnessThreshold = 128;
|
||||||
constexpr auto kLightnessDelta = 32;
|
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) {
|
[[nodiscard]] QJsonObject ParseMethodArgs(const QString &json) {
|
||||||
if (json.isEmpty()) {
|
if (json.isEmpty()) {
|
||||||
return {};
|
return {};
|
||||||
|
@ -99,6 +119,15 @@ constexpr auto kLightnessDelta = 32;
|
||||||
alpha);
|
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
|
} // namespace
|
||||||
|
|
||||||
class Panel::Button final : public RippleButton {
|
class Panel::Button final : public RippleButton {
|
||||||
|
@ -107,8 +136,11 @@ public:
|
||||||
~Button();
|
~Button();
|
||||||
|
|
||||||
void updateBg(QColor bg);
|
void updateBg(QColor bg);
|
||||||
|
void updateBg(not_null<const style::color*> paletteBg);
|
||||||
void updateFg(QColor fg);
|
void updateFg(QColor fg);
|
||||||
void updateArgs(MainButtonArgs &&args);
|
void updateFg(not_null<const style::color*> paletteFg);
|
||||||
|
|
||||||
|
void updateArgs(ButtonArgs &&args);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
|
@ -128,6 +160,9 @@ private:
|
||||||
style::owned_color _bg;
|
style::owned_color _bg;
|
||||||
RoundRect _roundRect;
|
RoundRect _roundRect;
|
||||||
|
|
||||||
|
rpl::lifetime _bgLifetime;
|
||||||
|
rpl::lifetime _fgLifetime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Panel::Progress {
|
struct Panel::Progress {
|
||||||
|
@ -171,15 +206,33 @@ Panel::Button::~Button() = default;
|
||||||
void Panel::Button::updateBg(QColor bg) {
|
void Panel::Button::updateBg(QColor bg) {
|
||||||
_bg.update(bg);
|
_bg.update(bg);
|
||||||
_roundRect.setColor(_bg.color());
|
_roundRect.setColor(_bg.color());
|
||||||
|
_bgLifetime.destroy();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Panel::Button::updateBg(not_null<const style::color*> paletteBg) {
|
||||||
|
updateBg((*paletteBg)->c);
|
||||||
|
_bgLifetime = style::PaletteChanged(
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
updateBg((*paletteBg)->c);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void Panel::Button::updateFg(QColor fg) {
|
void Panel::Button::updateFg(QColor fg) {
|
||||||
_fg = fg;
|
_fg = fg;
|
||||||
|
_fgLifetime.destroy();
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::Button::updateArgs(MainButtonArgs &&args) {
|
void Panel::Button::updateFg(not_null<const style::color*> 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);
|
_textFull = std::move(args.text);
|
||||||
setDisabled(!args.isActive);
|
setDisabled(!args.isActive);
|
||||||
setPointerCursor(false);
|
setPointerCursor(false);
|
||||||
|
@ -266,10 +319,7 @@ void Panel::Button::setupProgressGeometry() {
|
||||||
void Panel::Button::paintEvent(QPaintEvent *e) {
|
void Panel::Button::paintEvent(QPaintEvent *e) {
|
||||||
Painter p(this);
|
Painter p(this);
|
||||||
|
|
||||||
_roundRect.paintSomeRounded(
|
_roundRect.paint(p, rect());
|
||||||
p,
|
|
||||||
rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }),
|
|
||||||
RectPart::BottomLeft | RectPart::BottomRight);
|
|
||||||
|
|
||||||
if (!isDisabled()) {
|
if (!isDisabled()) {
|
||||||
const auto ripple = ResolveRipple(_bg.color()->c);
|
const auto ripple = ResolveRipple(_bg.color()->c);
|
||||||
|
@ -292,12 +342,7 @@ void Panel::Button::paintEvent(QPaintEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QImage Panel::Button::prepareRippleMask() const {
|
QImage Panel::Button::prepareRippleMask() const {
|
||||||
return RippleAnimation::MaskByDrawer(size(), false, [&](QPainter &p) {
|
return RippleAnimation::RoundRectMask(size(), st::callRadius);
|
||||||
p.drawRoundedRect(
|
|
||||||
rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }),
|
|
||||||
st::callRadius,
|
|
||||||
st::callRadius);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint Panel::Button::prepareRippleStartPosition() const {
|
QPoint Panel::Button::prepareRippleStartPosition() const {
|
||||||
|
@ -599,7 +644,7 @@ void Panel::createWebviewBottom() {
|
||||||
) | rpl::start_with_next([=](QRect inner, int height) {
|
) | rpl::start_with_next([=](QRect inner, int height) {
|
||||||
bottom->move(inner.x(), inner.y() + inner.height() - height);
|
bottom->move(inner.x(), inner.y() + inner.height() - height);
|
||||||
bottom->resizeToWidth(inner.width());
|
bottom->resizeToWidth(inner.width());
|
||||||
updateFooterHeight();
|
layoutButtons();
|
||||||
}, bottom->lifetime());
|
}, bottom->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,7 +678,9 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
||||||
}
|
}
|
||||||
if (_webviewBottom.get() == bottom) {
|
if (_webviewBottom.get() == bottom) {
|
||||||
_webviewBottom = nullptr;
|
_webviewBottom = nullptr;
|
||||||
|
_secondaryButton = nullptr;
|
||||||
_mainButton = nullptr;
|
_mainButton = nullptr;
|
||||||
|
_bottomButtonsBg = nullptr;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!raw->widget()) {
|
if (!raw->widget()) {
|
||||||
|
@ -655,7 +702,6 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
updateFooterHeight();
|
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
container->geometryValue(),
|
container->geometryValue(),
|
||||||
_footerHeight.value()
|
_footerHeight.value()
|
||||||
|
@ -681,7 +727,9 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
||||||
} else if (command == "web_app_switch_inline_query") {
|
} else if (command == "web_app_switch_inline_query") {
|
||||||
switchInlineQueryMessage(arguments);
|
switchInlineQueryMessage(arguments);
|
||||||
} else if (command == "web_app_setup_main_button") {
|
} 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") {
|
} else if (command == "web_app_setup_back_button") {
|
||||||
processBackButtonMessage(arguments);
|
processBackButtonMessage(arguments);
|
||||||
} else if (command == "web_app_setup_settings_button") {
|
} else if (command == "web_app_setup_settings_button") {
|
||||||
|
@ -714,6 +762,8 @@ bool Panel::createWebview(const Webview::ThemeParams ¶ms) {
|
||||||
requestClipboardText(arguments);
|
requestClipboardText(arguments);
|
||||||
} else if (command == "web_app_set_header_color") {
|
} else if (command == "web_app_set_header_color") {
|
||||||
processHeaderColor(arguments);
|
processHeaderColor(arguments);
|
||||||
|
} else if (command == "web_app_set_bottom_bar_color") {
|
||||||
|
processBottomBarColor(arguments);
|
||||||
} else if (command == "share_score") {
|
} else if (command == "share_score") {
|
||||||
_delegate->botHandleMenuButton(MenuButton::ShareGame);
|
_delegate->botHandleMenuButton(MenuButton::ShareGame);
|
||||||
}
|
}
|
||||||
|
@ -745,6 +795,7 @@ postEvent: function(eventType, eventData) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layoutButtons();
|
||||||
setupProgressGeometry();
|
setupProgressGeometry();
|
||||||
|
|
||||||
base::qt_signal_producer(
|
base::qt_signal_producer(
|
||||||
|
@ -1096,12 +1147,12 @@ void Panel::requestClipboardText(const QJsonObject &args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Panel::allowOpenLink() const {
|
bool Panel::allowOpenLink() const {
|
||||||
const auto now = crl::now();
|
//const auto now = crl::now();
|
||||||
if (_mainButtonLastClick
|
//if (_mainButtonLastClick
|
||||||
&& _mainButtonLastClick + kProcessClickTimeout >= now) {
|
// && _mainButtonLastClick + kProcessClickTimeout >= now) {
|
||||||
_mainButtonLastClick = 0;
|
// _mainButtonLastClick = 0;
|
||||||
return true;
|
// return true;
|
||||||
}
|
//}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1109,12 +1160,12 @@ bool Panel::allowClipboardQuery() const {
|
||||||
if (!_allowClipboardRead) {
|
if (!_allowClipboardRead) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto now = crl::now();
|
//const auto now = crl::now();
|
||||||
if (_mainButtonLastClick
|
//if (_mainButtonLastClick
|
||||||
&& _mainButtonLastClick + kProcessClickTimeout >= now) {
|
// && _mainButtonLastClick + kProcessClickTimeout >= now) {
|
||||||
_mainButtonLastClick = 0;
|
// _mainButtonLastClick = 0;
|
||||||
return true;
|
// return true;
|
||||||
}
|
//}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1157,14 +1208,16 @@ void Panel::setupClosingBehaviour(const QJsonObject &args) {
|
||||||
_closeNeedConfirmation = args["need_confirmation"].toBool();
|
_closeNeedConfirmation = args["need_confirmation"].toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::processMainButtonMessage(const QJsonObject &args) {
|
void Panel::processButtonMessage(
|
||||||
|
std::unique_ptr<Button> &button,
|
||||||
|
const QJsonObject &args) {
|
||||||
if (args.isEmpty()) {
|
if (args.isEmpty()) {
|
||||||
_delegate->botClose();
|
_delegate->botClose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto shown = [&] {
|
const auto shown = [&] {
|
||||||
return _mainButton && !_mainButton->isHidden();
|
return button && !button->isHidden();
|
||||||
};
|
};
|
||||||
const auto wasShown = shown();
|
const auto wasShown = shown();
|
||||||
const auto guard = gsl::finally([&] {
|
const auto guard = gsl::finally([&] {
|
||||||
|
@ -1175,42 +1228,38 @@ void Panel::processMainButtonMessage(const QJsonObject &args) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!_mainButton) {
|
const auto text = args["text"].toString().trimmed();
|
||||||
if (args["is_visible"].toBool()) {
|
const auto visible = args["is_visible"].toBool() && !text.isEmpty();
|
||||||
createMainButton();
|
if (!button) {
|
||||||
|
if (visible) {
|
||||||
|
createButton(button);
|
||||||
|
_bottomButtonsBg->show();
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto bg = ParseColor(args["color"].toString())) {
|
if (const auto bg = ParseColor(args["color"].toString())) {
|
||||||
_mainButton->updateBg(*bg);
|
button->updateBg(*bg);
|
||||||
_bgLifetime.destroy();
|
|
||||||
} else {
|
} else {
|
||||||
_mainButton->updateBg(st::windowBgActive->c);
|
button->updateBg(&st::windowBgActive);
|
||||||
_bgLifetime = style::PaletteChanged(
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
_mainButton->updateBg(st::windowBgActive->c);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto fg = ParseColor(args["text_color"].toString())) {
|
if (const auto fg = ParseColor(args["text_color"].toString())) {
|
||||||
_mainButton->updateFg(*fg);
|
button->updateFg(*fg);
|
||||||
_fgLifetime.destroy();
|
|
||||||
} else {
|
} else {
|
||||||
_mainButton->updateFg(st::windowFgActive->c);
|
button->updateFg(&st::windowFgActive);
|
||||||
_fgLifetime = style::PaletteChanged(
|
|
||||||
) | rpl::start_with_next([=] {
|
|
||||||
_mainButton->updateFg(st::windowFgActive->c);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_mainButton->updateArgs({
|
button->updateArgs({
|
||||||
.isActive = args["is_active"].toBool(),
|
.isActive = args["is_active"].toBool(),
|
||||||
.isVisible = args["is_visible"].toBool(),
|
.isVisible = visible,
|
||||||
.isProgressVisible = args["is_progress_visible"].toBool(),
|
.isProgressVisible = args["is_progress_visible"].toBool(),
|
||||||
.text = args["text"].toString(),
|
.text = args["text"].toString(),
|
||||||
});
|
});
|
||||||
|
if (button.get() == _secondaryButton.get()) {
|
||||||
|
_secondaryPosition = ParsePosition(args["position"].toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::processBackButtonMessage(const QJsonObject &args) {
|
void Panel::processBackButtonMessage(const QJsonObject &args) {
|
||||||
|
@ -1225,11 +1274,12 @@ void Panel::processHeaderColor(const QJsonObject &args) {
|
||||||
if (const auto color = ParseColor(args["color"].toString())) {
|
if (const auto color = ParseColor(args["color"].toString())) {
|
||||||
_widget->overrideTitleColor(color);
|
_widget->overrideTitleColor(color);
|
||||||
_headerColorLifetime.destroy();
|
_headerColorLifetime.destroy();
|
||||||
} else if (args["color_key"].toString() == u"secondary_bg_color"_q) {
|
} else if (const auto color = LookupNamedColor(
|
||||||
_widget->overrideTitleColor(st::boxDividerBg->c);
|
args["color_key"].toString())) {
|
||||||
|
_widget->overrideTitleColor((*color)->c);
|
||||||
_headerColorLifetime = style::PaletteChanged(
|
_headerColorLifetime = style::PaletteChanged(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
_widget->overrideTitleColor(st::boxDividerBg->c);
|
_widget->overrideTitleColor((*color)->c);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
_widget->overrideTitleColor(std::nullopt);
|
_widget->overrideTitleColor(std::nullopt);
|
||||||
|
@ -1237,37 +1287,146 @@ void Panel::processHeaderColor(const QJsonObject &args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::createMainButton() {
|
void Panel::processBottomBarColor(const QJsonObject &args) {
|
||||||
_mainButton = std::make_unique<Button>(
|
if (const auto color = ParseColor(args["color"].toString())) {
|
||||||
_widget.get(),
|
_widget->overrideBottomBarColor(color);
|
||||||
st::botWebViewBottomButton);
|
_bottomBarColor = color;
|
||||||
const auto button = _mainButton.get();
|
_bottomBarColorLifetime.destroy();
|
||||||
|
} else if (const auto color = LookupNamedColor(
|
||||||
button->setClickedCallback([=] {
|
args["color_key"].toString())) {
|
||||||
if (!button->isDisabled()) {
|
_widget->overrideBottomBarColor((*color)->c);
|
||||||
postEvent("main_button_pressed");
|
_bottomBarColor = (*color)->c;
|
||||||
_mainButtonLastClick = crl::now();
|
_headerColorLifetime = style::PaletteChanged(
|
||||||
}
|
) | rpl::start_with_next([=] {
|
||||||
});
|
_widget->overrideBottomBarColor((*color)->c);
|
||||||
button->hide();
|
_bottomBarColor = (*color)->c;
|
||||||
|
});
|
||||||
rpl::combine(
|
} else {
|
||||||
_webviewParent->geometryValue() | rpl::map([=] {
|
_widget->overrideBottomBarColor(std::nullopt);
|
||||||
return _widget->innerGeometry();
|
_bottomBarColor = std::nullopt;
|
||||||
}),
|
_headerColorLifetime.destroy();
|
||||||
button->shownValue(),
|
}
|
||||||
button->heightValue()
|
if (const auto raw = _bottomButtonsBg.get()) {
|
||||||
) | rpl::start_with_next([=](QRect inner, bool shown, int height) {
|
raw->update();
|
||||||
button->move(inner.x(), inner.y() + inner.height() - height);
|
}
|
||||||
button->resizeToWidth(inner.width());
|
|
||||||
_webviewBottom->setVisible(!shown);
|
|
||||||
updateFooterHeight();
|
|
||||||
}, button->lifetime());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::updateFooterHeight() {
|
void Panel::createButton(std::unique_ptr<Button> &button) {
|
||||||
_footerHeight = (_mainButton && !_mainButton->isHidden())
|
if (!_bottomButtonsBg) {
|
||||||
? _mainButton->height()
|
_bottomButtonsBg = std::make_unique<RpWidget>(_widget.get());
|
||||||
|
|
||||||
|
const auto raw = _bottomButtonsBg.get();
|
||||||
|
raw->paintRequest() | rpl::start_with_next([=] {
|
||||||
|
auto p = QPainter(raw);
|
||||||
|
auto hq = PainterHighQualityEnabler(p);
|
||||||
|
p.setPen(Qt::NoPen);
|
||||||
|
p.setBrush(_bottomBarColor.value_or(st::windowBg->c));
|
||||||
|
p.drawRoundedRect(
|
||||||
|
raw->rect().marginsAdded({ 0, 2 * st::callRadius, 0, 0 }),
|
||||||
|
st::callRadius,
|
||||||
|
st::callRadius);
|
||||||
|
}, raw->lifetime());
|
||||||
|
}
|
||||||
|
button = std::make_unique<Button>(
|
||||||
|
_bottomButtonsBg.get(),
|
||||||
|
st::botWebViewBottomButton);
|
||||||
|
const auto raw = button.get();
|
||||||
|
|
||||||
|
raw->setClickedCallback([=] {
|
||||||
|
if (!raw->isDisabled()) {
|
||||||
|
if (raw == _mainButton.get()) {
|
||||||
|
postEvent("main_button_pressed");
|
||||||
|
} else if (raw == _secondaryButton.get()) {
|
||||||
|
postEvent("secondary_button_pressed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
raw->hide();
|
||||||
|
|
||||||
|
rpl::combine(
|
||||||
|
raw->shownValue(),
|
||||||
|
raw->heightValue()
|
||||||
|
) | rpl::start_with_next([=] {
|
||||||
|
layoutButtons();
|
||||||
|
}, raw->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Panel::layoutButtons() {
|
||||||
|
const auto inner = _widget->innerGeometry();
|
||||||
|
const auto shown = [](std::unique_ptr<Button> &button) {
|
||||||
|
return button && !button->isHidden();
|
||||||
|
};
|
||||||
|
const auto any = shown(_mainButton) || shown(_secondaryButton);
|
||||||
|
_webviewBottom->setVisible(!any);
|
||||||
|
if (any) {
|
||||||
|
_bottomButtonsBg->show();
|
||||||
|
|
||||||
|
const auto one = shown(_mainButton)
|
||||||
|
? _mainButton.get()
|
||||||
|
: _secondaryButton.get();
|
||||||
|
const auto both = shown(_mainButton) && shown(_secondaryButton);
|
||||||
|
const auto vertical = both
|
||||||
|
&& ((_secondaryPosition == RectPart::Top)
|
||||||
|
|| (_secondaryPosition == RectPart::Bottom));
|
||||||
|
const auto padding = st::botWebViewBottomPadding;
|
||||||
|
const auto height = padding.top()
|
||||||
|
+ (vertical
|
||||||
|
? (_mainButton->height()
|
||||||
|
+ st::botWebViewBottomSkip.y()
|
||||||
|
+ _secondaryButton->height())
|
||||||
|
: one->height())
|
||||||
|
+ padding.bottom();
|
||||||
|
_bottomButtonsBg->setGeometry(
|
||||||
|
inner.x(),
|
||||||
|
inner.y() + inner.height() - height,
|
||||||
|
inner.width(),
|
||||||
|
height);
|
||||||
|
auto left = padding.left();
|
||||||
|
auto bottom = height - padding.bottom();
|
||||||
|
auto available = inner.width() - padding.left() - padding.right();
|
||||||
|
if (!both) {
|
||||||
|
one->resizeToWidth(available);
|
||||||
|
one->move(left, bottom - one->height());
|
||||||
|
} else if (_secondaryPosition == RectPart::Top) {
|
||||||
|
_mainButton->resizeToWidth(available);
|
||||||
|
bottom -= _mainButton->height();
|
||||||
|
_mainButton->move(left, bottom);
|
||||||
|
bottom -= st::botWebViewBottomSkip.y();
|
||||||
|
_secondaryButton->resizeToWidth(available);
|
||||||
|
bottom -= _secondaryButton->height();
|
||||||
|
_secondaryButton->move(left, bottom);
|
||||||
|
} else if (_secondaryPosition == RectPart::Bottom) {
|
||||||
|
_secondaryButton->resizeToWidth(available);
|
||||||
|
bottom -= _secondaryButton->height();
|
||||||
|
_secondaryButton->move(left, bottom);
|
||||||
|
bottom -= st::botWebViewBottomSkip.y();
|
||||||
|
_mainButton->resizeToWidth(available);
|
||||||
|
bottom -= _mainButton->height();
|
||||||
|
_mainButton->move(left, bottom);
|
||||||
|
} else if (_secondaryPosition == RectPart::Left) {
|
||||||
|
available = (available - st::botWebViewBottomSkip.x()) / 2;
|
||||||
|
_secondaryButton->resizeToWidth(available);
|
||||||
|
bottom -= _secondaryButton->height();
|
||||||
|
_secondaryButton->move(left, bottom);
|
||||||
|
_mainButton->resizeToWidth(available);
|
||||||
|
_mainButton->move(
|
||||||
|
inner.width() - padding.right() - available,
|
||||||
|
bottom);
|
||||||
|
} else {
|
||||||
|
available = (available - st::botWebViewBottomSkip.x()) / 2;
|
||||||
|
_mainButton->resizeToWidth(available);
|
||||||
|
bottom -= _mainButton->height();
|
||||||
|
_mainButton->move(left, bottom);
|
||||||
|
_secondaryButton->resizeToWidth(available);
|
||||||
|
_secondaryButton->move(
|
||||||
|
inner.width() - padding.right() - available,
|
||||||
|
bottom);
|
||||||
|
}
|
||||||
|
} else if (_bottomButtonsBg) {
|
||||||
|
_bottomButtonsBg->hide();
|
||||||
|
}
|
||||||
|
_footerHeight = any
|
||||||
|
? _bottomButtonsBg->height()
|
||||||
: _webviewBottom->height();
|
: _webviewBottom->height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/object_ptr.h"
|
#include "base/object_ptr.h"
|
||||||
#include "base/weak_ptr.h"
|
#include "base/weak_ptr.h"
|
||||||
#include "base/flags.h"
|
#include "base/flags.h"
|
||||||
|
#include "ui/rect_part.h"
|
||||||
|
#include "ui/round_rect.h"
|
||||||
#include "webview/webview_common.h"
|
#include "webview/webview_common.h"
|
||||||
|
|
||||||
class QJsonObject;
|
class QJsonObject;
|
||||||
|
@ -32,13 +34,6 @@ namespace Ui::BotWebView {
|
||||||
|
|
||||||
[[nodiscard]] TextWithEntities ErrorText(const Webview::Available &info);
|
[[nodiscard]] TextWithEntities ErrorText(const Webview::Available &info);
|
||||||
|
|
||||||
struct MainButtonArgs {
|
|
||||||
bool isActive = false;
|
|
||||||
bool isVisible = false;
|
|
||||||
bool isProgressVisible = false;
|
|
||||||
QString text;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class MenuButton {
|
enum class MenuButton {
|
||||||
None = 0x00,
|
None = 0x00,
|
||||||
OpenBot = 0x01,
|
OpenBot = 0x01,
|
||||||
|
@ -126,10 +121,13 @@ private:
|
||||||
void setTitle(rpl::producer<QString> title);
|
void setTitle(rpl::producer<QString> title);
|
||||||
void sendDataMessage(const QJsonObject &args);
|
void sendDataMessage(const QJsonObject &args);
|
||||||
void switchInlineQueryMessage(const QJsonObject &args);
|
void switchInlineQueryMessage(const QJsonObject &args);
|
||||||
void processMainButtonMessage(const QJsonObject &args);
|
void processButtonMessage(
|
||||||
|
std::unique_ptr<Button> &button,
|
||||||
|
const QJsonObject &args);
|
||||||
void processBackButtonMessage(const QJsonObject &args);
|
void processBackButtonMessage(const QJsonObject &args);
|
||||||
void processSettingsButtonMessage(const QJsonObject &args);
|
void processSettingsButtonMessage(const QJsonObject &args);
|
||||||
void processHeaderColor(const QJsonObject &args);
|
void processHeaderColor(const QJsonObject &args);
|
||||||
|
void processBottomBarColor(const QJsonObject &args);
|
||||||
void openTgLink(const QJsonObject &args);
|
void openTgLink(const QJsonObject &args);
|
||||||
void openExternalLink(const QJsonObject &args);
|
void openExternalLink(const QJsonObject &args);
|
||||||
void openInvoice(const QJsonObject &args);
|
void openInvoice(const QJsonObject &args);
|
||||||
|
@ -144,7 +142,7 @@ private:
|
||||||
void replyCustomMethod(QJsonValue requestId, QJsonObject response);
|
void replyCustomMethod(QJsonValue requestId, QJsonObject response);
|
||||||
void requestClipboardText(const QJsonObject &args);
|
void requestClipboardText(const QJsonObject &args);
|
||||||
void setupClosingBehaviour(const QJsonObject &args);
|
void setupClosingBehaviour(const QJsonObject &args);
|
||||||
void createMainButton();
|
void createButton(std::unique_ptr<Button> &button);
|
||||||
void scheduleCloseWithConfirmation();
|
void scheduleCloseWithConfirmation();
|
||||||
void closeWithConfirmation();
|
void closeWithConfirmation();
|
||||||
void sendViewport();
|
void sendViewport();
|
||||||
|
@ -158,7 +156,7 @@ private:
|
||||||
[[nodiscard]] bool progressWithBackground() const;
|
[[nodiscard]] bool progressWithBackground() const;
|
||||||
[[nodiscard]] QRect progressRect() const;
|
[[nodiscard]] QRect progressRect() const;
|
||||||
void setupProgressGeometry();
|
void setupProgressGeometry();
|
||||||
void updateFooterHeight();
|
void layoutButtons();
|
||||||
|
|
||||||
Webview::StorageId _storageId;
|
Webview::StorageId _storageId;
|
||||||
const not_null<Delegate*> _delegate;
|
const not_null<Delegate*> _delegate;
|
||||||
|
@ -170,14 +168,16 @@ private:
|
||||||
std::unique_ptr<RpWidget> _webviewBottom;
|
std::unique_ptr<RpWidget> _webviewBottom;
|
||||||
rpl::variable<QString> _bottomText;
|
rpl::variable<QString> _bottomText;
|
||||||
QPointer<RpWidget> _webviewParent;
|
QPointer<RpWidget> _webviewParent;
|
||||||
|
std::unique_ptr<RpWidget> _bottomButtonsBg;
|
||||||
std::unique_ptr<Button> _mainButton;
|
std::unique_ptr<Button> _mainButton;
|
||||||
mutable crl::time _mainButtonLastClick = 0;
|
std::unique_ptr<Button> _secondaryButton;
|
||||||
|
RectPart _secondaryPosition = RectPart::Left;
|
||||||
rpl::variable<int> _footerHeight = 0;
|
rpl::variable<int> _footerHeight = 0;
|
||||||
std::unique_ptr<Progress> _progress;
|
std::unique_ptr<Progress> _progress;
|
||||||
rpl::event_stream<> _themeUpdateForced;
|
rpl::event_stream<> _themeUpdateForced;
|
||||||
|
std::optional<QColor> _bottomBarColor;
|
||||||
rpl::lifetime _headerColorLifetime;
|
rpl::lifetime _headerColorLifetime;
|
||||||
rpl::lifetime _fgLifetime;
|
rpl::lifetime _bottomBarColorLifetime;
|
||||||
rpl::lifetime _bgLifetime;
|
|
||||||
bool _webviewProgress = false;
|
bool _webviewProgress = false;
|
||||||
bool _themeUpdateScheduled = false;
|
bool _themeUpdateScheduled = false;
|
||||||
bool _hiddenForPayment = false;
|
bool _hiddenForPayment = false;
|
||||||
|
|
|
@ -1503,6 +1503,7 @@ bool ReadPaletteValues(const QByteArray &content, Fn<bool(QLatin1String name, QL
|
||||||
{ "section_header_text_color", st::windowActiveTextFg },
|
{ "section_header_text_color", st::windowActiveTextFg },
|
||||||
{ "subtitle_text_color", st::windowSubTextFg },
|
{ "subtitle_text_color", st::windowSubTextFg },
|
||||||
{ "destructive_text_color", st::attentionButtonFg },
|
{ "destructive_text_color", st::attentionButtonFg },
|
||||||
|
{ "bottom_bar_bg_color", st::windowBg },
|
||||||
};
|
};
|
||||||
auto object = QJsonObject();
|
auto object = QJsonObject();
|
||||||
const auto wrap = [](QColor color) {
|
const auto wrap = [](QColor color) {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9ca74272a0ec33bac83c5b61a73d523902eb96cd
|
Subproject commit f90a42009d8dd28c818bb3c6916f4303fb9bcf0c
|
Loading…
Add table
Reference in a new issue