From da423b5bd28296921cad04276002cbb198b777d4 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 19 Apr 2024 16:01:58 +0400
Subject: [PATCH] Add a general FastShareLink method.

---
 Telegram/SourceFiles/boxes/share_box.cpp | 116 ++++++++++++++++++++++-
 Telegram/SourceFiles/boxes/share_box.h   |   7 ++
 Telegram/SourceFiles/iv/iv_instance.cpp  |  86 +----------------
 3 files changed, 122 insertions(+), 87 deletions(-)

diff --git a/Telegram/SourceFiles/boxes/share_box.cpp b/Telegram/SourceFiles/boxes/share_box.cpp
index 4581fac40..32ec893d6 100644
--- a/Telegram/SourceFiles/boxes/share_box.cpp
+++ b/Telegram/SourceFiles/boxes/share_box.cpp
@@ -234,7 +234,10 @@ void ShareBox::prepareCommentField() {
 	const auto field = _comment->entity();
 
 	field->submits(
-	) | rpl::start_with_next([=] { submit({}); }, field->lifetime());
+	) | rpl::start_with_next([=] {
+		submit({});
+	}, field->lifetime());
+
 	if (const auto show = uiShow(); show->valid()) {
 		InitMessageFieldHandlers(
 			_descriptor.session,
@@ -246,6 +249,14 @@ void ShareBox::prepareCommentField() {
 	}
 	field->setSubmitSettings(Core::App().settings().sendSubmitWay());
 
+	field->changes() | rpl::start_with_next([=] {
+		if (!field->getLastText().isEmpty()) {
+			setCloseByOutsideClick(false);
+		} else if (_inner->selected().empty()) {
+			setCloseByOutsideClick(true);
+		}
+	}, field->lifetime());
+
 	Ui::SendPendingMoveResizeEvents(_comment);
 	if (_bottomWidget) {
 		Ui::SendPendingMoveResizeEvents(_bottomWidget);
@@ -255,8 +266,6 @@ void ShareBox::prepareCommentField() {
 void ShareBox::prepare() {
 	prepareCommentField();
 
-	setCloseByOutsideClick(false);
-
 	_select->resizeToWidth(st::boxWideWidth);
 	Ui::SendPendingMoveResizeEvents(_select);
 
@@ -313,6 +322,12 @@ void ShareBox::prepare() {
 			not_null<Data::Thread*> thread,
 			bool checked) {
 		innerSelectedChanged(thread, checked);
+		if (checked) {
+			setCloseByOutsideClick(false);
+		} else if (_inner->selected().empty()
+			&& _comment->entity()->getLastText().isEmpty()) {
+			setCloseByOutsideClick(true);
+		}
 	});
 
 	Ui::Emoji::SuggestionsController::Init(
@@ -1678,6 +1693,101 @@ void FastShareMessage(
 		Ui::LayerOption::CloseOther);
 }
 
+void FastShareLink(
+		not_null<Window::SessionController*> controller,
+		const QString &url) {
+	FastShareLink(controller->uiShow(), url);
+}
+
+void FastShareLink(
+		std::shared_ptr<Main::SessionShow> show,
+		const QString &url) {
+	const auto box = std::make_shared<QPointer<Ui::BoxContent>>();
+	const auto sending = std::make_shared<bool>();
+	auto copyCallback = [=] {
+		QGuiApplication::clipboard()->setText(url);
+		show->showToast(tr::lng_background_link_copied(tr::now));
+	};
+	auto submitCallback = [=](
+			std::vector<not_null<::Data::Thread*>> &&result,
+			TextWithTags &&comment,
+			Api::SendOptions options,
+			::Data::ForwardOptions) {
+		if (*sending || result.empty()) {
+			return;
+		}
+
+		const auto error = [&] {
+			for (const auto thread : result) {
+				const auto error = GetErrorTextForSending(
+					thread,
+					{ .text = &comment });
+				if (!error.isEmpty()) {
+					return std::make_pair(error, thread);
+				}
+			}
+			return std::make_pair(QString(), result.front());
+		}();
+		if (!error.first.isEmpty()) {
+			auto text = TextWithEntities();
+			if (result.size() > 1) {
+				text.append(
+					Ui::Text::Bold(error.second->chatListName())
+				).append("\n\n");
+			}
+			text.append(error.first);
+			if (const auto weak = *box) {
+				weak->getDelegate()->show(Ui::MakeConfirmBox({
+					.text = text,
+					.inform = true,
+				}));
+			}
+			return;
+		}
+
+		*sending = true;
+		if (!comment.text.isEmpty()) {
+			comment.text = url + "\n" + comment.text;
+			const auto add = url.size() + 1;
+			for (auto &tag : comment.tags) {
+				tag.offset += add;
+			}
+		} else {
+			comment.text = url;
+		}
+		auto &api = show->session().api();
+		for (const auto thread : result) {
+			auto message = Api::MessageToSend(
+				Api::SendAction(thread, options));
+			message.textWithTags = comment;
+			message.action.clearDraft = false;
+			api.sendMessage(std::move(message));
+		}
+		if (*box) {
+			(*box)->closeBox();
+		}
+		show->showToast(tr::lng_share_done(tr::now));
+	};
+	auto filterCallback = [](not_null<::Data::Thread*> thread) {
+		if (const auto user = thread->peer()->asUser()) {
+			if (user->canSendIgnoreRequirePremium()) {
+				return true;
+			}
+		}
+		return ::Data::CanSend(thread, ChatRestriction::SendOther);
+	};
+	*box = show->show(
+		Box<ShareBox>(ShareBox::Descriptor{
+			.session = &show->session(),
+			.copyCallback = std::move(copyCallback),
+			.submitCallback = std::move(submitCallback),
+			.filterCallback = std::move(filterCallback),
+			.premiumRequiredError = SharePremiumRequiredError(),
+		}),
+		Ui::LayerOption::KeepOther,
+		anim::type::normal);
+}
+
 auto SharePremiumRequiredError()
 -> Fn<RecipientPremiumRequiredError(not_null<UserData*>)> {
 	return WritePremiumRequiredError;
diff --git a/Telegram/SourceFiles/boxes/share_box.h b/Telegram/SourceFiles/boxes/share_box.h
index d5cd22ffa..253a8228e 100644
--- a/Telegram/SourceFiles/boxes/share_box.h
+++ b/Telegram/SourceFiles/boxes/share_box.h
@@ -37,6 +37,7 @@ struct SendOptions;
 
 namespace Main {
 class Session;
+class SessionShow;
 } // namespace Main
 
 namespace Dialogs {
@@ -68,6 +69,12 @@ void ShareGameScoreByHash(
 void FastShareMessage(
 	not_null<Window::SessionController*> controller,
 	not_null<HistoryItem*> item);
+void FastShareLink(
+	not_null<Window::SessionController*> controller,
+	const QString &url);
+void FastShareLink(
+	std::shared_ptr<Main::SessionShow> show,
+	const QString &url);
 
 struct RecipientPremiumRequiredError;
 [[nodiscard]] auto SharePremiumRequiredError()
diff --git a/Telegram/SourceFiles/iv/iv_instance.cpp b/Telegram/SourceFiles/iv/iv_instance.cpp
index 2362a6b61..5b8fead1a 100644
--- a/Telegram/SourceFiles/iv/iv_instance.cpp
+++ b/Telegram/SourceFiles/iv/iv_instance.cpp
@@ -297,80 +297,6 @@ ShareBoxResult Shown::shareBox(ShareBoxDescriptor &&descriptor) {
 		state->destroyRequests.fire({});
 	}, wrap->lifetime());
 
-	const auto box = std::make_shared<QPointer<Ui::BoxContent>>();
-	const auto sending = std::make_shared<bool>();
-	auto copyCallback = [=] {
-		QGuiApplication::clipboard()->setText(url);
-		show->showToast(tr::lng_background_link_copied(tr::now));
-	};
-	auto submitCallback = [=](
-			std::vector<not_null<::Data::Thread*>> &&result,
-			TextWithTags &&comment,
-			Api::SendOptions options,
-			::Data::ForwardOptions) {
-		if (*sending || result.empty()) {
-			return;
-		}
-
-		const auto error = [&] {
-			for (const auto thread : result) {
-				const auto error = GetErrorTextForSending(
-					thread,
-					{ .text = &comment });
-				if (!error.isEmpty()) {
-					return std::make_pair(error, thread);
-				}
-			}
-			return std::make_pair(QString(), result.front());
-		}();
-		if (!error.first.isEmpty()) {
-			auto text = TextWithEntities();
-			if (result.size() > 1) {
-				text.append(
-					Ui::Text::Bold(error.second->chatListName())
-				).append("\n\n");
-			}
-			text.append(error.first);
-			if (const auto weak = *box) {
-				weak->getDelegate()->show(Ui::MakeConfirmBox({
-					.text = text,
-					.inform = true,
-				}));
-			}
-			return;
-		}
-
-		*sending = true;
-		if (!comment.text.isEmpty()) {
-			comment.text = url + "\n" + comment.text;
-			const auto add = url.size() + 1;
-			for (auto &tag : comment.tags) {
-				tag.offset += add;
-			}
-		} else {
-			comment.text = url;
-		}
-		auto &api = _session->api();
-		for (const auto thread : result) {
-			auto message = Api::MessageToSend(
-				Api::SendAction(thread, options));
-			message.textWithTags = comment;
-			message.action.clearDraft = false;
-			api.sendMessage(std::move(message));
-		}
-		if (*box) {
-			(*box)->closeBox();
-		}
-		show->showToast(tr::lng_share_done(tr::now));
-	};
-	auto filterCallback = [](not_null<::Data::Thread*> thread) {
-		if (const auto user = thread->peer()->asUser()) {
-			if (user->canSendIgnoreRequirePremium()) {
-				return true;
-			}
-		}
-		return ::Data::CanSend(thread, ChatRestriction::SendOther);
-	};
 	const auto focus = crl::guard(layer, [=] {
 		if (!layer->window()->isActiveWindow()) {
 			layer->window()->activateWindow();
@@ -383,16 +309,8 @@ ShareBoxResult Shown::shareBox(ShareBoxDescriptor &&descriptor) {
 		.hide = [=] { show->hideLayer(); },
 		.destroyRequests = state->destroyRequests.events(),
 	};
-	*box = show->show(
-		Box<ShareBox>(ShareBox::Descriptor{
-			.session = _session,
-			.copyCallback = std::move(copyCallback),
-			.submitCallback = std::move(submitCallback),
-			.filterCallback = std::move(filterCallback),
-			.premiumRequiredError = SharePremiumRequiredError(),
-		}),
-		Ui::LayerOption::KeepOther,
-		anim::type::normal);
+
+	FastShareLink(Main::MakeSessionShow(show, _session), url);
 	return result;
 }