1 /*
2 This file is part of Telegram Desktop,
3 the official desktop application for the Telegram messaging service.
4 
5 For license and copyright information please follow this link:
6 https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
7 */
8 #pragma once
9 
10 #include "core/core_settings.h"
11 #include "mtproto/mtproto_auth_key.h"
12 #include "mtproto/mtproto_proxy_data.h"
13 #include "base/timer.h"
14 
15 class MainWindow;
16 class MainWidget;
17 class FileUploader;
18 class Translator;
19 
20 namespace Storage {
21 class Databases;
22 } // namespace Storage
23 
24 namespace Window {
25 class Controller;
26 } // namespace Window
27 
28 namespace Window {
29 namespace Notifications {
30 class System;
31 } // namespace Notifications
32 } // namespace Window
33 
34 namespace ChatHelpers {
35 class EmojiKeywords;
36 } // namespace ChatHelpers
37 
38 namespace App {
39 void quit();
40 } // namespace App
41 
42 namespace Main {
43 class Domain;
44 class Account;
45 class Session;
46 } // namespace Main
47 
48 namespace Ui {
49 namespace Animations {
50 class Manager;
51 } // namespace Animations
52 namespace Emoji {
53 class UniversalImages;
54 } // namespace Emoji
55 class BoxContent;
56 } // namespace Ui
57 
58 namespace MTP {
59 class Config;
60 class Instance;
61 class AuthKey;
62 using AuthKeyPtr = std::shared_ptr<AuthKey>;
63 using AuthKeysList = std::vector<AuthKeyPtr>;
64 } // namespace MTP
65 
66 namespace Media {
67 namespace Audio {
68 class Instance;
69 } // namespace Audio
70 namespace View {
71 class OverlayWidget;
72 } // namespace View
73 namespace Player {
74 class FloatController;
75 class FloatDelegate;
76 } // namespace Player
77 } // namespace Media
78 
79 namespace Lang {
80 class Instance;
81 class Translator;
82 class CloudManager;
83 } // namespace Lang
84 
85 namespace Data {
86 struct CloudTheme;
87 } // namespace Data
88 
89 namespace Stickers {
90 class EmojiImageLoader;
91 } // namespace Stickers
92 
93 namespace Export {
94 class Manager;
95 } // namespace Export
96 
97 namespace Calls {
98 class Instance;
99 } // namespace Calls
100 
101 namespace Core {
102 
103 class Launcher;
104 struct LocalUrlHandler;
105 
106 class Application final : public QObject {
107 public:
108 	struct ProxyChange {
109 		MTP::ProxyData was;
110 		MTP::ProxyData now;
111 	};
112 
113 	Application(not_null<Launcher*> launcher);
114 	Application(const Application &other) = delete;
115 	Application &operator=(const Application &other) = delete;
116 	~Application();
117 
launcher()118 	[[nodiscard]] not_null<Launcher*> launcher() const {
119 		return _launcher;
120 	}
121 
122 	void run();
123 
animationManager()124 	[[nodiscard]] Ui::Animations::Manager &animationManager() const {
125 		return *_animationsManager;
126 	}
notifications()127 	[[nodiscard]] Window::Notifications::System &notifications() const {
128 		Expects(_notifications != nullptr);
129 
130 		return *_notifications;
131 	}
132 
133 	// Windows interface.
134 	bool hasActiveWindow(not_null<Main::Session*> session) const;
135 	void saveCurrentDraftsToHistories();
136 	[[nodiscard]] Window::Controller *activeWindow() const;
137 	bool closeActiveWindow();
138 	bool minimizeActiveWindow();
139 	[[nodiscard]] QWidget *getFileDialogParent();
140 	void notifyFileDialogShown(bool shown);
141 	void checkSystemDarkMode();
142 
143 	// Media view interface.
144 	void checkMediaViewActivation();
145 	bool hideMediaView();
146 
147 	[[nodiscard]] QPoint getPointForCallPanelCenter() const;
148 
149 	void startSettingsAndBackground();
settings()150 	[[nodiscard]] Settings &settings() {
151 		return _settings;
152 	}
153 	void saveSettingsDelayed(crl::time delay = kDefaultSaveDelay);
154 	void saveSettings();
155 
156 	// Fallback config and proxy.
157 	[[nodiscard]] MTP::Config &fallbackProductionConfig() const;
158 	void refreshFallbackProductionConfig(const MTP::Config &config);
159 	void constructFallbackProductionConfig(const QByteArray &serialized);
160 	void setCurrentProxy(
161 		const MTP::ProxyData &proxy,
162 		MTP::ProxyData::Settings settings);
163 	[[nodiscard]] rpl::producer<ProxyChange> proxyChanges() const;
164 	void badMtprotoConfigurationError();
165 
166 	// Databases.
databases()167 	[[nodiscard]] Storage::Databases &databases() {
168 		return *_databases;
169 	}
170 
171 	// Domain component.
domain()172 	[[nodiscard]] Main::Domain &domain() const {
173 		return *_domain;
174 	}
175 	[[nodiscard]] Main::Account &activeAccount() const;
176 	[[nodiscard]] bool someSessionExists() const;
exportManager()177 	[[nodiscard]] Export::Manager &exportManager() const {
178 		return *_exportManager;
179 	}
180 	[[nodiscard]] bool exportPreventsQuit();
181 
182 	// Main::Session component.
183 	Main::Session *maybeActiveSession() const;
184 	[[nodiscard]] int unreadBadge() const;
185 	[[nodiscard]] bool unreadBadgeMuted() const;
186 	[[nodiscard]] rpl::producer<> unreadBadgeChanges() const;
187 
188 	// Media component.
audio()189 	[[nodiscard]] Media::Audio::Instance &audio() {
190 		return *_audio;
191 	}
192 
193 	// Langpack and emoji keywords.
langpack()194 	[[nodiscard]] Lang::Instance &langpack() {
195 		return *_langpack;
196 	}
langCloudManager()197 	[[nodiscard]] Lang::CloudManager *langCloudManager() {
198 		return _langCloudManager.get();
199 	}
200 	[[nodiscard]] bool offerLegacyLangPackSwitch() const;
201 	[[nodiscard]] bool canApplyLangPackWithoutRestart() const;
emojiKeywords()202 	[[nodiscard]] ChatHelpers::EmojiKeywords &emojiKeywords() {
203 		return *_emojiKeywords;
204 	}
205 	[[nodiscard]] auto emojiImageLoader() const
206 	-> const crl::object_on_queue<Stickers::EmojiImageLoader> & {
207 		return _emojiImageLoader;
208 	}
209 
210 	// Internal links.
211 	void checkStartUrl();
212 	bool openLocalUrl(const QString &url, QVariant context);
213 	bool openInternalUrl(const QString &url, QVariant context);
214 	[[nodiscard]] QString changelogLink() const;
215 
216 	// Float player.
217 	void setDefaultFloatPlayerDelegate(
218 		not_null<Media::Player::FloatDelegate*> delegate);
219 	void replaceFloatPlayerDelegate(
220 		not_null<Media::Player::FloatDelegate*> replacement);
221 	void restoreFloatPlayerDelegate(
222 		not_null<Media::Player::FloatDelegate*> replacement);
223 	[[nodiscard]] rpl::producer<FullMsgId> floatPlayerClosed() const;
224 
225 	// Calls.
calls()226 	Calls::Instance &calls() const {
227 		return *_calls;
228 	}
229 
230 	void logout(Main::Account *account = nullptr);
231 	void forceLogOut(
232 		not_null<Main::Account*> account,
233 		const TextWithEntities &explanation);
234 	void checkLocalTime();
235 	void lockByPasscode();
236 	void unlockPasscode();
237 	[[nodiscard]] bool passcodeLocked() const;
238 	rpl::producer<bool> passcodeLockChanges() const;
239 	rpl::producer<bool> passcodeLockValue() const;
240 
241 	void checkAutoLock(crl::time lastNonIdleTime = 0);
242 	void checkAutoLockIn(crl::time time);
243 	void localPasscodeChanged();
244 
245 	[[nodiscard]] crl::time lastNonIdleTime() const;
246 	void updateNonIdle();
247 
248 	void registerLeaveSubscription(not_null<QWidget*> widget);
249 	void unregisterLeaveSubscription(not_null<QWidget*> widget);
250 
251 	// Sandbox interface.
252 	void postponeCall(FnMut<void()> &&callable);
253 	void refreshGlobalProxy();
254 
255 	void quitPreventFinished();
256 
257 	void handleAppActivated();
258 	void handleAppDeactivated();
259 	[[nodiscard]] rpl::producer<bool> appDeactivatedValue() const;
260 
261 	void switchDebugMode();
262 	void switchFreeType();
263 	void writeInstallBetaVersionsSetting();
264 
265 	void preventOrInvoke(Fn<void()> &&callback);
266 
267 	void call_handleObservables();
268 
269 	// Global runtime variables.
270 	void setScreenIsLocked(bool locked);
271 	bool screenIsLocked() const;
272 
273 	static void RegisterUrlScheme();
274 
275 protected:
276 	bool eventFilter(QObject *object, QEvent *event) override;
277 
278 private:
279 	static constexpr auto kDefaultSaveDelay = crl::time(1000);
280 
281 	friend bool IsAppLaunched();
282 	friend Application &App();
283 
284 	void clearEmojiSourceImages();
285 	[[nodiscard]] auto prepareEmojiSourceImages()
286 		-> std::shared_ptr<Ui::Emoji::UniversalImages>;
287 	void startLocalStorage();
288 	void startShortcuts();
289 	void startDomain();
290 	void startEmojiImageLoader();
291 	void startSystemDarkModeViewer();
292 
293 	friend void App::quit();
294 	static void QuitAttempt();
295 	void quitDelayed();
296 	[[nodiscard]] bool readyToQuit();
297 
298 	void showOpenGLCrashNotification();
299 	void clearPasscodeLock();
300 
301 	bool openCustomUrl(
302 		const QString &protocol,
303 		const std::vector<LocalUrlHandler> &handlers,
304 		const QString &url,
305 		const QVariant &context);
306 
307 	static Application *Instance;
308 	struct InstanceSetter {
InstanceSetterInstanceSetter309 		InstanceSetter(not_null<Application*> instance) {
310 			Expects(Instance == nullptr);
311 
312 			Instance = instance;
313 		}
314 	};
315 	InstanceSetter _setter = { this };
316 
317 	not_null<Launcher*> _launcher;
318 	rpl::event_stream<ProxyChange> _proxyChanges;
319 
320 	// Some fields are just moved from the declaration.
321 	struct Private;
322 	const std::unique_ptr<Private> _private;
323 	Settings _settings;
324 
325 	const std::unique_ptr<Storage::Databases> _databases;
326 	const std::unique_ptr<Ui::Animations::Manager> _animationsManager;
327 	crl::object_on_queue<Stickers::EmojiImageLoader> _emojiImageLoader;
328 	base::Timer _clearEmojiImageLoaderTimer;
329 	const std::unique_ptr<Media::Audio::Instance> _audio;
330 	mutable std::unique_ptr<MTP::Config> _fallbackProductionConfig;
331 
332 	// Notifications should be destroyed before _audio, after _domain.
333 	// Mutable because is created in run() after OpenSSL is inited.
334 	std::unique_ptr<Window::Notifications::System> _notifications;
335 
336 	const std::unique_ptr<Main::Domain> _domain;
337 	const std::unique_ptr<Export::Manager> _exportManager;
338 	const std::unique_ptr<Calls::Instance> _calls;
339 	std::unique_ptr<Window::Controller> _window;
340 	std::unique_ptr<Media::View::OverlayWidget> _mediaView;
341 	const std::unique_ptr<Lang::Instance> _langpack;
342 	const std::unique_ptr<Lang::CloudManager> _langCloudManager;
343 	const std::unique_ptr<ChatHelpers::EmojiKeywords> _emojiKeywords;
344 	std::unique_ptr<Lang::Translator> _translator;
345 	QPointer<Ui::BoxContent> _badProxyDisableBox;
346 
347 	std::unique_ptr<Media::Player::FloatController> _floatPlayers;
348 	Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr;
349 	Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr;
350 
351 	rpl::variable<bool> _passcodeLock;
352 	bool _screenIsLocked = false;
353 
354 	crl::time _shouldLockAt = 0;
355 	base::Timer _autoLockTimer;
356 
357 	std::optional<base::Timer> _saveSettingsTimer;
358 
359 	struct LeaveFilter {
360 		std::vector<QPointer<QWidget>> registered;
361 		QPointer<QObject> filter;
362 	};
363 	base::flat_map<not_null<QWidget*>, LeaveFilter> _leaveFilters;
364 
365 	rpl::lifetime _lifetime;
366 
367 	crl::time _lastNonIdleTime = 0;
368 
369 };
370 
371 [[nodiscard]] bool IsAppLaunched();
372 [[nodiscard]] Application &App();
373 
374 } // namespace Core
375