From 864959aee0381362c715aaff8e490e60e6d2e1b3 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Tue, 25 Apr 2023 11:45:31 +0400
Subject: [PATCH] Hide login code with a spoiler in chats list.

---
 Telegram/SourceFiles/calls/calls_instance.cpp |  5 +++
 Telegram/SourceFiles/calls/calls_instance.h   |  1 +
 Telegram/SourceFiles/core/application.cpp     |  4 +++
 Telegram/SourceFiles/core/application.h       |  1 +
 .../dialogs/ui/dialogs_message_view.cpp       |  1 +
 Telegram/SourceFiles/history/history_item.cpp | 35 +++++++++++++++++--
 Telegram/SourceFiles/history/history_item.h   |  7 +++-
 .../history/view/history_view_item_preview.h  |  1 +
 .../window/notifications_manager.cpp          |  8 ++++-
 .../window/notifications_manager.h            |  1 +
 .../window/notifications_manager_default.cpp  |  1 +
 11 files changed, 61 insertions(+), 4 deletions(-)

diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp
index 4ea1264c4..456b6d767 100644
--- a/Telegram/SourceFiles/calls/calls_instance.cpp
+++ b/Telegram/SourceFiles/calls/calls_instance.cpp
@@ -556,6 +556,11 @@ FnMut<void()> Instance::addAsyncWaiter() {
 	};
 }
 
+bool Instance::isSharingScreen() const {
+	return (_currentCall && _currentCall->isSharingScreen())
+		|| (_currentGroupCall && _currentGroupCall->isSharingScreen());
+}
+
 bool Instance::isQuitPrevent() {
 	if (!_currentCall || _currentCall->isIncomingWaiting()) {
 		return false;
diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h
index 679419711..4113a600e 100644
--- a/Telegram/SourceFiles/calls/calls_instance.h
+++ b/Telegram/SourceFiles/calls/calls_instance.h
@@ -105,6 +105,7 @@ public:
 
 	[[nodiscard]] FnMut<void()> addAsyncWaiter();
 
+	[[nodiscard]] bool isSharingScreen() const;
 	[[nodiscard]] bool isQuitPrevent();
 
 private:
diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp
index 4c1bc7233..21a54c785 100644
--- a/Telegram/SourceFiles/core/application.cpp
+++ b/Telegram/SourceFiles/core/application.cpp
@@ -1573,6 +1573,10 @@ QPoint Application::getPointForCallPanelCenter() const {
 	return QGuiApplication::primaryScreen()->geometry().center();
 }
 
+bool Application::isSharingScreen() const {
+	return _calls->isSharingScreen();
+}
+
 // macOS Qt bug workaround, sometimes no leaveEvent() gets to the nested widgets.
 void Application::registerLeaveSubscription(not_null<QWidget*> widget) {
 #ifdef Q_OS_MAC
diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h
index 0488dec3c..3ad642c6b 100644
--- a/Telegram/SourceFiles/core/application.h
+++ b/Telegram/SourceFiles/core/application.h
@@ -195,6 +195,7 @@ public:
 	bool hideMediaView();
 
 	[[nodiscard]] QPoint getPointForCallPanelCenter() const;
+	[[nodiscard]] bool isSharingScreen() const;
 
 	void startSettingsAndBackground();
 	[[nodiscard]] Settings &settings();
diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp
index cb9fb4ee9..b1f59fb43 100644
--- a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp
+++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp
@@ -157,6 +157,7 @@ void MessageView::prepare(
 	}
 	options.existing = &_imagesCache;
 	options.ignoreTopic = true;
+	options.spoilerLoginCode = true;
 	auto preview = item->toPreview(options);
 	const auto hasImages = !preview.images.empty();
 	const auto history = item->history();
diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp
index c72d2454f..e4ccb977f 100644
--- a/Telegram/SourceFiles/history/history_item.cpp
+++ b/Telegram/SourceFiles/history/history_item.cpp
@@ -80,6 +80,26 @@ constexpr auto kPinnedMessageTextLimit = 16;
 
 using ItemPreview = HistoryView::ItemPreview;
 
+[[nodiscard]] TextWithEntities SpoilerLoginCode(TextWithEntities text) {
+	const auto r = QRegularExpression(u"([\\d\\-]{5,7})"_q);
+	const auto m = r.match(text.text);
+	if (!m.hasMatch()) {
+		return text;
+	}
+	const auto codeStart = m.capturedStart(1);
+	const auto codeLength = m.capturedLength(1);
+	auto i = text.entities.begin();
+	const auto e = text.entities.end();
+	while (i != e && i->offset() < codeStart) {
+		if (i->offset() + i->length() > codeStart) {
+			return text; // Entities should not intersect code.
+		}
+		++i;
+	}
+	text.entities.insert(i, { EntityType::Spoiler, codeStart, codeLength });
+	return text;
+}
+
 [[nodiscard]] bool HasNotEmojiAndSpaces(const QString &text) {
 	if (text.isEmpty()) {
 		return false;
@@ -2770,8 +2790,9 @@ bool HistoryItem::isEmpty() const {
 		&& !Has<HistoryMessageLogEntryOriginal>();
 }
 
-TextWithEntities HistoryItem::notificationText() const {
-	const auto result = [&] {
+TextWithEntities HistoryItem::notificationText(
+		NotificationTextOptions options) const {
+	auto result = [&] {
 		if (_media && !isService()) {
 			return _media->notificationText();
 		} else if (!emptyText()) {
@@ -2779,6 +2800,11 @@ TextWithEntities HistoryItem::notificationText() const {
 		}
 		return TextWithEntities();
 	}();
+	if (options.spoilerLoginCode
+		&& !out()
+		&& history()->peer->isNotificationsUser()) {
+		result = SpoilerLoginCode(std::move(result));
+	}
 	if (result.text.size() <= kNotificationTextLimit) {
 		return result;
 	}
@@ -2808,6 +2834,11 @@ ItemPreview HistoryItem::toPreview(ToPreviewOptions options) const {
 		}
 		return {};
 	}();
+	if (options.spoilerLoginCode
+		&& !out()
+		&& history()->peer->isNotificationsUser()) {
+		result.text = SpoilerLoginCode(std::move(result.text));
+	}
 	const auto fromSender = [](not_null<PeerData*> sender) {
 		return sender->isSelf()
 			? tr::lng_from_you(tr::now)
diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h
index e6dcac508..3ce4cdcc5 100644
--- a/Telegram/SourceFiles/history/history_item.h
+++ b/Telegram/SourceFiles/history/history_item.h
@@ -82,6 +82,7 @@ class Element;
 class Message;
 class Service;
 class ServiceMessagePainter;
+struct NotificationTextOptions;
 } // namespace HistoryView
 
 class HistoryItem final : public RuntimeComposer<HistoryItem> {
@@ -355,8 +356,12 @@ public:
 	void indexAsNewItem();
 	void removeFromSharedMediaIndex();
 
+	struct NotificationTextOptions {
+		bool spoilerLoginCode = false;
+	};
 	[[nodiscard]] QString notificationHeader() const;
-	[[nodiscard]] TextWithEntities notificationText() const;
+	[[nodiscard]] TextWithEntities notificationText(
+		NotificationTextOptions options = {}) const;
 
 	using ToPreviewOptions = HistoryView::ToPreviewOptions;
 	using ItemPreview = HistoryView::ItemPreview;
diff --git a/Telegram/SourceFiles/history/view/history_view_item_preview.h b/Telegram/SourceFiles/history/view/history_view_item_preview.h
index 4348743b3..7ac0a2b18 100644
--- a/Telegram/SourceFiles/history/view/history_view_item_preview.h
+++ b/Telegram/SourceFiles/history/view/history_view_item_preview.h
@@ -37,6 +37,7 @@ struct ToPreviewOptions {
 	bool generateImages = true;
 	bool ignoreGroup = false;
 	bool ignoreTopic = true;
+	bool spoilerLoginCode = false;
 	bool translated = false;
 };
 
diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp
index 8344723df..1d69be114 100644
--- a/Telegram/SourceFiles/window/notifications_manager.cpp
+++ b/Telegram/SourceFiles/window/notifications_manager.cpp
@@ -856,6 +856,10 @@ Manager::DisplayOptions Manager::getNotificationOptions(
 			&& (!topic || !Data::CanSendTexts(topic)))
 		|| peer->isBroadcast()
 		|| (peer->slowmodeSecondsLeft() > 0);
+	result.spoilerLoginCode = item
+		&& !item->out()
+		&& peer->isNotificationsUser()
+		&& Core::App().isSharingScreen();
 	return result;
 }
 
@@ -1167,7 +1171,9 @@ void NativeManager::doShowNotification(NotificationFields &&fields) {
 		? tr::lng_forward_messages(tr::now, lt_count, fields.forwardedCount)
 		: item->groupId()
 		? tr::lng_in_dlg_album(tr::now)
-		: TextWithPermanentSpoiler(item->notificationText());
+		: TextWithPermanentSpoiler(item->notificationText({
+			.spoilerLoginCode = options.spoilerLoginCode,
+		}));
 
 	// #TODO optimize
 	auto userpicView = item->history()->peer->createUserpicView();
diff --git a/Telegram/SourceFiles/window/notifications_manager.h b/Telegram/SourceFiles/window/notifications_manager.h
index fb0a010d4..9d7224c74 100644
--- a/Telegram/SourceFiles/window/notifications_manager.h
+++ b/Telegram/SourceFiles/window/notifications_manager.h
@@ -316,6 +316,7 @@ public:
 		bool hideMessageText = false;
 		bool hideMarkAsRead = false;
 		bool hideReplyButton = false;
+		bool spoilerLoginCode = false;
 	};
 	[[nodiscard]] DisplayOptions getNotificationOptions(
 		HistoryItem *item,
diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp
index 80cca195e..f68524d1c 100644
--- a/Telegram/SourceFiles/window/notifications_manager_default.cpp
+++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp
@@ -932,6 +932,7 @@ void Notification::updateNotifyDisplay() {
 				? _item->toPreview({
 					.hideSender = reminder,
 					.generateImages = false,
+					.spoilerLoginCode = options.spoilerLoginCode,
 				}).text
 				: ((!_author.isEmpty()
 						? Ui::Text::PlainLink(_author)