From 3c6037a79849f55e6dd269a4107aed06780940ac Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Tue, 9 Jan 2024 13:11:06 +0400
Subject: [PATCH] Custom context menu for saved-tags reactions.

---
 Telegram/Resources/langs/lang.strings         |  4 +-
 .../data/data_message_reactions.cpp           |  6 +-
 .../SourceFiles/data/data_message_reactions.h |  2 +
 .../view/history_view_context_menu.cpp        | 63 +++++++++++++++++++
 .../history_view_reactions_button.cpp         |  3 +-
 .../reactions/history_view_reactions_button.h |  1 +
 6 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index 9d0707518..98055e5fc 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -2749,7 +2749,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_context_seen_reacted#other" = "{count} Reacted";
 "lng_context_seen_reacted_none" = "Nobody Reacted";
 "lng_context_seen_reacted_all" = "Show All Reactions";
-"lng_context_set_as_quick" = "Set As Quick";
+"lng_context_set_as_quick" = "Set as Quick";
+"lng_context_filter_by_tag" = "Filter by Tag";
+"lng_context_remove_tag" = "Remove Tag";
 "lng_context_delete_from_disk" = "Delete from disk";
 "lng_context_delete_all_files" = "Delete all files";
 "lng_context_save_custom_sound" = "Save for notifications";
diff --git a/Telegram/SourceFiles/data/data_message_reactions.cpp b/Telegram/SourceFiles/data/data_message_reactions.cpp
index 9e1726b7a..4ba9c2db4 100644
--- a/Telegram/SourceFiles/data/data_message_reactions.cpp
+++ b/Telegram/SourceFiles/data/data_message_reactions.cpp
@@ -179,6 +179,7 @@ PossibleItemReactionsRef LookupPossibleReactions(
 			}
 		}
 		result.customAllowed = premiumPossible;
+		result.tags = true;
 	} else if (limited) {
 		result.recent.reserve(all.size());
 		add([&](const Reaction &reaction) {
@@ -243,11 +244,12 @@ PossibleItemReactionsRef LookupPossibleReactions(
 
 PossibleItemReactions::PossibleItemReactions(
 	const PossibleItemReactionsRef &other)
-	: recent(other.recent | ranges::views::transform([](const auto &value) {
+: recent(other.recent | ranges::views::transform([](const auto &value) {
 	return *value;
 }) | ranges::to_vector)
 , morePremiumAvailable(other.morePremiumAvailable)
-, customAllowed(other.customAllowed) {
+, customAllowed(other.customAllowed)
+, tags(other.tags){
 }
 
 Reactions::Reactions(not_null<Session*> owner)
diff --git a/Telegram/SourceFiles/data/data_message_reactions.h b/Telegram/SourceFiles/data/data_message_reactions.h
index 2743bffc8..5e8721665 100644
--- a/Telegram/SourceFiles/data/data_message_reactions.h
+++ b/Telegram/SourceFiles/data/data_message_reactions.h
@@ -42,6 +42,7 @@ struct PossibleItemReactionsRef {
 	std::vector<not_null<const Reaction*>> recent;
 	bool morePremiumAvailable = false;
 	bool customAllowed = false;
+	bool tags = false;
 };
 
 struct PossibleItemReactions {
@@ -51,6 +52,7 @@ struct PossibleItemReactions {
 	std::vector<Reaction> recent;
 	bool morePremiumAvailable = false;
 	bool customAllowed = false;
+	bool tags = false;
 };
 
 [[nodiscard]] PossibleItemReactionsRef LookupPossibleReactions(
diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp
index 22fcc710b..856639aa8 100644
--- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp
+++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp
@@ -26,6 +26,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "history/view/media/history_view_web_page.h"
 #include "history/view/reactions/history_view_reactions_list.h"
 #include "ui/widgets/popup_menu.h"
+#include "ui/widgets/menu/menu_action.h"
+#include "ui/widgets/menu/menu_common.h"
 #include "ui/widgets/menu/menu_multiline_action.h"
 #include "ui/image/image.h"
 #include "ui/toast/toast.h"
@@ -1293,6 +1295,62 @@ void AddWhoReactedAction(
 		showAllChosen));
 }
 
+void ShowTagMenu(
+		not_null<base::unique_qptr<Ui::PopupMenu>*> menu,
+		QPoint position,
+		not_null<QWidget*> context,
+		not_null<HistoryItem*> item,
+		const Data::ReactionId &id,
+		not_null<Window::SessionController*> controller) {
+	using namespace Data;
+	const auto itemId = item->fullId();
+	const auto owner = &controller->session().data();
+	*menu = base::make_unique_q<Ui::PopupMenu>(
+		context,
+		st::popupMenuExpandedSeparator);
+	(*menu)->addAction(tr::lng_context_filter_by_tag(tr::now), [=] {
+		HashtagClickHandler(SearchTagToQuery(id)).onClick({
+			.button = Qt::LeftButton,
+			.other = QVariant::fromValue(ClickHandlerContext{
+				.sessionWindow = controller,
+			}),
+		});
+	}, &st::menuIconFave);
+
+	const auto removeTag = [=] {
+		if (const auto item = owner->message(itemId)) {
+			const auto &list = item->reactions();
+			if (ranges::contains(list, id, &MessageReaction::id)) {
+				item->toggleReaction(
+					id,
+					HistoryItem::ReactionSource::Quick);
+			}
+		}
+	};
+	(*menu)->addAction(base::make_unique_q<Ui::Menu::Action>(
+		(*menu)->menu(),
+		st::menuWithIconsAttention,
+		Ui::Menu::CreateAction(
+			(*menu)->menu(),
+			tr::lng_context_remove_tag(tr::now),
+			removeTag),
+		&st::menuIconDisableAttention,
+		&st::menuIconDisableAttention));
+
+	if (const auto custom = id.custom()) {
+		if (const auto set = owner->document(custom)->sticker()) {
+			if (set->set.id) {
+				AddEmojiPacksAction(
+					menu->get(),
+					{ set->set },
+					EmojiPacksSource::Reaction,
+					controller);
+			}
+		}
+	}
+	(*menu)->popup(position);
+}
+
 void ShowWhoReactedMenu(
 		not_null<base::unique_qptr<Ui::PopupMenu>*> menu,
 		QPoint position,
@@ -1301,6 +1359,11 @@ void ShowWhoReactedMenu(
 		const Data::ReactionId &id,
 		not_null<Window::SessionController*> controller,
 		rpl::lifetime &lifetime) {
+	if (item->reactionsAreTags()) {
+		ShowTagMenu(menu, position, context, item, id, controller);
+		return;
+	}
+
 	struct State {
 		int addedToBottom = 0;
 	};
diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp
index 2081a85e7..171ad9d03 100644
--- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp
+++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.cpp
@@ -451,6 +451,7 @@ void Manager::applyList(const Data::PossibleItemReactionsRef &reactions) {
 			: reactions.morePremiumAvailable
 			? Button::Premium
 			: */Button::None));
+	_tagsStrip = reactions.tags;
 }
 
 QMargins Manager::innerMargins() const {
@@ -814,7 +815,7 @@ bool Manager::showContextMenu(
 		const ReactionId &favorite) {
 	const auto selected = _strip.selected();
 	const auto id = std::get_if<ReactionId>(&selected);
-	if (!id || id->empty()) {
+	if (!id || id->empty() || _tagsStrip) {
 		return false;
 	} else if (*id == favorite) {
 		return true;
diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h
index 793382198..eb9c7fc5d 100644
--- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h
+++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions_button.h
@@ -235,6 +235,7 @@ private:
 
 	rpl::variable<int> _uniqueLimit = 0;
 	bool _showingAll = false;
+	bool _tagsStrip = false;
 
 	std::optional<ButtonParameters> _scheduledParameters;
 	base::Timer _buttonShowTimer;