Improve support shortcuts handling.

This commit is contained in:
John Preston 2018-12-29 17:09:45 +04:00
parent 219b824338
commit 496d711684
6 changed files with 84 additions and 24 deletions

View File

@ -26,6 +26,8 @@ const auto AutoRepeatCommands = base::flat_set<Command>{
Command::MediaNext, Command::MediaNext,
Command::ChatPrevious, Command::ChatPrevious,
Command::ChatNext, Command::ChatNext,
Command::ChatFirst,
Command::ChatLast,
}; };
const auto MediaCommands = base::flat_set<Command>{ const auto MediaCommands = base::flat_set<Command>{
@ -363,7 +365,7 @@ void Manager::set(const QString &keys, Command command) {
nullptr, nullptr,
nullptr, nullptr,
Qt::ApplicationShortcut); Qt::ApplicationShortcut);
if (AutoRepeatCommands.contains(command)) { if (!AutoRepeatCommands.contains(command)) {
shortcut->setAutoRepeat(false); shortcut->setAutoRepeat(false);
} }
const auto isMediaShortcut = MediaCommands.contains(command); const auto isMediaShortcut = MediaCommands.contains(command);

View File

@ -1758,6 +1758,14 @@ PeerData *DialogsInner::updateFromParentDrag(QPoint globalPosition) {
return nullptr; return nullptr;
} }
void DialogsInner::setLoadMoreCallback(Fn<void()> callback) {
_loadMoreCallback = std::move(callback);
}
rpl::producer<> DialogsInner::listBottomReached() const {
return _listBottomReached.events();
}
void DialogsInner::visibleTopBottomUpdated( void DialogsInner::visibleTopBottomUpdated(
int visibleTop, int visibleTop,
int visibleBottom) { int visibleBottom) {
@ -2803,21 +2811,40 @@ void DialogsInner::setupShortcuts() {
return; return;
} }
const auto row = _controller->activeChatEntryCurrent(); 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) { if (row.key) {
const auto prev = computeJump(chatListEntryBefore(row), -1);
const auto next = computeJump(chatListEntryAfter(row), 1);
request->check(Command::ChatPrevious) && request->handle([=] { request->check(Command::ChatPrevious) && request->handle([=] {
return jumpToDialogRow(prev); return jumpToDialogRow(previous);
}); });
request->check(Command::ChatNext) && request->handle([=] { request->check(Command::ChatNext) && request->handle([=] {
return jumpToDialogRow(next); return jumpToDialogRow(next);
}); });
} }
request->check(Command::ChatFirst) && request->handle([=] { request->check(Command::ChatFirst) && request->handle([=] {
return jumpToDialogRow(computeJump(chatListEntryFirst(), 1)); return jumpToDialogRow(first);
}); });
request->check(Command::ChatLast) && request->handle([=] { request->check(Command::ChatLast) && request->handle([=] {
return jumpToDialogRow(computeJump(chatListEntryLast(), -1)); return jumpToDialogRow(last);
}); });
if (Auth().supportMode() && row.key.history()) { if (Auth().supportMode() && row.key.history()) {
request->check( request->check(
@ -2832,21 +2859,35 @@ void DialogsInner::setupShortcuts() {
Dialogs::RowDescriptor DialogsInner::computeJump( Dialogs::RowDescriptor DialogsInner::computeJump(
const Dialogs::RowDescriptor &to, const Dialogs::RowDescriptor &to,
int skipDirection) { JumpSkip skip) {
auto result = to; auto result = to;
if (Auth().supportMode()) { if (Auth().supportMode() && result.key) {
while (result.key const auto down = (skip == JumpSkip::NextOrEnd)
&& !result.key.entry()->chatListUnreadCount() || (skip == JumpSkip::NextOrOriginal);
while (!result.key.entry()->chatListUnreadCount()
&& !result.key.entry()->chatListUnreadMark()) { && !result.key.entry()->chatListUnreadMark()) {
result = (skipDirection > 0) const auto next = down
? chatListEntryAfter(result) ? chatListEntryAfter(result)
: chatListEntryBefore(result); : chatListEntryBefore(result);
if (next.key) {
result = next;
} else {
if (skip == JumpSkip::PreviousOrOriginal
|| skip == JumpSkip::NextOrOriginal) {
result = to;
}
break;
}
} }
} }
return result; return result;
} }
bool DialogsInner::jumpToDialogRow(const Dialogs::RowDescriptor &to) { bool DialogsInner::jumpToDialogRow(const Dialogs::RowDescriptor &to) {
if (to == chatListEntryLast()) {
_listBottomReached.fire({});
}
if (const auto history = to.key.history()) { if (const auto history = to.key.history()) {
Ui::showPeerHistory( Ui::showPeerHistory(
history, history,

View File

@ -93,9 +93,8 @@ public:
PeerData *updateFromParentDrag(QPoint globalPosition); PeerData *updateFromParentDrag(QPoint globalPosition);
void setLoadMoreCallback(Fn<void()> callback) { void setLoadMoreCallback(Fn<void()> callback);
_loadMoreCallback = std::move(callback); [[nodiscard]] rpl::producer<> listBottomReached() const;
}
base::Observable<UserData*> searchFromUserChanged; base::Observable<UserData*> searchFromUserChanged;
@ -141,6 +140,13 @@ private:
struct PeerSearchResult; struct PeerSearchResult;
using PeerSearchResults = std::vector<std::unique_ptr<PeerSearchResult>>; using PeerSearchResults = std::vector<std::unique_ptr<PeerSearchResult>>;
enum class JumpSkip {
PreviousOrBegin,
NextOrEnd,
PreviousOrOriginal,
NextOrOriginal,
};
struct ChosenRow { struct ChosenRow {
Dialogs::Key key; Dialogs::Key key;
Data::MessagePosition message; Data::MessagePosition message;
@ -189,7 +195,7 @@ private:
void setupShortcuts(); void setupShortcuts();
Dialogs::RowDescriptor computeJump( Dialogs::RowDescriptor computeJump(
const Dialogs::RowDescriptor &to, const Dialogs::RowDescriptor &to,
int skipDirection); JumpSkip skip);
bool jumpToDialogRow(const Dialogs::RowDescriptor &to); bool jumpToDialogRow(const Dialogs::RowDescriptor &to);
Dialogs::RowDescriptor chatListEntryBefore( Dialogs::RowDescriptor chatListEntryBefore(
@ -365,6 +371,7 @@ private:
Dialogs::Key _menuKey; Dialogs::Key _menuKey;
Fn<void()> _loadMoreCallback; Fn<void()> _loadMoreCallback;
rpl::event_stream<> _listBottomReached;
base::unique_qptr<Ui::PopupMenu> _menu; base::unique_qptr<Ui::PopupMenu> _menu;

View File

@ -85,7 +85,8 @@ struct RowDescriptor {
}; };
inline bool operator==(const RowDescriptor &a, const RowDescriptor &b) { 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) { inline bool operator!=(const RowDescriptor &a, const RowDescriptor &b) {

View File

@ -226,6 +226,10 @@ DialogsWidget::DialogsWidget(QWidget *parent, not_null<Window::Controller*> cont
loadDialogs(); loadDialogs();
} }
}); });
_inner->listBottomReached(
) | rpl::start_with_next([=] {
loadMoreBlockedByDateChats();
}, lifetime());
_filter->setFocusPolicy(Qt::StrongFocus); _filter->setFocusPolicy(Qt::StrongFocus);
_filter->customUpDown(true); _filter->customUpDown(true);
@ -530,14 +534,7 @@ void DialogsWidget::refreshLoadMoreButton() {
st::dialogsLoadMore, st::dialogsLoadMore,
st::dialogsLoadMore); st::dialogsLoadMore);
_loadMoreChats->addClickHandler([=] { _loadMoreChats->addClickHandler([=] {
if (_loadMoreChats->isDisabled()) { loadMoreBlockedByDateChats();
return;
}
const auto max = Auth().settings().supportChatsTimeSlice();
_dialogsLoadTill = _dialogsOffsetDate
? (_dialogsOffsetDate - max)
: (unixtime() - max);
loadDialogs();
}); });
updateControlsGeometry(); updateControlsGeometry();
} }
@ -546,6 +543,17 @@ void DialogsWidget::refreshLoadMoreButton() {
_loadMoreChats->setText(loading ? "Loading..." : "Load more"); _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( void DialogsWidget::pinnedDialogsReceived(
const MTPmessages_PeerDialogs &result, const MTPmessages_PeerDialogs &result,
mtpRequestId requestId) { mtpRequestId requestId) {

View File

@ -165,6 +165,7 @@ private:
void refreshSupportFilteredResults(); void refreshSupportFilteredResults();
bool loadingBlockedByDate() const; bool loadingBlockedByDate() const;
void refreshLoadMoreButton(); void refreshLoadMoreButton();
void loadMoreBlockedByDateChats();
bool dialogsFailed(const RPCError &error, mtpRequestId req); bool dialogsFailed(const RPCError &error, mtpRequestId req);
bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req); bool searchFailed(DialogsSearchRequestType type, const RPCError &error, mtpRequestId req);