From 97b0288c7dcdd1595a5bba5362d2bfb53f35fa62 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 30 Nov 2018 17:27:33 +0400
Subject: [PATCH] Add automatic loading of videos/files.

---
 .../SourceFiles/data/data_auto_download.cpp   |  4 +
 Telegram/SourceFiles/data/data_document.cpp   | 80 +++++++++++--------
 Telegram/SourceFiles/data/data_document.h     |  1 +
 .../SourceFiles/ui/image/image_source.cpp     | 41 ++++++----
 Telegram/SourceFiles/ui/image/image_source.h  |  1 +
 5 files changed, 76 insertions(+), 51 deletions(-)

diff --git a/Telegram/SourceFiles/data/data_auto_download.cpp b/Telegram/SourceFiles/data/data_auto_download.cpp
index 4efa07a08..290ecda9c 100644
--- a/Telegram/SourceFiles/data/data_auto_download.cpp
+++ b/Telegram/SourceFiles/data/data_auto_download.cpp
@@ -18,6 +18,7 @@ namespace AutoDownload {
 namespace {
 
 constexpr auto kDefaultMaxSize = 10 * 1024 * 1024;
+constexpr auto kNonCacheMaxSize = 2 * 1024 * 1024;
 constexpr auto kVersion = char(1);
 
 template <typename Enum>
@@ -38,6 +39,9 @@ void SetDefaultsForSource(Full &data, Source source) {
 	data.setBytesLimit(source, Type::VoiceMessage, kDefaultMaxSize);
 	data.setBytesLimit(source, Type::VideoMessage, kDefaultMaxSize);
 	data.setBytesLimit(source, Type::GIF, kDefaultMaxSize);
+	data.setBytesLimit(source, Type::File, kNonCacheMaxSize);
+	data.setBytesLimit(source, Type::Video, kNonCacheMaxSize);
+	data.setBytesLimit(source, Type::Music, kNonCacheMaxSize);
 }
 
 const Full &Defaults() {
diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp
index 4ceb5d6ec..fa8fb29a9 100644
--- a/Telegram/SourceFiles/data/data_document.cpp
+++ b/Telegram/SourceFiles/data/data_document.cpp
@@ -632,38 +632,42 @@ void DocumentData::unload() {
 void DocumentData::automaticLoad(
 		Data::FileOrigin origin,
 		const HistoryItem *item) {
-	if (loaded() || status != FileReady) return;
-
-	if (saveToCache() && _loader != CancelledMtpFileLoader) {
-		if (type == StickerDocument
-			|| isAnimation()
-			|| (isVoiceMessage() && item)) {
-			const auto shouldLoadFromCloud = item
-				? Data::AutoDownload::Should(
-					Auth().settings().autoDownload(),
-					item->history()->peer,
-					this)
-				: Data::AutoDownload::Should(
-					Auth().settings().autoDownload(),
-					this);
-			const auto loadFromCloud = shouldLoadFromCloud
-				? LoadFromCloudOrLocal
-				: LoadFromLocalOnly;
-			save(
-				origin,
-				QString(),
-				_actionOnLoad,
-				_actionOnLoadMsgId,
-				loadFromCloud,
-				true);
-		}
+	if (status != FileReady || loaded() || cancelled()) {
+		return;
+	} else if (!item && type != StickerDocument && !isAnimation()) {
+		return;
 	}
+	const auto toCache = saveToCache();
+	if (!toCache && Global::AskDownloadPath()) {
+		// We need a filename, but we're supposed to ask user for it.
+		// No automatic download in this case.
+		return;
+	}
+	const auto filename = toCache
+		? QString()
+		: documentSaveFilename(this);
+	const auto shouldLoadFromCloud = item
+		? Data::AutoDownload::Should(
+			Auth().settings().autoDownload(),
+			item->history()->peer,
+			this)
+		: Data::AutoDownload::Should(
+			Auth().settings().autoDownload(),
+			this);
+	const auto loadFromCloud = shouldLoadFromCloud
+		? LoadFromCloudOrLocal
+		: LoadFromLocalOnly;
+	save(
+		origin,
+		filename,
+		_actionOnLoad,
+		_actionOnLoadMsgId,
+		loadFromCloud,
+		true);
 }
 
 void DocumentData::automaticLoadSettingsChanged() {
-	if (_loader != CancelledMtpFileLoader
-		|| status != FileReady
-		|| loaded()) {
+	if (!cancelled() || status != FileReady || loaded()) {
 		return;
 	}
 	_loader = nullptr;
@@ -790,7 +794,7 @@ bool DocumentData::loaded(FilePathResolveType type) const {
 
 void DocumentData::destroyLoader(mtpFileLoader *newValue) const {
 	const auto loader = std::exchange(_loader, newValue);
-	if (_loader == CancelledMtpFileLoader) {
+	if (cancelled()) {
 		loader->cancel();
 	}
 	loader->stop();
@@ -798,7 +802,7 @@ void DocumentData::destroyLoader(mtpFileLoader *newValue) const {
 }
 
 bool DocumentData::loading() const {
-	return _loader && _loader != CancelledMtpFileLoader;
+	return _loader && !cancelled();
 }
 
 QString DocumentData::loadingFilePath() const {
@@ -874,7 +878,7 @@ void DocumentData::save(
 		return;
 	}
 
-	if (_loader == CancelledMtpFileLoader) {
+	if (cancelled()) {
 		_loader = nullptr;
 	}
 	if (_loader) {
@@ -887,7 +891,9 @@ void DocumentData::save(
 	_actionOnLoad = action;
 	_actionOnLoadMsgId = actionMsgId;
 	if (_loader) {
-		if (fromCloud == LoadFromCloudOrLocal) _loader->permitLoadFromCloud();
+		if (fromCloud == LoadFromCloudOrLocal) {
+			_loader->permitLoadFromCloud();
+		}
 	} else {
 		status = FileReady;
 		if (hasWebLocation()) {
@@ -922,6 +928,8 @@ void DocumentData::save(
 
 		_loader->connect(_loader, SIGNAL(progress(FileLoader*)), App::main(), SLOT(documentLoadProgress(FileLoader*)));
 		_loader->connect(_loader, SIGNAL(failed(FileLoader*,bool)), App::main(), SLOT(documentLoadFailed(FileLoader*,bool)));
+	}
+	if (loading()) {
 		_loader->start();
 	}
 	_session->data().notifyDocumentLayoutChanged(this);
@@ -934,13 +942,15 @@ void DocumentData::cancel() {
 
 	destroyLoader(CancelledMtpFileLoader);
 	_session->data().notifyDocumentLayoutChanged(this);
-	if (auto main = App::main()) {
-		main->documentLoadProgress(this);
-	}
+	App::main()->documentLoadProgress(this);
 
 	_actionOnLoad = ActionOnLoadNone;
 }
 
+bool DocumentData::cancelled() const {
+	return (_loader == CancelledMtpFileLoader);
+}
+
 VoiceWaveform documentWaveformDecode(const QByteArray &encoded5bit) {
 	auto bitsCount = static_cast<int>(encoded5bit.size() * 8);
 	auto valuesCount = bitsCount / 5;
diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h
index 1d6079060..716960678 100644
--- a/Telegram/SourceFiles/data/data_document.h
+++ b/Telegram/SourceFiles/data/data_document.h
@@ -106,6 +106,7 @@ public:
 		LoadFromCloudSetting fromCloud = LoadFromCloudOrLocal,
 		bool autoLoading = false);
 	void cancel();
+	bool cancelled() const;
 	float64 progress() const;
 	int32 loadOffset() const;
 	bool uploading() const;
diff --git a/Telegram/SourceFiles/ui/image/image_source.cpp b/Telegram/SourceFiles/ui/image/image_source.cpp
index 071d2b309..8910bb0bd 100644
--- a/Telegram/SourceFiles/ui/image/image_source.cpp
+++ b/Telegram/SourceFiles/ui/image/image_source.cpp
@@ -299,14 +299,14 @@ QImage RemoteSource::takeLoaded() {
 }
 
 bool RemoteSource::loaderValid() const {
-	return _loader && _loader != CancelledFileLoader;
+	return _loader && !cancelled();
 }
 
 void RemoteSource::destroyLoader(FileLoader *newValue) {
 	Expects(loaderValid());
 
 	const auto loader = std::exchange(_loader, newValue);
-	if (_loader == CancelledFileLoader) {
+	if (cancelled()) {
 		loader->cancel();
 	}
 	loader->stop();
@@ -350,21 +350,26 @@ bool RemoteSource::loading() {
 void RemoteSource::automaticLoad(
 		Data::FileOrigin origin,
 		const HistoryItem *item) {
-	if (_loader != CancelledFileLoader && item) {
-		const auto loadFromCloud = Data::AutoDownload::Should(
-			Auth().settings().autoDownload(),
-			item->history()->peer,
-			this);
+	if (!item || cancelled()) {
+		return;
+	}
+	const auto loadFromCloud = Data::AutoDownload::Should(
+		Auth().settings().autoDownload(),
+		item->history()->peer,
+		this);
 
-		if (_loader) {
-			if (loadFromCloud) _loader->permitLoadFromCloud();
-		} else {
-			_loader = createLoader(
-				origin,
-				loadFromCloud ? LoadFromCloudOrLocal : LoadFromLocalOnly,
-				true);
-			if (_loader) _loader->start();
+	if (_loader) {
+		if (loadFromCloud) {
+			_loader->permitLoadFromCloud();
 		}
+	} else {
+		_loader = createLoader(
+			origin,
+			loadFromCloud ? LoadFromCloudOrLocal : LoadFromLocalOnly,
+			true);
+	}
+	if (loaderValid()) {
+		_loader->start();
 	}
 }
 
@@ -386,11 +391,15 @@ void RemoteSource::load(
 	}
 }
 
+bool RemoteSource::cancelled() const {
+	return (_loader == CancelledFileLoader);
+}
+
 void RemoteSource::loadEvenCancelled(
 		Data::FileOrigin origin,
 		bool loadFirst,
 		bool prior) {
-	if (_loader == CancelledFileLoader) {
+	if (cancelled()) {
 		_loader = nullptr;
 	}
 	return load(origin, loadFirst, prior);
diff --git a/Telegram/SourceFiles/ui/image/image_source.h b/Telegram/SourceFiles/ui/image/image_source.h
index 061ea028d..5ee77a0d2 100644
--- a/Telegram/SourceFiles/ui/image/image_source.h
+++ b/Telegram/SourceFiles/ui/image/image_source.h
@@ -169,6 +169,7 @@ protected:
 
 private:
 	bool loaderValid() const;
+	bool cancelled() const;
 	void destroyLoader(FileLoader *newValue = nullptr);
 
 	FileLoader *_loader = nullptr;