From 2df4d194740113165fa39f7fbdcd432f340aa4e9 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 29 Dec 2017 21:17:07 +0300
Subject: [PATCH] Move changelogs from ApiWrap to a separate module.

---
 Telegram/SourceFiles/apiwrap.cpp         |  67 +--------
 Telegram/SourceFiles/apiwrap.h           |   8 +-
 Telegram/SourceFiles/auth_session.cpp    |   8 +-
 Telegram/SourceFiles/auth_session.h      |   5 +
 Telegram/SourceFiles/core/changelogs.cpp | 179 +++++++++++++++++++++++
 Telegram/SourceFiles/core/changelogs.h   |  50 +++++++
 Telegram/gyp/telegram_sources.txt        |   2 +
 7 files changed, 254 insertions(+), 65 deletions(-)
 create mode 100644 Telegram/SourceFiles/core/changelogs.cpp
 create mode 100644 Telegram/SourceFiles/core/changelogs.h

diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 2e7a05d1c..070ef68dd 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -38,7 +38,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "storage/localstorage.h"
 #include "auth_session.h"
 #include "boxes/confirm_box.h"
-#include "window/themes/window_theme.h"
 #include "window/notifications_manager.h"
 #include "chat_helpers/message_field.h"
 #include "chat_helpers/stickers.h"
@@ -144,64 +143,14 @@ ApiWrap::ApiWrap(not_null<AuthSession*> session)
 , _fileLoader(std::make_unique<TaskQueue>(kFileLoaderQueueStopTimeout)) {
 }
 
-void ApiWrap::start() {
-	Window::Theme::Background()->start();
-	requestAppChangelogs();
-}
-
-void ApiWrap::requestAppChangelogs() {
-	auto oldAppVersion = Local::oldMapVersion();
-	if (oldAppVersion > 0 && oldAppVersion < AppVersion) {
-		_changelogSubscription = subscribe(_session->data().moreChatsLoaded(), [this, oldAppVersion] {
-			auto oldVersionString = qsl("%1.%2.%3").arg(oldAppVersion / 1000000).arg((oldAppVersion % 1000000) / 1000).arg(oldAppVersion % 1000);
-			request(MTPhelp_GetAppChangelog(MTP_string(oldVersionString))).done([this, oldAppVersion](const MTPUpdates &result) {
-				applyUpdates(result);
-
-				auto resultEmpty = true;
-				switch (result.type()) {
-				case mtpc_updateShortMessage:
-				case mtpc_updateShortChatMessage:
-				case mtpc_updateShort: resultEmpty = false; break;
-				case mtpc_updatesCombined: resultEmpty = result.c_updatesCombined().vupdates.v.isEmpty(); break;
-				case mtpc_updates: resultEmpty = result.c_updates().vupdates.v.isEmpty(); break;
-				case mtpc_updatesTooLong:
-				case mtpc_updateShortSentMessage: LOG(("API Error: Bad updates type in app changelog.")); break;
-				}
-				if (resultEmpty) {
-					addLocalChangelogs(oldAppVersion);
-				}
-			}).send();
-			unsubscribe(base::take(_changelogSubscription));
-		});
-	}
-}
-
-void ApiWrap::addLocalChangelogs(int oldAppVersion) {
-	auto addedSome = false;
-	auto addLocalChangelog = [this, &addedSome](const QString &text) {
-		auto textWithEntities = TextWithEntities { text };
-		TextUtilities::ParseEntities(textWithEntities, TextParseLinks);
-		App::wnd()->serviceNotification(textWithEntities, MTP_messageMediaEmpty(), unixtime());
-		addedSome = true;
-	};
-	if (cAlphaVersion() || cBetaVersion()) {
-		auto addLocalAlphaChangelog = [this, oldAppVersion, addLocalChangelog](int changeVersion, const char *changes) {
-			if (oldAppVersion < changeVersion) {
-				auto changeVersionString = QString::number(changeVersion / 1000000) + '.' + QString::number((changeVersion % 1000000) / 1000) + ((changeVersion % 1000) ? ('.' + QString::number(changeVersion % 1000)) : QString());
-				auto text = qsl("New in version %1:\n\n").arg(changeVersionString) + QString::fromUtf8(changes).trimmed();
-				addLocalChangelog(text);
-			}
-		};
-		addLocalAlphaChangelog(1001024, "\xE2\x80\x94 Radically improved navigation. New side panel on the right with quick access to shared media and group members.\n\xE2\x80\x94 Pinned Messages. If you are a channel admin, pin messages to focus your subscribers\xE2\x80\x99 attention on important announcements.\n\xE2\x80\x94 Also supported clearing history in supergroups and added a host of minor improvements.");
-		addLocalAlphaChangelog(1001026, "\xE2\x80\x94 Admin badges in supergroup messages.\n\xE2\x80\x94 Fix crashing on launch in OS X 10.6.\n\xE2\x80\x94 Bug fixes and other minor improvements.");
-		addLocalAlphaChangelog(1001027, "\xE2\x80\x94 Saved Messages. Bookmark messages by forwarding them to \xE2\x80\x9C""Saved Messages\xE2\x80\x9D. Access them from the Chats list or from the side menu.");
-		addLocalAlphaChangelog(1002002, "\xE2\x80\x94 Grouped photos and videos are displayed as albums.");
-		addLocalAlphaChangelog(1002004, "\xE2\x80\x94 Group media into an album when sharing multiple photos and videos.\n\xE2\x80\x94 Bug fixes and other minor improvements.");
-	}
-	if (!addedSome) {
-		auto text = lng_new_version_wrap(lt_version, str_const_toString(AppVersionStr), lt_changes, lang(lng_new_version_minor), lt_link, qsl("https://desktop.telegram.org/changelog")).trimmed();
-		addLocalChangelog(text);
-	}
+void ApiWrap::requestChangelog(
+		const QString &sinceVersion,
+		base::lambda<void(const MTPUpdates &result)> callback) {
+	request(MTPhelp_GetAppChangelog(
+		MTP_string(sinceVersion)
+	)).done(
+		callback
+	).send();
 }
 
 void ApiWrap::applyUpdates(
diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h
index 7df05faf0..874c4c57e 100644
--- a/Telegram/SourceFiles/apiwrap.h
+++ b/Telegram/SourceFiles/apiwrap.h
@@ -56,7 +56,6 @@ class ApiWrap : private MTP::Sender, private base::Subscriber {
 public:
 	ApiWrap(not_null<AuthSession*> session);
 
-	void start();
 	void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0);
 
 	using RequestMessageDataCallback = base::lambda<void(ChannelData*, MsgId)>;
@@ -70,6 +69,10 @@ public:
 	void requestAdmins(not_null<ChannelData*> channel);
 	void requestParticipantsCountDelayed(not_null<ChannelData*> channel);
 
+	void requestChangelog(
+		const QString &sinceVersion,
+		base::lambda<void(const MTPUpdates &result)> callback);
+
 	void requestChannelMembersForAdd(
 		not_null<ChannelData*> channel,
 		base::lambda<void(const MTPchannels_ChannelParticipants&)> callback);
@@ -234,8 +237,6 @@ private:
 	using MessageDataRequests = QMap<MsgId, MessageDataRequest>;
 	using SharedMediaType = Storage::SharedMediaType;
 
-	void requestAppChangelogs();
-	void addLocalChangelogs(int oldAppVersion);
 	void updatesReceived(const MTPUpdates &updates);
 	void checkQuitPreventFinished();
 
@@ -344,7 +345,6 @@ private:
 		uint64 randomId);
 
 	not_null<AuthSession*> _session;
-	mtpRequestId _changelogSubscription = 0;
 
 	MessageDataRequests _messageDataRequests;
 	QMap<ChannelData*, MessageDataRequests> _channelMessageDataRequests;
diff --git a/Telegram/SourceFiles/auth_session.cpp b/Telegram/SourceFiles/auth_session.cpp
index bc5db1b4d..2ee3906f3 100644
--- a/Telegram/SourceFiles/auth_session.cpp
+++ b/Telegram/SourceFiles/auth_session.cpp
@@ -22,6 +22,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 
 #include "apiwrap.h"
 #include "messenger.h"
+#include "core/changelogs.h"
 #include "storage/file_download.h"
 #include "storage/file_upload.h"
 #include "storage/localstorage.h"
@@ -29,6 +30,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
 #include "storage/serialize_common.h"
 #include "history/history_item_components.h"
 #include "window/notifications_manager.h"
+#include "window/themes/window_theme.h"
 #include "platform/platform_specific.h"
 #include "calls/calls_instance.h"
 #include "window/section_widget.h"
@@ -408,8 +410,10 @@ AuthSession::AuthSession(UserId userId)
 , _downloader(std::make_unique<Storage::Downloader>())
 , _uploader(std::make_unique<Storage::Uploader>())
 , _storage(std::make_unique<Storage::Facade>())
-, _notifications(std::make_unique<Window::Notifications::System>(this)) {
+, _notifications(std::make_unique<Window::Notifications::System>(this))
+, _changelogs(Core::Changelogs::Create(this)) {
 	Expects(_userId != 0);
+
 	_saveDataTimer.setCallback([this] {
 		Local::writeUserSettings();
 	});
@@ -417,7 +421,7 @@ AuthSession::AuthSession(UserId userId)
 		_shouldLockAt = 0;
 		notifications().updateAll();
 	});
-	_api->start();
+	Window::Theme::Background()->start();
 }
 
 bool AuthSession::Exists() {
diff --git a/Telegram/SourceFiles/auth_session.h b/Telegram/SourceFiles/auth_session.h
index 1bf2ec502..8eb3c2c3c 100644
--- a/Telegram/SourceFiles/auth_session.h
+++ b/Telegram/SourceFiles/auth_session.h
@@ -50,6 +50,10 @@ namespace ChatHelpers {
 enum class SelectorTab;
 } // namespace ChatHelpers
 
+namespace Core {
+class Changelogs;
+} // namespace Core
+
 class AuthSessionData final {
 public:
 	base::Variable<bool> &contactsLoaded() {
@@ -414,5 +418,6 @@ private:
 	const std::unique_ptr<Storage::Uploader> _uploader;
 	const std::unique_ptr<Storage::Facade> _storage;
 	const std::unique_ptr<Window::Notifications::System> _notifications;
+	const std::unique_ptr<Core::Changelogs> _changelogs;
 
 };
diff --git a/Telegram/SourceFiles/core/changelogs.cpp b/Telegram/SourceFiles/core/changelogs.cpp
new file mode 100644
index 000000000..33c51dab2
--- /dev/null
+++ b/Telegram/SourceFiles/core/changelogs.cpp
@@ -0,0 +1,179 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
+*/
+#include "core/changelogs.h"
+
+#include "storage/localstorage.h"
+#include "lang/lang_keys.h"
+#include "mainwindow.h"
+#include "apiwrap.h"
+
+namespace Core {
+namespace {
+
+std::map<int, const char*> AlphaLogs() {
+	return {
+	{
+		1001024,
+		"\xE2\x80\x94 Radically improved navigation. "
+		"New side panel on the right with quick access to "
+		"shared media and group members.\n"
+
+		"\xE2\x80\x94 Pinned Messages. If you are a channel admin, "
+		"pin messages to focus your subscribers\xE2\x80\x99 attention "
+		"on important announcements.\n"
+
+		"\xE2\x80\x94 Also supported clearing history in supergroups "
+		"and added a host of minor improvements."
+	},
+	{
+		1001026,
+		"\xE2\x80\x94 Admin badges in supergroup messages.\n"
+		"\xE2\x80\x94 Fix crashing on launch in OS X 10.6.\n"
+		"\xE2\x80\x94 Bug fixes and other minor improvements."
+	},
+	{
+		1001027,
+		"\xE2\x80\x94 Saved Messages. Bookmark messages by forwarding them "
+		"to \xE2\x80\x9C""Saved Messages\xE2\x80\x9D. "
+		"Access them from the Chats list or from the side menu."
+	},
+	{
+		1002002,
+		"\xE2\x80\x94 Grouped photos and videos are displayed as albums."
+	},
+	{
+		1002004,
+		"\xE2\x80\x94 Group media into an album "
+		"when sharing multiple photos and videos.\n"
+
+		"\xE2\x80\x94 Bug fixes and other minor improvements."
+	}
+	};
+}
+
+QString FormatVersionDisplay(int version) {
+	return QString::number(version / 1000000)
+		+ '.' + QString::number((version % 1000000) / 1000)
+		+ ((version % 1000)
+			? ('.' + QString::number(version % 1000))
+			: QString());
+}
+
+QString FormatVersionPrecise(int version) {
+	return QString::number(version / 1000000)
+		+ '.' + QString::number((version % 1000000) / 1000)
+		+ '.' + QString::number(version % 1000);
+}
+
+} // namespace
+
+Changelogs::Changelogs(not_null<AuthSession*> session, int oldVersion)
+: _session(session)
+, _oldVersion(oldVersion) {
+	_chatsSubscription = subscribe(
+		_session->data().moreChatsLoaded(),
+		[this] { requestCloudLogs(); });
+}
+
+std::unique_ptr<Changelogs> Changelogs::Create(
+		not_null<AuthSession*> session) {
+	const auto oldVersion = Local::oldMapVersion();
+	return (oldVersion > 0 && oldVersion < AppVersion)
+		? std::make_unique<Changelogs>(session, oldVersion)
+		: nullptr;
+}
+
+void Changelogs::requestCloudLogs() {
+	unsubscribe(base::take(_chatsSubscription));
+
+	const auto callback = [this](const MTPUpdates &result) {
+		_session->api().applyUpdates(result);
+
+		auto resultEmpty = true;
+		switch (result.type()) {
+		case mtpc_updateShortMessage:
+		case mtpc_updateShortChatMessage:
+		case mtpc_updateShort:
+			resultEmpty = false;
+			break;
+		case mtpc_updatesCombined:
+			resultEmpty = result.c_updatesCombined().vupdates.v.isEmpty();
+			break;
+		case mtpc_updates:
+			resultEmpty = result.c_updates().vupdates.v.isEmpty();
+			break;
+		case mtpc_updatesTooLong:
+		case mtpc_updateShortSentMessage:
+			LOG(("API Error: Bad updates type in app changelog."));
+			break;
+		}
+		if (resultEmpty) {
+			addLocalLogs();
+		}
+	};
+	_session->api().requestChangelog(
+		FormatVersionPrecise(_oldVersion),
+		base::lambda_guarded(this, callback));
+}
+
+void Changelogs::addLocalLogs() {
+	if (cAlphaVersion() || cBetaVersion()) {
+		addAlphaLogs();
+	}
+	if (!_addedSomeLocal) {
+		const auto text = lng_new_version_wrap(
+			lt_version,
+			str_const_toString(AppVersionStr),
+			lt_changes,
+			lang(lng_new_version_minor),
+			lt_link,
+			qsl("https://desktop.telegram.org/changelog"));
+		addLocalLog(text.trimmed());
+	}
+}
+
+void Changelogs::addLocalLog(const QString &text) {
+	auto textWithEntities = TextWithEntities{ text };
+	TextUtilities::ParseEntities(textWithEntities, TextParseLinks);
+	App::wnd()->serviceNotification(
+		textWithEntities,
+		MTP_messageMediaEmpty(),
+		unixtime());
+	_addedSomeLocal = true;
+};
+
+void Changelogs::addAlphaLogs() {
+	for (const auto[version, changes] : AlphaLogs()) {
+		addAlphaLog(version, changes);
+	}
+}
+
+void Changelogs::addAlphaLog(int changeVersion, const char *changes) {
+	if (_oldVersion >= changeVersion) {
+		return;
+	}
+	const auto version = FormatVersionDisplay(changeVersion);
+	const auto text = qsl("New in version %1:\n\n").arg(version)
+		+ QString::fromUtf8(changes).trimmed();
+	addLocalLog(text);
+}
+
+} // namespace Core
diff --git a/Telegram/SourceFiles/core/changelogs.h b/Telegram/SourceFiles/core/changelogs.h
new file mode 100644
index 000000000..cb27c4469
--- /dev/null
+++ b/Telegram/SourceFiles/core/changelogs.h
@@ -0,0 +1,50 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
+*/
+#pragma once
+
+#include "base/weak_ptr.h"
+
+class AuthSession;
+
+namespace Core {
+
+class Changelogs : public base::has_weak_ptr, private base::Subscriber {
+public:
+	Changelogs(not_null<AuthSession*> session, int oldVersion);
+
+	static std::unique_ptr<Changelogs> Create(
+		not_null<AuthSession*> session);
+
+private:
+	void requestCloudLogs();
+	void addLocalLogs();
+	void addLocalLog(const QString &text);
+	void addAlphaLogs();
+	void addAlphaLog(int changeVersion, const char *changes);
+
+	const not_null<AuthSession*> _session;
+	const int _oldVersion = 0;
+	int _chatsSubscription = 0;
+	bool _addedSomeLocal = false;
+
+};
+
+} // namespace Core
diff --git a/Telegram/gyp/telegram_sources.txt b/Telegram/gyp/telegram_sources.txt
index f407a4f5c..5d2f627ed 100644
--- a/Telegram/gyp/telegram_sources.txt
+++ b/Telegram/gyp/telegram_sources.txt
@@ -139,6 +139,8 @@
 <(src_loc)/chat_helpers/tabbed_selector.cpp
 <(src_loc)/chat_helpers/tabbed_selector.h
 <(src_loc)/core/basic_types.h
+<(src_loc)/core/changelogs.cpp
+<(src_loc)/core/changelogs.h
 <(src_loc)/core/click_handler.cpp
 <(src_loc)/core/click_handler.h
 <(src_loc)/core/click_handler_types.cpp