diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index 362387458..99da56122 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -1912,10 +1912,30 @@ void PeerListContent::selectSkipPage(int height, int direction) { selectSkip(rowsToSkip * direction); } +void PeerListContent::selectLast() { + const auto rowsCount = shownRowsCount(); + const auto newSelectedIndex = rowsCount - 1; + _selected.index.value = newSelectedIndex; + _selected.element = 0; + if (newSelectedIndex >= 0) { + auto top = (newSelectedIndex > 0) ? getRowTop(RowIndex(newSelectedIndex)) : 0; + auto bottom = (newSelectedIndex + 1 < rowsCount) ? getRowTop(RowIndex(newSelectedIndex + 1)) : height(); + _scrollToRequests.fire({ top, bottom }); + } + + update(); + + _selectedIndex = _selected.index.value; +} + rpl::producer PeerListContent::selectedIndexValue() const { return _selectedIndex.value(); } +int PeerListContent::selectedIndex() const { + return _selectedIndex.current(); +} + bool PeerListContent::hasSelection() const { return _selected.index.value >= 0; } diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index b276364d4..e4a00d939 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -603,6 +603,7 @@ public: }; SkipResult selectSkip(int direction); void selectSkipPage(int height, int direction); + void selectLast(); enum class Mode { Default, @@ -611,6 +612,7 @@ public: void setMode(Mode mode); [[nodiscard]] rpl::producer selectedIndexValue() const; + [[nodiscard]] int selectedIndex() const; [[nodiscard]] bool hasSelection() const; [[nodiscard]] bool hasPressed() const; void clearSelection(); diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp index f380c47d6..3f021593a 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.cpp @@ -985,8 +985,16 @@ void Suggestions::setupChannels() { } void Suggestions::selectJump(Qt::Key direction, int pageSize) { + if (_tab.current() == Tab::Chats) { + selectJumpChats(direction, pageSize); + } else { + selectJumpChannels(direction, pageSize); + } +} + +void Suggestions::selectJumpChats(Qt::Key direction, int pageSize) { const auto recentHasSelection = [=] { - return _recentSelectJump(Qt::Key(), 0) == JumpResult::Applied; + return _recentSelectJump({}, 0) == JumpResult::Applied; }; if (pageSize) { if (direction == Qt::Key_Down || direction == Qt::Key_Up) { @@ -1007,7 +1015,7 @@ void Suggestions::selectJump(Qt::Key direction, int pageSize) { } else if (direction == Qt::Key_Up) { if (_recentSelectJump(direction, pageSize) == JumpResult::AppliedAndOut) { - _topPeers->selectByKeyboard(Qt::Key()); + _topPeers->selectByKeyboard({}); _chatsScroll->scrollTo(0); } else { _topPeers->deselectByKeyboard(); @@ -1021,7 +1029,7 @@ void Suggestions::selectJump(Qt::Key direction, int pageSize) { } else if (!_topPeersWrap->toggled() || recentHasSelection()) { _recentSelectJump(direction, pageSize); } else { - _topPeers->selectByKeyboard(Qt::Key()); + _topPeers->selectByKeyboard({}); _chatsScroll->scrollTo(0); } } else if (direction == Qt::Key_Left || direction == Qt::Key_Right) { @@ -1032,6 +1040,69 @@ void Suggestions::selectJump(Qt::Key direction, int pageSize) { } } +void Suggestions::selectJumpChannels(Qt::Key direction, int pageSize) { + const auto myChannelsHasSelection = [=] { + return _myChannelsSelectJump({}, 0) == JumpResult::Applied; + }; + const auto recommendationsHasSelection = [=] { + return _recommendationsSelectJump({}, 0) == JumpResult::Applied; + }; + if (pageSize) { + if (direction == Qt::Key_Down) { + if (recommendationsHasSelection()) { + _recommendationsSelectJump(direction, pageSize); + } else if (myChannelsHasSelection()) { + if (_myChannelsSelectJump(direction, pageSize) + == JumpResult::AppliedAndOut) { + _recommendationsSelectJump(direction, 0); + } + } else if (_myChannelsCount.current()) { + _myChannelsSelectJump(direction, 0); + _myChannelsSelectJump(direction, pageSize); + } else if (_recommendationsCount.current()) { + _recommendationsSelectJump(direction, 0); + _recommendationsSelectJump(direction, pageSize); + } + } else if (direction == Qt::Key_Up) { + if (myChannelsHasSelection()) { + if (_myChannelsSelectJump(direction, pageSize) + == JumpResult::AppliedAndOut) { + _channelsScroll->scrollTo(0); + } + } else if (recommendationsHasSelection()) { + if (_recommendationsSelectJump(direction, pageSize) + == JumpResult::AppliedAndOut) { + _myChannelsSelectJump(direction, -1); + } + } + } + } else if (direction == Qt::Key_Up) { + if (myChannelsHasSelection()) { + _myChannelsSelectJump(direction, 0); + } else if (_recommendationsSelectJump(direction, 0) + == JumpResult::AppliedAndOut) { + _myChannelsSelectJump(direction, -1); + } else if (!recommendationsHasSelection()) { + if (_myChannelsSelectJump(direction, 0) + == JumpResult::AppliedAndOut) { + _channelsScroll->scrollTo(0); + } + } + } else if (direction == Qt::Key_Down) { + if (recommendationsHasSelection()) { + _recommendationsSelectJump(direction, 0); + } else if (_myChannelsSelectJump(direction, 0) + == JumpResult::AppliedAndOut) { + _recommendationsSelectJump(direction, 0); + } else if (!myChannelsHasSelection()) { + if (_recommendationsSelectJump(direction, 0) + == JumpResult::AppliedAndOut) { + _myChannelsSelectJump(direction, 0); + } + } + } +} + void Suggestions::chooseRow() { if (!_topPeers->chooseRow()) { _recentPeersChoose(); @@ -1316,19 +1387,33 @@ object_ptr> Suggestions::setupMyChannels() { _myChannelsChoose = [=] { return raw->submitted(); }; - _myChannelsSelectJump = [raw](Qt::Key direction, int pageSize) { + _myChannelsSelectJump = [=](Qt::Key direction, int pageSize) { const auto had = raw->hasSelection(); if (direction == Qt::Key()) { return had ? JumpResult::Applied : JumpResult::NotApplied; } else if (direction == Qt::Key_Up && !had) { + if (pageSize < 0) { + raw->selectLast(); + return raw->hasSelection() + ? JumpResult::Applied + : JumpResult::NotApplied; + } return JumpResult::NotApplied; } else if (direction == Qt::Key_Down || direction == Qt::Key_Up) { + const auto was = raw->selectedIndex(); const auto delta = (direction == Qt::Key_Down) ? 1 : -1; if (pageSize > 0) { raw->selectSkipPage(pageSize, delta); } else { raw->selectSkip(delta); } + if (had + && delta > 0 + && _recommendationsCount.current() + && raw->selectedIndex() == was) { + raw->clearSelection(); + return JumpResult::AppliedAndOut; + } return raw->hasSelection() ? JumpResult::Applied : had diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h index a0d3e30f2..49b74fa74 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_suggestions.h @@ -87,6 +87,9 @@ private: void setupChats(); void setupChannels(); + void selectJumpChats(Qt::Key direction, int pageSize); + void selectJumpChannels(Qt::Key direction, int pageSize); + [[nodiscard]] object_ptr> setupRecentPeers( RecentPeersList recentPeers); [[nodiscard]] object_ptr> setupEmptyRecent();