mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Add bot menu button with webview open support.
This commit is contained in:
parent
d35b8f82a3
commit
94c6793e92
9 changed files with 143 additions and 10 deletions
|
@ -1755,6 +1755,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_bot_add_to_menu_done" = "Bot added to the menu.";
|
"lng_bot_add_to_menu_done" = "Bot added to the menu.";
|
||||||
"lng_bot_menu_not_supported" = "This bot isn't supported in the attach menu.";
|
"lng_bot_menu_not_supported" = "This bot isn't supported in the attach menu.";
|
||||||
"lng_bot_menu_already_added" = "This bot is already added in your attach menu.";
|
"lng_bot_menu_already_added" = "This bot is already added in your attach menu.";
|
||||||
|
"lng_bot_menu_button" = "Menu";
|
||||||
|
|
||||||
"lng_typing" = "typing";
|
"lng_typing" = "typing";
|
||||||
"lng_user_typing" = "{user} is typing";
|
"lng_user_typing" = "{user} is typing";
|
||||||
|
|
|
@ -133,10 +133,23 @@ void UserData::setBotInfo(const MTPBotInfo &info) {
|
||||||
const auto changedCommands = Data::UpdateBotCommands(
|
const auto changedCommands = Data::UpdateBotCommands(
|
||||||
botInfo->commands,
|
botInfo->commands,
|
||||||
d.vcommands());
|
d.vcommands());
|
||||||
|
auto text = QString();
|
||||||
|
auto url = QString();
|
||||||
|
d.vmenu_button().match([&](const MTPDbotMenuButton &data) {
|
||||||
|
text = qs(data.vtext());
|
||||||
|
url = qs(data.vurl());
|
||||||
|
}, [&](const auto &) {
|
||||||
|
});
|
||||||
|
const auto changedButton = (botInfo->botMenuButtonText != text)
|
||||||
|
|| (botInfo->botMenuButtonUrl != url);
|
||||||
|
if (changedButton) {
|
||||||
|
botInfo->botMenuButtonText = text;
|
||||||
|
botInfo->botMenuButtonUrl = url;
|
||||||
|
}
|
||||||
|
|
||||||
botInfo->inited = true;
|
botInfo->inited = true;
|
||||||
|
|
||||||
if (changedCommands) {
|
if (changedCommands || changedButton) {
|
||||||
owner().botCommandsChanged(this);
|
owner().botCommandsChanged(this);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
|
@ -612,6 +612,10 @@ HistoryWidget::HistoryWidget(
|
||||||
) | rpl::filter([=](not_null<PeerData*> peer) {
|
) | rpl::filter([=](not_null<PeerData*> peer) {
|
||||||
return _peer && (_peer == peer);
|
return _peer && (_peer == peer);
|
||||||
}) | rpl::start_with_next([=] {
|
}) | rpl::start_with_next([=] {
|
||||||
|
if (updateCmdStartShown()) {
|
||||||
|
updateControlsVisibility();
|
||||||
|
updateControlsGeometry();
|
||||||
|
}
|
||||||
if (_fieldAutocomplete->clearFilteredBotCommands()) {
|
if (_fieldAutocomplete->clearFilteredBotCommands()) {
|
||||||
checkFieldAutocomplete();
|
checkFieldAutocomplete();
|
||||||
}
|
}
|
||||||
|
@ -2701,6 +2705,9 @@ void HistoryWidget::updateControlsVisibility() {
|
||||||
_botKeyboardShow->hide();
|
_botKeyboardShow->hide();
|
||||||
_botKeyboardHide->hide();
|
_botKeyboardHide->hide();
|
||||||
_botCommandStart->hide();
|
_botCommandStart->hide();
|
||||||
|
if (_botMenuButton) {
|
||||||
|
_botMenuButton->hide();
|
||||||
|
}
|
||||||
if (_tabbedPanel) {
|
if (_tabbedPanel) {
|
||||||
_tabbedPanel->hide();
|
_tabbedPanel->hide();
|
||||||
}
|
}
|
||||||
|
@ -2751,6 +2758,9 @@ void HistoryWidget::updateControlsVisibility() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_attachToggle->show();
|
_attachToggle->show();
|
||||||
|
if (_botMenuButton) {
|
||||||
|
_botMenuButton->show();
|
||||||
|
}
|
||||||
if (_silent) {
|
if (_silent) {
|
||||||
_silent->show();
|
_silent->show();
|
||||||
}
|
}
|
||||||
|
@ -2798,6 +2808,9 @@ void HistoryWidget::updateControlsVisibility() {
|
||||||
if (_sendAs) {
|
if (_sendAs) {
|
||||||
_sendAs->hide();
|
_sendAs->hide();
|
||||||
}
|
}
|
||||||
|
if (_botMenuButton) {
|
||||||
|
_botMenuButton->hide();
|
||||||
|
}
|
||||||
_kbScroll->hide();
|
_kbScroll->hide();
|
||||||
_fieldBarCancel->hide();
|
_fieldBarCancel->hide();
|
||||||
_tabbedSelectorToggle->hide();
|
_tabbedSelectorToggle->hide();
|
||||||
|
@ -4427,19 +4440,66 @@ void HistoryWidget::updateSendButtonType() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::updateCmdStartShown() {
|
bool HistoryWidget::updateCmdStartShown() {
|
||||||
|
const auto bot = (_peer && _peer->asUser()->isBot())
|
||||||
|
? _peer->asUser()
|
||||||
|
: nullptr;
|
||||||
bool cmdStartShown = false;
|
bool cmdStartShown = false;
|
||||||
if (_history && _peer && ((_peer->isChat() && _peer->asChat()->botStatus > 0) || (_peer->isMegagroup() && _peer->asChannel()->mgInfo->botStatus > 0) || (_peer->isUser() && _peer->asUser()->isBot()))) {
|
if (_history && _peer && ((_peer->isChat() && _peer->asChat()->botStatus > 0) || (_peer->isMegagroup() && _peer->asChannel()->mgInfo->botStatus > 0))) {
|
||||||
if (!isBotStart() && !isBlocked() && !_keyboard->hasMarkup() && !_keyboard->forceReply() && !_editMsgId) {
|
if (!isBotStart() && !isBlocked() && !_keyboard->hasMarkup() && !_keyboard->forceReply() && !_editMsgId) {
|
||||||
if (!HasSendText(_field)) {
|
if (!HasSendText(_field)) {
|
||||||
cmdStartShown = true;
|
cmdStartShown = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (_cmdStartShown != cmdStartShown) {
|
const auto commandsChanged = (_cmdStartShown != cmdStartShown);
|
||||||
_cmdStartShown = cmdStartShown;
|
auto buttonChanged = false;
|
||||||
return true;
|
if (!bot
|
||||||
|
|| (bot->botInfo->botMenuButtonUrl.isEmpty()
|
||||||
|
&& bot->botInfo->commands.empty())) {
|
||||||
|
buttonChanged = (_botMenuButton != nullptr);
|
||||||
|
_botMenuButton.destroy();
|
||||||
|
} else if (!_botMenuButton) {
|
||||||
|
buttonChanged = true;
|
||||||
|
_botMenuButtonText = bot->botInfo->botMenuButtonText;
|
||||||
|
_botMenuButton.create(
|
||||||
|
this,
|
||||||
|
(_botMenuButtonText.isEmpty()
|
||||||
|
? tr::lng_bot_menu_button()
|
||||||
|
: rpl::single(_botMenuButtonText)),
|
||||||
|
st::historyBotMenuButton);
|
||||||
|
_botMenuButton->setTextTransform(
|
||||||
|
Ui::RoundButton::TextTransform::NoTransform);
|
||||||
|
_botMenuButton->setFullRadius(true);
|
||||||
|
_botMenuButton->setClickedCallback([=] {
|
||||||
|
const auto user = _peer ? _peer->asUser() : nullptr;
|
||||||
|
const auto bot = (user && user->isBot()) ? user : nullptr;
|
||||||
|
if (bot && !bot->botInfo->botMenuButtonUrl.isEmpty()) {
|
||||||
|
session().attachWebView().requestMenu(controller(), bot);
|
||||||
|
} else if (!_fieldAutocomplete->isHidden()) {
|
||||||
|
_fieldAutocomplete->hideAnimated();
|
||||||
|
} else {
|
||||||
|
_fieldAutocomplete->showFiltered(_peer, "/", true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_botMenuButton->widthValue(
|
||||||
|
) | rpl::start_with_next([=](int width) {
|
||||||
|
if (width > st::historyBotMenuMaxWidth) {
|
||||||
|
_botMenuButton->setFullWidth(st::historyBotMenuMaxWidth);
|
||||||
|
} else {
|
||||||
|
updateFieldSize();
|
||||||
|
}
|
||||||
|
}, _botMenuButton->lifetime());
|
||||||
}
|
}
|
||||||
return false;
|
const auto textChanged = _botMenuButton
|
||||||
|
&& (_botMenuButtonText != bot->botInfo->botMenuButtonText);
|
||||||
|
if (textChanged) {
|
||||||
|
_botMenuButtonText = bot->botInfo->botMenuButtonText;
|
||||||
|
_botMenuButton->setText(_botMenuButtonText.isEmpty()
|
||||||
|
? tr::lng_bot_menu_button()
|
||||||
|
: rpl::single(_botMenuButtonText));
|
||||||
|
}
|
||||||
|
_cmdStartShown = cmdStartShown;
|
||||||
|
return commandsChanged || buttonChanged || textChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HistoryWidget::searchInChat() {
|
void HistoryWidget::searchInChat() {
|
||||||
|
@ -4697,12 +4757,16 @@ void HistoryWidget::moveFieldControls() {
|
||||||
_kbScroll->setGeometryToLeft(0, bottom, width(), keyboardHeight);
|
_kbScroll->setGeometryToLeft(0, bottom, width(), keyboardHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// _attachToggle (_sendAs) ------- _inlineResults ---------------------------------- _tabbedPanel -------- _fieldBarCancel
|
// (_botMenuButton) _attachToggle (_sendAs) ---- _inlineResults ------------------------------ _tabbedPanel ------ _fieldBarCancel
|
||||||
// (_attachDocument|_attachPhoto) _field (_ttlInfo) (_scheduled) (_silent|_cmdStart|_kbShow) (_kbHide|_tabbedSelectorToggle) _send
|
// (_attachDocument|_attachPhoto) _field (_ttlInfo) (_scheduled) (_silent|_cmdStart|_kbShow) (_kbHide|_tabbedSelectorToggle) _send
|
||||||
// (_botStart|_unblock|_joinChannel|_muteUnmute|_reportMessages)
|
// (_botStart|_unblock|_joinChannel|_muteUnmute|_reportMessages)
|
||||||
|
|
||||||
auto buttonsBottom = bottom - _attachToggle->height();
|
auto buttonsBottom = bottom - _attachToggle->height();
|
||||||
auto left = st::historySendRight;
|
auto left = st::historySendRight;
|
||||||
|
if (_botMenuButton) {
|
||||||
|
const auto skip = st::historyBotMenuSkip;
|
||||||
|
_botMenuButton->moveToLeft(left + skip, buttonsBottom + skip); left += skip + _botMenuButton->width();
|
||||||
|
}
|
||||||
_attachToggle->moveToLeft(left, buttonsBottom); left += _attachToggle->width();
|
_attachToggle->moveToLeft(left, buttonsBottom); left += _attachToggle->width();
|
||||||
if (_sendAs) {
|
if (_sendAs) {
|
||||||
_sendAs->moveToLeft(left, buttonsBottom); left += _sendAs->width();
|
_sendAs->moveToLeft(left, buttonsBottom); left += _sendAs->width();
|
||||||
|
@ -4762,6 +4826,7 @@ void HistoryWidget::updateFieldSize() {
|
||||||
- st::historySendRight
|
- st::historySendRight
|
||||||
- _send->width()
|
- _send->width()
|
||||||
- _tabbedSelectorToggle->width();
|
- _tabbedSelectorToggle->width();
|
||||||
|
if (_botMenuButton) fieldWidth -= st::historyBotMenuSkip + _botMenuButton->width();
|
||||||
if (_sendAs) fieldWidth -= _sendAs->width();
|
if (_sendAs) fieldWidth -= _sendAs->width();
|
||||||
if (kbShowShown) fieldWidth -= _botKeyboardShow->width();
|
if (kbShowShown) fieldWidth -= _botKeyboardShow->width();
|
||||||
if (_cmdStartShown) fieldWidth -= _botCommandStart->width();
|
if (_cmdStartShown) fieldWidth -= _botCommandStart->width();
|
||||||
|
|
|
@ -738,6 +738,8 @@ private:
|
||||||
object_ptr<Ui::FlatButton> _joinChannel;
|
object_ptr<Ui::FlatButton> _joinChannel;
|
||||||
object_ptr<Ui::FlatButton> _muteUnmute;
|
object_ptr<Ui::FlatButton> _muteUnmute;
|
||||||
object_ptr<Ui::FlatButton> _reportMessages;
|
object_ptr<Ui::FlatButton> _reportMessages;
|
||||||
|
object_ptr<Ui::RoundButton> _botMenuButton = { nullptr };
|
||||||
|
QString _botMenuButtonText;
|
||||||
object_ptr<Ui::IconButton> _attachToggle;
|
object_ptr<Ui::IconButton> _attachToggle;
|
||||||
object_ptr<Ui::SendAsButton> _sendAs = { nullptr };
|
object_ptr<Ui::SendAsButton> _sendAs = { nullptr };
|
||||||
object_ptr<Ui::EmojiButton> _tabbedSelectorToggle;
|
object_ptr<Ui::EmojiButton> _tabbedSelectorToggle;
|
||||||
|
|
|
@ -572,6 +572,40 @@ void AttachWebView::requestSimple(const WebViewButton &button) {
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AttachWebView::requestMenu(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<UserData*> bot) {
|
||||||
|
cancel();
|
||||||
|
_bot = bot;
|
||||||
|
_peer = bot;
|
||||||
|
const auto url = bot->botInfo->botMenuButtonUrl;
|
||||||
|
const auto text = bot->botInfo->botMenuButtonText;
|
||||||
|
confirmOpen(controller, [=] {
|
||||||
|
using Flag = MTPmessages_RequestWebView::Flag;
|
||||||
|
_requestId = _session->api().request(MTPmessages_RequestWebView(
|
||||||
|
MTP_flags(Flag::f_theme_params
|
||||||
|
| Flag::f_url
|
||||||
|
| Flag::f_from_bot_menu),
|
||||||
|
_bot->input,
|
||||||
|
_bot->inputUser,
|
||||||
|
MTP_string(url),
|
||||||
|
MTPstring(),
|
||||||
|
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams())),
|
||||||
|
MTPint()
|
||||||
|
)).done([=](const MTPWebViewResult &result) {
|
||||||
|
_requestId = 0;
|
||||||
|
result.match([&](const MTPDwebViewResultUrl &data) {
|
||||||
|
show(data.vquery_id().v, qs(data.vurl()), text);
|
||||||
|
});
|
||||||
|
}).fail([=](const MTP::Error &error) {
|
||||||
|
_requestId = 0;
|
||||||
|
if (error.type() == u"BOT_INVALID"_q) {
|
||||||
|
requestBots();
|
||||||
|
}
|
||||||
|
}).send();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void AttachWebView::confirmOpen(
|
void AttachWebView::confirmOpen(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
Fn<void()> done) {
|
Fn<void()> done) {
|
||||||
|
|
|
@ -64,6 +64,9 @@ public:
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
const WebViewButton &button);
|
const WebViewButton &button);
|
||||||
|
void requestMenu(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
not_null<UserData*> bot);
|
||||||
|
|
||||||
void cancel();
|
void cancel();
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,7 @@ void Panel::Button::updateFg(QColor fg) {
|
||||||
|
|
||||||
void Panel::Button::updateArgs(MainButtonArgs &&args) {
|
void Panel::Button::updateArgs(MainButtonArgs &&args) {
|
||||||
_textFull = std::move(args.text);
|
_textFull = std::move(args.text);
|
||||||
|
setDisabled(!args.isActive);
|
||||||
setVisible(args.isVisible);
|
setVisible(args.isVisible);
|
||||||
toggleProgress(args.isProgressVisible);
|
toggleProgress(args.isProgressVisible);
|
||||||
update();
|
update();
|
||||||
|
@ -251,8 +252,11 @@ void Panel::Button::paintEvent(QPaintEvent *e) {
|
||||||
p,
|
p,
|
||||||
rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }),
|
rect().marginsAdded({ 0, st::callRadius * 2, 0, 0 }),
|
||||||
RectPart::BottomLeft | RectPart::BottomRight);
|
RectPart::BottomLeft | RectPart::BottomRight);
|
||||||
const auto ripple = ResolveRipple(_bg.color()->c);
|
|
||||||
paintRipple(p, rect().topLeft(), &ripple);
|
if (!isDisabled()) {
|
||||||
|
const auto ripple = ResolveRipple(_bg.color()->c);
|
||||||
|
paintRipple(p, rect().topLeft(), &ripple);
|
||||||
|
}
|
||||||
|
|
||||||
p.setFont(_st.font);
|
p.setFont(_st.font);
|
||||||
|
|
||||||
|
@ -646,6 +650,7 @@ void Panel::processMainButtonMessage(const QJsonValue &value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_mainButton->updateArgs({
|
_mainButton->updateArgs({
|
||||||
|
.isActive = args["is_active"].toBool(),
|
||||||
.isVisible = args["is_visible"].toBool(),
|
.isVisible = args["is_visible"].toBool(),
|
||||||
.isProgressVisible = args["is_progress_visible"].toBool(),
|
.isProgressVisible = args["is_progress_visible"].toBool(),
|
||||||
.text = args["text"].toString(),
|
.text = args["text"].toString(),
|
||||||
|
@ -659,7 +664,9 @@ void Panel::createMainButton() {
|
||||||
const auto button = _mainButton.get();
|
const auto button = _mainButton.get();
|
||||||
|
|
||||||
button->setClickedCallback([=] {
|
button->setClickedCallback([=] {
|
||||||
postEvent("main_button_pressed");
|
if (!button->isDisabled()) {
|
||||||
|
postEvent("main_button_pressed");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
button->hide();
|
button->hide();
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct Available;
|
||||||
namespace Ui::BotWebView {
|
namespace Ui::BotWebView {
|
||||||
|
|
||||||
struct MainButtonArgs {
|
struct MainButtonArgs {
|
||||||
|
bool isActive = false;
|
||||||
bool isVisible = false;
|
bool isVisible = false;
|
||||||
bool isProgressVisible = false;
|
bool isProgressVisible = false;
|
||||||
QString text;
|
QString text;
|
||||||
|
|
|
@ -239,6 +239,13 @@ historyComposeFieldMaxHeight: 224px;
|
||||||
|
|
||||||
historySendPadding: 9px;
|
historySendPadding: 9px;
|
||||||
historySendRight: 2px;
|
historySendRight: 2px;
|
||||||
|
historyBotMenuSkip: 8px;
|
||||||
|
historyBotMenuMaxWidth: 160px;
|
||||||
|
historyBotMenuButton: RoundButton(defaultActiveButton) {
|
||||||
|
width: -24px;
|
||||||
|
height: 30px;
|
||||||
|
textTop: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
historyComposeButton: FlatButton {
|
historyComposeButton: FlatButton {
|
||||||
color: windowActiveTextFg;
|
color: windowActiveTextFg;
|
||||||
|
|
Loading…
Add table
Reference in a new issue