Implement keyboard navigation for recent peers.
This commit is contained in:
parent
051ca51d3b
commit
19f5d95a3c
|
@ -3165,32 +3165,25 @@ void Widget::keyPressEvent(QKeyEvent *e) {
|
||||||
//}
|
//}
|
||||||
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
|
||||||
submit();
|
submit();
|
||||||
|
} else if (_suggestions
|
||||||
|
&& (e->key() == Qt::Key_Down
|
||||||
|
|| e->key() == Qt::Key_Up
|
||||||
|
|| e->key() == Qt::Key_Left
|
||||||
|
|| e->key() == Qt::Key_Right)) {
|
||||||
|
_suggestions->selectJump(Qt::Key(e->key()));
|
||||||
} else if (e->key() == Qt::Key_Down) {
|
} else if (e->key() == Qt::Key_Down) {
|
||||||
if (_suggestions) {
|
_inner->selectSkip(1);
|
||||||
_suggestions->selectSkip(1);
|
|
||||||
} else {
|
|
||||||
_inner->selectSkip(1);
|
|
||||||
}
|
|
||||||
} else if (e->key() == Qt::Key_Up) {
|
} else if (e->key() == Qt::Key_Up) {
|
||||||
if (_suggestions) {
|
|
||||||
_suggestions->selectSkip(-1);
|
|
||||||
} else {
|
|
||||||
_inner->selectSkip(-1);
|
|
||||||
}
|
|
||||||
_inner->selectSkip(-1);
|
_inner->selectSkip(-1);
|
||||||
} else if (e->key() == Qt::Key_Left && _suggestions) {
|
|
||||||
_suggestions->selectLeft();
|
|
||||||
} else if (e->key() == Qt::Key_Right && _suggestions) {
|
|
||||||
_suggestions->selectRight();
|
|
||||||
} else if (e->key() == Qt::Key_PageDown) {
|
} else if (e->key() == Qt::Key_PageDown) {
|
||||||
if (_suggestions) {
|
if (_suggestions) {
|
||||||
_suggestions->selectSkipPage(_scroll->height(), 1);
|
_suggestions->selectJump(Qt::Key_Down, _scroll->height());
|
||||||
} else {
|
} else {
|
||||||
_inner->selectSkipPage(_scroll->height(), 1);
|
_inner->selectSkipPage(_scroll->height(), 1);
|
||||||
}
|
}
|
||||||
} else if (e->key() == Qt::Key_PageUp) {
|
} else if (e->key() == Qt::Key_PageUp) {
|
||||||
if (_suggestions) {
|
if (_suggestions) {
|
||||||
_suggestions->selectSkipPage(_scroll->height(), -1);
|
_suggestions->selectJump(Qt::Key_Up, _scroll->height());
|
||||||
} else {
|
} else {
|
||||||
_inner->selectSkipPage(_scroll->height(), -1);
|
_inner->selectSkipPage(_scroll->height(), -1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -491,43 +491,60 @@ Suggestions::Suggestions(
|
||||||
|
|
||||||
Suggestions::~Suggestions() = default;
|
Suggestions::~Suggestions() = default;
|
||||||
|
|
||||||
void Suggestions::selectSkip(int delta) {
|
void Suggestions::selectJump(Qt::Key direction, int pageSize) {
|
||||||
if (!delta) {
|
const auto recentHasSelection = [=] {
|
||||||
return;
|
return _recentSelectJump(Qt::Key(), 0) == JumpResult::Applied;
|
||||||
} else if (delta > 0) {
|
};
|
||||||
const auto hasRecent = false;
|
if (pageSize) {
|
||||||
if (hasRecent && (_topPeers->selectedByKeyboard() || delta > 1)) {
|
if (direction == Qt::Key_Down || direction == Qt::Key_Up) {
|
||||||
_topPeers->deselectByKeyboard();
|
_topPeers->deselectByKeyboard();
|
||||||
|
if (!recentHasSelection()) {
|
||||||
|
if (direction == Qt::Key_Down) {
|
||||||
|
_recentSelectJump(direction, 0);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_recentSelectJump(direction, pageSize) == JumpResult::AppliedAndOut) {
|
||||||
|
if (direction == Qt::Key_Up) {
|
||||||
|
_scroll->scrollTo(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (direction == Qt::Key_Up) {
|
||||||
|
if (_recentSelectJump(direction, pageSize)
|
||||||
|
== JumpResult::AppliedAndOut) {
|
||||||
|
_topPeers->selectByKeyboard(Qt::Key());
|
||||||
|
_scroll->scrollTo(0);
|
||||||
} else {
|
} else {
|
||||||
_topPeers->selectByKeyboard(0);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (_topPeers->selectedByKeyboard()) {
|
|
||||||
_topPeers->deselectByKeyboard();
|
_topPeers->deselectByKeyboard();
|
||||||
}
|
}
|
||||||
}
|
} else if (direction == Qt::Key_Down) {
|
||||||
}
|
if (_topPeers->selectedByKeyboard()) {
|
||||||
|
if (_recentCount.current() > 0) {
|
||||||
void Suggestions::selectSkipPage(int height, int direction) {
|
_topPeers->deselectByKeyboard();
|
||||||
if (_topPeers->selectedByKeyboard()) {
|
_recentSelectJump(direction, pageSize);
|
||||||
_topPeers->deselectByKeyboard();
|
}
|
||||||
|
} else if (!_topPeersWrap->toggled() || recentHasSelection()) {
|
||||||
|
_recentSelectJump(direction, pageSize);
|
||||||
|
} else {
|
||||||
|
_topPeers->selectByKeyboard(Qt::Key());
|
||||||
|
_scroll->scrollTo(0);
|
||||||
|
}
|
||||||
|
} else if (direction == Qt::Key_Left || direction == Qt::Key_Right) {
|
||||||
|
if (!recentHasSelection()) {
|
||||||
|
_topPeers->selectByKeyboard(direction);
|
||||||
|
_scroll->scrollTo(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Suggestions::chooseRow() {
|
void Suggestions::chooseRow() {
|
||||||
if (_topPeers->chooseRow()) {
|
if (!_topPeers->chooseRow()) {
|
||||||
return;
|
_recentPeersChoose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Suggestions::selectLeft() {
|
|
||||||
_topPeers->selectLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Suggestions::selectRight() {
|
|
||||||
_topPeers->selectRight();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Suggestions::paintEvent(QPaintEvent *e) {
|
void Suggestions::paintEvent(QPaintEvent *e) {
|
||||||
QPainter(this).fillRect(e->rect(), st::windowBg);
|
QPainter(this).fillRect(e->rect(), st::windowBg);
|
||||||
}
|
}
|
||||||
|
@ -559,7 +576,39 @@ object_ptr<Ui::SlideWrap<>> Suggestions::setupRecentPeers(
|
||||||
}, lifetime);
|
}, lifetime);
|
||||||
|
|
||||||
auto content = object_ptr<PeerListContent>(_content, controller);
|
auto content = object_ptr<PeerListContent>(_content, controller);
|
||||||
delegate->setContent(content);
|
|
||||||
|
const auto raw = content.data();
|
||||||
|
_recentPeersChoose = [=] {
|
||||||
|
return raw->submitted();
|
||||||
|
};
|
||||||
|
_recentSelectJump = [raw](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) {
|
||||||
|
return JumpResult::NotApplied;
|
||||||
|
} else if (direction == Qt::Key_Down || direction == Qt::Key_Up) {
|
||||||
|
const auto delta = (direction == Qt::Key_Down) ? 1 : -1;
|
||||||
|
if (pageSize > 0) {
|
||||||
|
raw->selectSkipPage(pageSize, delta);
|
||||||
|
} else {
|
||||||
|
raw->selectSkip(delta);
|
||||||
|
}
|
||||||
|
return raw->hasSelection()
|
||||||
|
? JumpResult::Applied
|
||||||
|
: had
|
||||||
|
? JumpResult::AppliedAndOut
|
||||||
|
: JumpResult::NotApplied;
|
||||||
|
}
|
||||||
|
return JumpResult::NotApplied;
|
||||||
|
};
|
||||||
|
raw->scrollToRequests(
|
||||||
|
) | rpl::start_with_next([this](Ui::ScrollToRequest request) {
|
||||||
|
const auto add = _topPeersWrap->toggled() ? _topPeers->height() : 0;
|
||||||
|
_scroll->scrollToY(request.ymin + add, request.ymax + add);
|
||||||
|
}, lifetime);
|
||||||
|
|
||||||
|
delegate->setContent(raw);
|
||||||
controller->setDelegate(delegate);
|
controller->setDelegate(delegate);
|
||||||
|
|
||||||
return object_ptr<Ui::SlideWrap<>>(this, std::move(content));
|
return object_ptr<Ui::SlideWrap<>>(this, std::move(content));
|
||||||
|
|
|
@ -41,10 +41,7 @@ public:
|
||||||
RecentPeersList recentPeers);
|
RecentPeersList recentPeers);
|
||||||
~Suggestions();
|
~Suggestions();
|
||||||
|
|
||||||
void selectSkip(int delta);
|
void selectJump(Qt::Key direction, int pageSize = 0);
|
||||||
void selectSkipPage(int height, int direction);
|
|
||||||
void selectLeft();
|
|
||||||
void selectRight();
|
|
||||||
void chooseRow();
|
void chooseRow();
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<not_null<PeerData*>> topPeerChosen() const {
|
[[nodiscard]] rpl::producer<not_null<PeerData*>> topPeerChosen() const {
|
||||||
|
@ -55,6 +52,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
enum class JumpResult {
|
||||||
|
NotApplied,
|
||||||
|
Applied,
|
||||||
|
AppliedAndOut,
|
||||||
|
};
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *e) override;
|
void paintEvent(QPaintEvent *e) override;
|
||||||
void resizeEvent(QResizeEvent *e) override;
|
void resizeEvent(QResizeEvent *e) override;
|
||||||
|
|
||||||
|
@ -70,6 +73,8 @@ private:
|
||||||
const not_null<TopPeersStrip*> _topPeers;
|
const not_null<TopPeersStrip*> _topPeers;
|
||||||
|
|
||||||
rpl::variable<int> _recentCount;
|
rpl::variable<int> _recentCount;
|
||||||
|
Fn<bool()> _recentPeersChoose;
|
||||||
|
Fn<JumpResult(Qt::Key, int)> _recentSelectJump;
|
||||||
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _recentPeers;
|
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _recentPeers;
|
||||||
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _emptyRecent;
|
const not_null<Ui::SlideWrap<Ui::RpWidget>*> _emptyRecent;
|
||||||
|
|
||||||
|
|
|
@ -282,20 +282,29 @@ bool TopPeersStrip::selectedByKeyboard() const {
|
||||||
return _selectionByKeyboard && _selected >= 0;
|
return _selectionByKeyboard && _selected >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopPeersStrip::selectByKeyboard(int delta) {
|
void TopPeersStrip::selectByKeyboard(Qt::Key direction) {
|
||||||
if (_entries.empty()) {
|
if (_entries.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_selectionByKeyboard = true;
|
if (direction == Qt::Key()) {
|
||||||
if (!delta) {
|
_selectionByKeyboard = true;
|
||||||
if (_selected < 0) {
|
if (_selected < 0) {
|
||||||
setSelected(0);
|
setSelected(0);
|
||||||
scrollToSelected();
|
scrollToSelected();
|
||||||
}
|
}
|
||||||
return;
|
} else if (direction == Qt::Key_Left) {
|
||||||
|
if (_selected > 0) {
|
||||||
|
_selectionByKeyboard = true;
|
||||||
|
setSelected(_selected - 1);
|
||||||
|
scrollToSelected();
|
||||||
|
}
|
||||||
|
} else if (direction == Qt::Key_Right) {
|
||||||
|
if (_selected + 1 < _entries.size()) {
|
||||||
|
_selectionByKeyboard = true;
|
||||||
|
setSelected(_selected + 1);
|
||||||
|
scrollToSelected();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setSelected(std::clamp(_selected + delta, 0, int(_entries.size()) - 1));
|
|
||||||
scrollToSelected();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopPeersStrip::deselectByKeyboard() {
|
void TopPeersStrip::deselectByKeyboard() {
|
||||||
|
@ -305,22 +314,6 @@ void TopPeersStrip::deselectByKeyboard() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopPeersStrip::selectLeft() {
|
|
||||||
if (_selected > 0) {
|
|
||||||
_selectionByKeyboard = true;
|
|
||||||
setSelected(_selected - 1);
|
|
||||||
scrollToSelected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TopPeersStrip::selectRight() {
|
|
||||||
if (_selected + 1 < _entries.size()) {
|
|
||||||
_selectionByKeyboard = true;
|
|
||||||
setSelected(_selected + 1);
|
|
||||||
scrollToSelected();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TopPeersStrip::chooseRow() {
|
bool TopPeersStrip::chooseRow() {
|
||||||
if (_selected >= 0) {
|
if (_selected >= 0) {
|
||||||
Assert(_selected < _entries.size());
|
Assert(_selected < _entries.size());
|
||||||
|
|
|
@ -53,9 +53,7 @@ public:
|
||||||
void removeLocally(uint64 id = 0);
|
void removeLocally(uint64 id = 0);
|
||||||
|
|
||||||
[[nodiscard]] bool selectedByKeyboard() const;
|
[[nodiscard]] bool selectedByKeyboard() const;
|
||||||
void selectByKeyboard(int delta);
|
void selectByKeyboard(Qt::Key direction);
|
||||||
void selectLeft();
|
|
||||||
void selectRight();
|
|
||||||
void deselectByKeyboard();
|
void deselectByKeyboard();
|
||||||
bool chooseRow();
|
bool chooseRow();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue