Skip to content

Commit 5f11211

Browse files
futpibjohn-preston
authored andcommitted
Freeze chat list order while mouse hovers over it
When subscribed to many active chats, the list reorders too quickly, causing misclicks. Freeze the visual order while the mouse is over the chat list and replay deferred reorderings when the mouse leaves or after 5 seconds of inactivity. Fixes #1504.
1 parent 68e1504 commit 5f11211

6 files changed

Lines changed: 54 additions & 1 deletion

File tree

Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,20 @@ void IndexedList::adjustNames(
194194
}
195195
}
196196

197+
void IndexedList::freeze() {
198+
_list.freeze();
199+
for (auto &[ch, list] : _index) {
200+
list.freeze();
201+
}
202+
}
203+
204+
void IndexedList::unfreeze() {
205+
_list.unfreeze();
206+
for (auto &[ch, list] : _index) {
207+
list.unfreeze();
208+
}
209+
}
210+
197211
void IndexedList::remove(Key key, Row *replacedBy) {
198212
if (_list.remove(key, replacedBy)) {
199213
for (const auto &ch : key.entry()->chatListFirstLetters()) {

Telegram/SourceFiles/dialogs/dialogs_indexed_list.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class IndexedList {
2424
Row *addByName(Key key);
2525
void adjustByDate(const RowsByLetter &links);
2626
void moveToTop(Key key);
27+
void freeze();
28+
void unfreeze();
2729
bool updateHeight(Key key, float64 narrowRatio);
2830
bool updateHeights(float64 narrowRatio);
2931

Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ For license and copyright information please follow this link:
9595
namespace Dialogs {
9696
namespace {
9797

98+
constexpr auto kFreezeTimeout = crl::time(5000);
9899
constexpr auto kHashtagResultsLimit = 5;
99100
constexpr auto kStartReorderThreshold = 30;
100101
constexpr auto kStartDragToFilterThresholdX = kStartReorderThreshold;
@@ -291,7 +292,8 @@ InnerWidget::InnerWidget(
291292
, _narrowWidth(st::defaultDialogRow.padding.left()
292293
+ st::defaultDialogRow.photoSize
293294
+ st::defaultDialogRow.padding.left())
294-
, _childListShown(std::move(childListShown)) {
295+
, _childListShown(std::move(childListShown))
296+
, _freezeTimer([=] { _shownList->unfreeze(); update(); }) {
295297
setAttribute(Qt::WA_OpaquePaintEvent, true);
296298

297299
style::PaletteChanged(
@@ -1678,6 +1680,13 @@ void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
16781680
return;
16791681
}
16801682

1683+
if (_lastMousePosition && *_lastMousePosition != globalPosition) {
1684+
if (!_freezeTimer.isActive()) {
1685+
_shownList->freeze();
1686+
}
1687+
_freezeTimer.callOnce(kFreezeTimeout);
1688+
}
1689+
16811690
if (_pressed && (e->buttons() & Qt::LeftButton)) {
16821691
const auto local = e->pos();
16831692
const auto outside = _dragging ? false : true;
@@ -3052,6 +3061,8 @@ void InnerWidget::updateDialogRow(
30523061

30533062
void InnerWidget::enterEventHook(QEnterEvent *e) {
30543063
setMouseTracking(true);
3064+
_shownList->freeze();
3065+
_freezeTimer.callOnce(kFreezeTimeout);
30553066
}
30563067

30573068
Row *InnerWidget::shownRowByKey(Key key) {
@@ -3134,14 +3145,18 @@ void InnerWidget::refreshShownList() {
31343145
? session().data().chatsFilters().chatsList(_filterId)->indexed()
31353146
: session().data().chatsList(_openedFolder)->indexed();
31363147
if (_shownList != list) {
3148+
_shownList->unfreeze();
31373149
_shownList = list;
31383150
_shownList->updateHeights(_narrowRatio);
31393151
}
31403152
}
31413153

31423154
void InnerWidget::leaveEventHook(QEvent *e) {
31433155
setMouseTracking(false);
3156+
_freezeTimer.cancel();
3157+
_shownList->unfreeze();
31443158
clearSelection();
3159+
update();
31453160
}
31463161

31473162
void InnerWidget::dragLeft() {

Telegram/SourceFiles/dialogs/dialogs_inner_widget.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,7 @@ class InnerWidget final : public Ui::RpWidget {
678678
rpl::event_stream<> _touchCancelRequests;
679679

680680
rpl::variable<ChildListShown> _childListShown;
681+
base::Timer _freezeTimer;
681682
float64 _narrowRatio = 0.;
682683
bool _geometryInited = false;
683684

Telegram/SourceFiles/dialogs/dialogs_list.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ void List::adjustByName(not_null<Row*> row) {
8484
void List::adjustByDate(not_null<Row*> row) {
8585
Expects(_sortMode == SortMode::Date);
8686

87+
if (_frozen) {
88+
_pendingAdjust.emplace(row);
89+
return;
90+
}
91+
8792
const auto key = row->sortKey(_filterId);
8893
const auto index = row->index();
8994
const auto i = _rows.begin() + index;
@@ -103,6 +108,17 @@ void List::adjustByDate(not_null<Row*> row) {
103108
}
104109
}
105110

111+
void List::freeze() {
112+
_frozen = true;
113+
}
114+
115+
void List::unfreeze() {
116+
_frozen = false;
117+
for (const auto &row : base::take(_pendingAdjust)) {
118+
adjustByDate(row);
119+
}
120+
}
121+
106122
bool List::updateHeight(Key key, float64 narrowRatio) {
107123
const auto i = _rowByKey.find(key);
108124
if (i == _rowByKey.cend()) {
@@ -170,6 +186,7 @@ bool List::remove(Key key, Row *replacedBy) {
170186
}
171187

172188
const auto row = i->second.get();
189+
_pendingAdjust.remove(row);
173190
row->entry()->owner().dialogsRowReplaced({ row, replacedBy });
174191

175192
auto top = row->top();

Telegram/SourceFiles/dialogs/dialogs_list.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class List final {
5252
not_null<Row*> addByName(Key key);
5353
bool moveToTop(Key key);
5454
void adjustByDate(not_null<Row*> row);
55+
void freeze();
56+
void unfreeze();
5557
bool updateHeight(Key key, float64 narrowRatio);
5658
bool updateHeights(float64 narrowRatio);
5759
bool remove(Key key, Row *replacedBy = nullptr);
@@ -82,8 +84,10 @@ class List final {
8284
SortMode _sortMode = SortMode();
8385
FilterId _filterId = 0;
8486
float64 _narrowRatio = 0.;
87+
bool _frozen = false;
8588
std::vector<not_null<Row*>> _rows;
8689
std::map<Key, std::unique_ptr<Row>> _rowByKey;
90+
base::flat_set<not_null<Row*>> _pendingAdjust;
8791

8892
};
8993

0 commit comments

Comments
 (0)