From 3b1d13eac91e1f46aa0e29f916f1a8ff447b435b Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 17 Mar 2023 17:51:53 +0400 Subject: [PATCH] Clear memory while scrolling in topics / discussions. --- .../history/view/history_view_list_widget.cpp | 25 ++++++++++++++++--- .../history/view/history_view_list_widget.h | 12 +++++---- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 85347cb76..639c35ce5 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -490,6 +490,8 @@ void ListWidget::setGeometryCrashAnnotations(not_null view) { } void ListWidget::refreshRows(const Data::MessagesSlice &old) { + Expects(_viewsCapacity.empty()); + saveScrollState(); const auto addedToEndFrom = (old.skippedAfter == 0 @@ -507,13 +509,14 @@ void ListWidget::refreshRows(const Data::MessagesSlice &old) { _resizePending = true; _items.clear(); _items.reserve(_slice.ids.size()); + std::swap(_views, _viewsCapacity); auto nearestIndex = -1; for (const auto &fullId : _slice.ids) { if (const auto item = session().data().message(fullId)) { if (_slice.nearestToAround == fullId) { nearestIndex = int(_items.size()); } - const auto view = enforceViewForItem(item); + const auto view = enforceViewForItem(item, _viewsCapacity); _items.push_back(view); if (destroyingBarElement == view) { destroyingBarElement = nullptr; @@ -541,6 +544,13 @@ void ListWidget::refreshRows(const Data::MessagesSlice &old) { _bar = {}; } + for (const auto &[item, view] : _viewsCapacity) { + if (const auto raw = view.get()) { + viewReplaced(raw, nullptr); + } + } + _viewsCapacity.clear(); + checkUnreadBarCreation(); restoreScrollState(); if (!_itemsRevealHeight) { @@ -868,9 +878,16 @@ Element *ListWidget::viewForItem(const HistoryItem *item) const { } not_null ListWidget::enforceViewForItem( - not_null item) { - if (const auto view = viewForItem(item)) { - return view; + not_null item, + ViewsMap &old) { + if (const auto i = old.find(item); i != end(old)) { + if (i->second) { + return _views.emplace( + item, + base::take(i->second)).first->second.get(); + } else if (const auto j = _views.find(item); j != end(_views)) { + return j->second.get(); + } } const auto [i, ok] = _views.emplace( item, diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.h b/Telegram/SourceFiles/history/view/history_view_list_widget.h index c8ad5f1fc..ad3517723 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.h +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.h @@ -359,6 +359,9 @@ private: using PointState = HistoryView::PointState; using CursorState = HistoryView::CursorState; using ChosenReaction = HistoryView::Reactions::ChosenReaction; + using ViewsMap = base::flat_map< + not_null, + std::unique_ptr>; struct MouseState { MouseState(); @@ -433,7 +436,9 @@ private: Element *viewForItem(FullMsgId itemId) const; Element *viewForItem(const HistoryItem *item) const; - not_null enforceViewForItem(not_null item); + not_null enforceViewForItem( + not_null item, + ViewsMap &old); void mouseActionStart( const QPoint &globalPosition, @@ -623,10 +628,7 @@ private: int _idsLimit = kMinimalIdsLimit; Data::MessagesSlice _slice; std::vector> _items; - std::map< - not_null, - std::unique_ptr, - std::less<>> _views; + ViewsMap _views, _viewsCapacity; int _itemsTop = 0; int _itemsWidth = 0; int _itemsHeight = 0;