diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index 18120e99f6..c0ea166e01 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -1562,8 +1562,13 @@ void PeerListContent::handleMouseMove(QPoint globalPosition) { selectByMouse(globalPosition); } -void PeerListContent::cancelPress() { - setPressed(Selected()); +void PeerListContent::pressLeftToContextMenu(bool shown) { + if (shown) { + setContexted(_pressed); + setPressed(Selected()); + } else { + setContexted(Selected()); + } } void PeerListContent::mousePressEvent(QMouseEvent *e) { diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index eb764d36b8..47febc1adf 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -347,7 +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; + virtual void peerListPressLeftToContextMenu(bool shown) = 0; template void peerListAddSelectedPeers(PeerDataRange &&range) { @@ -662,7 +662,7 @@ public: void refreshRows(); void mouseLeftGeometry(); - void cancelPress(); + void pressLeftToContextMenu(bool shown); void setSearchMode(PeerListSearchMode mode); void changeCheckState( @@ -1000,8 +1000,8 @@ public: not_null row, bool highlightRow, Fn)> destroyed = nullptr) override; - void peerListCancelPress() override { - _content->cancelPress(); + void peerListPressLeftToContextMenu(bool shown) override { + _content->pressLeftToContextMenu(shown); } protected: diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp index 0b768661eb..179b088870 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp @@ -86,7 +86,9 @@ private: }; -class ControllerWithPreviews : public PeerListController { +class ControllerWithPreviews + : public PeerListController + , public base::has_weak_ptr { public: explicit ControllerWithPreviews( not_null window); @@ -103,9 +105,7 @@ private: }; -class RecentsController final - : public ControllerWithPreviews - , public base::has_weak_ptr { +class RecentsController final : public ControllerWithPreviews { public: RecentsController( not_null window, @@ -153,9 +153,7 @@ private: }; -class MyChannelsController final - : public ControllerWithPreviews - , public base::has_weak_ptr { +class MyChannelsController final : public ControllerWithPreviews { public: explicit MyChannelsController( not_null window); @@ -188,9 +186,7 @@ private: }; -class RecommendationsController final - : public ControllerWithPreviews - , public base::has_weak_ptr { +class RecommendationsController final : public ControllerWithPreviews { public: explicit RecommendationsController( not_null window); @@ -426,15 +422,17 @@ ControllerWithPreviews::ControllerWithPreviews( bool ControllerWithPreviews::rowTrackPress(not_null row) { const auto peer = row->peer(); const auto history = peer->owner().history(peer); + const auto callback = crl::guard(this, [=](bool shown) { + delegate()->peerListPressLeftToContextMenu(shown); + }); if (base::IsAltPressed()) { - _window->showChatPreview({ history, FullMsgId() }); - delegate()->peerListCancelPress(); + _window->showChatPreview({ history, FullMsgId() }, callback); 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() }); + _window->scheduleChatPreview({ history, FullMsgId() }, callback); return true; } return false; @@ -982,8 +980,8 @@ void Suggestions::setupChats() { }, _topPeers->lifetime()); _topPeers->pressed() | rpl::start_with_next([=](uint64 peerIdRaw) { - handlePressForChatPreview(PeerId(peerIdRaw), [=] { - _topPeers->cancelPress(); + handlePressForChatPreview(PeerId(peerIdRaw), [=](bool shown) { + _topPeers->pressLeftToContextMenu(shown); }); }, _topPeers->lifetime()); @@ -1036,12 +1034,8 @@ void Suggestions::setupChats() { void Suggestions::handlePressForChatPreview( PeerId id, - Fn cancelPress) { - const auto callback = crl::guard(this, [=](bool shown) { - if (shown) { - cancelPress(); - } - }); + Fn callback) { + callback = crl::guard(this, callback); const auto row = RowDescriptor( _controller->session().data().history(id), FullMsgId()); diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h index 16e07d15b5..734ec554c3 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h @@ -122,7 +122,7 @@ private: void startSlideAnimation(); void finishShow(); - void handlePressForChatPreview(PeerId id, Fn cancelPress); + void handlePressForChatPreview(PeerId id, Fn callback); const not_null _controller; diff --git a/Telegram/SourceFiles/dialogs/ui/top_peers_strip.cpp b/Telegram/SourceFiles/dialogs/ui/top_peers_strip.cpp index 48ec566968..67cafb98cc 100644 --- a/Telegram/SourceFiles/dialogs/ui/top_peers_strip.cpp +++ b/Telegram/SourceFiles/dialogs/ui/top_peers_strip.cpp @@ -381,14 +381,7 @@ void TopPeersStrip::stripMouseReleaseEvent(QMouseEvent *e) { _mouseDownPosition = std::nullopt; }); - const auto pressed = std::exchange(_pressed, -1); - if (pressed >= 0) { - Assert(pressed < _entries.size()); - auto &entry = _entries[pressed]; - if (entry.ripple) { - entry.ripple->lastStop(); - } - } + const auto pressed = clearPressed(); if (finishDragging()) { return; } @@ -400,6 +393,18 @@ void TopPeersStrip::stripMouseReleaseEvent(QMouseEvent *e) { } } +int TopPeersStrip::clearPressed() { + const auto pressed = std::exchange(_pressed, -1); + if (pressed >= 0) { + Assert(pressed < _entries.size()); + auto &entry = _entries[pressed]; + if (entry.ripple) { + entry.ripple->lastStop(); + } + } + return pressed; +} + void TopPeersStrip::updateScrollMax(int newWidth) { if (_expandAnimation.animating()) { return; @@ -441,15 +446,13 @@ rpl::producer<> TopPeersStrip::pressCancelled() const { return _pressCancelled.events(); } -void TopPeersStrip::cancelPress() { - const auto pressed = std::exchange(_pressed, -1); - if (pressed >= 0) { - Assert(pressed < _entries.size()); - auto &entry = _entries[pressed]; - if (entry.ripple) { - entry.ripple->lastStop(); - } +void TopPeersStrip::pressLeftToContextMenu(bool shown) { + if (!shown) { + _contexted = -1; + update(); + return; } + _contexted = clearPressed(); if (finishDragging()) { return; } @@ -491,6 +494,9 @@ void TopPeersStrip::removeLocally(uint64 id) { if (_pressed > index) { --_pressed; } + if (_contexted > index) { + --_contexted; + } updateScrollMax(); _count = int(_entries.size()); update(); @@ -603,8 +609,17 @@ void TopPeersStrip::apply(const TopPeersList &list) { } auto now = std::vector(); - auto selectedId = (_selected >= 0) ? _entries[_selected].id : 0; - auto pressedId = (_pressed >= 0) ? _entries[_pressed].id : 0; + const auto selectedId = (_selected >= 0) ? _entries[_selected].id : 0; + const auto pressedId = (_pressed >= 0) ? _entries[_pressed].id : 0; + const auto contextedId = (_contexted >= 0) ? _entries[_contexted].id : 0; + const auto restoreIndex = [&](uint64 id) { + if (!id) { + return -1; + } + const auto i = ranges::find(_entries, id, &Entry::id); + return (i != end(_entries)) ? int(i - begin(_entries)) : -1; + }; + for (const auto &entry : list.entries) { if (_removed.contains(entry.id)) { continue; @@ -627,18 +642,9 @@ void TopPeersStrip::apply(const TopPeersList &list) { } } _entries = std::move(now); - if (selectedId) { - const auto i = ranges::find(_entries, selectedId, &Entry::id); - if (i != end(_entries)) { - _selected = int(i - begin(_entries)); - } - } - if (pressedId) { - const auto i = ranges::find(_entries, pressedId, &Entry::id); - if (i != end(_entries)) { - _pressed = int(i - begin(_entries)); - } - } + _selected = restoreIndex(selectedId); + _pressed = restoreIndex(pressedId); + _contexted = restoreIndex(contextedId); updateScrollMax(); unsubscribeUserpics(); _count = int(_entries.size()); @@ -736,7 +742,11 @@ void TopPeersStrip::paintStrip(QRect clip) { auto x = int(base::SafeRound(-shift + from * fsingle + added)); auto y = row * st.height; - const auto highlighted = (_pressed >= 0) ? _pressed : _selected; + const auto highlighted = (_contexted >= 0) + ? _contexted + : (_pressed >= 0) + ? _pressed + : _selected; for (auto i = from; i != till; ++i) { auto &entry = _entries[i]; const auto selected = (i == highlighted); diff --git a/Telegram/SourceFiles/dialogs/ui/top_peers_strip.h b/Telegram/SourceFiles/dialogs/ui/top_peers_strip.h index 4dddd28909..f33ec722b2 100644 --- a/Telegram/SourceFiles/dialogs/ui/top_peers_strip.h +++ b/Telegram/SourceFiles/dialogs/ui/top_peers_strip.h @@ -63,7 +63,7 @@ public: bool selectByKeyboard(Qt::Key direction); void deselectByKeyboard(); bool chooseRow(); - void cancelPress(); + void pressLeftToContextMenu(bool shown); uint64 updateFromParentDrag(QPoint globalPosition); void dragLeft(); @@ -105,6 +105,7 @@ private: [[nodiscard]] QRect innerRounded() const; [[nodiscard]] int scrollLeft() const; [[nodiscard]] Layout currentLayout() const; + int clearPressed(); void apply(const TopPeersList &list); void apply(Entry &entry, const TopPeersEntry &data); @@ -132,6 +133,7 @@ private: int _selected = -1; int _pressed = -1; + int _contexted = -1; bool _selectionByKeyboard = false; bool _hiddenLocally = false;