diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index dca4a065b..18120e99f 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_widgets.h" #include // XXH64. +#include [[nodiscard]] PeerListRowId UniqueRowIdFromString(const QString &d) { return XXH64(d.data(), d.size() * sizeof(ushort), 0); @@ -1552,13 +1553,24 @@ void PeerListContent::handleMouseMove(QPoint globalPosition) { && *_lastMousePosition == globalPosition) { return; } + if (_trackPressStart + && ((*_trackPressStart - globalPosition).manhattanLength() + > QApplication::startDragDistance())) { + _trackPressStart = std::nullopt; + _controller->rowTrackPressCancel(); + } selectByMouse(globalPosition); } +void PeerListContent::cancelPress() { + setPressed(Selected()); +} + void PeerListContent::mousePressEvent(QMouseEvent *e) { _pressButton = e->button(); selectByMouse(e->globalPos()); setPressed(_selected); + _trackPressStart = {}; if (auto row = getRow(_selected.index)) { auto updateCallback = [this, row, hint = _selected.index] { updateRow(row, hint); @@ -1586,8 +1598,11 @@ void PeerListContent::mousePressEvent(QMouseEvent *e) { row->addRipple(_st.item, maskGenerator, point, std::move(updateCallback)); } } + if (_pressButton == Qt::LeftButton && _controller->rowTrackPress(row)) { + _trackPressStart = e->globalPos(); + } } - if (anim::Disabled() && !_selected.element) { + if (anim::Disabled() && !_trackPressStart && !_selected.element) { mousePressReleased(e->button()); } } @@ -1597,6 +1612,9 @@ void PeerListContent::mouseReleaseEvent(QMouseEvent *e) { } void PeerListContent::mousePressReleased(Qt::MouseButton button) { + _trackPressStart = {}; + _controller->rowTrackPressCancel(); + updateRow(_pressed.index); updateRow(_selected.index); diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index 4349fd8c6..eb764d36b 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -347,6 +347,7 @@ public: virtual void peerListSortRows(Fn compare) = 0; virtual int peerListPartitionRows(Fn border) = 0; virtual std::shared_ptr peerListUiShow() = 0; + virtual void peerListCancelPress() = 0; template void peerListAddSelectedPeers(PeerDataRange &&range) { @@ -478,6 +479,12 @@ public: } } + virtual bool rowTrackPress(not_null row) { + return false; + } + virtual void rowTrackPressCancel() { + } + virtual void loadMoreRows() { } virtual void itemDeselectedHook(not_null peer) { @@ -655,6 +662,7 @@ public: void refreshRows(); void mouseLeftGeometry(); + void cancelPress(); void setSearchMode(PeerListSearchMode mode); void changeCheckState( @@ -829,6 +837,7 @@ private: bool _mouseSelection = false; std::optional _lastMousePosition; Qt::MouseButton _pressButton = Qt::LeftButton; + std::optional _trackPressStart; rpl::event_stream _scrollToRequests; @@ -991,6 +1000,9 @@ public: not_null row, bool highlightRow, Fn)> destroyed = nullptr) override; + void peerListCancelPress() override { + _content->cancelPress(); + } protected: not_null content() const { diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp index 28802c811..0b768661e 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp @@ -86,8 +86,25 @@ private: }; +class ControllerWithPreviews : public PeerListController { +public: + explicit ControllerWithPreviews( + not_null window); + + [[nodiscard]] not_null window() const { + return _window; + } + + bool rowTrackPress(not_null row) override; + void rowTrackPressCancel() override; + +private: + const not_null _window; + +}; + class RecentsController final - : public PeerListController + : public ControllerWithPreviews , public base::has_weak_ptr { public: RecentsController( @@ -115,7 +132,6 @@ private: void subscribeToEvents(); [[nodiscard]] Fn removeAllCallback(); - const not_null _window; RecentPeersList _recent; rpl::variable _count; rpl::event_stream> _chosen; @@ -138,7 +154,7 @@ private: }; class MyChannelsController final - : public PeerListController + : public ControllerWithPreviews , public base::has_weak_ptr { public: explicit MyChannelsController( @@ -163,7 +179,6 @@ private: void appendRow(not_null channel); void fill(bool force = false); - const not_null _window; std::vector> _channels; rpl::variable _toggleExpanded = nullptr; rpl::variable _count = 0; @@ -174,7 +189,7 @@ private: }; class RecommendationsController final - : public PeerListController + : public ControllerWithPreviews , public base::has_weak_ptr { public: explicit RecommendationsController( @@ -201,7 +216,6 @@ private: void setupDivider(); void appendRow(not_null channel); - const not_null _window; rpl::variable _count; History *_activeHistory = nullptr; bool _requested = false; @@ -404,10 +418,36 @@ const style::PeerListItem &ChannelRow::computeSt( return _active ? st::recentPeersItemActive : st::recentPeersItem; } +ControllerWithPreviews::ControllerWithPreviews( + not_null window) +: _window(window) { +} + +bool ControllerWithPreviews::rowTrackPress(not_null row) { + const auto peer = row->peer(); + const auto history = peer->owner().history(peer); + if (base::IsAltPressed()) { + _window->showChatPreview({ history, FullMsgId() }); + delegate()->peerListCancelPress(); + return false; + } + const auto point = delegate()->peerListLastRowMousePosition(); + const auto &st = computeListSt().item; + if (point && point->x() < st.photoPosition.x() + st.photoSize) { + _window->scheduleChatPreview({ history, FullMsgId() }); + return true; + } + return false; +} + +void ControllerWithPreviews::rowTrackPressCancel() { + _window->cancelScheduledPreview(); +} + RecentsController::RecentsController( not_null window, RecentPeersList list) -: _window(window) +: ControllerWithPreviews(window) , _recent(std::move(list)) { } @@ -429,7 +469,7 @@ void RecentsController::rowClicked(not_null row) { Fn RecentsController::removeAllCallback() { const auto weak = base::make_weak(this); - const auto session = &_window->session(); + const auto session = &this->session(); return crl::guard(session, [=] { if (weak) { _count = 0; @@ -450,7 +490,7 @@ base::unique_qptr RecentsController::rowContextMenu( st::popupMenuWithIcons); const auto peer = row->peer(); const auto weak = base::make_weak(this); - const auto session = &_window->session(); + const auto session = &this->session(); const auto removeOne = crl::guard(session, [=] { if (weak) { const auto rowId = peer->id.value; @@ -463,7 +503,7 @@ base::unique_qptr RecentsController::rowContextMenu( session->recentPeers().remove(peer); }); FillEntryMenu(Ui::Menu::CreateAddActionCallback(result), { - .controller = _window, + .controller = window(), .peer = peer, .removeOneText = tr::lng_recent_remove(tr::now), .removeOne = removeOne, @@ -475,7 +515,7 @@ base::unique_qptr RecentsController::rowContextMenu( } Main::Session &RecentsController::session() const { - return _window->session(); + return window()->session(); } QString RecentsController::savedMessagesChatStatus() const { @@ -496,7 +536,7 @@ void RecentsController::setupDivider() { tr::lng_recent_clear(tr::now), st::searchedBarLink); clear->setClickedCallback(RemoveAllConfirm( - _window, + window(), tr::lng_recent_clear_sure(tr::now), removeAllCallback())); rpl::combine( @@ -555,7 +595,7 @@ void RecentsController::subscribeToEvents() { MyChannelsController::MyChannelsController( not_null window) -: _window(window) { +: ControllerWithPreviews(window) { } void MyChannelsController::prepare() { @@ -679,7 +719,7 @@ base::unique_qptr MyChannelsController::rowContextMenu( const auto peer = row->peer(); const auto addAction = Ui::Menu::CreateAddActionCallback(result); Window::FillDialogsEntryMenu( - _window, + window(), Dialogs::EntryState{ .key = peer->owner().history(peer), .section = Dialogs::EntryState::Section::ContextMenu, @@ -689,7 +729,7 @@ base::unique_qptr MyChannelsController::rowContextMenu( } Main::Session &MyChannelsController::session() const { - return _window->session(); + return window()->session(); } void MyChannelsController::setupDivider() { @@ -760,7 +800,7 @@ void MyChannelsController::setupDivider() { RecommendationsController::RecommendationsController( not_null window) -: _window(window) { +: ControllerWithPreviews(window) { } void RecommendationsController::prepare() { @@ -795,7 +835,7 @@ void RecommendationsController::fill() { delegate()->peerListRefreshRows(); _count = delegate()->peerListFullRowsCount(); - _window->activeChatValue() | rpl::start_with_next([=](const Key &key) { + window()->activeChatValue() | rpl::start_with_next([=](const Key &key) { const auto history = key.history(); if (_activeHistory == history) { return; @@ -841,7 +881,7 @@ base::unique_qptr RecommendationsController::rowContextMenu( } Main::Session &RecommendationsController::session() const { - return _window->session(); + return window()->session(); } void RecommendationsController::setupDivider() {