Generate previews async in cloud themes list.
This commit is contained in:
		
							parent
							
								
									048658f838
								
							
						
					
					
						commit
						eebcdb842d
					
				
					 7 changed files with 100 additions and 56 deletions
				
			
		|  | @ -272,6 +272,18 @@ void CloudThemes::parseThemes(const QVector<MTPTheme> &list) { | ||||||
| 			LOG(("API Error: Unexpected themeDocumentNotModified.")); | 			LOG(("API Error: Unexpected themeDocumentNotModified.")); | ||||||
| 		}); | 		}); | ||||||
| 	} | 	} | ||||||
|  | 	checkCurrentTheme(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CloudThemes::checkCurrentTheme() { | ||||||
|  | 	const auto &object = Window::Theme::Background()->themeObject(); | ||||||
|  | 	if (!object.cloud.id || !object.cloud.documentId) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	const auto i = ranges::find(_list, object.cloud.id, &CloudTheme::id); | ||||||
|  | 	if (i == end(_list)) { | ||||||
|  | 		install(); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| rpl::producer<> CloudThemes::updated() const { | rpl::producer<> CloudThemes::updated() const { | ||||||
|  |  | ||||||
|  | @ -56,6 +56,7 @@ private: | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	void parseThemes(const QVector<MTPTheme> &list); | 	void parseThemes(const QVector<MTPTheme> &list); | ||||||
|  | 	void checkCurrentTheme(); | ||||||
| 
 | 
 | ||||||
| 	void install(); | 	void install(); | ||||||
| 	void setupReload(); | 	void setupReload(); | ||||||
|  |  | ||||||
|  | @ -259,13 +259,20 @@ bool loadBackground(zlib::FileToRead &file, QByteArray *outBackground, bool *out | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool loadTheme( | bool LoadTheme( | ||||||
| 		const QByteArray &content, | 		const QByteArray &content, | ||||||
| 		const std::optional<QByteArray> &editedPalette, |  | ||||||
| 		Cached &cache, |  | ||||||
| 		const Colorizer &colorizer, | 		const Colorizer &colorizer, | ||||||
|  | 		const std::optional<QByteArray> &editedPalette, | ||||||
|  | 		Cached *cache = nullptr, | ||||||
| 		Instance *out = nullptr) { | 		Instance *out = nullptr) { | ||||||
| 	cache = Cached(); | 	if (content.size() < 4) { | ||||||
|  | 		LOG(("Theme Error: Bad theme content size: %1").arg(content.size())); | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (cache) { | ||||||
|  | 		*cache = Cached(); | ||||||
|  | 	} | ||||||
| 	zlib::FileToRead file(content); | 	zlib::FileToRead file(content); | ||||||
| 
 | 
 | ||||||
| 	const auto emptyColorizer = Colorizer(); | 	const auto emptyColorizer = Colorizer(); | ||||||
|  | @ -289,7 +296,9 @@ bool loadTheme( | ||||||
| 		if (!loadColorScheme(schemeContent, paletteColorizer, out)) { | 		if (!loadColorScheme(schemeContent, paletteColorizer, out)) { | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 		Background()->saveAdjustableColors(); | 		if (!out) { | ||||||
|  | 			Background()->saveAdjustableColors(); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		auto backgroundTiled = false; | 		auto backgroundTiled = false; | ||||||
| 		auto backgroundContent = QByteArray(); | 		auto backgroundContent = QByteArray(); | ||||||
|  | @ -314,30 +323,37 @@ bool loadTheme( | ||||||
| 			if (colorizer) { | 			if (colorizer) { | ||||||
| 				Colorize(background, colorizer); | 				Colorize(background, colorizer); | ||||||
| 			} | 			} | ||||||
| 			auto buffer = QBuffer(&cache.background); | 			if (cache) { | ||||||
| 			if (!background.save(&buffer, "BMP")) { | 				auto buffer = QBuffer(&cache->background); | ||||||
| 				LOG(("Theme Error: could not write background image as a BMP to cache.")); | 				if (!background.save(&buffer, "BMP")) { | ||||||
| 				return false; | 					LOG(("Theme Error: could not write background image as a BMP to cache.")); | ||||||
|  | 					return false; | ||||||
|  | 				} | ||||||
|  | 				cache->tiled = backgroundTiled; | ||||||
| 			} | 			} | ||||||
| 			cache.tiled = backgroundTiled; | 			applyBackground(std::move(background), backgroundTiled, out); | ||||||
| 
 |  | ||||||
| 			applyBackground(std::move(background), cache.tiled, out); |  | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		// Looks like it is not a .zip theme.
 | 		// Looks like it is not a .zip theme.
 | ||||||
| 		if (!loadColorScheme(editedPalette.value_or(content), paletteColorizer, out)) { | 		if (!loadColorScheme(editedPalette.value_or(content), paletteColorizer, out)) { | ||||||
| 			return false; | 			return false; | ||||||
| 		} | 		} | ||||||
| 		Background()->saveAdjustableColors(); | 		if (!out) { | ||||||
|  | 			Background()->saveAdjustableColors(); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	if (out) { | 	if (out) { | ||||||
| 		cache.colors = out->palette.save(); | 		out->palette.finalize(); | ||||||
| 	} else { | 	} | ||||||
| 		cache.colors = style::main_palette::save(); | 	if (cache) { | ||||||
|  | 		if (out) { | ||||||
|  | 			cache->colors = out->palette.save(); | ||||||
|  | 		} else { | ||||||
|  | 			cache->colors = style::main_palette::save(); | ||||||
|  | 		} | ||||||
|  | 		cache->paletteChecksum = style::palette::Checksum(); | ||||||
|  | 		cache->contentChecksum = hashCrc32(content.constData(), content.size()); | ||||||
| 	} | 	} | ||||||
| 	cache.paletteChecksum = style::palette::Checksum(); |  | ||||||
| 	cache.contentChecksum = hashCrc32(content.constData(), content.size()); |  | ||||||
| 
 |  | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -396,7 +412,7 @@ bool InitializeFromSaved(Saved &&saved) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	const auto colorizer = ColorizerForTheme(saved.object.pathAbsolute); | 	const auto colorizer = ColorizerForTheme(saved.object.pathAbsolute); | ||||||
| 	if (!loadTheme(saved.object.content, editing, saved.cache, colorizer)) { | 	if (!LoadTheme(saved.object.content, colorizer, editing, &saved.cache)) { | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 	if (editing) { | 	if (editing) { | ||||||
|  | @ -1046,11 +1062,11 @@ void ChatBackground::reapplyWithNightMode( | ||||||
| 		auto preview = std::make_unique<Preview>(); | 		auto preview = std::make_unique<Preview>(); | ||||||
| 		preview->object = std::move(read.object); | 		preview->object = std::move(read.object); | ||||||
| 		preview->instance.cached = std::move(read.cache); | 		preview->instance.cached = std::move(read.cache); | ||||||
| 		const auto loaded = loadTheme( | 		const auto loaded = LoadTheme( | ||||||
| 			preview->object.content, | 			preview->object.content, | ||||||
| 			std::nullopt, |  | ||||||
| 			preview->instance.cached, |  | ||||||
| 			ColorizerForTheme(path), | 			ColorizerForTheme(path), | ||||||
|  | 			std::nullopt, | ||||||
|  | 			&preview->instance.cached, | ||||||
| 			&preview->instance); | 			&preview->instance); | ||||||
| 		if (!loaded) { | 		if (!loaded) { | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -1252,28 +1268,21 @@ void ResetToSomeDefault() { | ||||||
| 		IsNightMode()); | 		IsNightMode()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool LoadFromContent( |  | ||||||
| 		const QByteArray &content, |  | ||||||
| 		not_null<Instance*> out, |  | ||||||
| 		const Colorizer &colorizer) { |  | ||||||
| 	if (content.size() < 4) { |  | ||||||
| 		LOG(("Theme Error: Bad theme content size: %1").arg(content.size())); |  | ||||||
| 		return false; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return loadTheme(content, std::nullopt, out->cached, colorizer, out); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool LoadFromFile( | bool LoadFromFile( | ||||||
| 		const QString &path, | 		const QString &path, | ||||||
| 		not_null<Instance*> out, | 		not_null<Instance*> out, | ||||||
|  | 		Cached *outCache, | ||||||
| 		not_null<QByteArray*> outContent) { | 		not_null<QByteArray*> outContent) { | ||||||
| 	*outContent = readThemeContent(path); | 	*outContent = readThemeContent(path); | ||||||
| 	return LoadFromContent(*outContent, out, ColorizerForTheme(path)); | 	const auto colorizer = ColorizerForTheme(path); | ||||||
|  | 	return LoadTheme(*outContent, colorizer, std::nullopt, outCache, out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool LoadFromContent(const QByteArray &content, not_null<Instance*> out) { | bool LoadFromContent( | ||||||
| 	return LoadFromContent(content, out, {}); | 		const QByteArray &content, | ||||||
|  | 		not_null<Instance*> out, | ||||||
|  | 		Cached *outCache) { | ||||||
|  | 	return LoadTheme(content, Colorizer(), std::nullopt, outCache, out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| QString EditingPalettePath() { | QString EditingPalettePath() { | ||||||
|  |  | ||||||
|  | @ -84,8 +84,12 @@ void Revert(); | ||||||
| bool LoadFromFile( | bool LoadFromFile( | ||||||
| 	const QString &file, | 	const QString &file, | ||||||
| 	not_null<Instance*> out, | 	not_null<Instance*> out, | ||||||
|  | 	Cached *outCache, | ||||||
| 	not_null<QByteArray*> outContent); | 	not_null<QByteArray*> outContent); | ||||||
| bool LoadFromContent(const QByteArray &content, not_null<Instance*> out); | bool LoadFromContent( | ||||||
|  | 	const QByteArray &content, | ||||||
|  | 	not_null<Instance*> out, | ||||||
|  | 	Cached *outCache); | ||||||
| QColor CountAverageColor(const QImage &image); | QColor CountAverageColor(const QImage &image); | ||||||
| QColor AdjustedColor(QColor original, QColor background); | QColor AdjustedColor(QColor original, QColor background); | ||||||
| QImage ProcessBackgroundImage(QImage image); | QImage ProcessBackgroundImage(QImage image); | ||||||
|  |  | ||||||
|  | @ -925,13 +925,15 @@ std::unique_ptr<Preview> PreviewFromFile( | ||||||
| 	object.pathRelative = filepath.isEmpty() | 	object.pathRelative = filepath.isEmpty() | ||||||
| 		? object.pathAbsolute | 		? object.pathAbsolute | ||||||
| 		: QDir().relativeFilePath(filepath); | 		: QDir().relativeFilePath(filepath); | ||||||
|  | 	const auto instance = &result->instance; | ||||||
|  | 	const auto cache = &result->instance.cached; | ||||||
| 	if (bytes.isEmpty()) { | 	if (bytes.isEmpty()) { | ||||||
| 		if (!LoadFromFile(filepath, &result->instance, &object.content)) { | 		if (!LoadFromFile(filepath, instance, cache, &object.content)) { | ||||||
| 			return nullptr; | 			return nullptr; | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		object.content = bytes; | 		object.content = bytes; | ||||||
| 		if (!LoadFromContent(bytes, &result->instance)) { | 		if (!LoadFromContent(bytes, instance, cache)) { | ||||||
| 			return nullptr; | 			return nullptr; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -91,7 +91,7 @@ constexpr auto kShowPerRow = 4; | ||||||
| 		return std::nullopt; | 		return std::nullopt; | ||||||
| 	} | 	} | ||||||
| 	auto instance = Instance(); | 	auto instance = Instance(); | ||||||
| 	if (!LoadFromContent(content, &instance)) { | 	if (!LoadFromContent(content, &instance, nullptr)) { | ||||||
| 		return std::nullopt; | 		return std::nullopt; | ||||||
| 	} | 	} | ||||||
| 	auto result = CloudListColors(); | 	auto result = CloudListColors(); | ||||||
|  | @ -519,10 +519,16 @@ void CloudList::refreshElementUsing( | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CloudList::refreshColors(Element &element) { | void CloudList::refreshColors(Element &element) { | ||||||
| 	if (element.id() == kFakeCloudThemeId) { | 	const auto currentId = Background()->themeObject().cloud.id; | ||||||
|  | 	const auto documentId = element.theme.documentId; | ||||||
|  | 	const auto document = documentId | ||||||
|  | 		? _window->session().data().document(documentId).get() | ||||||
|  | 		: nullptr; | ||||||
|  | 	if (element.id() == kFakeCloudThemeId | ||||||
|  | 		|| ((element.id() == currentId) | ||||||
|  | 			&& (!document || !document->isTheme()))) { | ||||||
| 		element.check->setColors(ColorsFromCurrentTheme()); | 		element.check->setColors(ColorsFromCurrentTheme()); | ||||||
| 	} else if (const auto documentId = element.theme.documentId) { | 	} else if (document) { | ||||||
| 		const auto document = _window->session().data().document(documentId); |  | ||||||
| 		document->save(Data::FileOrigin(), QString()); // #TODO themes
 | 		document->save(Data::FileOrigin(), QString()); // #TODO themes
 | ||||||
| 		if (document->loaded()) { | 		if (document->loaded()) { | ||||||
| 			refreshColorsFromDocument(element, document); | 			refreshColorsFromDocument(element, document); | ||||||
|  | @ -598,17 +604,26 @@ bool CloudList::amCreator(const Data::CloudTheme &theme) const { | ||||||
| void CloudList::refreshColorsFromDocument( | void CloudList::refreshColorsFromDocument( | ||||||
| 		Element &element, | 		Element &element, | ||||||
| 		not_null<DocumentData*> document) { | 		not_null<DocumentData*> document) { | ||||||
| 	auto colors = ColorsFromTheme( | 	const auto id = element.id(); | ||||||
| 		document->filepath(), | 	const auto path = document->filepath(); | ||||||
| 		document->data()); | 	const auto data = document->data(); | ||||||
| 	if (!colors) { | 	crl::async([=, guard = element.generating.make_guard()]() mutable { | ||||||
| 		return; | 		crl::on_main(std::move(guard), [ | ||||||
| 	} | 			=, | ||||||
| 	if (colors->background.isNull()) { | 			result = ColorsFromTheme(path, data) | ||||||
| 		colors->background = ColorsFromCurrentTheme().background; | 		]() mutable { | ||||||
| 	} | 			const auto i = ranges::find(_elements, id, &Element::id); | ||||||
| 	element.check->setColors(*colors); | 			if (i == end(_elements) || !result) { | ||||||
| 	setWaiting(element, false); | 				return; | ||||||
|  | 			} | ||||||
|  | 			auto &element = *i; | ||||||
|  | 			if (result->background.isNull()) { | ||||||
|  | 				result->background = ColorsFromCurrentTheme().background; | ||||||
|  | 			} | ||||||
|  | 			element.check->setColors(*result); | ||||||
|  | 			setWaiting(element, false); | ||||||
|  | 		}); | ||||||
|  | 	}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CloudList::subscribeToDownloadFinished() { | void CloudList::subscribeToDownloadFinished() { | ||||||
|  |  | ||||||
|  | @ -86,6 +86,7 @@ private: | ||||||
| 		Data::CloudTheme theme; | 		Data::CloudTheme theme; | ||||||
| 		not_null<CloudListCheck*> check; | 		not_null<CloudListCheck*> check; | ||||||
| 		std::unique_ptr<Ui::Radiobutton> button; | 		std::unique_ptr<Ui::Radiobutton> button; | ||||||
|  | 		base::binary_guard generating; | ||||||
| 		bool waiting = false; | 		bool waiting = false; | ||||||
| 
 | 
 | ||||||
| 		uint64 id() const { | 		uint64 id() const { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 John Preston
						John Preston