Add keyboard navigation to top peers.

This commit is contained in:
John Preston 2024-04-11 13:55:38 +04:00
parent a6c1def6fe
commit e1c21b908c
5 changed files with 162 additions and 7 deletions

View file

@ -1720,7 +1720,10 @@ void Widget::escape() {
}
void Widget::submit() {
if (_inner->chooseRow()) {
if (_suggestions) {
_suggestions->chooseRow();
return;
} else if (_inner->chooseRow()) {
return;
}
const auto state = _inner->state();
@ -3142,13 +3145,34 @@ void Widget::keyPressEvent(QKeyEvent *e) {
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
submit();
} else if (e->key() == Qt::Key_Down) {
_inner->selectSkip(1);
if (_suggestions) {
_suggestions->selectSkip(1);
} else {
_inner->selectSkip(1);
}
} else if (e->key() == Qt::Key_Up) {
if (_suggestions) {
_suggestions->selectSkip(-1);
} else {
_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) {
_inner->selectSkipPage(_scroll->height(), 1);
if (_suggestions) {
_suggestions->selectSkipPage(_scroll->height(), 1);
} else {
_inner->selectSkipPage(_scroll->height(), 1);
}
} else if (e->key() == Qt::Key_PageUp) {
_inner->selectSkipPage(_scroll->height(), -1);
if (_suggestions) {
_suggestions->selectSkipPage(_scroll->height(), -1);
} else {
_inner->selectSkipPage(_scroll->height(), -1);
}
} else if (!(e->modifiers() & ~Qt::ShiftModifier)
&& e->key() != Qt::Key_Shift
&& !_openedFolder

View file

@ -100,6 +100,43 @@ Suggestions::Suggestions(
Suggestions::~Suggestions() = default;
void Suggestions::selectSkip(int delta) {
if (!delta) {
return;
} else if (delta > 0) {
const auto hasRecent = false;
if (hasRecent && (_topPeers->selectedByKeyboard() || delta > 1)) {
_topPeers->deselectByKeyboard();
} else {
_topPeers->selectByKeyboard(0);
}
} else {
if (_topPeers->selectedByKeyboard()) {
_topPeers->deselectByKeyboard();
}
}
}
void Suggestions::selectSkipPage(int height, int direction) {
if (_topPeers->selectedByKeyboard()) {
_topPeers->deselectByKeyboard();
}
}
void Suggestions::chooseRow() {
if (_topPeers->chooseRow()) {
return;
}
}
void Suggestions::selectLeft() {
_topPeers->selectLeft();
}
void Suggestions::selectRight() {
_topPeers->selectRight();
}
void Suggestions::paintEvent(QPaintEvent *e) {
QPainter(this).fillRect(e->rect(), st::windowBg);
}

View file

@ -36,6 +36,12 @@ public:
rpl::producer<TopPeersList> topPeers);
~Suggestions();
void selectSkip(int delta);
void selectSkipPage(int height, int direction);
void selectLeft();
void selectRight();
void chooseRow();
[[nodiscard]] rpl::producer<PeerId> topPeerChosen() const {
return _topPeerChosen.events();
}

View file

@ -94,6 +94,11 @@ void TopPeersStrip::wheelEvent(QWheelEvent *e) {
e->accept();
}
void TopPeersStrip::leaveEventHook(QEvent *e) {
setSelected(-1);
_selectionByKeyboard = false;
}
void TopPeersStrip::mousePressEvent(QMouseEvent *e) {
if (e->button() != Qt::LeftButton) {
return;
@ -123,7 +128,11 @@ void TopPeersStrip::mousePressEvent(QMouseEvent *e) {
}
void TopPeersStrip::mouseMoveEvent(QMouseEvent *e) {
if (_lastMousePosition == e->globalPos() && _selectionByKeyboard) {
return;
}
_lastMousePosition = e->globalPos();
_selectionByKeyboard = false;
updateSelected();
if (!_dragging && _mouseDownPosition) {
@ -259,6 +268,58 @@ void TopPeersStrip::removeLocally(uint64 id) {
update();
}
bool TopPeersStrip::selectedByKeyboard() const {
return _selectionByKeyboard && _selected >= 0;
}
void TopPeersStrip::selectByKeyboard(int delta) {
if (_entries.empty()) {
return;
}
_selectionByKeyboard = true;
if (!delta) {
if (_selected < 0) {
setSelected(0);
scrollToSelected();
}
return;
}
setSelected(std::clamp(_selected + delta, 0, int(_entries.size()) - 1));
scrollToSelected();
}
void TopPeersStrip::deselectByKeyboard() {
if (_selectionByKeyboard) {
_selectionByKeyboard = false;
setSelected(-1);
}
}
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() {
if (_selected >= 0) {
Assert(_selected < _entries.size());
_clicks.fire_copy(_entries[_selected].id);
return true;
}
return false;
}
void TopPeersStrip::apply(const TopPeersList &list) {
auto now = std::vector<Entry>();
@ -542,9 +603,10 @@ void TopPeersStrip::updateSelected() {
const auto x = p.x();
const auto single = st.photoLeft * 2 + st.photo;
const auto index = (_scrollLeft + x) / single;
const auto selected = (index < 0 || index >= _entries.size())
? -1
: index;
setSelected((index < 0 || index >= _entries.size()) ? -1 : index);
}
void TopPeersStrip::setSelected(int selected) {
if (_selected != selected) {
const auto over = (selected >= 0);
if (over != (_selected >= 0)) {
@ -555,4 +617,19 @@ void TopPeersStrip::updateSelected() {
}
}
void TopPeersStrip::scrollToSelected() {
if (_selected < 0) {
return;
}
const auto &st = st::topPeers;
const auto single = st.photoLeft * 2 + st.photo;
const auto left = _selected * single;
const auto right = left + single;
if (_scrollLeft > left) {
_scrollLeft = std::clamp(left, 0, _scrollLeftMax);
} else if (_scrollLeft + width() < right) {
_scrollLeft = std::clamp(right - width(), 0, _scrollLeftMax);
}
}
} // namespace Dialogs

View file

@ -52,6 +52,13 @@ public:
void removeLocally(uint64 id);
[[nodiscard]] bool selectedByKeyboard() const;
void selectByKeyboard(int delta);
void selectLeft();
void selectRight();
void deselectByKeyboard();
bool chooseRow();
private:
struct Entry;
@ -62,9 +69,12 @@ private:
void mouseMoveEvent(QMouseEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
void leaveEventHook(QEvent *e) override;
void updateScrollMax();
void updateSelected();
void setSelected(int selected);
void scrollToSelected();
void checkDragging();
bool finishDragging();
void subscribeUserpic(Entry &entry);
@ -94,6 +104,7 @@ private:
int _selected = -1;
int _pressed = -1;
bool _selectionByKeyboard = false;
Ui::RoundRect _selection;
base::unique_qptr<Ui::PopupMenu> _menu;