mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Implement switch_webview and "web_app_switch_inline_query".
This commit is contained in:
parent
34c1bd950e
commit
4fe568cb82
17 changed files with 415 additions and 152 deletions
|
@ -289,10 +289,11 @@ bool SwitchInlineBotButtonReceived(
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
|
void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
|
||||||
const auto controller = context.sessionWindow.get();
|
const auto strong = context.sessionWindow.get();
|
||||||
if (!controller) {
|
if (!strong) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const auto controller = not_null{ strong };
|
||||||
const auto item = controller->session().data().message(context.itemId);
|
const auto item = controller->session().data().message(context.itemId);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -110,6 +110,9 @@ struct EntryState {
|
||||||
FilterId filterId = 0;
|
FilterId filterId = 0;
|
||||||
MsgId rootId = 0;
|
MsgId rootId = 0;
|
||||||
MsgId currentReplyToId = 0;
|
MsgId currentReplyToId = 0;
|
||||||
|
|
||||||
|
friend inline constexpr auto operator<=>(EntryState, EntryState) noexcept
|
||||||
|
= default;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Dialogs
|
} // namespace Dialogs
|
||||||
|
|
|
@ -924,8 +924,8 @@ void HistoryWidget::refreshJoinChannelText() {
|
||||||
void HistoryWidget::refreshTopBarActiveChat() {
|
void HistoryWidget::refreshTopBarActiveChat() {
|
||||||
const auto state = computeDialogsEntryState();
|
const auto state = computeDialogsEntryState();
|
||||||
_topBar->setActiveChat(state, _history->sendActionPainter());
|
_topBar->setActiveChat(state, _history->sendActionPainter());
|
||||||
if (_inlineResults) {
|
if (state.key) {
|
||||||
_inlineResults->setCurrentDialogsEntryState(state);
|
controller()->setCurrentDialogsEntryState(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1477,8 +1477,6 @@ void HistoryWidget::applyInlineBotQuery(UserData *bot, const QString &query) {
|
||||||
sendInlineResult(result);
|
sendInlineResult(result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_inlineResults->setCurrentDialogsEntryState(
|
|
||||||
computeDialogsEntryState());
|
|
||||||
_inlineResults->setSendMenuType([=] { return sendMenuType(); });
|
_inlineResults->setSendMenuType([=] { return sendMenuType(); });
|
||||||
_inlineResults->requesting(
|
_inlineResults->requesting(
|
||||||
) | rpl::start_with_next([=](bool requesting) {
|
) | rpl::start_with_next([=](bool requesting) {
|
||||||
|
@ -1761,14 +1759,21 @@ void HistoryWidget::setInnerFocus() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HistoryWidget::notify_switchInlineBotButtonReceived(const QString &query, UserData *samePeerBot, MsgId samePeerReplyTo) {
|
bool HistoryWidget::notify_switchInlineBotButtonReceived(
|
||||||
|
const QString &query,
|
||||||
|
UserData *samePeerBot,
|
||||||
|
MsgId samePeerReplyTo) {
|
||||||
if (samePeerBot) {
|
if (samePeerBot) {
|
||||||
if (_history) {
|
if (_history) {
|
||||||
const auto textWithTags = TextWithTags{
|
const auto textWithTags = TextWithTags{
|
||||||
'@' + samePeerBot->username() + ' ' + query,
|
'@' + samePeerBot->username() + ' ' + query,
|
||||||
TextWithTags::Tags(),
|
TextWithTags::Tags(),
|
||||||
};
|
};
|
||||||
MessageCursor cursor = { int(textWithTags.text.size()), int(textWithTags.text.size()), QFIXED_MAX };
|
MessageCursor cursor = {
|
||||||
|
int(textWithTags.text.size()),
|
||||||
|
int(textWithTags.text.size()),
|
||||||
|
QFIXED_MAX,
|
||||||
|
};
|
||||||
_history->setLocalDraft(std::make_unique<Data::Draft>(
|
_history->setLocalDraft(std::make_unique<Data::Draft>(
|
||||||
textWithTags,
|
textWithTags,
|
||||||
0, // replyTo
|
0, // replyTo
|
||||||
|
@ -1782,39 +1787,11 @@ bool HistoryWidget::notify_switchInlineBotButtonReceived(const QString &query, U
|
||||||
const auto to = bot->isBot()
|
const auto to = bot->isBot()
|
||||||
? bot->botInfo->inlineReturnTo
|
? bot->botInfo->inlineReturnTo
|
||||||
: Dialogs::EntryState();
|
: Dialogs::EntryState();
|
||||||
const auto history = to.key.owningHistory();
|
if (!to.key.owningHistory()) {
|
||||||
if (!history) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bot->botInfo->inlineReturnTo = Dialogs::EntryState();
|
bot->botInfo->inlineReturnTo = Dialogs::EntryState();
|
||||||
using Section = Dialogs::EntryState::Section;
|
controller()->switchInlineQuery(to, bot, query);
|
||||||
|
|
||||||
const auto textWithTags = TextWithTags{
|
|
||||||
'@' + bot->username() + ' ' + query,
|
|
||||||
TextWithTags::Tags(),
|
|
||||||
};
|
|
||||||
MessageCursor cursor = { int(textWithTags.text.size()), int(textWithTags.text.size()), QFIXED_MAX };
|
|
||||||
auto draft = std::make_unique<Data::Draft>(
|
|
||||||
textWithTags,
|
|
||||||
to.currentReplyToId,
|
|
||||||
to.rootId,
|
|
||||||
cursor,
|
|
||||||
Data::PreviewState::Allowed);
|
|
||||||
|
|
||||||
if (to.section == Section::Scheduled) {
|
|
||||||
history->setDraft(Data::DraftKey::Scheduled(), std::move(draft));
|
|
||||||
controller()->showSection(
|
|
||||||
std::make_shared<HistoryView::ScheduledMemento>(history));
|
|
||||||
} else {
|
|
||||||
history->setLocalDraft(std::move(draft));
|
|
||||||
if (to.section == Section::Replies) {
|
|
||||||
controller()->showRepliesForMessage(history, to.rootId);
|
|
||||||
} else if (history == _history) {
|
|
||||||
applyDraft();
|
|
||||||
} else {
|
|
||||||
controller()->showPeerHistory(history->peer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -2417,6 +2394,7 @@ void HistoryWidget::refreshAttachBotsMenu() {
|
||||||
}
|
}
|
||||||
_attachBotsMenu = InlineBots::MakeAttachBotsMenu(
|
_attachBotsMenu = InlineBots::MakeAttachBotsMenu(
|
||||||
this,
|
this,
|
||||||
|
controller(),
|
||||||
_history->peer,
|
_history->peer,
|
||||||
[=] { return prepareSendAction({}); },
|
[=] { return prepareSendAction({}); },
|
||||||
[=](bool compress) { chooseAttach(compress); });
|
[=](bool compress) { chooseAttach(compress); });
|
||||||
|
|
|
@ -1022,9 +1022,6 @@ void ComposeControls::setCurrentDialogsEntryState(Dialogs::EntryState state) {
|
||||||
_currentDialogsEntryState = state;
|
_currentDialogsEntryState = state;
|
||||||
updateForwarding();
|
updateForwarding();
|
||||||
registerDraftSource();
|
registerDraftSource();
|
||||||
if (_inlineResults) {
|
|
||||||
_inlineResults->setCurrentDialogsEntryState(state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerData *ComposeControls::sendAsPeer() const {
|
PeerData *ComposeControls::sendAsPeer() const {
|
||||||
|
@ -2405,6 +2402,7 @@ void ComposeControls::updateAttachBotsMenu() {
|
||||||
}
|
}
|
||||||
_attachBotsMenu = InlineBots::MakeAttachBotsMenu(
|
_attachBotsMenu = InlineBots::MakeAttachBotsMenu(
|
||||||
_parent,
|
_parent,
|
||||||
|
_window,
|
||||||
_history->peer,
|
_history->peer,
|
||||||
_sendActionFactory,
|
_sendActionFactory,
|
||||||
[=](bool compress) { _attachRequests.fire_copy(compress); });
|
[=](bool compress) { _attachRequests.fire_copy(compress); });
|
||||||
|
@ -2860,8 +2858,6 @@ void ComposeControls::applyInlineBotQuery(
|
||||||
_inlineResults = std::make_unique<InlineBots::Layout::Widget>(
|
_inlineResults = std::make_unique<InlineBots::Layout::Widget>(
|
||||||
_parent,
|
_parent,
|
||||||
_window);
|
_window);
|
||||||
_inlineResults->setCurrentDialogsEntryState(
|
|
||||||
_currentDialogsEntryState);
|
|
||||||
_inlineResults->setResultSelectedCallback([=](
|
_inlineResults->setResultSelectedCallback([=](
|
||||||
InlineBots::ResultSelected result) {
|
InlineBots::ResultSelected result) {
|
||||||
if (result.open) {
|
if (result.open) {
|
||||||
|
|
|
@ -1461,6 +1461,7 @@ void RepliesWidget::refreshTopBarActiveChat() {
|
||||||
};
|
};
|
||||||
_topBar->setActiveChat(state, _sendAction.get());
|
_topBar->setActiveChat(state, _sendAction.get());
|
||||||
_composeControls->setCurrentDialogsEntryState(state);
|
_composeControls->setCurrentDialogsEntryState(state);
|
||||||
|
controller()->setCurrentDialogsEntryState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
MsgId RepliesWidget::replyToId() const {
|
MsgId RepliesWidget::replyToId() const {
|
||||||
|
@ -1961,6 +1962,10 @@ bool RepliesWidget::showInternal(
|
||||||
if (!logMemento->getHighlightId()) {
|
if (!logMemento->getHighlightId()) {
|
||||||
showAtPosition(Data::UnreadMessagePosition);
|
showAtPosition(Data::UnreadMessagePosition);
|
||||||
}
|
}
|
||||||
|
if (params.reapplyLocalDraft) {
|
||||||
|
_composeControls->applyDraft(
|
||||||
|
ComposeControls::FieldHistoryAction::NewEntry);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,7 @@ ScheduledWidget::ScheduledWidget(
|
||||||
};
|
};
|
||||||
_topBar->setActiveChat(state, nullptr);
|
_topBar->setActiveChat(state, nullptr);
|
||||||
_composeControls->setCurrentDialogsEntryState(state);
|
_composeControls->setCurrentDialogsEntryState(state);
|
||||||
|
controller->setCurrentDialogsEntryState(state);
|
||||||
|
|
||||||
_topBar->move(0, 0);
|
_topBar->move(0, 0);
|
||||||
_topBar->resizeToWidth(width());
|
_topBar->resizeToWidth(width());
|
||||||
|
@ -924,6 +925,10 @@ bool ScheduledWidget::showInternal(
|
||||||
if (auto logMemento = dynamic_cast<ScheduledMemento*>(memento.get())) {
|
if (auto logMemento = dynamic_cast<ScheduledMemento*>(memento.get())) {
|
||||||
if (logMemento->getHistory() == history()) {
|
if (logMemento->getHistory() == history()) {
|
||||||
restoreState(logMemento);
|
restoreState(logMemento);
|
||||||
|
if (params.reapplyLocalDraft) {
|
||||||
|
_composeControls->applyDraft(
|
||||||
|
ComposeControls::FieldHistoryAction::NewEntry);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#include "inline_bots/bot_attach_web_view.h"
|
#include "inline_bots/bot_attach_web_view.h"
|
||||||
|
|
||||||
|
#include "api/api_common.h"
|
||||||
#include "data/data_user.h"
|
#include "data/data_user.h"
|
||||||
#include "data/data_file_origin.h"
|
#include "data/data_file_origin.h"
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
|
@ -42,6 +43,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "base/random.h"
|
#include "base/random.h"
|
||||||
#include "base/timer_rpl.h"
|
#include "base/timer_rpl.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
#include "styles/style_menu_icons.h"
|
#include "styles/style_menu_icons.h"
|
||||||
|
|
||||||
|
@ -57,18 +59,6 @@ struct ParsedBot {
|
||||||
bool inactive = false;
|
bool inactive = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] bool IsSame(
|
|
||||||
const std::optional<Api::SendAction> &a,
|
|
||||||
const Api::SendAction &b) {
|
|
||||||
// Check fields that are sent to API in bot attach webview requests.
|
|
||||||
return a.has_value()
|
|
||||||
&& (a->history == b.history)
|
|
||||||
&& (a->replyTo == b.replyTo)
|
|
||||||
&& (a->topicRootId == b.topicRootId)
|
|
||||||
&& (a->options.sendAs == b.options.sendAs)
|
|
||||||
&& (a->options.silent == b.options.silent);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] DocumentData *ResolveIcon(
|
[[nodiscard]] DocumentData *ResolveIcon(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPDattachMenuBot &data) {
|
const MTPDattachMenuBot &data) {
|
||||||
|
@ -132,10 +122,29 @@ struct ParsedBot {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] PeerTypes PeerTypesFromNames(
|
||||||
|
const std::vector<QString> &names) {
|
||||||
|
auto result = PeerTypes();
|
||||||
|
for (const auto &name : names) {
|
||||||
|
//, bots, groups, channels
|
||||||
|
result |= (name == u"users"_q)
|
||||||
|
? PeerType::User
|
||||||
|
: name == u"bots"_q
|
||||||
|
? PeerType::Bot
|
||||||
|
: name == u"groups"_q
|
||||||
|
? PeerType::Group
|
||||||
|
: name == u"channels"_q
|
||||||
|
? PeerType::Broadcast
|
||||||
|
: PeerType(0);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void ShowChooseBox(
|
void ShowChooseBox(
|
||||||
not_null<Window::SessionController*> controller,
|
not_null<Window::SessionController*> controller,
|
||||||
PeerTypes types,
|
PeerTypes types,
|
||||||
Fn<void(not_null<Data::Thread*>)> callback) {
|
Fn<void(not_null<Data::Thread*>)> callback,
|
||||||
|
rpl::producer<QString> titleOverride = nullptr) {
|
||||||
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
|
const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
|
||||||
auto done = [=](not_null<Data::Thread*> thread) mutable {
|
auto done = [=](not_null<Data::Thread*> thread) mutable {
|
||||||
if (const auto strong = *weak) {
|
if (const auto strong = *weak) {
|
||||||
|
@ -159,7 +168,10 @@ void ShowChooseBox(
|
||||||
return (types & PeerType::Group);
|
return (types & PeerType::Group);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
auto initBox = [](not_null<PeerListBox*> box) {
|
auto initBox = [=](not_null<PeerListBox*> box) {
|
||||||
|
if (titleOverride) {
|
||||||
|
box->setTitle(std::move(titleOverride));
|
||||||
|
}
|
||||||
box->addButton(tr::lng_cancel(), [box] {
|
box->addButton(tr::lng_cancel(), [box] {
|
||||||
box->closeBox();
|
box->closeBox();
|
||||||
});
|
});
|
||||||
|
@ -407,6 +419,13 @@ PeerTypes ParseChooseTypes(QStringView choose) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AttachWebView::Context {
|
||||||
|
base::weak_ptr<Window::SessionController> controller;
|
||||||
|
Dialogs::EntryState dialogsEntryState;
|
||||||
|
Api::SendAction action;
|
||||||
|
bool fromSwitch = false;
|
||||||
|
};
|
||||||
|
|
||||||
AttachWebView::AttachWebView(not_null<Main::Session*> session)
|
AttachWebView::AttachWebView(not_null<Main::Session*> session)
|
||||||
: _session(session) {
|
: _session(session) {
|
||||||
}
|
}
|
||||||
|
@ -416,6 +435,7 @@ AttachWebView::~AttachWebView() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachWebView::request(
|
void AttachWebView::request(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
const Api::SendAction &action,
|
const Api::SendAction &action,
|
||||||
const QString &botUsername,
|
const QString &botUsername,
|
||||||
const QString &startCommand) {
|
const QString &startCommand) {
|
||||||
|
@ -423,7 +443,8 @@ void AttachWebView::request(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto username = _bot ? _bot->username() : _botUsername;
|
const auto username = _bot ? _bot->username() : _botUsername;
|
||||||
if (IsSame(_action, action)
|
const auto context = LookupContext(controller, action);
|
||||||
|
if (IsSame(_context, context)
|
||||||
&& username.toLower() == botUsername.toLower()
|
&& username.toLower() == botUsername.toLower()
|
||||||
&& _startCommand == startCommand) {
|
&& _startCommand == startCommand) {
|
||||||
if (_panel) {
|
if (_panel) {
|
||||||
|
@ -433,18 +454,55 @@ void AttachWebView::request(
|
||||||
}
|
}
|
||||||
cancel();
|
cancel();
|
||||||
|
|
||||||
_action = action;
|
_context = std::make_unique<Context>(context);
|
||||||
_botUsername = botUsername;
|
_botUsername = botUsername;
|
||||||
_startCommand = startCommand;
|
_startCommand = startCommand;
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AttachWebView::Context AttachWebView::LookupContext(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
const Api::SendAction &action) {
|
||||||
|
return {
|
||||||
|
.controller = controller,
|
||||||
|
.dialogsEntryState = controller->currentDialogsEntryState(),
|
||||||
|
.action = action,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AttachWebView::IsSame(
|
||||||
|
const std::unique_ptr<Context> &a,
|
||||||
|
const Context &b) {
|
||||||
|
// Check fields that are sent to API in bot attach webview requests.
|
||||||
|
return a
|
||||||
|
&& (a->controller == b.controller)
|
||||||
|
&& (a->dialogsEntryState == b.dialogsEntryState)
|
||||||
|
&& (a->fromSwitch == b.fromSwitch)
|
||||||
|
&& (a->action.history == b.action.history)
|
||||||
|
&& (a->action.replyTo == b.action.replyTo)
|
||||||
|
&& (a->action.topicRootId == b.action.topicRootId)
|
||||||
|
&& (a->action.options.sendAs == b.action.options.sendAs)
|
||||||
|
&& (a->action.options.silent == b.action.options.silent);
|
||||||
|
}
|
||||||
|
|
||||||
void AttachWebView::request(
|
void AttachWebView::request(
|
||||||
Window::SessionController *controller,
|
not_null<Window::SessionController*> controller,
|
||||||
const Api::SendAction &action,
|
const Api::SendAction &action,
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
const WebViewButton &button) {
|
const WebViewButton &button) {
|
||||||
if (IsSame(_action, action) && _bot == bot) {
|
requestWithOptionalConfirm(
|
||||||
|
bot,
|
||||||
|
button,
|
||||||
|
LookupContext(controller, action),
|
||||||
|
button.fromMenu ? nullptr : controller.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachWebView::requestWithOptionalConfirm(
|
||||||
|
not_null<UserData*> bot,
|
||||||
|
const WebViewButton &button,
|
||||||
|
const Context &context,
|
||||||
|
Window::SessionController *controllerForConfirm) {
|
||||||
|
if (IsSame(_context, context) && _bot == bot) {
|
||||||
if (_panel) {
|
if (_panel) {
|
||||||
_panel->requestActivate();
|
_panel->requestActivate();
|
||||||
} else if (_requestId) {
|
} else if (_requestId) {
|
||||||
|
@ -454,9 +512,9 @@ void AttachWebView::request(
|
||||||
cancel();
|
cancel();
|
||||||
|
|
||||||
_bot = bot;
|
_bot = bot;
|
||||||
_action = action;
|
_context = std::make_unique<Context>(context);
|
||||||
if (controller) {
|
if (controllerForConfirm) {
|
||||||
confirmOpen(controller, [=] {
|
confirmOpen(controllerForConfirm, [=] {
|
||||||
request(button);
|
request(button);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -465,30 +523,31 @@ void AttachWebView::request(
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachWebView::request(const WebViewButton &button) {
|
void AttachWebView::request(const WebViewButton &button) {
|
||||||
Expects(_action.has_value() && _bot != nullptr);
|
Expects(_context != nullptr && _bot != nullptr);
|
||||||
|
|
||||||
_startCommand = button.startCommand;
|
_startCommand = button.startCommand;
|
||||||
|
const auto &action = _context->action;
|
||||||
|
|
||||||
using Flag = MTPmessages_RequestWebView::Flag;
|
using Flag = MTPmessages_RequestWebView::Flag;
|
||||||
const auto flags = Flag::f_theme_params
|
const auto flags = Flag::f_theme_params
|
||||||
| (button.url.isEmpty() ? Flag(0) : Flag::f_url)
|
| (button.url.isEmpty() ? Flag(0) : Flag::f_url)
|
||||||
| (_startCommand.isEmpty() ? Flag(0) : Flag::f_start_param)
|
| (_startCommand.isEmpty() ? Flag(0) : Flag::f_start_param)
|
||||||
| (_action->replyTo ? Flag::f_reply_to_msg_id : Flag(0))
|
| (action.replyTo ? Flag::f_reply_to_msg_id : Flag(0))
|
||||||
| (_action->topicRootId ? Flag::f_top_msg_id : Flag(0))
|
| (action.topicRootId ? Flag::f_top_msg_id : Flag(0))
|
||||||
| (_action->options.sendAs ? Flag::f_send_as : Flag(0))
|
| (action.options.sendAs ? Flag::f_send_as : Flag(0))
|
||||||
| (_action->options.silent ? Flag::f_silent : Flag(0));
|
| (action.options.silent ? Flag::f_silent : Flag(0));
|
||||||
_requestId = _session->api().request(MTPmessages_RequestWebView(
|
_requestId = _session->api().request(MTPmessages_RequestWebView(
|
||||||
MTP_flags(flags),
|
MTP_flags(flags),
|
||||||
_action->history->peer->input,
|
action.history->peer->input,
|
||||||
_bot->inputUser,
|
_bot->inputUser,
|
||||||
MTP_bytes(button.url),
|
MTP_bytes(button.url),
|
||||||
MTP_string(_startCommand),
|
MTP_string(_startCommand),
|
||||||
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)),
|
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)),
|
||||||
MTP_string("tdesktop"),
|
MTP_string("tdesktop"),
|
||||||
MTP_int(_action->replyTo.bare),
|
MTP_int(action.replyTo.bare),
|
||||||
MTP_int(_action->topicRootId.bare),
|
MTP_int(action.topicRootId.bare),
|
||||||
(_action->options.sendAs
|
(action.options.sendAs
|
||||||
? _action->options.sendAs->input
|
? action.options.sendAs->input
|
||||||
: MTP_inputPeerEmpty())
|
: MTP_inputPeerEmpty())
|
||||||
)).done([=](const MTPWebViewResult &result) {
|
)).done([=](const MTPWebViewResult &result) {
|
||||||
_requestId = 0;
|
_requestId = 0;
|
||||||
|
@ -512,7 +571,7 @@ void AttachWebView::cancel() {
|
||||||
_session->api().request(base::take(_requestId)).cancel();
|
_session->api().request(base::take(_requestId)).cancel();
|
||||||
_session->api().request(base::take(_prolongId)).cancel();
|
_session->api().request(base::take(_prolongId)).cancel();
|
||||||
_panel = nullptr;
|
_panel = nullptr;
|
||||||
_action = std::nullopt;
|
_context = nullptr;
|
||||||
_bot = nullptr;
|
_bot = nullptr;
|
||||||
_botUsername = QString();
|
_botUsername = QString();
|
||||||
_startCommand = QString();
|
_startCommand = QString();
|
||||||
|
@ -551,21 +610,35 @@ void AttachWebView::requestBots() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachWebView::requestAddToMenu(
|
void AttachWebView::requestAddToMenu(
|
||||||
const std::optional<Api::SendAction> &action,
|
not_null<UserData*> bot,
|
||||||
|
const QString &startCommand) {
|
||||||
|
requestAddToMenu(bot, startCommand, nullptr, std::nullopt, PeerTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttachWebView::requestAddToMenu(
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
const QString &startCommand,
|
const QString &startCommand,
|
||||||
Window::SessionController *controller,
|
Window::SessionController *controller,
|
||||||
|
std::optional<Api::SendAction> action,
|
||||||
PeerTypes chooseTypes) {
|
PeerTypes chooseTypes) {
|
||||||
|
Expects(controller != nullptr || _context != nullptr);
|
||||||
|
|
||||||
if (!bot->isBot() || !bot->botInfo->supportsAttachMenu) {
|
if (!bot->isBot() || !bot->botInfo->supportsAttachMenu) {
|
||||||
Ui::ShowMultilineToast({
|
Ui::ShowMultilineToast({
|
||||||
.text = { tr::lng_bot_menu_not_supported(tr::now) },
|
.text = { tr::lng_bot_menu_not_supported(tr::now) },
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const auto wasController = (controller != nullptr);
|
||||||
_addToMenuChooseController = base::make_weak(controller);
|
_addToMenuChooseController = base::make_weak(controller);
|
||||||
_addToMenuStartCommand = startCommand;
|
_addToMenuStartCommand = startCommand;
|
||||||
_addToMenuChooseTypes = chooseTypes;
|
_addToMenuChooseTypes = chooseTypes;
|
||||||
_addToMenuAction = action;
|
if (!controller) {
|
||||||
|
_addToMenuContext = base::take(_context);
|
||||||
|
} else if (action) {
|
||||||
|
_addToMenuContext = std::make_unique<Context>(
|
||||||
|
LookupContext(controller, *action));
|
||||||
|
}
|
||||||
if (_addToMenuId) {
|
if (_addToMenuId) {
|
||||||
if (_addToMenuBot == bot) {
|
if (_addToMenuBot == bot) {
|
||||||
return;
|
return;
|
||||||
|
@ -578,32 +651,35 @@ void AttachWebView::requestAddToMenu(
|
||||||
)).done([=](const MTPAttachMenuBotsBot &result) {
|
)).done([=](const MTPAttachMenuBotsBot &result) {
|
||||||
_addToMenuId = 0;
|
_addToMenuId = 0;
|
||||||
const auto bot = base::take(_addToMenuBot);
|
const auto bot = base::take(_addToMenuBot);
|
||||||
const auto contextAction = base::take(_addToMenuAction);
|
const auto context = std::shared_ptr(base::take(_addToMenuContext));
|
||||||
const auto chooseTypes = base::take(_addToMenuChooseTypes);
|
const auto chooseTypes = base::take(_addToMenuChooseTypes);
|
||||||
const auto startCommand = base::take(_addToMenuStartCommand);
|
const auto startCommand = base::take(_addToMenuStartCommand);
|
||||||
const auto chooseController = base::take(_addToMenuChooseController);
|
const auto chooseController = base::take(_addToMenuChooseController);
|
||||||
const auto open = [=](PeerTypes types) {
|
const auto open = [=](PeerTypes types) {
|
||||||
if (const auto useTypes = chooseTypes & types) {
|
const auto strong = chooseController.get();
|
||||||
if (const auto strong = chooseController.get()) {
|
if (!strong) {
|
||||||
const auto done = [=](not_null<Data::Thread*> thread) {
|
if (wasController) {
|
||||||
strong->showThread(thread);
|
// Just ignore the click if controller was destroyed.
|
||||||
request(
|
return true;
|
||||||
nullptr,
|
|
||||||
Api::SendAction(thread),
|
|
||||||
bot,
|
|
||||||
{ .startCommand = startCommand });
|
|
||||||
};
|
|
||||||
ShowChooseBox(strong, useTypes, done);
|
|
||||||
}
|
}
|
||||||
|
} else if (const auto useTypes = chooseTypes & types) {
|
||||||
|
const auto done = [=](not_null<Data::Thread*> thread) {
|
||||||
|
strong->showThread(thread);
|
||||||
|
requestWithOptionalConfirm(
|
||||||
|
bot,
|
||||||
|
{ .startCommand = startCommand },
|
||||||
|
LookupContext(strong, Api::SendAction(thread)));
|
||||||
|
};
|
||||||
|
ShowChooseBox(strong, useTypes, done);
|
||||||
return true;
|
return true;
|
||||||
} else if (!contextAction) {
|
}
|
||||||
|
if (!context) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
request(
|
requestWithOptionalConfirm(
|
||||||
nullptr,
|
|
||||||
*contextAction,
|
|
||||||
bot,
|
bot,
|
||||||
{ .startCommand = startCommand });
|
{ .startCommand = startCommand },
|
||||||
|
*context);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
result.match([&](const MTPDattachMenuBotsBot &data) {
|
result.match([&](const MTPDattachMenuBotsBot &data) {
|
||||||
|
@ -630,7 +706,7 @@ void AttachWebView::requestAddToMenu(
|
||||||
}).fail([=] {
|
}).fail([=] {
|
||||||
_addToMenuId = 0;
|
_addToMenuId = 0;
|
||||||
_addToMenuBot = nullptr;
|
_addToMenuBot = nullptr;
|
||||||
_addToMenuAction = std::nullopt;
|
_addToMenuContext = nullptr;
|
||||||
_addToMenuStartCommand = QString();
|
_addToMenuStartCommand = QString();
|
||||||
Ui::ShowMultilineToast({
|
Ui::ShowMultilineToast({
|
||||||
.text = { tr::lng_bot_menu_not_supported(tr::now) },
|
.text = { tr::lng_bot_menu_not_supported(tr::now) },
|
||||||
|
@ -648,6 +724,9 @@ void AttachWebView::removeFromMenu(not_null<UserData*> bot) {
|
||||||
|
|
||||||
void AttachWebView::resolve() {
|
void AttachWebView::resolve() {
|
||||||
resolveUsername(_botUsername, [=](not_null<PeerData*> bot) {
|
resolveUsername(_botUsername, [=](not_null<PeerData*> bot) {
|
||||||
|
if (!_context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_bot = bot->asUser();
|
_bot = bot->asUser();
|
||||||
if (!_bot) {
|
if (!_bot) {
|
||||||
Ui::ShowMultilineToast({
|
Ui::ShowMultilineToast({
|
||||||
|
@ -655,7 +734,7 @@ void AttachWebView::resolve() {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
requestAddToMenu(_action, _bot, _startCommand);
|
requestAddToMenu(_bot, _startCommand);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -696,7 +775,10 @@ void AttachWebView::requestSimple(
|
||||||
const WebViewButton &button) {
|
const WebViewButton &button) {
|
||||||
cancel();
|
cancel();
|
||||||
_bot = bot;
|
_bot = bot;
|
||||||
_action = Api::SendAction(bot->owner().history(bot));
|
_context = std::make_unique<Context>(LookupContext(
|
||||||
|
controller,
|
||||||
|
Api::SendAction(bot->owner().history(bot))));
|
||||||
|
_context->fromSwitch = button.fromSwitch;
|
||||||
confirmOpen(controller, [=] {
|
confirmOpen(controller, [=] {
|
||||||
requestSimple(button);
|
requestSimple(button);
|
||||||
});
|
});
|
||||||
|
@ -705,7 +787,8 @@ void AttachWebView::requestSimple(
|
||||||
void AttachWebView::requestSimple(const WebViewButton &button) {
|
void AttachWebView::requestSimple(const WebViewButton &button) {
|
||||||
using Flag = MTPmessages_RequestSimpleWebView::Flag;
|
using Flag = MTPmessages_RequestSimpleWebView::Flag;
|
||||||
_requestId = _session->api().request(MTPmessages_RequestSimpleWebView(
|
_requestId = _session->api().request(MTPmessages_RequestSimpleWebView(
|
||||||
MTP_flags(Flag::f_theme_params),
|
MTP_flags(Flag::f_theme_params
|
||||||
|
| (button.fromSwitch ? Flag::f_from_switch_webview : Flag())),
|
||||||
_bot->inputUser,
|
_bot->inputUser,
|
||||||
MTP_bytes(button.url),
|
MTP_bytes(button.url),
|
||||||
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)),
|
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)),
|
||||||
|
@ -726,29 +809,32 @@ void AttachWebView::requestMenu(
|
||||||
not_null<UserData*> bot) {
|
not_null<UserData*> bot) {
|
||||||
cancel();
|
cancel();
|
||||||
_bot = bot;
|
_bot = bot;
|
||||||
_action = Api::SendAction(bot->owner().history(bot));
|
_context = std::make_unique<Context>(LookupContext(
|
||||||
|
controller,
|
||||||
|
Api::SendAction(bot->owner().history(bot))));
|
||||||
const auto url = bot->botInfo->botMenuButtonUrl;
|
const auto url = bot->botInfo->botMenuButtonUrl;
|
||||||
const auto text = bot->botInfo->botMenuButtonText;
|
const auto text = bot->botInfo->botMenuButtonText;
|
||||||
confirmOpen(controller, [=] {
|
confirmOpen(controller, [=] {
|
||||||
|
const auto &action = _context->action;
|
||||||
using Flag = MTPmessages_RequestWebView::Flag;
|
using Flag = MTPmessages_RequestWebView::Flag;
|
||||||
_requestId = _session->api().request(MTPmessages_RequestWebView(
|
_requestId = _session->api().request(MTPmessages_RequestWebView(
|
||||||
MTP_flags(Flag::f_theme_params
|
MTP_flags(Flag::f_theme_params
|
||||||
| Flag::f_url
|
| Flag::f_url
|
||||||
| Flag::f_from_bot_menu
|
| Flag::f_from_bot_menu
|
||||||
| (_action->replyTo? Flag::f_reply_to_msg_id : Flag(0))
|
| (action.replyTo? Flag::f_reply_to_msg_id : Flag(0))
|
||||||
| (_action->topicRootId ? Flag::f_top_msg_id : Flag(0))
|
| (action.topicRootId ? Flag::f_top_msg_id : Flag(0))
|
||||||
| (_action->options.sendAs ? Flag::f_send_as : Flag(0))
|
| (action.options.sendAs ? Flag::f_send_as : Flag(0))
|
||||||
| (_action->options.silent ? Flag::f_silent : Flag(0))),
|
| (action.options.silent ? Flag::f_silent : Flag(0))),
|
||||||
_action->history->peer->input,
|
action.history->peer->input,
|
||||||
_bot->inputUser,
|
_bot->inputUser,
|
||||||
MTP_string(url),
|
MTP_string(url),
|
||||||
MTPstring(), // start_param
|
MTPstring(), // start_param
|
||||||
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)),
|
MTP_dataJSON(MTP_bytes(Window::Theme::WebViewParams().json)),
|
||||||
MTP_string("tdesktop"),
|
MTP_string("tdesktop"),
|
||||||
MTP_int(_action->replyTo.bare),
|
MTP_int(action.replyTo.bare),
|
||||||
MTP_int(_action->topicRootId.bare),
|
MTP_int(action.topicRootId.bare),
|
||||||
(_action->options.sendAs
|
(action.options.sendAs
|
||||||
? _action->options.sendAs->input
|
? action.options.sendAs->input
|
||||||
: MTP_inputPeerEmpty())
|
: MTP_inputPeerEmpty())
|
||||||
)).done([=](const MTPWebViewResult &result) {
|
)).done([=](const MTPWebViewResult &result) {
|
||||||
_requestId = 0;
|
_requestId = 0;
|
||||||
|
@ -801,13 +887,16 @@ void AttachWebView::show(
|
||||||
const QString &url,
|
const QString &url,
|
||||||
const QString &buttonText,
|
const QString &buttonText,
|
||||||
bool allowClipboardRead) {
|
bool allowClipboardRead) {
|
||||||
Expects(_bot != nullptr && _action.has_value());
|
Expects(_bot != nullptr && _context != nullptr);
|
||||||
|
|
||||||
const auto close = crl::guard(this, [=] {
|
const auto close = crl::guard(this, [=] {
|
||||||
crl::on_main(this, [=] { cancel(); });
|
crl::on_main(this, [=] { cancel(); });
|
||||||
});
|
});
|
||||||
const auto sendData = crl::guard(this, [=](QByteArray data) {
|
const auto sendData = crl::guard(this, [=](QByteArray data) {
|
||||||
if (!_action || _action->history->peer != _bot || queryId) {
|
if (!_context
|
||||||
|
|| _context->fromSwitch
|
||||||
|
|| _context->action.history->peer != _bot
|
||||||
|
|| queryId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto randomId = base::RandomValue<uint64>();
|
const auto randomId = base::RandomValue<uint64>();
|
||||||
|
@ -821,6 +910,43 @@ void AttachWebView::show(
|
||||||
}).send();
|
}).send();
|
||||||
crl::on_main(this, [=] { cancel(); });
|
crl::on_main(this, [=] { cancel(); });
|
||||||
});
|
});
|
||||||
|
const auto switchInlineQuery = crl::guard(this, [=](
|
||||||
|
std::vector<QString> typeNames,
|
||||||
|
QString query) {
|
||||||
|
const auto controller = _context
|
||||||
|
? _context->controller.get()
|
||||||
|
: nullptr;
|
||||||
|
const auto types = PeerTypesFromNames(typeNames);
|
||||||
|
if (!_bot
|
||||||
|
|| !_bot->isBot()
|
||||||
|
|| _bot->botInfo->inlinePlaceholder.isEmpty()
|
||||||
|
|| !controller) {
|
||||||
|
return;
|
||||||
|
} else if (!types) {
|
||||||
|
if (_context->dialogsEntryState.key.owningHistory()) {
|
||||||
|
controller->switchInlineQuery(
|
||||||
|
_context->dialogsEntryState,
|
||||||
|
_bot,
|
||||||
|
query);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const auto botAndQuery = '@'
|
||||||
|
+ _bot->username()
|
||||||
|
+ ' '
|
||||||
|
+ query;
|
||||||
|
const auto done = [=](not_null<Data::Thread*> thread) {
|
||||||
|
return controller->content()->inlineSwitchChosen(
|
||||||
|
thread,
|
||||||
|
botAndQuery);
|
||||||
|
};
|
||||||
|
ShowChooseBox(
|
||||||
|
controller,
|
||||||
|
types,
|
||||||
|
done,
|
||||||
|
tr::lng_inline_switch_choose());
|
||||||
|
}
|
||||||
|
crl::on_main(this, [=] { cancel(); });
|
||||||
|
});
|
||||||
const auto handleLocalUri = [close](QString uri) {
|
const auto handleLocalUri = [close](QString uri) {
|
||||||
const auto local = Core::TryConvertUrlToLocal(uri);
|
const auto local = Core::TryConvertUrlToLocal(uri);
|
||||||
if (uri == local || Core::InternalPassportLink(local)) {
|
if (uri == local || Core::InternalPassportLink(local)) {
|
||||||
|
@ -868,7 +994,8 @@ void AttachWebView::show(
|
||||||
const auto hasSettings = (attached != end(_attachBots))
|
const auto hasSettings = (attached != end(_attachBots))
|
||||||
&& !attached->inactive
|
&& !attached->inactive
|
||||||
&& attached->hasSettings;
|
&& attached->hasSettings;
|
||||||
const auto hasOpenBot = !_action || (_bot != _action->history->peer);
|
const auto hasOpenBot = !_context
|
||||||
|
|| (_bot != _context->action.history->peer);
|
||||||
const auto hasRemoveFromMenu = (attached != end(_attachBots))
|
const auto hasRemoveFromMenu = (attached != end(_attachBots))
|
||||||
&& !attached->inactive;
|
&& !attached->inactive;
|
||||||
const auto buttons = (hasSettings ? Button::Settings : Button::None)
|
const auto buttons = (hasSettings ? Button::Settings : Button::None)
|
||||||
|
@ -919,6 +1046,7 @@ void AttachWebView::show(
|
||||||
.handleLocalUri = handleLocalUri,
|
.handleLocalUri = handleLocalUri,
|
||||||
.handleInvoice = handleInvoice,
|
.handleInvoice = handleInvoice,
|
||||||
.sendData = sendData,
|
.sendData = sendData,
|
||||||
|
.switchInlineQuery = switchInlineQuery,
|
||||||
.close = close,
|
.close = close,
|
||||||
.phone = _session->user()->phone(),
|
.phone = _session->user()->phone(),
|
||||||
.menuButtons = buttons,
|
.menuButtons = buttons,
|
||||||
|
@ -931,7 +1059,11 @@ void AttachWebView::show(
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachWebView::started(uint64 queryId) {
|
void AttachWebView::started(uint64 queryId) {
|
||||||
Expects(_action.has_value() && _bot != nullptr);
|
Expects(_bot != nullptr && _context != nullptr);
|
||||||
|
|
||||||
|
if (_context->fromSwitch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_session->data().webViewResultSent(
|
_session->data().webViewResultSent(
|
||||||
) | rpl::filter([=](const Data::Session::WebViewResultSent &sent) {
|
) | rpl::filter([=](const Data::Session::WebViewResultSent &sent) {
|
||||||
|
@ -940,6 +1072,7 @@ void AttachWebView::started(uint64 queryId) {
|
||||||
cancel();
|
cancel();
|
||||||
}, _panel->lifetime());
|
}, _panel->lifetime());
|
||||||
|
|
||||||
|
const auto action = _context->action;
|
||||||
base::timer_each(
|
base::timer_each(
|
||||||
kProlongTimeout
|
kProlongTimeout
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
|
@ -947,17 +1080,17 @@ void AttachWebView::started(uint64 queryId) {
|
||||||
_session->api().request(base::take(_prolongId)).cancel();
|
_session->api().request(base::take(_prolongId)).cancel();
|
||||||
_prolongId = _session->api().request(MTPmessages_ProlongWebView(
|
_prolongId = _session->api().request(MTPmessages_ProlongWebView(
|
||||||
MTP_flags(Flag(0)
|
MTP_flags(Flag(0)
|
||||||
| (_action->replyTo ? Flag::f_reply_to_msg_id : Flag(0))
|
| (action.replyTo ? Flag::f_reply_to_msg_id : Flag(0))
|
||||||
| (_action->topicRootId ? Flag::f_top_msg_id : Flag(0))
|
| (action.topicRootId ? Flag::f_top_msg_id : Flag(0))
|
||||||
| (_action->options.sendAs ? Flag::f_send_as : Flag(0))
|
| (action.options.sendAs ? Flag::f_send_as : Flag(0))
|
||||||
| (_action->options.silent ? Flag::f_silent : Flag(0))),
|
| (action.options.silent ? Flag::f_silent : Flag(0))),
|
||||||
_action->history->peer->input,
|
action.history->peer->input,
|
||||||
_bot->inputUser,
|
_bot->inputUser,
|
||||||
MTP_long(queryId),
|
MTP_long(queryId),
|
||||||
MTP_int(_action->replyTo.bare),
|
MTP_int(action.replyTo.bare),
|
||||||
MTP_int(_action->topicRootId.bare),
|
MTP_int(action.topicRootId.bare),
|
||||||
(_action->options.sendAs
|
(action.options.sendAs
|
||||||
? _action->options.sendAs->input
|
? action.options.sendAs->input
|
||||||
: MTP_inputPeerEmpty())
|
: MTP_inputPeerEmpty())
|
||||||
)).done([=] {
|
)).done([=] {
|
||||||
_prolongId = 0;
|
_prolongId = 0;
|
||||||
|
@ -1041,6 +1174,7 @@ void AttachWebView::toggleInMenu(
|
||||||
|
|
||||||
std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Fn<Api::SendAction()> actionFactory,
|
Fn<Api::SendAction()> actionFactory,
|
||||||
Fn<void(bool)> attach) {
|
Fn<void(bool)> attach) {
|
||||||
|
@ -1076,7 +1210,7 @@ std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
||||||
}
|
}
|
||||||
const auto callback = [=] {
|
const auto callback = [=] {
|
||||||
bots->request(
|
bots->request(
|
||||||
nullptr,
|
controller,
|
||||||
actionFactory(),
|
actionFactory(),
|
||||||
bot.user,
|
bot.user,
|
||||||
{ .fromMenu = true });
|
{ .fromMenu = true });
|
||||||
|
|
|
@ -7,11 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "api/api_common.h"
|
|
||||||
#include "mtproto/sender.h"
|
#include "mtproto/sender.h"
|
||||||
#include "base/weak_ptr.h"
|
#include "base/weak_ptr.h"
|
||||||
#include "base/flags.h"
|
#include "base/flags.h"
|
||||||
|
|
||||||
|
namespace Api {
|
||||||
|
struct SendAction;
|
||||||
|
} // namespace Api
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class GenericBox;
|
class GenericBox;
|
||||||
class DropdownMenu;
|
class DropdownMenu;
|
||||||
|
@ -71,13 +74,15 @@ public:
|
||||||
QString startCommand;
|
QString startCommand;
|
||||||
QByteArray url;
|
QByteArray url;
|
||||||
bool fromMenu = false;
|
bool fromMenu = false;
|
||||||
|
bool fromSwitch = false;
|
||||||
};
|
};
|
||||||
void request(
|
void request(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
const Api::SendAction &action,
|
const Api::SendAction &action,
|
||||||
const QString &botUsername,
|
const QString &botUsername,
|
||||||
const QString &startCommand);
|
const QString &startCommand);
|
||||||
void request(
|
void request(
|
||||||
Window::SessionController *controller,
|
not_null<Window::SessionController*> controller,
|
||||||
const Api::SendAction &action,
|
const Api::SendAction &action,
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
const WebViewButton &button);
|
const WebViewButton &button);
|
||||||
|
@ -100,16 +105,34 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void requestAddToMenu(
|
void requestAddToMenu(
|
||||||
const std::optional<Api::SendAction> &action,
|
not_null<UserData*> bot,
|
||||||
|
const QString &startCommand);
|
||||||
|
void requestAddToMenu(
|
||||||
not_null<UserData*> bot,
|
not_null<UserData*> bot,
|
||||||
const QString &startCommand,
|
const QString &startCommand,
|
||||||
Window::SessionController *controller = nullptr,
|
Window::SessionController *controller,
|
||||||
PeerTypes chooseTypes = {});
|
std::optional<Api::SendAction> action,
|
||||||
|
PeerTypes chooseTypes);
|
||||||
void removeFromMenu(not_null<UserData*> bot);
|
void removeFromMenu(not_null<UserData*> bot);
|
||||||
|
|
||||||
static void ClearAll();
|
static void ClearAll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct Context;
|
||||||
|
|
||||||
|
[[nodiscard]] static Context LookupContext(
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
|
const Api::SendAction &action);
|
||||||
|
[[nodiscard]] static bool IsSame(
|
||||||
|
const std::unique_ptr<Context> &a,
|
||||||
|
const Context &b);
|
||||||
|
|
||||||
|
void requestWithOptionalConfirm(
|
||||||
|
not_null<UserData*> bot,
|
||||||
|
const WebViewButton &button,
|
||||||
|
const Context &context,
|
||||||
|
Window::SessionController *controllerForConfirm = nullptr);
|
||||||
|
|
||||||
void resolve();
|
void resolve();
|
||||||
void request(const WebViewButton &button);
|
void request(const WebViewButton &button);
|
||||||
void requestSimple(const WebViewButton &button);
|
void requestSimple(const WebViewButton &button);
|
||||||
|
@ -143,7 +166,7 @@ private:
|
||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
|
|
||||||
std::optional<Api::SendAction> _action;
|
std::unique_ptr<Context> _context;
|
||||||
UserData *_bot = nullptr;
|
UserData *_bot = nullptr;
|
||||||
QString _botUsername;
|
QString _botUsername;
|
||||||
QString _startCommand;
|
QString _startCommand;
|
||||||
|
@ -155,7 +178,7 @@ private:
|
||||||
uint64 _botsHash = 0;
|
uint64 _botsHash = 0;
|
||||||
mtpRequestId _botsRequestId = 0;
|
mtpRequestId _botsRequestId = 0;
|
||||||
|
|
||||||
std::optional<Api::SendAction> _addToMenuAction;
|
std::unique_ptr<Context> _addToMenuContext;
|
||||||
UserData *_addToMenuBot = nullptr;
|
UserData *_addToMenuBot = nullptr;
|
||||||
mtpRequestId _addToMenuId = 0;
|
mtpRequestId _addToMenuId = 0;
|
||||||
QString _addToMenuStartCommand;
|
QString _addToMenuStartCommand;
|
||||||
|
@ -171,6 +194,7 @@ private:
|
||||||
|
|
||||||
[[nodiscard]] std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
[[nodiscard]] std::unique_ptr<Ui::DropdownMenu> MakeAttachBotsMenu(
|
||||||
not_null<QWidget*> parent,
|
not_null<QWidget*> parent,
|
||||||
|
not_null<Window::SessionController*> controller,
|
||||||
not_null<PeerData*> peer,
|
not_null<PeerData*> peer,
|
||||||
Fn<Api::SendAction()> actionFactory,
|
Fn<Api::SendAction()> actionFactory,
|
||||||
Fn<void(bool)> attach);
|
Fn<void(bool)> attach);
|
||||||
|
|
|
@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
#include "data/data_chat_participant_status.h"
|
#include "data/data_chat_participant_status.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "inline_bots/bot_attach_web_view.h"
|
||||||
#include "inline_bots/inline_bot_result.h"
|
#include "inline_bots/inline_bot_result.h"
|
||||||
#include "inline_bots/inline_bot_layout_item.h"
|
#include "inline_bots/inline_bot_layout_item.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
@ -453,6 +454,7 @@ void Inner::refreshSwitchPmButton(const CacheEntry *entry) {
|
||||||
if (!entry || entry->switchPmText.isEmpty()) {
|
if (!entry || entry->switchPmText.isEmpty()) {
|
||||||
_switchPmButton.destroy();
|
_switchPmButton.destroy();
|
||||||
_switchPmStartToken.clear();
|
_switchPmStartToken.clear();
|
||||||
|
_switchPmUrl = QByteArray();
|
||||||
} else {
|
} else {
|
||||||
if (!_switchPmButton) {
|
if (!_switchPmButton) {
|
||||||
_switchPmButton.create(this, nullptr, st::switchPmButton);
|
_switchPmButton.create(this, nullptr, st::switchPmButton);
|
||||||
|
@ -462,6 +464,7 @@ void Inner::refreshSwitchPmButton(const CacheEntry *entry) {
|
||||||
}
|
}
|
||||||
_switchPmButton->setText(rpl::single(entry->switchPmText));
|
_switchPmButton->setText(rpl::single(entry->switchPmText));
|
||||||
_switchPmStartToken = entry->switchPmStartToken;
|
_switchPmStartToken = entry->switchPmStartToken;
|
||||||
|
_switchPmUrl = entry->switchPmUrl;
|
||||||
const auto buttonTop = st::stickerPanPadding;
|
const auto buttonTop = st::stickerPanPadding;
|
||||||
_switchPmButton->move(st::inlineResultsLeft - st::roundRadiusSmall, buttonTop);
|
_switchPmButton->move(st::inlineResultsLeft - st::roundRadiusSmall, buttonTop);
|
||||||
if (isRestrictedView()) {
|
if (isRestrictedView()) {
|
||||||
|
@ -667,9 +670,17 @@ void Inner::repaintItems(crl::time now) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Inner::switchPm() {
|
void Inner::switchPm() {
|
||||||
if (_inlineBot && _inlineBot->isBot()) {
|
if (!_inlineBot || !_inlineBot->isBot()) {
|
||||||
|
return;
|
||||||
|
} else if (!_switchPmUrl.isEmpty()) {
|
||||||
|
_inlineBot->session().attachWebView().requestSimple(
|
||||||
|
_controller,
|
||||||
|
_inlineBot,
|
||||||
|
{ .url = _switchPmUrl, .fromSwitch = true });
|
||||||
|
} else {
|
||||||
_inlineBot->botInfo->startToken = _switchPmStartToken;
|
_inlineBot->botInfo->startToken = _switchPmStartToken;
|
||||||
_inlineBot->botInfo->inlineReturnTo = _currentDialogsEntryState;
|
_inlineBot->botInfo->inlineReturnTo
|
||||||
|
= _controller->currentDialogsEntryState();
|
||||||
_controller->showPeerHistory(
|
_controller->showPeerHistory(
|
||||||
_inlineBot,
|
_inlineBot,
|
||||||
Window::SectionShow::Way::ClearStack,
|
Window::SectionShow::Way::ClearStack,
|
||||||
|
|
|
@ -54,7 +54,9 @@ using Results = std::vector<std::unique_ptr<Result>>;
|
||||||
|
|
||||||
struct CacheEntry {
|
struct CacheEntry {
|
||||||
QString nextOffset;
|
QString nextOffset;
|
||||||
QString switchPmText, switchPmStartToken;
|
QString switchPmText;
|
||||||
|
QString switchPmStartToken;
|
||||||
|
QByteArray switchPmUrl;
|
||||||
Results results;
|
Results results;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -87,9 +89,6 @@ public:
|
||||||
void setResultSelectedCallback(Fn<void(ResultSelected)> callback) {
|
void setResultSelectedCallback(Fn<void(ResultSelected)> callback) {
|
||||||
_resultSelectedCallback = std::move(callback);
|
_resultSelectedCallback = std::move(callback);
|
||||||
}
|
}
|
||||||
void setCurrentDialogsEntryState(Dialogs::EntryState state) {
|
|
||||||
_currentDialogsEntryState = state;
|
|
||||||
}
|
|
||||||
void setSendMenuType(Fn<SendMenu::Type()> &&callback);
|
void setSendMenuType(Fn<SendMenu::Type()> &&callback);
|
||||||
|
|
||||||
// Ui::AbstractTooltipShower interface.
|
// Ui::AbstractTooltipShower interface.
|
||||||
|
@ -160,7 +159,7 @@ private:
|
||||||
|
|
||||||
object_ptr<Ui::RoundButton> _switchPmButton = { nullptr };
|
object_ptr<Ui::RoundButton> _switchPmButton = { nullptr };
|
||||||
QString _switchPmStartToken;
|
QString _switchPmStartToken;
|
||||||
Dialogs::EntryState _currentDialogsEntryState;
|
QByteArray _switchPmUrl;
|
||||||
|
|
||||||
object_ptr<Ui::FlatLabel> _restrictedLabel = { nullptr };
|
object_ptr<Ui::FlatLabel> _restrictedLabel = { nullptr };
|
||||||
|
|
||||||
|
|
|
@ -263,10 +263,6 @@ void Widget::setSendMenuType(Fn<SendMenu::Type()> &&callback) {
|
||||||
_inner->setSendMenuType(std::move(callback));
|
_inner->setSendMenuType(std::move(callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::setCurrentDialogsEntryState(Dialogs::EntryState state) {
|
|
||||||
_inner->setCurrentDialogsEntryState(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Widget::hideAnimated() {
|
void Widget::hideAnimated() {
|
||||||
if (isHidden()) return;
|
if (isHidden()) return;
|
||||||
if (_hiding) return;
|
if (_hiding) return;
|
||||||
|
@ -384,13 +380,16 @@ void Widget::inlineResultsDone(const MTPmessages_BotResults &result) {
|
||||||
auto entry = it->second.get();
|
auto entry = it->second.get();
|
||||||
entry->nextOffset = qs(d.vnext_offset().value_or_empty());
|
entry->nextOffset = qs(d.vnext_offset().value_or_empty());
|
||||||
if (const auto switchPm = d.vswitch_pm()) {
|
if (const auto switchPm = d.vswitch_pm()) {
|
||||||
switchPm->match([&](const MTPDinlineBotSwitchPM &data) {
|
entry->switchPmText = qs(switchPm->data().vtext());
|
||||||
entry->switchPmText = qs(data.vtext());
|
entry->switchPmStartToken = qs(switchPm->data().vstart_param());
|
||||||
entry->switchPmStartToken = qs(data.vstart_param());
|
entry->switchPmUrl = QByteArray();
|
||||||
});
|
} else if (const auto switchWebView = d.vswitch_webview()) {
|
||||||
|
entry->switchPmText = qs(switchWebView->data().vtext());
|
||||||
|
entry->switchPmStartToken = QString();
|
||||||
|
entry->switchPmUrl = switchWebView->data().vurl().v;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto count = v.size()) {
|
if (const auto count = v.size()) {
|
||||||
entry->results.reserve(entry->results.size() + count);
|
entry->results.reserve(entry->results.size() + count);
|
||||||
}
|
}
|
||||||
auto added = 0;
|
auto added = 0;
|
||||||
|
|
|
@ -76,7 +76,6 @@ public:
|
||||||
|
|
||||||
void setResultSelectedCallback(Fn<void(ResultSelected)> callback);
|
void setResultSelectedCallback(Fn<void(ResultSelected)> callback);
|
||||||
void setSendMenuType(Fn<SendMenu::Type()> &&callback);
|
void setSendMenuType(Fn<SendMenu::Type()> &&callback);
|
||||||
void setCurrentDialogsEntryState(Dialogs::EntryState state);
|
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<bool> requesting() const {
|
[[nodiscard]] rpl::producer<bool> requesting() const {
|
||||||
return _requesting.events();
|
return _requesting.events();
|
||||||
|
|
|
@ -1341,7 +1341,9 @@ void MainWidget::showHistory(
|
||||||
_controller->window().activate();
|
_controller->window().activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(_history->peer() && _history->peer()->id == peerId)
|
const auto alreadyThatPeer = _history->peer()
|
||||||
|
&& (_history->peer()->id == peerId);
|
||||||
|
if (!alreadyThatPeer
|
||||||
&& preventsCloseSection(
|
&& preventsCloseSection(
|
||||||
[=] { showHistory(peerId, params, showAtMsgId); },
|
[=] { showHistory(peerId, params, showAtMsgId); },
|
||||||
params)) {
|
params)) {
|
||||||
|
@ -1424,17 +1426,24 @@ void MainWidget::showHistory(
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto animationParams = animatedShow() ? prepareHistoryAnimation(peerId) : Window::SectionSlideParams();
|
auto animationParams = animatedShow()
|
||||||
|
? prepareHistoryAnimation(peerId)
|
||||||
|
: Window::SectionSlideParams();
|
||||||
|
|
||||||
if (!back && (way != Way::ClearStack)) {
|
if (!back && (way != Way::ClearStack)) {
|
||||||
// This may modify the current section, for example remove its contents.
|
// This may modify the current section, for example remove its contents.
|
||||||
saveSectionInStack();
|
saveSectionInStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_history->peer() && _history->peer()->id != peerId && way != Way::Forward) {
|
if (_history->peer()
|
||||||
|
&& _history->peer()->id != peerId
|
||||||
|
&& way != Way::Forward) {
|
||||||
clearBotStartToken(_history->peer());
|
clearBotStartToken(_history->peer());
|
||||||
}
|
}
|
||||||
_history->showHistory(peerId, showAtMsgId);
|
_history->showHistory(peerId, showAtMsgId);
|
||||||
|
if (alreadyThatPeer && params.reapplyLocalDraft) {
|
||||||
|
_history->applyDraft(HistoryWidget::FieldHistoryAction::NewEntry);
|
||||||
|
}
|
||||||
|
|
||||||
auto noPeer = !_history->peer();
|
auto noPeer = !_history->peer();
|
||||||
auto onlyDialogs = noPeer && isOneColumn();
|
auto onlyDialogs = noPeer && isOneColumn();
|
||||||
|
|
|
@ -318,6 +318,7 @@ Panel::Panel(
|
||||||
Fn<bool(QString)> handleLocalUri,
|
Fn<bool(QString)> handleLocalUri,
|
||||||
Fn<void(QString)> handleInvoice,
|
Fn<void(QString)> handleInvoice,
|
||||||
Fn<void(QByteArray)> sendData,
|
Fn<void(QByteArray)> sendData,
|
||||||
|
Fn<void(std::vector<QString>, QString)> switchInlineQuery,
|
||||||
Fn<void()> close,
|
Fn<void()> close,
|
||||||
QString phone,
|
QString phone,
|
||||||
MenuButtons menuButtons,
|
MenuButtons menuButtons,
|
||||||
|
@ -328,6 +329,7 @@ Panel::Panel(
|
||||||
, _handleLocalUri(std::move(handleLocalUri))
|
, _handleLocalUri(std::move(handleLocalUri))
|
||||||
, _handleInvoice(std::move(handleInvoice))
|
, _handleInvoice(std::move(handleInvoice))
|
||||||
, _sendData(std::move(sendData))
|
, _sendData(std::move(sendData))
|
||||||
|
, _switchInlineQuery(std::move(switchInlineQuery))
|
||||||
, _close(std::move(close))
|
, _close(std::move(close))
|
||||||
, _phone(phone)
|
, _phone(phone)
|
||||||
, _menuButtons(menuButtons)
|
, _menuButtons(menuButtons)
|
||||||
|
@ -625,6 +627,8 @@ bool Panel::createWebview() {
|
||||||
_close();
|
_close();
|
||||||
} else if (command == "web_app_data_send") {
|
} else if (command == "web_app_data_send") {
|
||||||
sendDataMessage(arguments);
|
sendDataMessage(arguments);
|
||||||
|
} else if (command == "web_app_switch_inline_query") {
|
||||||
|
switchInlineQueryMessage(arguments);
|
||||||
} else if (command == "web_app_setup_main_button") {
|
} else if (command == "web_app_setup_main_button") {
|
||||||
processMainButtonMessage(arguments);
|
processMainButtonMessage(arguments);
|
||||||
} else if (command == "web_app_setup_back_button") {
|
} else if (command == "web_app_setup_back_button") {
|
||||||
|
@ -702,6 +706,38 @@ void Panel::sendDataMessage(const QJsonObject &args) {
|
||||||
_sendData(data.toUtf8());
|
_sendData(data.toUtf8());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Panel::switchInlineQueryMessage(const QJsonObject &args) {
|
||||||
|
if (args.isEmpty()) {
|
||||||
|
_close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto query = args["query"].toString();
|
||||||
|
if (query.isEmpty()) {
|
||||||
|
LOG(("BotWebView Error: Bad 'query' in switchInlineQueryMessage."));
|
||||||
|
_close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto valid = base::flat_set<QString>{
|
||||||
|
u"users"_q,
|
||||||
|
u"bots"_q,
|
||||||
|
u"groups"_q,
|
||||||
|
u"channels"_q,
|
||||||
|
};
|
||||||
|
auto types = std::vector<QString>();
|
||||||
|
for (const auto &value : args["chat_types"].toArray()) {
|
||||||
|
const auto type = value.toString();
|
||||||
|
if (valid.contains(type)) {
|
||||||
|
types.push_back(type);
|
||||||
|
} else {
|
||||||
|
LOG(("BotWebView Error: "
|
||||||
|
"Bad chat type in switchInlineQueryMessage: %1.").arg(type));
|
||||||
|
types.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_switchInlineQuery(types, query);
|
||||||
|
}
|
||||||
|
|
||||||
void Panel::openTgLink(const QJsonObject &args) {
|
void Panel::openTgLink(const QJsonObject &args) {
|
||||||
if (args.isEmpty()) {
|
if (args.isEmpty()) {
|
||||||
_close();
|
_close();
|
||||||
|
@ -1129,6 +1165,7 @@ std::unique_ptr<Panel> Show(Args &&args) {
|
||||||
std::move(args.handleLocalUri),
|
std::move(args.handleLocalUri),
|
||||||
std::move(args.handleInvoice),
|
std::move(args.handleInvoice),
|
||||||
std::move(args.sendData),
|
std::move(args.sendData),
|
||||||
|
std::move(args.switchInlineQuery),
|
||||||
std::move(args.close),
|
std::move(args.close),
|
||||||
args.phone,
|
args.phone,
|
||||||
args.menuButtons,
|
args.menuButtons,
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
Fn<bool(QString)> handleLocalUri,
|
Fn<bool(QString)> handleLocalUri,
|
||||||
Fn<void(QString)> handleInvoice,
|
Fn<void(QString)> handleInvoice,
|
||||||
Fn<void(QByteArray)> sendData,
|
Fn<void(QByteArray)> sendData,
|
||||||
|
Fn<void(std::vector<QString>, QString)> switchInlineQuery,
|
||||||
Fn<void()> close,
|
Fn<void()> close,
|
||||||
QString phone,
|
QString phone,
|
||||||
MenuButtons menuButtons,
|
MenuButtons menuButtons,
|
||||||
|
@ -88,6 +89,7 @@ private:
|
||||||
void hideWebviewProgress();
|
void hideWebviewProgress();
|
||||||
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 processMainButtonMessage(const QJsonObject &args);
|
void processMainButtonMessage(const QJsonObject &args);
|
||||||
void processBackButtonMessage(const QJsonObject &args);
|
void processBackButtonMessage(const QJsonObject &args);
|
||||||
void openTgLink(const QJsonObject &args);
|
void openTgLink(const QJsonObject &args);
|
||||||
|
@ -116,6 +118,7 @@ private:
|
||||||
Fn<bool(QString)> _handleLocalUri;
|
Fn<bool(QString)> _handleLocalUri;
|
||||||
Fn<void(QString)> _handleInvoice;
|
Fn<void(QString)> _handleInvoice;
|
||||||
Fn<void(QByteArray)> _sendData;
|
Fn<void(QByteArray)> _sendData;
|
||||||
|
Fn<void(std::vector<QString>, QString)> _switchInlineQuery;
|
||||||
Fn<void()> _close;
|
Fn<void()> _close;
|
||||||
QString _phone;
|
QString _phone;
|
||||||
bool _closeNeedConfirmation = false;
|
bool _closeNeedConfirmation = false;
|
||||||
|
@ -147,6 +150,7 @@ struct Args {
|
||||||
Fn<bool(QString)> handleLocalUri;
|
Fn<bool(QString)> handleLocalUri;
|
||||||
Fn<void(QString)> handleInvoice;
|
Fn<void(QString)> handleInvoice;
|
||||||
Fn<void(QByteArray)> sendData;
|
Fn<void(QByteArray)> sendData;
|
||||||
|
Fn<void(std::vector<QString>, QString)> switchInlineQuery;
|
||||||
Fn<void()> close;
|
Fn<void()> close;
|
||||||
QString phone;
|
QString phone;
|
||||||
MenuButtons menuButtons;
|
MenuButtons menuButtons;
|
||||||
|
|
|
@ -434,6 +434,7 @@ void SessionNavigation::showPeerByLinkResolved(
|
||||||
const auto history = peer->owner().history(peer);
|
const auto history = peer->owner().history(peer);
|
||||||
showPeerHistory(history, params, msgId);
|
showPeerHistory(history, params, msgId);
|
||||||
peer->session().attachWebView().request(
|
peer->session().attachWebView().request(
|
||||||
|
parentController(),
|
||||||
Api::SendAction(history),
|
Api::SendAction(history),
|
||||||
attachBotUsername,
|
attachBotUsername,
|
||||||
info.attachBotToggleCommand.value_or(QString()));
|
info.attachBotToggleCommand.value_or(QString()));
|
||||||
|
@ -448,13 +449,13 @@ void SessionNavigation::showPeerByLinkResolved(
|
||||||
? contextPeer->asUser()
|
? contextPeer->asUser()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
bot->session().attachWebView().requestAddToMenu(
|
bot->session().attachWebView().requestAddToMenu(
|
||||||
|
bot,
|
||||||
|
*info.attachBotToggleCommand,
|
||||||
|
parentController(),
|
||||||
(contextUser
|
(contextUser
|
||||||
? Api::SendAction(
|
? Api::SendAction(
|
||||||
contextUser->owner().history(contextUser))
|
contextUser->owner().history(contextUser))
|
||||||
: std::optional<Api::SendAction>()),
|
: std::optional<Api::SendAction>()),
|
||||||
bot,
|
|
||||||
*info.attachBotToggleCommand,
|
|
||||||
parentController(),
|
|
||||||
info.attachBotChooseTypes);
|
info.attachBotChooseTypes);
|
||||||
} else {
|
} else {
|
||||||
crl::on_main(this, [=] {
|
crl::on_main(this, [=] {
|
||||||
|
@ -1150,6 +1151,54 @@ bool SessionController::jumpToChatListEntry(Dialogs::RowDescriptor row) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionController::setCurrentDialogsEntryState(
|
||||||
|
Dialogs::EntryState state) {
|
||||||
|
_currentDialogsEntryState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialogs::EntryState SessionController::currentDialogsEntryState() const {
|
||||||
|
return _currentDialogsEntryState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionController::switchInlineQuery(
|
||||||
|
Dialogs::EntryState to,
|
||||||
|
not_null<UserData*> bot,
|
||||||
|
const QString &query) {
|
||||||
|
Expects(to.key.owningHistory() != nullptr);
|
||||||
|
|
||||||
|
using Section = Dialogs::EntryState::Section;
|
||||||
|
|
||||||
|
const auto history = to.key.owningHistory();
|
||||||
|
const auto textWithTags = TextWithTags{
|
||||||
|
'@' + bot->username() + ' ' + query,
|
||||||
|
TextWithTags::Tags(),
|
||||||
|
};
|
||||||
|
MessageCursor cursor = { int(textWithTags.text.size()), int(textWithTags.text.size()), QFIXED_MAX };
|
||||||
|
auto draft = std::make_unique<Data::Draft>(
|
||||||
|
textWithTags,
|
||||||
|
to.currentReplyToId,
|
||||||
|
to.rootId,
|
||||||
|
cursor,
|
||||||
|
Data::PreviewState::Allowed);
|
||||||
|
|
||||||
|
auto params = Window::SectionShow();
|
||||||
|
params.reapplyLocalDraft = true;
|
||||||
|
if (to.section == Section::Scheduled) {
|
||||||
|
history->setDraft(Data::DraftKey::Scheduled(), std::move(draft));
|
||||||
|
showSection(
|
||||||
|
std::make_shared<HistoryView::ScheduledMemento>(history),
|
||||||
|
params);
|
||||||
|
} else {
|
||||||
|
history->setLocalDraft(std::move(draft));
|
||||||
|
if (to.section == Section::Replies) {
|
||||||
|
const auto commentId = MsgId();
|
||||||
|
showRepliesForMessage(history, to.rootId, commentId, params);
|
||||||
|
} else {
|
||||||
|
showPeerHistory(history->peer, params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Dialogs::RowDescriptor SessionController::resolveChatNext(
|
Dialogs::RowDescriptor SessionController::resolveChatNext(
|
||||||
Dialogs::RowDescriptor from) const {
|
Dialogs::RowDescriptor from) const {
|
||||||
return content()->resolveChatNext(from);
|
return content()->resolveChatNext(from);
|
||||||
|
|
|
@ -171,6 +171,7 @@ struct SectionShow {
|
||||||
anim::activation activation = anim::activation::normal;
|
anim::activation activation = anim::activation::normal;
|
||||||
bool thirdColumn = false;
|
bool thirdColumn = false;
|
||||||
bool childColumn = false;
|
bool childColumn = false;
|
||||||
|
bool reapplyLocalDraft = false;
|
||||||
Origin origin;
|
Origin origin;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -373,6 +374,13 @@ public:
|
||||||
rpl::producer<Dialogs::Key> activeChatValue() const;
|
rpl::producer<Dialogs::Key> activeChatValue() const;
|
||||||
bool jumpToChatListEntry(Dialogs::RowDescriptor row);
|
bool jumpToChatListEntry(Dialogs::RowDescriptor row);
|
||||||
|
|
||||||
|
void setCurrentDialogsEntryState(Dialogs::EntryState state);
|
||||||
|
[[nodiscard]] Dialogs::EntryState currentDialogsEntryState() const;
|
||||||
|
void switchInlineQuery(
|
||||||
|
Dialogs::EntryState to,
|
||||||
|
not_null<UserData*> bot,
|
||||||
|
const QString &query);
|
||||||
|
|
||||||
[[nodiscard]] Dialogs::RowDescriptor resolveChatNext(
|
[[nodiscard]] Dialogs::RowDescriptor resolveChatNext(
|
||||||
Dialogs::RowDescriptor from = {}) const;
|
Dialogs::RowDescriptor from = {}) const;
|
||||||
[[nodiscard]] Dialogs::RowDescriptor resolveChatPrevious(
|
[[nodiscard]] Dialogs::RowDescriptor resolveChatPrevious(
|
||||||
|
@ -635,6 +643,8 @@ private:
|
||||||
int _chatEntryHistoryPosition = -1;
|
int _chatEntryHistoryPosition = -1;
|
||||||
bool _filtersActivated = false;
|
bool _filtersActivated = false;
|
||||||
|
|
||||||
|
Dialogs::EntryState _currentDialogsEntryState;
|
||||||
|
|
||||||
base::Timer _invitePeekTimer;
|
base::Timer _invitePeekTimer;
|
||||||
|
|
||||||
rpl::variable<FilterId> _activeChatsFilter;
|
rpl::variable<FilterId> _activeChatsFilter;
|
||||||
|
|
Loading…
Add table
Reference in a new issue