From d778276f5d518e7d046a0a969820a251dd85928e Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 24 Jan 2025 13:36:26 +0400
Subject: [PATCH] Reuse views in gifts lists.

---
 .../peer_gifts/info_peer_gifts_widget.cpp     | 58 ++++++++++++-------
 1 file changed, 38 insertions(+), 20 deletions(-)

diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp
index 75b27c6ee..eafc80936 100644
--- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp
+++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp
@@ -84,7 +84,8 @@ private:
 	};
 	struct View {
 		std::unique_ptr<GiftButton> button;
-		int entry = 0;
+		Data::SavedStarGiftId id;
+		int index = 0;
 	};
 
 	void visibleTopBottomUpdated(
@@ -96,7 +97,7 @@ private:
 	void loadMore();
 	void refreshButtons();
 	void validateButtons();
-	void showGift(int index);
+	void showGift(Data::SavedStarGiftId id);
 	void refreshAbout();
 
 	int resizeGetHeight(int width) override;
@@ -179,8 +180,8 @@ void InnerWidget::subscribeToUpdates() {
 				--_totalCount;
 			}
 			for (auto &view : _views) {
-				if (view.entry >= index) {
-					--view.entry;
+				if (view.index >= index) {
+					--view.index;
 				}
 			}
 		} else if (update.action == Action::Save
@@ -191,8 +192,9 @@ void InnerWidget::subscribeToUpdates() {
 				data.hidden = i->gift.hidden;
 			});
 			for (auto &view : _views) {
-				if (view.entry == index) {
-					view.entry = -1;
+				if (view.index == index) {
+					view.index = -1;
+					view.id = {};
 				}
 			}
 		} else {
@@ -263,7 +265,6 @@ void InnerWidget::loadMore() {
 
 		if (base::take(_reloading)) {
 			_entries.clear();
-			_views.clear();
 		}
 		_entries.reserve(_entries.size() + data.vgifts().v.size());
 		for (const auto &gift : data.vgifts().v) {
@@ -320,30 +321,44 @@ void InnerWidget::validateButtons() {
 	auto y = vskip + fromRow * oneh;
 	auto views = std::vector<View>();
 	views.reserve((tillRow - fromRow) * _perRow);
+	const auto idUsed = [&](const Data::SavedStarGiftId &id) {
+		for (auto j = fromRow; j != tillRow; ++j) {
+			for (auto i = 0; i != _perRow; ++i) {
+				const auto index = j * _perRow + i;
+				if (index >= _entries.size()) {
+					return false;
+				} else if (_entries[index].gift.id == id) {
+					return true;
+				}
+			}
+		}
+		return false;
+	};
 	const auto add = [&](int index) {
-		const auto already = ranges::find(_views, index, &View::entry);
+		const auto id = _entries[index].gift.id;
+		const auto already = ranges::find(_views, id, &View::id);
 		if (already != end(_views)) {
 			views.push_back(base::take(*already));
+			views.back().index = index;
 			return;
 		}
 		const auto &descriptor = _entries[index].descriptor;
 		const auto callback = [=] {
-			showGift(index);
+			showGift(id);
 		};
 		const auto unused = ranges::find_if(_views, [&](const View &v) {
-			return v.button
-				&& ((v.entry < fromRow * _perRow)
-					|| (v.entry >= tillRow * _perRow));
+			return v.button && !idUsed(v.id);
 		});
 		if (unused != end(_views)) {
 			views.push_back(base::take(*unused));
-			views.back().entry = index;
+			views.back().index = index;
 		} else {
 			auto button = std::make_unique<GiftButton>(this, &_delegate);
 			button->show();
 			views.push_back({
 				.button = std::move(button),
-				.entry = index,
+				.id = id,
+				.index = index,
 			});
 		}
 		views.back().button->setDescriptor(descriptor, mode);
@@ -367,12 +382,15 @@ void InnerWidget::validateButtons() {
 	std::swap(_views, views);
 }
 
-void InnerWidget::showGift(int index) {
-	_window->show(Box(
-		::Settings::SavedStarGiftBox,
-		_window,
-		_peer,
-		_entries[index].gift));
+void InnerWidget::showGift(Data::SavedStarGiftId id) {
+	const auto savedId = [](const Entry &entry) {
+		return entry.gift.id;
+	};
+	const auto i = ranges::find(_entries, id, savedId);
+	if (i != end(_entries)) {
+		using namespace ::Settings;
+		_window->show(Box(SavedStarGiftBox, _window, _peer, i->gift));
+	}
 }
 
 void InnerWidget::refreshAbout() {