diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 6aef6c8a7..d3c772c31 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -2326,10 +2326,34 @@ void InnerWidget::showChatPreview(bool onlyUserpic) { mousePressReleased(QCursor::pos(), Qt::NoButton, Qt::NoModifier); _chatPreviewKey = key; - _menu = HistoryView::MakeChatPreview(this, key.entry()); - if (!_menu) { + auto preview = HistoryView::MakeChatPreview(this, key.entry()); + if (!preview.menu) { return; } + _menu = std::move(preview.menu); + const auto weakMenu = Ui::MakeWeak(_menu.get()); + const auto weakThread = base::make_weak(key.entry()->asThread()); + const auto weakController = base::make_weak(_controller); + std::move( + preview.actions + ) | rpl::start_with_next([=](HistoryView::ChatPreviewAction action) { + if (const auto controller = weakController.get()) { + if (const auto thread = weakThread.get()) { + const auto itemId = action.openItemId; + const auto owner = &thread->owner(); + if (action.openInfo) { + controller->showPeerInfo(thread); + } else if (const auto item = owner->message(itemId)) { + controller->showMessage(item); + } else { + controller->showThread(thread); + } + } + } + if (const auto strong = weakMenu.data()) { + strong->hideMenu(); + } + }, _menu->lifetime()); QObject::connect(_menu.get(), &QObject::destroyed, [=] { if (_chatPreviewKey) { updateDialogRow(RowDescriptor(base::take(_chatPreviewKey), {})); diff --git a/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp b/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp index caca93da1..48b15494a 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp +++ b/Telegram/SourceFiles/history/view/history_view_chat_preview.cpp @@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/menu/menu_item_base.h" #include "window/themes/window_theme.h" #include "window/section_widget.h" +#include "window/window_session_controller.h" #include "styles/style_chat.h" namespace HistoryView { @@ -36,8 +37,12 @@ class Item final public: Item(not_null parent, not_null thread); - not_null action() const override; - bool isEnabled() const override; + [[nodiscard]] not_null action() const override; + [[nodiscard]] bool isEnabled() const override; + + [[nodiscard]] rpl::producer actions() { + return _actions.events(); + } private: int contentHeight() const override; @@ -146,6 +151,7 @@ private: const std::unique_ptr _scroll; QPointer _inner; + rpl::event_stream _actions; QImage _bg; @@ -180,6 +186,22 @@ Item::Item(not_null parent, not_null thread) using Type = Ui::ElasticScroll::OverscrollType; _scroll->setOverscrollTypes(Type::Real, Type::Real); + _scroll->events() | rpl::start_with_next([=](not_null e) { + if (e->type() == QEvent::MouseButtonPress) { + const auto relative = Ui::MapFrom( + _inner.data(), + _scroll.get(), + static_cast(e.get())->pos()); + if (const auto view = _inner->lookupItemByY(relative.y())) { + _actions.fire(ChatPreviewAction{ + .openItemId = view->data()->fullId(), + }); + } else { + _actions.fire(ChatPreviewAction{}); + } + } + }, lifetime()); + _inner->resizeToWidth(_scroll->width(), _scroll->height()); _inner->refreshViewer(); @@ -519,31 +541,36 @@ void Item::listLaunchDrag( } // namespace -base::unique_qptr MakeChatPreview( +ChatPreview MakeChatPreview( QWidget *parent, not_null entry) { const auto thread = entry->asThread(); if (!thread) { - return nullptr; + return {}; } else if (const auto history = entry->asHistory()) { if (history->peer->isForum()) { - return nullptr; + return {}; } } - auto result = base::make_unique_q( - parent, - st::previewMenu); + auto result = ChatPreview{ + .menu = base::make_unique_q( + parent, + st::previewMenu), + }; + const auto menu = result.menu.get(); - result->addAction(base::make_unique_q(result.get(), thread)); + auto action = base::make_unique_q(menu, thread); + result.actions = action->actions(); + menu->addAction(std::move(action)); if (const auto topic = thread->asTopic()) { - const auto weak = Ui::MakeWeak(result.get()); + const auto weak = Ui::MakeWeak(menu); topic->destroyed() | rpl::start_with_next([weak] { if (const auto strong = weak.data()) { LOG(("Preview hidden for a destroyed topic.")); strong->hideMenu(true); } - }, result->lifetime()); + }, menu->lifetime()); } return result; diff --git a/Telegram/SourceFiles/history/view/history_view_chat_preview.h b/Telegram/SourceFiles/history/view/history_view_chat_preview.h index 12a35bbba..9445b6171 100644 --- a/Telegram/SourceFiles/history/view/history_view_chat_preview.h +++ b/Telegram/SourceFiles/history/view/history_view_chat_preview.h @@ -19,7 +19,17 @@ class PopupMenu; namespace HistoryView { -[[nodiscard]] base::unique_qptr MakeChatPreview( +struct ChatPreviewAction { + FullMsgId openItemId; + bool openInfo = false; +}; + +struct ChatPreview { + base::unique_qptr menu; + rpl::producer actions; +}; + +[[nodiscard]] ChatPreview MakeChatPreview( QWidget *parent, not_null entry); diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index e951cd802..a320a67f7 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -1584,6 +1584,10 @@ bool ListWidget::hasSelectRestriction() const { != CopyRestrictionType::None; } +Element *ListWidget::lookupItemByY(int y) const { + return strictFindItemByY(y); +} + auto ListWidget::findViewForPinnedTracking(int top) const -> std::pair { const auto findScrollTopItem = [&](int top) diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index bd8ad7827..e5304bb44 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -344,6 +344,7 @@ public: [[nodiscard]] bool hasCopyRestrictionForSelected() const; [[nodiscard]] bool showCopyRestrictionForSelected(); [[nodiscard]] bool hasSelectRestriction() const; + [[nodiscard]] Element *lookupItemByY(int y) const; [[nodiscard]] std::pair findViewForPinnedTracking( int top) const;