mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 23:53:58 +02:00
Handle bot command clicks in Replies / Scheduled.
This commit is contained in:
parent
ac02e2be9e
commit
cf6ca3b1ac
25 changed files with 210 additions and 73 deletions
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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;
|
Main::Session *session = nullptr;
|
||||||
HashtagMentionType type = HashtagMentionType::Telegram;
|
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;
|
||||||
|
|
|
@ -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));
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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() };
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(
|
||||||
|
|
Loading…
Add table
Reference in a new issue