Provided more context for click handlers.

This commit is contained in:
23rd 2021-07-26 19:27:08 +03:00
parent 7c8b1cd5b1
commit 93bcd90fd4
10 changed files with 114 additions and 19 deletions

View file

@ -7,11 +7,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "chat_helpers/bot_keyboard.h" #include "chat_helpers/bot_keyboard.h"
#include "core/click_handler_types.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "window/window_session_controller.h"
#include "ui/cached_round_corners.h" #include "ui/cached_round_corners.h"
#include "facades.h" #include "facades.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
@ -98,9 +100,11 @@ int Style::minButtonWidth(HistoryMessageMarkupButton::Type type) const {
} // namespace } // namespace
BotKeyboard::BotKeyboard(not_null<Main::Session*> session, QWidget *parent) BotKeyboard::BotKeyboard(
not_null<Window::SessionController*> controller,
QWidget *parent)
: TWidget(parent) : TWidget(parent)
, _session(session) , _controller(controller)
, _st(&st::botKbButton) { , _st(&st::botKbButton) {
setGeometry(0, 0, _st->margin, st::botKbScroll.deltat); setGeometry(0, 0, _st->margin, st::botKbScroll.deltat);
_height = st::botKbScroll.deltat; _height = st::botKbScroll.deltat;
@ -137,7 +141,12 @@ void BotKeyboard::mouseReleaseEvent(QMouseEvent *e) {
updateSelected(); updateSelected();
if (ClickHandlerPtr activated = ClickHandler::unpressed()) { if (ClickHandlerPtr activated = ClickHandler::unpressed()) {
ActivateClickHandler(window(), activated, e->button()); ActivateClickHandler(window(), activated, {
e->button(),
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(_controller.get()),
})
});
} }
} }
@ -151,7 +160,8 @@ void BotKeyboard::leaveEventHook(QEvent *e) {
} }
bool BotKeyboard::moderateKeyActivate(int key) { bool BotKeyboard::moderateKeyActivate(int key) {
if (const auto item = _session->data().message(_wasForMsgId)) { const auto &data = _controller->session().data();
if (const auto item = data.message(_wasForMsgId)) {
if (const auto markup = item->Get<HistoryMessageReplyMarkup>()) { if (const auto markup = item->Get<HistoryMessageReplyMarkup>()) {
if (key >= Qt::Key_1 && key <= Qt::Key_2) { if (key >= Qt::Key_1 && key <= Qt::Key_2) {
const auto index = int(key - Qt::Key_1); const auto index = int(key - Qt::Key_1);

View file

@ -15,16 +15,18 @@ namespace style {
struct BotKeyboardButton; struct BotKeyboardButton;
} // namespace style } // namespace style
namespace Main { namespace Window {
class Session; class SessionController;
} // namespace Main } // namespace Window
class BotKeyboard class BotKeyboard
: public TWidget : public TWidget
, public Ui::AbstractTooltipShower , public Ui::AbstractTooltipShower
, public ClickHandlerHost { , public ClickHandlerHost {
public: public:
BotKeyboard(not_null<Main::Session*> session, QWidget *parent); BotKeyboard(
not_null<Window::SessionController*> controller,
QWidget *parent);
bool moderateKeyActivate(int index); bool moderateKeyActivate(int index);
@ -78,7 +80,7 @@ private:
void updateStyle(int newWidth); void updateStyle(int newWidth);
void clearSelection(); void clearSelection();
const not_null<Main::Session*> _session; const not_null<Window::SessionController*> _controller;
FullMsgId _wasForMsgId; FullMsgId _wasForMsgId;
QString _placeholder; QString _placeholder;
int _height = 0; int _height = 0;

View file

@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/stickers/data_stickers.h" #include "data/stickers/data_stickers.h"
#include "chat_helpers/send_context_menu.h" // SendMenu::FillSendMenu #include "chat_helpers/send_context_menu.h" // SendMenu::FillSendMenu
#include "core/click_handler_types.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
@ -415,7 +416,12 @@ void GifsListWidget::mouseReleaseEvent(QMouseEvent *e) {
if (dynamic_cast<InlineBots::Layout::SendClickHandler*>(activated.get())) { if (dynamic_cast<InlineBots::Layout::SendClickHandler*>(activated.get())) {
selectInlineResult(_selected, {}); selectInlineResult(_selected, {});
} else { } else {
ActivateClickHandler(window(), activated, e->button()); ActivateClickHandler(window(), activated, {
e->button(),
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(controller().get()),
})
});
} }
} }

View file

@ -23,11 +23,15 @@ class SessionController;
[[nodiscard]] bool UrlRequiresConfirmation(const QUrl &url); [[nodiscard]] bool UrlRequiresConfirmation(const QUrl &url);
class PeerData;
struct ClickHandlerContext { struct ClickHandlerContext {
FullMsgId itemId; FullMsgId itemId;
// Is filled from sections.
Fn<HistoryView::ElementDelegate*()> elementDelegate; Fn<HistoryView::ElementDelegate*()> elementDelegate;
base::weak_ptr<Window::SessionController> sessionWindow; base::weak_ptr<Window::SessionController> sessionWindow;
bool skipBotAutoLogin = false; bool skipBotAutoLogin = false;
// Is filled from peer info.
PeerData *peer = nullptr;
}; };
Q_DECLARE_METATYPE(ClickHandlerContext); Q_DECLARE_METATYPE(ClickHandlerContext);
@ -169,7 +173,6 @@ private:
}; };
class PeerData;
class BotCommandClickHandler : public TextClickHandler { class BotCommandClickHandler : public TextClickHandler {
public: public:
BotCommandClickHandler(const QString &cmd) : _cmd(cmd) { BotCommandClickHandler(const QString &cmd) : _cmd(cmd) {

View file

@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_utilities.h" #include "ui/text/text_utilities.h"
#include "ui/inactive_press.h" #include "ui/inactive_press.h"
#include "ui/effects/path_shift_gradient.h" #include "ui/effects/path_shift_gradient.h"
#include "core/click_handler_types.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "boxes/peers/edit_participant_box.h" #include "boxes/peers/edit_participant_box.h"
@ -1561,7 +1562,17 @@ void InnerWidget::mouseActionFinish(const QPoint &screenPos, Qt::MouseButton but
if (activated) { if (activated) {
mouseActionCancel(); mouseActionCancel();
ActivateClickHandler(window(), activated, button); ActivateClickHandler(window(), activated, {
button,
QVariant::fromValue(ClickHandlerContext{
.elementDelegate = [weak = Ui::MakeWeak(this)] {
return weak
? (ElementDelegate*)weak
: nullptr;
},
.sessionWindow = base::make_weak(_controller.get()),
})
});
return; return;
} }
if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && button != Qt::RightButton) { if (_mouseAction == MouseAction::PrepareDrag && !_pressWasInactive && button != Qt::RightButton) {

View file

@ -216,7 +216,7 @@ HistoryWidget::HistoryWidget(
tr::lng_message_ph()) tr::lng_message_ph())
, _kbScroll(this, st::botKbScroll) , _kbScroll(this, st::botKbScroll)
, _keyboard(_kbScroll->setOwnedWidget(object_ptr<BotKeyboard>( , _keyboard(_kbScroll->setOwnedWidget(object_ptr<BotKeyboard>(
&session(), controller,
this))) this)))
, _membersDropdownShowTimer([=] { showMembersDropdown(); }) , _membersDropdownShowTimer([=] { showMembersDropdown(); })
, _scrollTimer([=] { scrollByTimer(); }) , _scrollTimer([=] { scrollByTimer(); })

View file

@ -34,6 +34,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_overview.h" #include "styles/style_overview.h"
#include "styles/style_info.h" #include "styles/style_info.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/weak_ptr.h"
#include "media/player/media_player_instance.h" #include "media/player/media_player_instance.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
@ -2290,7 +2291,18 @@ void ListWidget::mouseActionFinish(
_wasSelectedText = false; _wasSelectedText = false;
if (activated) { if (activated) {
mouseActionCancel(); mouseActionCancel();
ActivateClickHandler(window(), activated, button); const auto found = findItemById(pressState.itemId);
const auto fullId = found
? found->layout->getItem()->fullId()
: FullMsgId();
ActivateClickHandler(window(), activated, {
button,
QVariant::fromValue(ClickHandlerContext{
.itemId = fullId,
.sessionWindow = base::make_weak(
_controller->parentController().get()),
})
});
return; return;
} }

View file

@ -46,6 +46,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwindow.h" // MainWindow::controller. #include "mainwindow.h" // MainWindow::controller.
#include "main/main_session.h" #include "main/main_session.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "facades.h" #include "facades.h"
#include "styles/style_info.h" #include "styles/style_info.h"
@ -189,9 +190,46 @@ DetailsFiller::DetailsFiller(
, _wrap(_parent) { , _wrap(_parent) {
} }
template <typename T>
bool SetClickContext(
const ClickHandlerPtr &handler,
const ClickContext &context) {
if (const auto casted = dynamic_pointer_cast<T>(handler)) {
casted->T::onClick(context);
return true;
}
return false;
}
object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() { object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
auto result = object_ptr<Ui::VerticalLayout>(_wrap); auto result = object_ptr<Ui::VerticalLayout>(_wrap);
auto tracker = Ui::MultiSlideTracker(); auto tracker = Ui::MultiSlideTracker();
// Fill context for a mention / hashtag / bot command link.
const auto infoClickFilter = [=,
peer = _peer.get(),
window = _controller->parentController()](
const ClickHandlerPtr &handler,
Qt::MouseButton button) {
const auto context = ClickContext{
button,
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(window.get()),
.peer = peer,
})
};
if (SetClickContext<BotCommandClickHandler>(handler, context)) {
return false;
} else if (SetClickContext<MentionClickHandler>(handler, context)) {
return false;
} else if (SetClickContext<HashtagClickHandler>(handler, context)) {
return false;
} else if (SetClickContext<CashtagClickHandler>(handler, context)) {
return false;
}
return true;
};
auto addInfoLineGeneric = [&]( auto addInfoLineGeneric = [&](
rpl::producer<QString> &&label, rpl::producer<QString> &&label,
rpl::producer<TextWithEntities> &&text, rpl::producer<TextWithEntities> &&text,
@ -203,6 +241,8 @@ object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
textSt, textSt,
st::infoProfileLabeledPadding); st::infoProfileLabeledPadding);
tracker.track(result->add(std::move(line.wrap))); tracker.track(result->add(std::move(line.wrap)));
line.text->setClickHandlerFilter(infoClickFilter);
return line.text; return line.text;
}; };
auto addInfoLine = [&]( auto addInfoLine = [&](

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_common.h" #include "api/api_common.h"
#include "chat_helpers/gifs_list_widget.h" // ChatHelpers::AddGifAction #include "chat_helpers/gifs_list_widget.h" // ChatHelpers::AddGifAction
#include "chat_helpers/send_context_menu.h" // SendMenu::FillSendMenu #include "chat_helpers/send_context_menu.h" // SendMenu::FillSendMenu
#include "core/click_handler_types.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_changes.h" #include "data/data_changes.h"
@ -237,7 +238,12 @@ void Inner::mouseReleaseEvent(QMouseEvent *e) {
if (dynamic_cast<SendClickHandler*>(activated.get()) || open) { if (dynamic_cast<SendClickHandler*>(activated.get()) || open) {
selectInlineResult(_selected, {}, !!open); selectInlineResult(_selected, {}, !!open);
} else { } else {
ActivateClickHandler(window(), activated, e->button()); ActivateClickHandler(window(), activated, {
e->button(),
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(_controller.get()),
})
});
} }
} }

View file

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "core/mime_type.h" #include "core/mime_type.h"
#include "core/ui_integration.h" #include "core/ui_integration.h"
@ -4299,10 +4300,14 @@ void OverlayWidget::handleMouseRelease(
} }
// There may be a mention / hashtag / bot command link. // There may be a mention / hashtag / bot command link.
// For now activate account for all activated links. // For now activate account for all activated links.
if (_session) { // findWindow() will activate account.
Core::App().domain().activate(&_session->account()); ActivateClickHandler(_widget, activated, {
} button,
ActivateClickHandler(_widget, activated, button); QVariant::fromValue(ClickHandlerContext{
.itemId = _msgid,
.sessionWindow = base::make_weak(findWindow()),
})
});
return; return;
} }