Fix reorder freeze in chats list.

This commit is contained in:
John Preston
2026-03-11 15:54:08 +04:00
parent cf2a44792f
commit 09f9819233
4 changed files with 87 additions and 10 deletions
@@ -1681,10 +1681,14 @@ void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
}
if (_lastMousePosition && *_lastMousePosition != globalPosition) {
if (!_freezeTimer.isActive()) {
_shownList->freeze();
if (skipChatsListFreeze()) {
unfreezeShownList(true);
} else {
if (!_freezeTimer.isActive()) {
_shownList->freeze();
}
_freezeTimer.callOnce(kFreezeTimeout);
}
_freezeTimer.callOnce(kFreezeTimeout);
}
if (_pressed && (e->buttons() & Qt::LeftButton)) {
@@ -1700,6 +1704,7 @@ void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
if (!_qdragging && outside && distanceExceeded) {
if (_pressed->history()) {
unfreezeShownList(true);
_dragging = _pressed;
_qdragging = _pressed;
InvokeQueued(this, [=] { performDrag(); });
@@ -1716,6 +1721,19 @@ void InnerWidget::mouseMoveEvent(QMouseEvent *e) {
}
}
bool InnerWidget::skipChatsListFreeze() const {
return _dragging != nullptr;
}
void InnerWidget::unfreezeShownList(bool updateIfWasFrozen) {
const auto wasFrozen = _freezeTimer.isActive();
_freezeTimer.cancel();
_shownList->unfreeze();
if (updateIfWasFrozen && wasFrozen) {
update();
}
}
void InnerWidget::performDrag() {
if (!_qdragging || !session().data().chatsFilters().has()) {
return;
@@ -2278,6 +2296,7 @@ void InnerWidget::checkReorderPinnedStart(QPoint localPosition) {
!= Dialogs::Ui::QuickDialogAction::Disabled)) {
return;
}
unfreezeShownList(true);
_dragging = _pressed;
startReorderPinned(localPosition);
}
@@ -3061,8 +3080,12 @@ void InnerWidget::updateDialogRow(
void InnerWidget::enterEventHook(QEnterEvent *e) {
setMouseTracking(true);
_shownList->freeze();
_freezeTimer.callOnce(kFreezeTimeout);
if (skipChatsListFreeze()) {
unfreezeShownList(false);
} else {
_shownList->freeze();
_freezeTimer.callOnce(kFreezeTimeout);
}
}
Row *InnerWidget::shownRowByKey(Key key) {
@@ -3153,15 +3176,16 @@ void InnerWidget::refreshShownList() {
void InnerWidget::leaveEventHook(QEvent *e) {
setMouseTracking(false);
_freezeTimer.cancel();
_shownList->unfreeze();
unfreezeShownList(false);
clearSelection();
update();
}
void InnerWidget::dragLeft() {
setMouseTracking(false);
unfreezeShownList(false);
clearSelection();
update();
}
FilterId InnerWidget::filterId() const {
@@ -3498,6 +3522,7 @@ void InnerWidget::dragPinnedFromTouch() {
return;
}
_dragStart = mapFromGlobal(global);
unfreezeShownList(true);
_dragging = _selected;
const auto now = mapFromGlobal(_touchDragNowGlobal.value_or(global));
startReorderPinned(now);
@@ -3697,6 +3722,7 @@ void InnerWidget::appendToFiltered(Key key) {
}
InnerWidget::~InnerWidget() {
unfreezeShownList(false);
session().data().stories().decrementPreloadingMainSources();
clearSearchResults();
}
@@ -3811,6 +3837,10 @@ void InnerWidget::trackResultsHistory(not_null<History*> history) {
}
Data::Thread *InnerWidget::updateFromParentDrag(QPoint globalPosition) {
if (!_freezeTimer.isActive()) {
_shownList->freeze();
}
_freezeTimer.callOnce(kFreezeTimeout);
selectByMouse(globalPosition);
const auto fromRow = [](Row *row) {
@@ -487,6 +487,8 @@ private:
void startReorderPinned(QPoint localPosition);
int updateReorderIndexGetCount();
bool updateReorderPinned(QPoint localPosition);
[[nodiscard]] bool skipChatsListFreeze() const;
void unfreezeShownList(bool updateIfWasFrozen);
void finishReorderPinned();
bool finishReorderOnRelease();
void stopReorderPinned();
+44 -3
View File
@@ -85,8 +85,13 @@ void List::adjustByDate(not_null<Row*> row) {
Expects(_sortMode == SortMode::Date);
if (_frozen) {
_pendingAdjust.emplace(row);
return;
const auto canAdjustWhileFrozen = _pendingAdjust.empty()
&& (row->entry()->fixedOnTopIndex()
|| row->entry()->isPinnedDialog(_filterId));
if (!canAdjustWhileFrozen) {
_pendingAdjust.emplace(row);
return;
}
}
const auto key = row->sortKey(_filterId);
@@ -114,9 +119,45 @@ void List::freeze() {
void List::unfreeze() {
_frozen = false;
for (const auto &row : base::take(_pendingAdjust)) {
auto pending = base::take(_pendingAdjust);
if (pending.empty()) {
return;
} else if (pending.size() == 1) {
adjustByDate(*pending.begin());
return;
}
for (const auto &row : pending) {
adjustByDate(row);
}
if (!sortedByDate()) {
sortByDate();
}
}
bool List::sortedByDate() const {
Expects(_sortMode == SortMode::Date);
for (auto i = 1, count = int(_rows.size()); i != count; ++i) {
if (_rows[i - 1]->sortKey(_filterId) < _rows[i]->sortKey(_filterId)) {
return false;
}
}
return true;
}
void List::sortByDate() {
Expects(_sortMode == SortMode::Date);
ranges::stable_sort(_rows, [&](Row *a, Row *b) {
return a->sortKey(_filterId) > b->sortKey(_filterId);
});
auto top = 0;
for (auto i = 0, count = int(_rows.size()); i != count; ++i) {
const auto row = _rows[i];
row->_index = i;
row->_top = top;
top += row->height();
}
}
bool List::updateHeight(Key key, float64 narrowRatio) {
@@ -24,6 +24,8 @@ public:
~List() = default;
void clear() {
_frozen = false;
_pendingAdjust.clear();
_rows.clear();
_rowByKey.clear();
}
@@ -76,6 +78,8 @@ public:
private:
void adjustByName(not_null<Row*> row);
[[nodiscard]] bool sortedByDate() const;
void sortByDate();
void rotate(
std::vector<not_null<Row*>>::iterator first,
std::vector<not_null<Row*>>::iterator middle,