Handle bot command clicks in Replies / Scheduled.

This commit is contained in:
John Preston 2020-11-10 19:38:21 +03:00
parent ac02e2be9e
commit cf6ca3b1ac
25 changed files with 210 additions and 73 deletions

View file

@ -180,20 +180,14 @@ auto CashtagClickHandler::getTextEntity() const -> TextEntity {
return { EntityType::Cashtag }; return { EntityType::Cashtag };
} }
PeerData *BotCommandClickHandler::_peer = nullptr;
UserData *BotCommandClickHandler::_bot = nullptr;
void BotCommandClickHandler::onClick(ClickContext context) const { void BotCommandClickHandler::onClick(ClickContext context) const {
const auto button = context.button; const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) { if (button == Qt::LeftButton || button == Qt::MiddleButton) {
if (auto peer = peerForCommand()) { const auto my = context.other.value<ClickHandlerContext>();
if (auto bot = peer->isUser() ? peer->asUser() : botForCommand()) { if (const auto delegate = my.elementDelegate ? my.elementDelegate() : nullptr) {
Ui::showPeerHistory(peer, ShowAtTheEndMsgId); delegate->elementSendBotCommand(_cmd, my.itemId);
App::sendBotCommand(peer, bot, _cmd); return;
return; } else if (auto peer = Ui::getPeerForMouseAction()) { // old way
}
}
if (auto peer = Ui::getPeerForMouseAction()) { // old way
auto bot = peer->isUser() ? peer->asUser() : nullptr; auto bot = peer->isUser() ? peer->asUser() : nullptr;
if (!bot) { if (!bot) {
if (const auto view = App::hoveredLinkItem()) { if (const auto view = App::hoveredLinkItem()) {

View file

@ -13,8 +13,18 @@ namespace Main {
class Session; class Session;
} // namespace Main } // namespace Main
namespace HistoryView {
class ElementDelegate;
} // namespace HistoryView
[[nodiscard]] bool UrlRequiresConfirmation(const QUrl &url); [[nodiscard]] bool UrlRequiresConfirmation(const QUrl &url);
struct ClickHandlerContext {
FullMsgId itemId;
Fn<HistoryView::ElementDelegate*()> elementDelegate;
};
Q_DECLARE_METATYPE(ClickHandlerContext);
class HiddenUrlClickHandler : public UrlClickHandler { class HiddenUrlClickHandler : public UrlClickHandler {
public: public:
HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) { HiddenUrlClickHandler(QString url) : UrlClickHandler(url, false) {
@ -165,30 +175,14 @@ public:
return _cmd; return _cmd;
} }
static void setPeerForCommand(PeerData *peer) {
_peer = peer;
}
static void setBotForCommand(UserData *bot) {
_bot = bot;
}
TextEntity getTextEntity() const override; TextEntity getTextEntity() const override;
protected: protected:
QString url() const override { QString url() const override {
return _cmd; return _cmd;
} }
static PeerData *peerForCommand() {
return _peer;
}
static UserData *botForCommand() {
return _bot;
}
private: private:
QString _cmd; QString _cmd;
static PeerData *_peer;
static UserData *_bot;
}; };

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "core/update_checker.h" #include "core/update_checker.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h"
#include "boxes/confirm_phone_box.h" #include "boxes/confirm_phone_box.h"
#include "boxes/background_preview_box.h" #include "boxes/background_preview_box.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
@ -76,11 +77,11 @@ bool ShowTheme(
if (!controller) { if (!controller) {
return false; return false;
} }
const auto clickFromMessageId = context.value<FullMsgId>(); const auto fromMessageId = context.value<ClickHandlerContext>().itemId;
Core::App().hideMediaView(); Core::App().hideMediaView();
controller->session().data().cloudThemes().resolve( controller->session().data().cloudThemes().resolve(
match->captured(1), match->captured(1),
clickFromMessageId); fromMessageId);
return true; return true;
} }
@ -280,7 +281,7 @@ bool ResolveUsername(
startToken = gameParam; startToken = gameParam;
post = ShowAtGameShareMsgId; post = ShowAtGameShareMsgId;
} }
const auto clickFromMessageId = context.value<FullMsgId>(); const auto fromMessageId = context.value<ClickHandlerContext>().itemId;
using Navigation = Window::SessionNavigation; using Navigation = Window::SessionNavigation;
controller->showPeerByLink(Navigation::PeerByLinkInfo{ controller->showPeerByLink(Navigation::PeerByLinkInfo{
.usernameOrId = domain, .usernameOrId = domain,
@ -295,7 +296,7 @@ bool ResolveUsername(
} }
: Navigation::RepliesByLinkInfo{ v::null }, : Navigation::RepliesByLinkInfo{ v::null },
.startToken = startToken, .startToken = startToken,
.clickFromMessageId = clickFromMessageId, .clickFromMessageId = fromMessageId,
}); });
return true; return true;
} }
@ -319,7 +320,7 @@ bool ResolvePrivatePost(
if (!channelId || !IsServerMsgId(msgId)) { if (!channelId || !IsServerMsgId(msgId)) {
return false; return false;
} }
const auto clickFromMessageId = context.value<FullMsgId>(); const auto fromMessageId = context.value<ClickHandlerContext>().itemId;
using Navigation = Window::SessionNavigation; using Navigation = Window::SessionNavigation;
controller->showPeerByLink(Navigation::PeerByLinkInfo{ controller->showPeerByLink(Navigation::PeerByLinkInfo{
.usernameOrId = channelId, .usernameOrId = channelId,
@ -333,7 +334,7 @@ bool ResolvePrivatePost(
Navigation::ThreadId{ threadId } Navigation::ThreadId{ threadId }
} }
: Navigation::RepliesByLinkInfo{ v::null }, : Navigation::RepliesByLinkInfo{ v::null },
.clickFromMessageId = clickFromMessageId, .clickFromMessageId = fromMessageId,
}); });
return true; return true;
} }

View file

@ -65,7 +65,7 @@ QString UiIntegration::timeFormat() {
std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler( std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
const EntityLinkData &data, const EntityLinkData &data,
const std::any &context) { const std::any &context) {
const auto my = std::any_cast<Context>(&context); const auto my = std::any_cast<MarkedTextContext>(&context);
switch (data.type) { switch (data.type) {
case EntityType::Url: case EntityType::Url:
return (!data.data.isEmpty() return (!data.data.isEmpty()
@ -82,6 +82,7 @@ std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
return std::make_shared<BotCommandClickHandler>(data.data); return std::make_shared<BotCommandClickHandler>(data.data);
case EntityType::Hashtag: case EntityType::Hashtag:
using HashtagMentionType = MarkedTextContext::HashtagMentionType;
if (my && my->type == HashtagMentionType::Twitter) { if (my && my->type == HashtagMentionType::Twitter) {
return std::make_shared<UrlClickHandler>( return std::make_shared<UrlClickHandler>(
(qsl("https://twitter.com/hashtag/") (qsl("https://twitter.com/hashtag/")
@ -101,6 +102,7 @@ std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
return std::make_shared<CashtagClickHandler>(data.data); return std::make_shared<CashtagClickHandler>(data.data);
case EntityType::Mention: case EntityType::Mention:
using HashtagMentionType = MarkedTextContext::HashtagMentionType;
if (my && my->type == HashtagMentionType::Twitter) { if (my && my->type == HashtagMentionType::Twitter) {
return std::make_shared<UrlClickHandler>( return std::make_shared<UrlClickHandler>(
qsl("https://twitter.com/") + data.data.mid(1), qsl("https://twitter.com/") + data.data.mid(1),

View file

@ -13,20 +13,25 @@ namespace Main {
class Session; class Session;
} // namespace Main } // namespace Main
namespace HistoryView {
class ElementDelegate;
} // namespace HistoryView
namespace Core { namespace Core {
class UiIntegration : public Ui::Integration { struct MarkedTextContext {
public:
enum class HashtagMentionType : uchar { enum class HashtagMentionType : uchar {
Telegram, Telegram,
Twitter, Twitter,
Instagram, Instagram,
}; };
struct Context {
Main::Session *session = nullptr;
HashtagMentionType type = HashtagMentionType::Telegram;
};
Main::Session *session = nullptr;
HashtagMentionType type = HashtagMentionType::Telegram;
};
class UiIntegration : public Ui::Integration {
public:
void postponeCall(FnMut<void()> &&callable) override; void postponeCall(FnMut<void()> &&callable) override;
void registerLeaveSubscription(not_null<QWidget*> widget) override; void registerLeaveSubscription(not_null<QWidget*> widget) override;
void unregisterLeaveSubscription(not_null<QWidget*> widget) override; void unregisterLeaveSubscription(not_null<QWidget*> widget) override;

View file

@ -600,6 +600,11 @@ bool InnerWidget::elementShownUnread(not_null<const Element*> view) {
return view->data()->unread(); return view->data()->unread();
} }
void InnerWidget::elementSendBotCommand(
const QString &command,
const FullMsgId &context) {
}
void InnerWidget::saveState(not_null<SectionMemento*> memento) { void InnerWidget::saveState(not_null<SectionMemento*> memento) {
memento->setFilter(std::move(_filter)); memento->setFilter(std::move(_filter));
memento->setAdmins(std::move(_admins)); memento->setAdmins(std::move(_admins));

View file

@ -116,6 +116,9 @@ public:
not_null<const HistoryView::Element*> view) override; not_null<const HistoryView::Element*> view) override;
bool elementShownUnread( bool elementShownUnread(
not_null<const HistoryView::Element*> view) override; not_null<const HistoryView::Element*> view) override;
void elementSendBotCommand(
const QString &command,
const FullMsgId &context) override;
~InnerWidget(); ~InnerWidget();

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <rpl/merge.h> #include <rpl/merge.h>
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "core/crash_reports.h" #include "core/crash_reports.h"
#include "core/click_handler_types.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_message.h" #include "history/history_message.h"
#include "history/view/media/history_view_media.h" #include "history/view/media/history_view_media.h"
@ -1330,7 +1331,14 @@ void HistoryInner::mouseActionFinish(
: FullMsgId(); : FullMsgId();
ActivateClickHandler(window(), activated, { ActivateClickHandler(window(), activated, {
button, button,
QVariant::fromValue(pressedItemId) QVariant::fromValue(ClickHandlerContext{
.itemId = pressedItemId,
.elementDelegate = [weak = Ui::MakeWeak(this)] {
return weak
? HistoryInner::ElementDelegate().get()
: nullptr;
},
})
}); });
return; return;
} }
@ -2540,6 +2548,24 @@ bool HistoryInner::elementIsGifPaused() {
return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any); return _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
} }
void HistoryInner::elementSendBotCommand(
const QString &command,
const FullMsgId &context) {
if (auto peer = Ui::getPeerForMouseAction()) { // old way
auto bot = peer->isUser() ? peer->asUser() : nullptr;
if (!bot) {
if (const auto view = App::hoveredLinkItem()) {
// may return nullptr
bot = view->data()->fromOriginal()->asUser();
}
}
Ui::showPeerHistory(peer, ShowAtTheEndMsgId);
App::sendBotCommand(peer, bot, command);
} else {
App::insertBotCommand(command);
}
}
auto HistoryInner::getSelectionState() const auto HistoryInner::getSelectionState() const
-> HistoryView::TopBarWidget::SelectedState { -> HistoryView::TopBarWidget::SelectedState {
auto result = HistoryView::TopBarWidget::SelectedState {}; auto result = HistoryView::TopBarWidget::SelectedState {};
@ -3434,6 +3460,13 @@ not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
bool elementShownUnread(not_null<const Element*> view) override { bool elementShownUnread(not_null<const Element*> view) override {
return view->data()->unread(); return view->data()->unread();
} }
void elementSendBotCommand(
const QString &command,
const FullMsgId &context) {
if (Instance) {
Instance->elementSendBotCommand(command, context);
}
}
}; };
static Result result; static Result result;

View file

@ -92,6 +92,9 @@ public:
const TextWithEntities &text, const TextWithEntities &text,
Fn<void()> hiddenCallback); Fn<void()> hiddenCallback);
bool elementIsGifPaused(); bool elementIsGifPaused();
void elementSendBotCommand(
const QString &command,
const FullMsgId &context);
void updateBotInfo(bool recount = true); void updateBotInfo(bool recount = true);

View file

@ -1464,7 +1464,7 @@ void HistoryMessage::setText(const TextWithEntities &textWithEntities) {
} }
clearIsolatedEmoji(); clearIsolatedEmoji();
const auto context = Core::UiIntegration::Context{ const auto context = Core::MarkedTextContext{
.session = &history()->session() .session = &history()->session()
}; };
_text.setMarkedText( _text.setMarkedText(

View file

@ -3405,15 +3405,9 @@ void HistoryWidget::sendBotCommand(
bool lastKeyboardUsed = (_keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)) && (_keyboard->forMsgId() == FullMsgId(_channel, replyTo)); bool lastKeyboardUsed = (_keyboard->forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)) && (_keyboard->forMsgId() == FullMsgId(_channel, replyTo));
QString toSend = cmd; const auto toSend = replyTo
if (bot && (!bot->isUser() || !bot->asUser()->isBot())) { ? cmd
bot = nullptr; : HistoryView::WrapBotCommandInChat(_peer, cmd, bot);
}
QString username = bot ? bot->asUser()->username : QString();
int32 botStatus = _peer->isChat() ? _peer->asChat()->botStatus : (_peer->isMegagroup() ? _peer->asChannel()->mgInfo->botStatus : -1);
if (!replyTo && toSend.indexOf('@') < 2 && !username.isEmpty() && (botStatus == 0 || botStatus == 2)) {
toSend += '@' + username;
}
auto message = ApiWrap::MessageToSend(_history); auto message = ApiWrap::MessageToSend(_history);
message.textWithTags = { toSend, TextWithTags::Tags() }; message.textWithTags = { toSend, TextWithTags::Tags() };

View file

@ -121,6 +121,11 @@ bool SimpleElementDelegate::elementShownUnread(
return view->data()->unread(); return view->data()->unread();
} }
void SimpleElementDelegate::elementSendBotCommand(
const QString &command,
const FullMsgId &context) {
}
TextSelection UnshiftItemSelection( TextSelection UnshiftItemSelection(
TextSelection selection, TextSelection selection,
uint16 byLength) { uint16 byLength) {

View file

@ -67,6 +67,9 @@ public:
virtual bool elementIsGifPaused() = 0; virtual bool elementIsGifPaused() = 0;
virtual bool elementHideReply(not_null<const Element*> view) = 0; virtual bool elementHideReply(not_null<const Element*> view) = 0;
virtual bool elementShownUnread(not_null<const Element*> view) = 0; virtual bool elementShownUnread(not_null<const Element*> view) = 0;
virtual void elementSendBotCommand(
const QString &command,
const FullMsgId &context) = 0;
}; };
@ -99,6 +102,9 @@ public:
bool elementIsGifPaused() override; bool elementIsGifPaused() override;
bool elementHideReply(not_null<const Element*> view) override; bool elementHideReply(not_null<const Element*> view) override;
bool elementShownUnread(not_null<const Element*> view) override; bool elementShownUnread(not_null<const Element*> view) override;
void elementSendBotCommand(
const QString &command,
const FullMsgId &context) override;
private: private:
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;

View file

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h" #include "mainwindow.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "layout.h" #include "layout.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
@ -37,6 +38,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_media_types.h" #include "data/data_media_types.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_peer.h" #include "data/data_peer.h"
#include "data/data_user.h"
#include "data/data_chat.h"
#include "data/data_channel.h"
#include "facades.h" #include "facades.h"
#include "styles/style_chat.h" #include "styles/style_chat.h"
@ -1290,6 +1294,12 @@ bool ListWidget::elementShownUnread(not_null<const Element*> view) {
return _delegate->listElementShownUnread(view); return _delegate->listElementShownUnread(view);
} }
void ListWidget::elementSendBotCommand(
const QString &command,
const FullMsgId &context) {
return _delegate->listSendBotCommand(command, context);
}
void ListWidget::saveState(not_null<ListMemento*> memento) { void ListWidget::saveState(not_null<ListMemento*> memento) {
memento->setAroundPosition(_aroundPosition); memento->setAroundPosition(_aroundPosition);
auto state = countScrollState(); auto state = countScrollState();
@ -2186,7 +2196,14 @@ void ListWidget::mouseActionFinish(
mouseActionCancel(); mouseActionCancel();
ActivateClickHandler(window(), activated, { ActivateClickHandler(window(), activated, {
button, button,
QVariant::fromValue(pressState.itemId) QVariant::fromValue(ClickHandlerContext{
.itemId = pressState.itemId,
.elementDelegate = [weak = Ui::MakeWeak(this)] {
return weak
? (ElementDelegate*)weak
: nullptr;
},
})
}); });
return; return;
} }
@ -2786,4 +2803,34 @@ void ConfirmSendNowSelectedItems(not_null<ListWidget*> widget) {
[=] { navigation->showBackFromStack(); }); [=] { navigation->showBackFromStack(); });
} }
QString WrapBotCommandInChat(
not_null<PeerData*> peer,
const QString &command,
const FullMsgId &context) {
auto result = command;
if (const auto item = peer->owner().message(context)) {
if (const auto user = item->fromOriginal()->asUser()) {
return WrapBotCommandInChat(peer, command, user);
}
}
return result;
}
QString WrapBotCommandInChat(
not_null<PeerData*> peer,
const QString &command,
not_null<UserData*> bot) {
if (!bot->isBot() || bot->username.isEmpty()) {
return command;
}
const auto botStatus = peer->isChat()
? peer->asChat()->botStatus
: peer->isMegagroup()
? peer->asChannel()->mgInfo->botStatus
: -1;
return ((command.indexOf('@') < 2) && (botStatus == 0 || botStatus == 2))
? command + '@' + bot->username
: command;
}
} // namespace HistoryView } // namespace HistoryView

View file

@ -87,6 +87,9 @@ public:
virtual bool listElementShownUnread(not_null<const Element*> view) = 0; virtual bool listElementShownUnread(not_null<const Element*> view) = 0;
virtual bool listIsGoodForAroundPosition( virtual bool listIsGoodForAroundPosition(
not_null<const Element*> view) = 0; not_null<const Element*> view) = 0;
virtual void listSendBotCommand(
const QString &command,
const FullMsgId &context) = 0;
}; };
@ -233,6 +236,9 @@ public:
bool elementIsGifPaused() override; bool elementIsGifPaused() override;
bool elementHideReply(not_null<const Element*> view) override; bool elementHideReply(not_null<const Element*> view) override;
bool elementShownUnread(not_null<const Element*> view) override; bool elementShownUnread(not_null<const Element*> view) override;
void elementSendBotCommand(
const QString &command,
const FullMsgId &context) override;
~ListWidget(); ~ListWidget();
@ -556,4 +562,13 @@ void ConfirmDeleteSelectedItems(not_null<ListWidget*> widget);
void ConfirmForwardSelectedItems(not_null<ListWidget*> widget); void ConfirmForwardSelectedItems(not_null<ListWidget*> widget);
void ConfirmSendNowSelectedItems(not_null<ListWidget*> widget); void ConfirmSendNowSelectedItems(not_null<ListWidget*> widget);
[[nodiscard]] QString WrapBotCommandInChat(
not_null<PeerData*> peer,
const QString &command,
const FullMsgId &context);
[[nodiscard]] QString WrapBotCommandInChat(
not_null<PeerData*> peer,
const QString &command,
not_null<UserData*> bot);
} // namespace HistoryView } // namespace HistoryView

View file

@ -639,6 +639,11 @@ bool PinnedWidget::listIsGoodForAroundPosition(
return IsServerMsgId(view->data()->id); return IsServerMsgId(view->data()->id);
} }
void PinnedWidget::listSendBotCommand(
const QString &command,
const FullMsgId &context) {
}
void PinnedWidget::confirmDeleteSelected() { void PinnedWidget::confirmDeleteSelected() {
ConfirmDeleteSelectedItems(_inner); ConfirmDeleteSelectedItems(_inner);
} }

View file

@ -93,6 +93,9 @@ public:
bool listElementHideReply(not_null<const Element*> view) override; bool listElementHideReply(not_null<const Element*> view) override;
bool listElementShownUnread(not_null<const Element*> view) override; bool listElementShownUnread(not_null<const Element*> view) override;
bool listIsGoodForAroundPosition(not_null<const Element*> view) override; bool listIsGoodForAroundPosition(not_null<const Element*> view) override;
void listSendBotCommand(
const QString &command,
const FullMsgId &context) override;
protected: protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;

View file

@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_session.h" #include "main/main_session.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_chat.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_replies_list.h" #include "data/data_replies_list.h"
#include "data/data_changes.h" #include "data/data_changes.h"
@ -445,11 +446,7 @@ void RepliesWidget::setupComposeControls() {
if (showSlowmodeError()) { if (showSlowmodeError()) {
return; return;
} }
auto message = ApiWrap::MessageToSend(_history); listSendBotCommand(command, FullMsgId());
message.textWithTags = { command };
message.action.replyTo = replyToId();
session().api().sendMessage(std::move(message));
finishSending();
}, lifetime()); }, lifetime());
const auto saveEditMsgRequestId = lifetime().make_state<mtpRequestId>(0); const auto saveEditMsgRequestId = lifetime().make_state<mtpRequestId>(0);
@ -1766,6 +1763,17 @@ bool RepliesWidget::listIsGoodForAroundPosition(
return IsServerMsgId(view->data()->id); return IsServerMsgId(view->data()->id);
} }
void RepliesWidget::listSendBotCommand(
const QString &command,
const FullMsgId &context) {
const auto text = WrapBotCommandInChat(_history->peer, command, context);
auto message = ApiWrap::MessageToSend(_history);
message.textWithTags = { text };
message.action.replyTo = replyToId();
session().api().sendMessage(std::move(message));
finishSending();
}
void RepliesWidget::confirmDeleteSelected() { void RepliesWidget::confirmDeleteSelected() {
ConfirmDeleteSelectedItems(_inner); ConfirmDeleteSelectedItems(_inner);
} }

View file

@ -126,6 +126,9 @@ public:
bool listElementHideReply(not_null<const Element*> view) override; bool listElementHideReply(not_null<const Element*> view) override;
bool listElementShownUnread(not_null<const Element*> view) override; bool listElementShownUnread(not_null<const Element*> view) override;
bool listIsGoodForAroundPosition(not_null<const Element*> view) override; bool listIsGoodForAroundPosition(not_null<const Element*> view) override;
void listSendBotCommand(
const QString &command,
const FullMsgId &context) override;
protected: protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;

View file

@ -182,15 +182,7 @@ void ScheduledWidget::setupComposeControls() {
_composeControls->sendCommandRequests( _composeControls->sendCommandRequests(
) | rpl::start_with_next([=](const QString &command) { ) | rpl::start_with_next([=](const QString &command) {
const auto callback = [=](Api::SendOptions options) { listSendBotCommand(command, FullMsgId());
auto message = ApiWrap::MessageToSend(_history);
message.textWithTags = { command };
message.action.options = options;
session().api().sendMessage(std::move(message));
};
Ui::show(
PrepareScheduleBox(this, sendMenuType(), callback),
Ui::LayerOption::KeepOther);
}, lifetime()); }, lifetime());
const auto saveEditMsgRequestId = lifetime().make_state<mtpRequestId>(0); const auto saveEditMsgRequestId = lifetime().make_state<mtpRequestId>(0);
@ -1185,6 +1177,21 @@ bool ScheduledWidget::listIsGoodForAroundPosition(
return true; return true;
} }
void ScheduledWidget::listSendBotCommand(
const QString &command,
const FullMsgId &context) {
const auto callback = [=](Api::SendOptions options) {
const auto text = WrapBotCommandInChat(_history->peer, command, context);
auto message = ApiWrap::MessageToSend(_history);
message.textWithTags = { text };
message.action.options = options;
session().api().sendMessage(std::move(message));
};
Ui::show(
PrepareScheduleBox(this, sendMenuType(), callback),
Ui::LayerOption::KeepOther);
}
void ScheduledWidget::confirmSendNowSelected() { void ScheduledWidget::confirmSendNowSelected() {
ConfirmSendNowSelectedItems(_inner); ConfirmSendNowSelectedItems(_inner);
} }

View file

@ -110,6 +110,9 @@ public:
bool listElementHideReply(not_null<const Element*> view) override; bool listElementHideReply(not_null<const Element*> view) override;
bool listElementShownUnread(not_null<const Element*> view) override; bool listElementShownUnread(not_null<const Element*> view) override;
bool listIsGoodForAroundPosition(not_null<const Element *> view) override; bool listIsGoodForAroundPosition(not_null<const Element *> view) override;
void listSendBotCommand(
const QString &command,
const FullMsgId &context) override;
protected: protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;

View file

@ -33,7 +33,7 @@ Game::Game(
, _title(st::msgMinWidth - st::webPageLeft) , _title(st::msgMinWidth - st::webPageLeft)
, _description(st::msgMinWidth - st::webPageLeft) { , _description(st::msgMinWidth - st::webPageLeft) {
if (!consumed.text.isEmpty()) { if (!consumed.text.isEmpty()) {
const auto context = Core::UiIntegration::Context{ const auto context = Core::MarkedTextContext{
.session = &history()->session() .session = &history()->session()
}; };
_description.setMarkedText( _description.setMarkedText(
@ -418,7 +418,7 @@ void Game::parentTextUpdated() {
if (const auto media = _parent->data()->media()) { if (const auto media = _parent->data()->media()) {
const auto consumed = media->consumedMessageText(); const auto consumed = media->consumedMessageText();
if (!consumed.text.isEmpty()) { if (!consumed.text.isEmpty()) {
const auto context = Core::UiIntegration::Context{ const auto context = Core::MarkedTextContext{
.session = &history()->session() .session = &history()->session()
}; };
_description.setMarkedText( _description.setMarkedText(

View file

@ -139,7 +139,7 @@ Ui::Text::String Media::createCaption(
- st::msgPadding.left() - st::msgPadding.left()
- st::msgPadding.right(); - st::msgPadding.right();
auto result = Ui::Text::String(minResizeWidth); auto result = Ui::Text::String(minResizeWidth);
const auto context = Core::UiIntegration::Context{ const auto context = Core::MarkedTextContext{
.session = &history()->session() .session = &history()->session()
}; };
result.setMarkedText( result.setMarkedText(

View file

@ -201,11 +201,12 @@ QSize WebPage::countOptimalSize() {
- st::msgPadding.right() - st::msgPadding.right()
- st::webPageLeft); - st::webPageLeft);
} }
auto context = Core::UiIntegration::Context(); auto context = Core::MarkedTextContext();
using MarkedTextContext = Core::MarkedTextContext;
if (_data->siteName == qstr("Twitter")) { if (_data->siteName == qstr("Twitter")) {
context.type = Core::UiIntegration::HashtagMentionType::Twitter; context.type = MarkedTextContext::HashtagMentionType::Twitter;
} else if (_data->siteName == qstr("Instagram")) { } else if (_data->siteName == qstr("Instagram")) {
context.type = Core::UiIntegration::HashtagMentionType::Instagram; context.type = MarkedTextContext::HashtagMentionType::Instagram;
} }
_description.setMarkedText( _description.setMarkedText(
st::webPageDescriptionStyle, st::webPageDescriptionStyle,

View file

@ -2018,7 +2018,7 @@ void OverlayWidget::refreshCaption(HistoryItem *item) {
const auto base = duration const auto base = duration
? DocumentTimestampLinkBase(_document, item->fullId()) ? DocumentTimestampLinkBase(_document, item->fullId())
: QString(); : QString();
const auto context = Core::UiIntegration::Context{ const auto context = Core::MarkedTextContext{
.session = &item->history()->session() .session = &item->history()->session()
}; };
_caption.setMarkedText( _caption.setMarkedText(