Add start bot command and handle via@ links.

This commit is contained in:
John Preston 2020-11-10 21:51:20 +03:00
parent 10adbecb9c
commit 4f22171dd6
19 changed files with 122 additions and 12 deletions

View file

@ -605,6 +605,9 @@ void InnerWidget::elementSendBotCommand(
const FullMsgId &context) { const FullMsgId &context) {
} }
void InnerWidget::elementHandleViaClick(not_null<UserData*> bot) {
}
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

@ -119,6 +119,7 @@ public:
void elementSendBotCommand( void elementSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) override; const FullMsgId &context) override;
void elementHandleViaClick(not_null<UserData*> bot) override;
~InnerWidget(); ~InnerWidget();

View file

@ -2566,6 +2566,10 @@ void HistoryInner::elementSendBotCommand(
} }
} }
void HistoryInner::elementHandleViaClick(not_null<UserData*> bot) {
App::insertBotCommand('@' + bot->username);
}
auto HistoryInner::getSelectionState() const auto HistoryInner::getSelectionState() const
-> HistoryView::TopBarWidget::SelectedState { -> HistoryView::TopBarWidget::SelectedState {
auto result = HistoryView::TopBarWidget::SelectedState {}; auto result = HistoryView::TopBarWidget::SelectedState {};
@ -3462,11 +3466,16 @@ not_null<HistoryView::ElementDelegate*> HistoryInner::ElementDelegate() {
} }
void elementSendBotCommand( void elementSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) { const FullMsgId &context) override {
if (Instance) { if (Instance) {
Instance->elementSendBotCommand(command, context); Instance->elementSendBotCommand(command, context);
} }
} }
void elementHandleViaClick(not_null<UserData*> bot) override {
if (Instance) {
Instance->elementHandleViaClick(bot);
}
}
}; };
static Result result; static Result result;

View file

@ -95,6 +95,7 @@ public:
void elementSendBotCommand( void elementSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context); const FullMsgId &context);
void elementHandleViaClick(not_null<UserData*> bot);
void updateBotInfo(bool recount = true); void updateBotInfo(bool recount = true);

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_message.h" #include "history/history_message.h"
#include "history/view/history_view_service_message.h" #include "history/view/history_view_service_message.h"
#include "history/view/media/history_view_document.h" #include "history/view/media/history_view_document.h"
#include "core/click_handler_types.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "media/audio/media_audio.h" #include "media/audio/media_audio.h"
#include "media/player/media_player_instance.h" #include "media/player/media_player_instance.h"
@ -45,7 +46,8 @@ void HistoryMessageVia::create(
bot = owner->user(userId); bot = owner->user(userId);
maxWidth = st::msgServiceNameFont->width( maxWidth = st::msgServiceNameFont->width(
tr::lng_inline_bot_via(tr::now, lt_inline_bot, '@' + bot->username)); tr::lng_inline_bot_via(tr::now, lt_inline_bot, '@' + bot->username));
link = std::make_shared<LambdaClickHandler>([bot = this->bot] { link = std::make_shared<LambdaClickHandler>([bot = this->bot](
ClickContext context) {
if (QGuiApplication::keyboardModifiers() == Qt::ControlModifier) { if (QGuiApplication::keyboardModifiers() == Qt::ControlModifier) {
if (const auto window = App::wnd()) { if (const auto window = App::wnd()) {
if (const auto controller = window->sessionController()) { if (const auto controller = window->sessionController()) {
@ -54,7 +56,12 @@ void HistoryMessageVia::create(
} }
} }
} }
App::insertBotCommand('@' + bot->username); const auto my = context.other.value<ClickHandlerContext>();
if (const auto delegate = my.elementDelegate ? my.elementDelegate() : nullptr) {
delegate->elementHandleViaClick(bot);
} else {
App::insertBotCommand('@' + bot->username);
}
}); });
} }

View file

@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_messages.h" #include "data/data_messages.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/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
#include "data/data_web_page.h" #include "data/data_web_page.h"
@ -521,6 +522,9 @@ ComposeControls::ComposeControls(
st::historyComposeField, st::historyComposeField,
Ui::InputField::Mode::MultiLine, Ui::InputField::Mode::MultiLine,
tr::lng_message_ph())) tr::lng_message_ph()))
, _botCommandStart(Ui::CreateChild<Ui::IconButton>(
_wrap.get(),
st::historyBotCommandStart))
, _autocomplete(std::make_unique<FieldAutocomplete>( , _autocomplete(std::make_unique<FieldAutocomplete>(
parent, parent,
window)) window))
@ -562,7 +566,21 @@ void ComposeControls::setHistory(SetHistoryArgs &&args) {
_window->tabbedSelector()->setCurrentPeer( _window->tabbedSelector()->setCurrentPeer(
history ? history->peer.get() : nullptr); history ? history->peer.get() : nullptr);
initWebpageProcess(); initWebpageProcess();
updateBotCommandShown();
updateControlsGeometry(_wrap->size());
updateControlsVisibility();
updateFieldPlaceholder(); updateFieldPlaceholder();
if (!_history) {
return;
}
const auto peer = _history->peer;
if (peer->isChat() && peer->asChat()->noParticipantInfo()) {
session().api().requestFullPeer(peer);
} else if (const auto channel = peer->asMegagroup()) {
if (!channel->mgInfo->botStatus) {
session().api().requestBots(channel);
}
}
} }
void ComposeControls::move(int x, int y) { void ComposeControls::move(int x, int y) {
@ -791,6 +809,8 @@ void ComposeControls::init() {
initWriteRestriction(); initWriteRestriction();
initVoiceRecordBar(); initVoiceRecordBar();
_botCommandStart->setClickedCallback([=] { setText({ "/" }); });
_wrap->sizeValue( _wrap->sizeValue(
) | rpl::start_with_next([=](QSize size) { ) | rpl::start_with_next([=](QSize size) {
updateControlsGeometry(size); updateControlsGeometry(size);
@ -1051,6 +1071,10 @@ void ComposeControls::fieldChanged() {
if (showRecordButton()) { if (showRecordButton()) {
//_previewCancelled = false; //_previewCancelled = false;
} }
if (updateBotCommandShown()) {
updateControlsVisibility();
updateControlsGeometry(_wrap->size());
}
InvokeQueued(_autocomplete.get(), [=] { InvokeQueued(_autocomplete.get(), [=] {
updateInlineBotQuery(); updateInlineBotQuery();
updateStickersByEmoji(); updateStickersByEmoji();
@ -1297,13 +1321,14 @@ void ComposeControls::finishAnimating() {
void ComposeControls::updateControlsGeometry(QSize size) { void ComposeControls::updateControlsGeometry(QSize size) {
// _attachToggle -- _inlineResults ------ _tabbedPanel -- _fieldBarCancel // _attachToggle -- _inlineResults ------ _tabbedPanel -- _fieldBarCancel
// (_attachDocument|_attachPhoto) _field _tabbedSelectorToggle _send // (_attachDocument|_attachPhoto) _field _botCommandStart _tabbedSelectorToggle _send
const auto fieldWidth = size.width() const auto fieldWidth = size.width()
- _attachToggle->width() - _attachToggle->width()
- st::historySendRight - st::historySendRight
- _send->width() - _send->width()
- _tabbedSelectorToggle->width(); - _tabbedSelectorToggle->width()
- (_botCommandShown ? _botCommandStart->width() : 0);
_field->resizeToWidth(fieldWidth); _field->resizeToWidth(fieldWidth);
const auto buttonsTop = size.height() - _attachToggle->height(); const auto buttonsTop = size.height() - _attachToggle->height();
@ -1324,6 +1349,8 @@ void ComposeControls::updateControlsGeometry(QSize size) {
_send->moveToRight(right, buttonsTop); _send->moveToRight(right, buttonsTop);
right += _send->width(); right += _send->width();
_tabbedSelectorToggle->moveToRight(right, buttonsTop); _tabbedSelectorToggle->moveToRight(right, buttonsTop);
right += _tabbedSelectorToggle->width();
_botCommandStart->moveToRight(right, buttonsTop);
_voiceRecordBar->resizeToWidth(size.width()); _voiceRecordBar->resizeToWidth(size.width());
_voiceRecordBar->moveToLeft( _voiceRecordBar->moveToLeft(
@ -1331,6 +1358,28 @@ void ComposeControls::updateControlsGeometry(QSize size) {
size.height() - _voiceRecordBar->height()); size.height() - _voiceRecordBar->height());
} }
void ComposeControls::updateControlsVisibility() {
_botCommandStart->setVisible(_botCommandShown);
}
bool ComposeControls::updateBotCommandShown() {
auto shown = false;
const auto peer = _history ? _history->peer.get() : nullptr;
if (peer
&& ((peer->isChat() && peer->asChat()->botStatus > 0)
|| (peer->isMegagroup() && peer->asChannel()->mgInfo->botStatus > 0)
|| (peer->isUser() && peer->asUser()->isBot()))) {
if (!HasSendText(_field)) {
shown = true;
}
}
if (_botCommandShown != shown) {
_botCommandShown = shown;
return true;
}
return false;
}
void ComposeControls::updateOuterGeometry(QRect rect) { void ComposeControls::updateOuterGeometry(QRect rect) {
if (_inlineResults) { if (_inlineResults) {
_inlineResults->moveBottom(rect.y()); _inlineResults->moveBottom(rect.y());
@ -1604,7 +1653,7 @@ void ComposeControls::initWebpageProcess() {
getWebPagePreview(); getWebPagePreview();
}); });
_window->session().changes().peerUpdates( session().changes().peerUpdates(
Data::PeerUpdate::Flag::Rights Data::PeerUpdate::Flag::Rights
) | rpl::filter([=](const Data::PeerUpdate &update) { ) | rpl::filter([=](const Data::PeerUpdate &update) {
return (update.peer.get() == peer); return (update.peer.get() == peer);
@ -1614,7 +1663,18 @@ void ComposeControls::initWebpageProcess() {
updateFieldPlaceholder(); updateFieldPlaceholder();
}, lifetime); }, lifetime);
_window->session().downloaderTaskFinished( base::ObservableViewer(
session().api().fullPeerUpdated()
) | rpl::filter([=](PeerData *peer) {
return _history && (_history->peer == peer);
}) | rpl::start_with_next([=] {
if (updateBotCommandShown()) {
updateControlsVisibility();
updateControlsGeometry(_wrap->size());
}
}, lifetime);
session().downloaderTaskFinished(
) | rpl::filter([=] { ) | rpl::filter([=] {
return (*previewData) return (*previewData)
&& ((*previewData)->document || (*previewData)->photo); && ((*previewData)->document || (*previewData)->photo);
@ -1622,7 +1682,7 @@ void ComposeControls::initWebpageProcess() {
requestRepaint requestRepaint
), lifetime); ), lifetime);
_window->session().data().webPageUpdates( session().data().webPageUpdates(
) | rpl::filter([=](not_null<WebPageData*> page) { ) | rpl::filter([=](not_null<WebPageData*> page) {
return (*previewData == page.get()); return (*previewData == page.get());
}) | rpl::start_with_next([=] { }) | rpl::start_with_next([=] {
@ -1652,7 +1712,7 @@ WebPageId ComposeControls::webPageId() const {
rpl::producer<Data::MessagePosition> ComposeControls::scrollRequests() const { rpl::producer<Data::MessagePosition> ComposeControls::scrollRequests() const {
return _header->scrollToItemRequests( return _header->scrollToItemRequests(
) | rpl::map([=](FullMsgId id) -> Data::MessagePosition { ) | rpl::map([=](FullMsgId id) -> Data::MessagePosition {
if (const auto item = _window->session().data().message(id)) { if (const auto item = session().data().message(id)) {
return item->position(); return item->position();
} }
return {}; return {};

View file

@ -187,6 +187,7 @@ private:
bool showRecordButton() const; bool showRecordButton() const;
void drawRestrictedWrite(Painter &p, const QString &error); void drawRestrictedWrite(Painter &p, const QString &error);
void updateOverStates(QPoint pos); void updateOverStates(QPoint pos);
bool updateBotCommandShown();
void cancelInlineBot(); void cancelInlineBot();
void clearInlineBot(); void clearInlineBot();
@ -217,6 +218,8 @@ private:
const not_null<Ui::IconButton*> _attachToggle; const not_null<Ui::IconButton*> _attachToggle;
const not_null<Ui::EmojiButton*> _tabbedSelectorToggle; const not_null<Ui::EmojiButton*> _tabbedSelectorToggle;
const not_null<Ui::InputField*> _field; const not_null<Ui::InputField*> _field;
const not_null<Ui::IconButton*> _botCommandStart;
std::unique_ptr<InlineBots::Layout::Widget> _inlineResults; std::unique_ptr<InlineBots::Layout::Widget> _inlineResults;
std::unique_ptr<ChatHelpers::TabbedPanel> _tabbedPanel; std::unique_ptr<ChatHelpers::TabbedPanel> _tabbedPanel;
std::unique_ptr<FieldAutocomplete> _autocomplete; std::unique_ptr<FieldAutocomplete> _autocomplete;
@ -243,6 +246,7 @@ private:
bool _inlineLookingUpBot = false; bool _inlineLookingUpBot = false;
mtpRequestId _inlineBotResolveRequestId = 0; mtpRequestId _inlineBotResolveRequestId = 0;
bool _isInlineBot = false; bool _isInlineBot = false;
bool _botCommandShown = false;
rpl::lifetime _uploaderSubscriptions; rpl::lifetime _uploaderSubscriptions;

View file

@ -126,6 +126,9 @@ void SimpleElementDelegate::elementSendBotCommand(
const FullMsgId &context) { const FullMsgId &context) {
} }
void SimpleElementDelegate::elementHandleViaClick(not_null<UserData*> bot) {
}
TextSelection UnshiftItemSelection( TextSelection UnshiftItemSelection(
TextSelection selection, TextSelection selection,
uint16 byLength) { uint16 byLength) {

View file

@ -70,6 +70,7 @@ public:
virtual void elementSendBotCommand( virtual void elementSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) = 0; const FullMsgId &context) = 0;
virtual void elementHandleViaClick(not_null<UserData*> bot) = 0;
}; };
@ -105,6 +106,7 @@ public:
void elementSendBotCommand( void elementSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) override; const FullMsgId &context) override;
void elementHandleViaClick(not_null<UserData*> bot) override;
private: private:
const not_null<Window::SessionController*> _controller; const not_null<Window::SessionController*> _controller;

View file

@ -1297,7 +1297,11 @@ bool ListWidget::elementShownUnread(not_null<const Element*> view) {
void ListWidget::elementSendBotCommand( void ListWidget::elementSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) { const FullMsgId &context) {
return _delegate->listSendBotCommand(command, context); _delegate->listSendBotCommand(command, context);
}
void ListWidget::elementHandleViaClick(not_null<UserData*> bot) {
_delegate->listHandleViaClick(bot);
} }
void ListWidget::saveState(not_null<ListMemento*> memento) { void ListWidget::saveState(not_null<ListMemento*> memento) {

View file

@ -90,6 +90,7 @@ public:
virtual void listSendBotCommand( virtual void listSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) = 0; const FullMsgId &context) = 0;
virtual void listHandleViaClick(not_null<UserData*> bot) = 0;
}; };
@ -239,6 +240,7 @@ public:
void elementSendBotCommand( void elementSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) override; const FullMsgId &context) override;
void elementHandleViaClick(not_null<UserData*> bot) override;
~ListWidget(); ~ListWidget();

View file

@ -644,6 +644,9 @@ void PinnedWidget::listSendBotCommand(
const FullMsgId &context) { const FullMsgId &context) {
} }
void PinnedWidget::listHandleViaClick(not_null<UserData*> bot) {
}
void PinnedWidget::confirmDeleteSelected() { void PinnedWidget::confirmDeleteSelected() {
ConfirmDeleteSelectedItems(_inner); ConfirmDeleteSelectedItems(_inner);
} }

View file

@ -96,6 +96,7 @@ public:
void listSendBotCommand( void listSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) override; const FullMsgId &context) override;
void listHandleViaClick(not_null<UserData*> bot) override;
protected: protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;

View file

@ -1779,6 +1779,10 @@ void RepliesWidget::listSendBotCommand(
finishSending(); finishSending();
} }
void RepliesWidget::listHandleViaClick(not_null<UserData*> bot) {
_composeControls->setText({ '@' + bot->username + ' ' });
}
void RepliesWidget::confirmDeleteSelected() { void RepliesWidget::confirmDeleteSelected() {
ConfirmDeleteSelectedItems(_inner); ConfirmDeleteSelectedItems(_inner);
} }

View file

@ -131,6 +131,7 @@ public:
void listSendBotCommand( void listSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) override; const FullMsgId &context) override;
void listHandleViaClick(not_null<UserData*> bot) override;
protected: protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;

View file

@ -1192,6 +1192,10 @@ void ScheduledWidget::listSendBotCommand(
Ui::LayerOption::KeepOther); Ui::LayerOption::KeepOther);
} }
void ScheduledWidget::listHandleViaClick(not_null<UserData*> bot) {
_composeControls->setText({ '@' + bot->username + ' ' });
}
void ScheduledWidget::confirmSendNowSelected() { void ScheduledWidget::confirmSendNowSelected() {
ConfirmSendNowSelectedItems(_inner); ConfirmSendNowSelectedItems(_inner);
} }

View file

@ -113,6 +113,7 @@ public:
void listSendBotCommand( void listSendBotCommand(
const QString &command, const QString &command,
const FullMsgId &context) override; const FullMsgId &context) override;
void listHandleViaClick(not_null<UserData*> bot) override;
protected: protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;

@ -1 +1 @@
Subproject commit ee68d3a63b4f1e550e7f93c1f8d6e8e372bc0f33 Subproject commit 4f22126e7e855b517857408abf2467cba163a6f2

@ -1 +1 @@
Subproject commit 77b6e43b17df43d64354ba7198e6a7695a636627 Subproject commit f06346fbf03900c278e1d59717e1387bffc03f39