From 496d711684efdea520c431e91e27468f29151fc3 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sat, 29 Dec 2018 17:09:45 +0400 Subject: [PATCH] Improve support shortcuts handling. --- Telegram/SourceFiles/core/shortcuts.cpp | 4 +- .../dialogs/dialogs_inner_widget.cpp | 61 ++++++++++++++++--- .../dialogs/dialogs_inner_widget.h | 15 +++-- Telegram/SourceFiles/dialogs/dialogs_key.h | 3 +- .../SourceFiles/dialogs/dialogs_widget.cpp | 24 +++++--- Telegram/SourceFiles/dialogs/dialogs_widget.h | 1 + 6 files changed, 84 insertions(+), 24 deletions(-) diff --git a/Telegram/SourceFiles/core/shortcuts.cpp b/Telegram/SourceFiles/core/shortcuts.cpp index 2c6dbcfaa..d8279bc50 100644 --- a/Telegram/SourceFiles/core/shortcuts.cpp +++ b/Telegram/SourceFiles/core/shortcuts.cpp @@ -26,6 +26,8 @@ const auto AutoRepeatCommands = base::flat_set{ Command::MediaNext, Command::ChatPrevious, Command::ChatNext, + Command::ChatFirst, + Command::ChatLast, }; const auto MediaCommands = base::flat_set{ @@ -363,7 +365,7 @@ void Manager::set(const QString &keys, Command command) { nullptr, nullptr, Qt::ApplicationShortcut); - if (AutoRepeatCommands.contains(command)) { + if (!AutoRepeatCommands.contains(command)) { shortcut->setAutoRepeat(false); } const auto isMediaShortcut = MediaCommands.contains(command); diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index cb5ddeeb7..4886a6531 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -1758,6 +1758,14 @@ PeerData *DialogsInner::updateFromParentDrag(QPoint globalPosition) { return nullptr; } +void DialogsInner::setLoadMoreCallback(Fn callback) { + _loadMoreCallback = std::move(callback); +} + +rpl::producer<> DialogsInner::listBottomReached() const { + return _listBottomReached.events(); +} + void DialogsInner::visibleTopBottomUpdated( int visibleTop, int visibleBottom) { @@ -2803,21 +2811,40 @@ void DialogsInner::setupShortcuts() { return; } const auto row = _controller->activeChatEntryCurrent(); + // Those should be computed before the call to request->handle. + const auto previous = row.key + ? computeJump( + chatListEntryBefore(row), + JumpSkip::PreviousOrBegin) + : row; + const auto next = row.key + ? computeJump( + chatListEntryAfter(row), + JumpSkip::NextOrEnd) + : row; + const auto first = [&] { + const auto to = chatListEntryFirst(); + const auto jump = computeJump(to, JumpSkip::NextOrOriginal); + return (to == row || jump == row || to == previous) ? to : jump; + }(); + const auto last = [&] { + const auto to = chatListEntryLast(); + const auto jump = computeJump(to, JumpSkip::PreviousOrOriginal); + return (to == row || jump == row || to == next) ? to : jump; + }(); if (row.key) { - const auto prev = computeJump(chatListEntryBefore(row), -1); - const auto next = computeJump(chatListEntryAfter(row), 1); request->check(Command::ChatPrevious) && request->handle([=] { - return jumpToDialogRow(prev); + return jumpToDialogRow(previous); }); request->check(Command::ChatNext) && request->handle([=] { return jumpToDialogRow(next); }); } request->check(Command::ChatFirst) && request->handle([=] { - return jumpToDialogRow(computeJump(chatListEntryFirst(), 1)); + return jumpToDialogRow(first); }); request->check(Command::ChatLast) && request->handle([=] { - return jumpToDialogRow(computeJump(chatListEntryLast(), -1)); + return jumpToDialogRow(last); }); if (Auth().supportMode() && row.key.history()) { request->check( @@ -2832,21 +2859,35 @@ void DialogsInner::setupShortcuts() { Dialogs::RowDescriptor DialogsInner::computeJump( const Dialogs::RowDescriptor &to, - int skipDirection) { + JumpSkip skip) { auto result = to; - if (Auth().supportMode()) { - while (result.key - && !result.key.entry()->chatListUnreadCount() + if (Auth().supportMode() && result.key) { + const auto down = (skip == JumpSkip::NextOrEnd) + || (skip == JumpSkip::NextOrOriginal); + while (!result.key.entry()->chatListUnreadCount() && !result.key.entry()->chatListUnreadMark()) { - result = (skipDirection > 0) + const auto next = down ? chatListEntryAfter(result) : chatListEntryBefore(result); + if (next.key) { + result = next; + } else { + if (skip == JumpSkip::PreviousOrOriginal + || skip == JumpSkip::NextOrOriginal) { + result = to; + } + break; + } } } return result; } bool DialogsInner::jumpToDialogRow(const Dialogs::RowDescriptor &to) { + if (to == chatListEntryLast()) { + _listBottomReached.fire({}); + } + if (const auto history = to.key.history()) { Ui::showPeerHistory( history, diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index b36aaf191..468028c1f 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -93,9 +93,8 @@ public: PeerData *updateFromParentDrag(QPoint globalPosition); - void setLoadMoreCallback(Fn callback) { - _loadMoreCallback = std::move(callback); - } + void setLoadMoreCallback(Fn callback); + [[nodiscard]] rpl::producer<> listBottomReached() const; base::Observable searchFromUserChanged; @@ -141,6 +140,13 @@ private: struct PeerSearchResult; using PeerSearchResults = std::vector>; + enum class JumpSkip { + PreviousOrBegin, + NextOrEnd, + PreviousOrOriginal, + NextOrOriginal, + }; + struct ChosenRow { Dialogs::Key key; Data::MessagePosition message; @@ -189,7 +195,7 @@ private: void setupShortcuts(); Dialogs::RowDescriptor computeJump( const Dialogs::RowDescriptor &to, - int skipDirection); + JumpSkip skip); bool jumpToDialogRow(const Dialogs::RowDescriptor &to); Dialogs::RowDescriptor chatListEntryBefore( @@ -365,6 +371,7 @@ private: Dialogs::Key _menuKey; Fn _loadMoreCallback; + rpl::event_stream<> _listBottomReached; base::unique_qptr _menu; diff --git a/Telegram/SourceFiles/dialogs/dialogs_key.h b/Telegram/SourceFiles/dialogs/dialogs_key.h index 7d712a6ec..295f205b7 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_key.h +++ b/Telegram/SourceFiles/dialogs/dialogs_key.h @@ -85,7 +85,8 @@ struct RowDescriptor { }; inline bool operator==(const RowDescriptor &a, const RowDescriptor &b) { - return (a.key == b.key) && (a.fullId == b.fullId); + return (a.key == b.key) + && ((a.fullId == b.fullId) || (!a.fullId.msg && !b.fullId.msg)); } inline bool operator!=(const RowDescriptor &a, const RowDescriptor &b) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 7812635c2..84d3bf75f 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -226,6 +226,10 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null cont loadDialogs(); } }); + _inner->listBottomReached( + ) | rpl::start_with_next([=] { + loadMoreBlockedByDateChats(); + }, lifetime()); _filter->setFocusPolicy(Qt::StrongFocus); _filter->customUpDown(true); @@ -530,14 +534,7 @@ void DialogsWidget::refreshLoadMoreButton() { st::dialogsLoadMore, st::dialogsLoadMore); _loadMoreChats->addClickHandler([=] { - if (_loadMoreChats->isDisabled()) { - return; - } - const auto max = Auth().settings().supportChatsTimeSlice(); - _dialogsLoadTill = _dialogsOffsetDate - ? (_dialogsOffsetDate - max) - : (unixtime() - max); - loadDialogs(); + loadMoreBlockedByDateChats(); }); updateControlsGeometry(); } @@ -546,6 +543,17 @@ void DialogsWidget::refreshLoadMoreButton() { _loadMoreChats->setText(loading ? "Loading..." : "Load more"); } +void DialogsWidget::loadMoreBlockedByDateChats() { + if (!_loadMoreChats || _loadMoreChats->isDisabled()) { + return; + } + const auto max = Auth().settings().supportChatsTimeSlice(); + _dialogsLoadTill = _dialogsOffsetDate + ? (_dialogsOffsetDate - max) + : (unixtime() - max); + loadDialogs(); +} + void DialogsWidget::pinnedDialogsReceived( const MTPmessages_PeerDialogs &result, mtpRequestId requestId) { diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h index 48f493c52..bbe9fb27c 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h @@ -165,6 +165,7 @@ private: void refreshSupportFilteredResults(); bool loadingBlockedByDate() const; void refreshLoadMoreButton(); + void loadMoreBlockedByDateChats(); bool dialogsFailed(const RPCError &error, mtpRequestId req); bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req);