From dc7a75441822aa303a87bbfb820299a7e9859c1e Mon Sep 17 00:00:00 2001
From: 23rd <23rd@vivaldi.net>
Date: Sun, 13 Dec 2020 16:08:16 +0300
Subject: [PATCH] Added ability to prevent application lock and account switch.

---
 Telegram/SourceFiles/core/application.cpp         | 12 ++++++++++--
 Telegram/SourceFiles/core/application.h           |  2 ++
 Telegram/SourceFiles/main/main_domain.cpp         |  6 ++++++
 Telegram/SourceFiles/main/main_domain.h           |  1 +
 Telegram/SourceFiles/mainwidget.cpp               | 14 ++++++++++----
 Telegram/SourceFiles/mainwidget.h                 |  8 +++++---
 Telegram/SourceFiles/mainwindow.cpp               |  7 +++++++
 Telegram/SourceFiles/mainwindow.h                 |  2 ++
 Telegram/SourceFiles/window/window_controller.cpp |  4 ++++
 Telegram/SourceFiles/window/window_controller.h   |  2 ++
 Telegram/SourceFiles/window/window_main_menu.cpp  |  6 ++++--
 11 files changed, 53 insertions(+), 11 deletions(-)

diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp
index 17d48f779..6b527cc10 100644
--- a/Telegram/SourceFiles/core/application.cpp
+++ b/Telegram/SourceFiles/core/application.cpp
@@ -789,9 +789,17 @@ bool Application::openCustomUrl(
 
 }
 
+void Application::preventOrInvoke(Fn<void()> &&callback) {
+	_window->preventOrInvoke(std::move(callback));
+}
+
 void Application::lockByPasscode() {
-	_passcodeLock = true;
-	_window->setupPasscodeLock();
+	preventOrInvoke([=] {
+		if (_window) {
+			_passcodeLock = true;
+			_window->setupPasscodeLock();
+		}
+	});
 }
 
 void Application::unlockPasscode() {
diff --git a/Telegram/SourceFiles/core/application.h b/Telegram/SourceFiles/core/application.h
index 82b5cd390..15a5fcb1a 100644
--- a/Telegram/SourceFiles/core/application.h
+++ b/Telegram/SourceFiles/core/application.h
@@ -277,6 +277,8 @@ public:
 	void switchFreeType();
 	void writeInstallBetaVersionsSetting();
 
+	void preventOrInvoke(Fn<void()> &&callback);
+
 	void call_handleObservables();
 
 protected:
diff --git a/Telegram/SourceFiles/main/main_domain.cpp b/Telegram/SourceFiles/main/main_domain.cpp
index 0501264dd..672da38dc 100644
--- a/Telegram/SourceFiles/main/main_domain.cpp
+++ b/Telegram/SourceFiles/main/main_domain.cpp
@@ -385,6 +385,12 @@ void Domain::checkForLastProductionConfig(
 	Core::App().refreshFallbackProductionConfig(mtp->config());
 }
 
+void Domain::maybeActivate(not_null<Main::Account*> account) {
+	Core::App().preventOrInvoke(crl::guard(account, [=] {
+		activate(account);
+	}));
+}
+
 void Domain::activate(not_null<Main::Account*> account) {
 	if (_active.current() == account.get()) {
 		return;
diff --git a/Telegram/SourceFiles/main/main_domain.h b/Telegram/SourceFiles/main/main_domain.h
index 4adadf21e..ad4d6f11f 100644
--- a/Telegram/SourceFiles/main/main_domain.h
+++ b/Telegram/SourceFiles/main/main_domain.h
@@ -63,6 +63,7 @@ public:
 	void notifyUnreadBadgeChanged();
 
 	[[nodiscard]] not_null<Main::Account*> add(MTP::Environment environment);
+	void maybeActivate(not_null<Main::Account*> account);
 	void activate(not_null<Main::Account*> account);
 	void addActivated(MTP::Environment environment);
 
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index ec111f0e0..2172cf0ea 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -1897,10 +1897,8 @@ bool MainWidget::stackIsEmpty() const {
 	return _stack.empty();
 }
 
-bool MainWidget::preventsCloseSection(
-		Fn<void()> callback,
-		const SectionShow &params) const {
-	if (params.thirdColumn || Core::App().passcodeLocked()) {
+bool MainWidget::preventsCloseSection(Fn<void()> callback) const {
+	if (Core::App().passcodeLocked()) {
 		return false;
 	}
 	auto copy = callback;
@@ -1908,6 +1906,14 @@ bool MainWidget::preventsCloseSection(
 		|| (_history && _history->preventsClose(std::move(callback)));
 }
 
+bool MainWidget::preventsCloseSection(
+		Fn<void()> callback,
+		const SectionShow &params) const {
+	return params.thirdColumn
+		? false
+		: preventsCloseSection(std::move(callback));
+}
+
 void MainWidget::showBackFromStack(
 		const SectionShow &params) {
 
diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h
index 41956098a..586157c83 100644
--- a/Telegram/SourceFiles/mainwidget.h
+++ b/Telegram/SourceFiles/mainwidget.h
@@ -223,6 +223,11 @@ public:
 	void closeBothPlayers();
 	void stopAndClosePlayer();
 
+	bool preventsCloseSection(Fn<void()> callback) const;
+	bool preventsCloseSection(
+		Fn<void()> callback,
+		const SectionShow &params) const;
+
 public slots:
 	void inlineResultLoadProgress(FileLoader *loader);
 	void inlineResultLoadFailed(FileLoader *loader, bool started);
@@ -274,9 +279,6 @@ private:
 		std::unique_ptr<Window::SectionMemento> &&memento,
 		const SectionShow &params);
 	void dropMainSection(Window::SectionWidget *widget);
-	bool preventsCloseSection(
-		Fn<void()> callback,
-		const SectionShow &params) const;
 
 	Window::SectionSlideParams prepareThirdSectionAnimation(Window::SectionWidget *section);
 
diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp
index 5e2047646..c80e59c11 100644
--- a/Telegram/SourceFiles/mainwindow.cpp
+++ b/Telegram/SourceFiles/mainwindow.cpp
@@ -221,6 +221,13 @@ QPixmap MainWindow::grabInner() {
 	return {};
 }
 
+void MainWindow::preventOrInvoke(Fn<void()> callback) {
+	if (_main && _main->preventsCloseSection(callback)) {
+		return;
+	}
+	callback();
+}
+
 void MainWindow::setupPasscodeLock() {
 	auto animated = (_main || _intro);
 	auto bg = animated ? grabInner() : QPixmap();
diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h
index 57a67eb50..d7d925cac 100644
--- a/Telegram/SourceFiles/mainwindow.h
+++ b/Telegram/SourceFiles/mainwindow.h
@@ -48,6 +48,8 @@ public:
 
 	void finishFirstShow();
 
+	void preventOrInvoke(Fn<void()> callback);
+
 	void setupPasscodeLock();
 	void clearPasscodeLock();
 	void setupIntro(Intro::EnterPoint point);
diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp
index fbb53d508..eb514d7e0 100644
--- a/Telegram/SourceFiles/window/window_controller.cpp
+++ b/Telegram/SourceFiles/window/window_controller.cpp
@@ -317,6 +317,10 @@ void Controller::close() {
 	_widget.close();
 }
 
+void Controller::preventOrInvoke(Fn<void()> &&callback) {
+	_widget.preventOrInvoke(std::move(callback));
+}
+
 QPoint Controller::getPointForCallPanelCenter() const {
 	Expects(_widget.windowHandle() != nullptr);
 
diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h
index 05c6e02fd..975626974 100644
--- a/Telegram/SourceFiles/window/window_controller.h
+++ b/Telegram/SourceFiles/window/window_controller.h
@@ -72,6 +72,8 @@ public:
 	void minimize();
 	void close();
 
+	void preventOrInvoke(Fn<void()> &&callback);
+
 	QPoint getPointForCallPanelCenter() const;
 
 private:
diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp
index c4cfe2a0b..2213c1b84 100644
--- a/Telegram/SourceFiles/window/window_main_menu.cpp
+++ b/Telegram/SourceFiles/window/window_main_menu.cpp
@@ -761,7 +761,7 @@ void MainMenu::rebuildAccounts() {
 				}
 				auto activate = [=, guard = _accountSwitchGuard.make_guard()]{
 					if (guard) {
-						Core::App().domain().activate(account);
+						Core::App().domain().maybeActivate(account);
 					}
 				};
 				base::call_delayed(
@@ -815,7 +815,9 @@ not_null<Ui::SlideWrap<Ui::RippleButton>*> MainMenu::setupAddAccount(
 	}, button->lifetime());
 
 	const auto add = [=](MTP::Environment environment) {
-		Core::App().domain().addActivated(environment);
+		Core::App().preventOrInvoke([=] {
+			Core::App().domain().addActivated(environment);
+		});
 	};
 
 	button->setAcceptBoth(true);