From 8e6825771ef31c37002fc876bf4305e7986470b5 Mon Sep 17 00:00:00 2001
From: 23rd <23rd@vivaldi.net>
Date: Mon, 30 May 2022 14:08:47 +0300
Subject: [PATCH] Added support of filters limit to side bar.

---
 .../SourceFiles/boxes/premium_limits_box.cpp  |  9 ++++
 .../SourceFiles/boxes/premium_limits_box.h    |  3 ++
 .../SourceFiles/settings/settings_folders.cpp |  7 +--
 .../window/window_filters_menu.cpp            | 51 ++++++++++---------
 .../SourceFiles/window/window_filters_menu.h  |  1 -
 Telegram/lib_ui                               |  2 +-
 6 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/Telegram/SourceFiles/boxes/premium_limits_box.cpp b/Telegram/SourceFiles/boxes/premium_limits_box.cpp
index e2e0b1571..4fae83754 100644
--- a/Telegram/SourceFiles/boxes/premium_limits_box.cpp
+++ b/Telegram/SourceFiles/boxes/premium_limits_box.cpp
@@ -903,3 +903,12 @@ int CurrentPremiumLimit(
 		premium ? keyPremium : keyDefault,
 		premium ? limitPremium : limitDefault);
 }
+
+int CurrentPremiumFiltersLimit(not_null<Main::Session*> session) {
+	return CurrentPremiumLimit(
+		session,
+		"dialog_filters_limit_default",
+		10,
+		"dialog_filters_limit_premium",
+		20);
+}
diff --git a/Telegram/SourceFiles/boxes/premium_limits_box.h b/Telegram/SourceFiles/boxes/premium_limits_box.h
index 9c19c19b4..ef97e9967 100644
--- a/Telegram/SourceFiles/boxes/premium_limits_box.h
+++ b/Telegram/SourceFiles/boxes/premium_limits_box.h
@@ -62,3 +62,6 @@ void FileSizeLimitBox(
 	int limitDefault,
 	const QString &keyPremium,
 	int limitPremium);
+
+[[nodiscard]] int CurrentPremiumFiltersLimit(
+	not_null<Main::Session*> session);
diff --git a/Telegram/SourceFiles/settings/settings_folders.cpp b/Telegram/SourceFiles/settings/settings_folders.cpp
index c30cfa964..70d062efb 100644
--- a/Telegram/SourceFiles/settings/settings_folders.cpp
+++ b/Telegram/SourceFiles/settings/settings_folders.cpp
@@ -327,12 +327,7 @@ void FilterRowButton::paintEvent(QPaintEvent *e) {
 
 	const auto session = &controller->session();
 	const auto limit = [=] {
-		return CurrentPremiumLimit(
-			session,
-			"dialog_filters_limit_default",
-			10,
-			"dialog_filters_limit_premium",
-			20);
+		return CurrentPremiumFiltersLimit(session);
 	};
 	AddSkip(container, st::settingsSectionSkip);
 	AddSubsectionTitle(container, tr::lng_filters_subtitle());
diff --git a/Telegram/SourceFiles/window/window_filters_menu.cpp b/Telegram/SourceFiles/window/window_filters_menu.cpp
index 74e953690..f913d8672 100644
--- a/Telegram/SourceFiles/window/window_filters_menu.cpp
+++ b/Telegram/SourceFiles/window/window_filters_menu.cpp
@@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "ui/widgets/popup_menu.h"
 #include "ui/boxes/confirm_box.h"
 #include "boxes/filters/edit_filter_box.h"
+#include "boxes/premium_limits_box.h"
 #include "settings/settings_common.h"
 #include "settings/settings_folders.h"
 #include "api/api_chat_filters.h"
@@ -127,17 +128,12 @@ void FiltersMenu::setup() {
 		const auto i = _filters.find(_activeFilterId);
 		if (i != end(_filters)) {
 			i->second->setActive(false);
-		} else if (!_activeFilterId && _all) {
-			_all->setActive(false);
 		}
 		_activeFilterId = id;
 		const auto j = _filters.find(_activeFilterId);
 		if (j != end(_filters)) {
 			j->second->setActive(true);
 			scrollToButton(j->second);
-		} else if (!_activeFilterId && _all) {
-			_all->setActive(true);
-			scrollToButton(_all);
 		}
 		_reorder->finishReordering();
 	}, _outer.lifetime());
@@ -194,24 +190,29 @@ void FiltersMenu::refresh() {
 	const auto reorderAll = premium();
 	if (!_list) {
 		setupList();
-	} else if (reorderAll && _all) {
-		_all = nullptr;
-	} else if (!reorderAll && !_all) {
-		_all = prepareAll();
 	}
 	_reorder->cancel();
+
+	_reorder->clearPinnedIntervals();
+	const auto maxLimit = CurrentPremiumFiltersLimit(&_session->session());
+	const auto premiumFrom = (reorderAll ? 0 : 1) + maxLimit;
+	if (!reorderAll) {
+		_reorder->addPinnedInterval(0, 1);
+	}
+	_reorder->addPinnedInterval(
+		premiumFrom,
+		std::max(1, int(filters->list().size()) - maxLimit));
+
 	auto now = base::flat_map<int, base::unique_qptr<Ui::SideBarButton>>();
 	for (const auto &filter : filters->list()) {
-		if (!reorderAll && !filter.id()) {
-			continue;
-		}
-		now.emplace(
+		const auto nextIsLocked = (now.size() >= premiumFrom);
+		auto button = prepareButton(
+			_list,
 			filter.id(),
-			prepareButton(
-				_list,
-				filter.id(),
-				filter.title(),
-				Ui::ComputeFilterIcon(filter)));
+			filter.title(),
+			Ui::ComputeFilterIcon(filter));
+		button->setLocked(nextIsLocked);
+		now.emplace(filter.id(), std::move(button));
 	}
 	_filters = std::move(now);
 	_reorder->start();
@@ -222,14 +223,13 @@ void FiltersMenu::refresh() {
 	// so we have to restore it.
 	_scroll.scrollToY(oldTop);
 	const auto i = _filters.find(_activeFilterId);
-	const auto button = ((i != end(_filters)) ? i->second : _all).get();
+	const auto button = ((i != end(_filters)) ? i->second.get() : nullptr);
 	if (button) {
 		scrollToButton(button);
 	}
 }
 
 void FiltersMenu::setupList() {
-	_all = premium() ? nullptr : prepareAll();
 	_list = _container->add(object_ptr<Ui::VerticalLayout>(_container));
 	_setup = prepareButton(
 		_container,
@@ -300,6 +300,8 @@ base::unique_qptr<Ui::SideBarButton> FiltersMenu::prepareButton(
 	raw->setClickedCallback([=] {
 		if (_reordering) {
 			return;
+		} else if (raw->locked()) {
+			_session->show(Box(FiltersLimitBox, &_session->session()));
 		} else if (id >= 0) {
 			_session->setActiveChatsFilter(id);
 		} else {
@@ -318,9 +320,12 @@ base::unique_qptr<Ui::SideBarButton> FiltersMenu::prepareButton(
 	});
 	if (id > 0) {
 		raw->events(
-		) | rpl::filter([=](not_null<QEvent*> e) {
+		) | rpl::filter([](not_null<QEvent*> e) {
 			return e->type() == QEvent::ContextMenu;
 		}) | rpl::start_with_next([=] {
+			if (raw->locked()) {
+				return;
+			}
 			showMenu(QCursor::pos(), id);
 		}, raw->lifetime());
 	}
@@ -401,12 +406,10 @@ void FiltersMenu::applyReorder(
 
 	const auto filters = &_session->session().data().chatsFilters();
 	const auto &list = filters->list();
-	if (_all) {
+	if (!premium()) {
 		if (list[0].id() != FilterId()) {
 			filters->moveAllToFront();
 		}
-		++oldPosition;
-		++newPosition;
 	}
 	Assert(oldPosition >= 0 && oldPosition < list.size());
 	Assert(newPosition >= 0 && newPosition < list.size());
diff --git a/Telegram/SourceFiles/window/window_filters_menu.h b/Telegram/SourceFiles/window/window_filters_menu.h
index 273f51d19..c640f70eb 100644
--- a/Telegram/SourceFiles/window/window_filters_menu.h
+++ b/Telegram/SourceFiles/window/window_filters_menu.h
@@ -64,7 +64,6 @@ private:
 	not_null<Ui::VerticalLayout*> _container;
 	Ui::VerticalLayout *_list = nullptr;
 	std::unique_ptr<Ui::VerticalLayoutReorder> _reorder;
-	base::unique_qptr<Ui::SideBarButton> _all;
 	base::unique_qptr<Ui::SideBarButton> _setup;
 	base::flat_map<FilterId, base::unique_qptr<Ui::SideBarButton>> _filters;
 	FilterId _activeFilterId = 0;
diff --git a/Telegram/lib_ui b/Telegram/lib_ui
index a78089716..676d8697c 160000
--- a/Telegram/lib_ui
+++ b/Telegram/lib_ui
@@ -1 +1 @@
-Subproject commit a78089716bf153b4283ec79757268d1047913f12
+Subproject commit 676d8697c6c704c6c5494f03f0bc78d006052768