Generate previews async in cloud themes list.

This commit is contained in:
John Preston 2019-09-09 09:59:57 +03:00
parent 048658f838
commit eebcdb842d
7 changed files with 100 additions and 56 deletions

View file

@ -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 {

View file

@ -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();

View file

@ -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;
} }
if (!out) {
Background()->saveAdjustableColors(); 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) {
auto buffer = QBuffer(&cache->background);
if (!background.save(&buffer, "BMP")) { if (!background.save(&buffer, "BMP")) {
LOG(("Theme Error: could not write background image as a BMP to cache.")); LOG(("Theme Error: could not write background image as a BMP to cache."));
return false; return false;
} }
cache.tiled = backgroundTiled; cache->tiled = backgroundTiled;
}
applyBackground(std::move(background), cache.tiled, out); applyBackground(std::move(background), backgroundTiled, 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;
} }
if (!out) {
Background()->saveAdjustableColors(); Background()->saveAdjustableColors();
} }
if (out) {
cache.colors = out->palette.save();
} else {
cache.colors = style::main_palette::save();
} }
cache.paletteChecksum = style::palette::Checksum(); if (out) {
cache.contentChecksum = hashCrc32(content.constData(), content.size()); out->palette.finalize();
}
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());
}
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() {

View file

@ -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);

View file

@ -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;
} }
} }

View file

@ -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 {
crl::on_main(std::move(guard), [
=,
result = ColorsFromTheme(path, data)
]() mutable {
const auto i = ranges::find(_elements, id, &Element::id);
if (i == end(_elements) || !result) {
return; return;
} }
if (colors->background.isNull()) { auto &element = *i;
colors->background = ColorsFromCurrentTheme().background; if (result->background.isNull()) {
result->background = ColorsFromCurrentTheme().background;
} }
element.check->setColors(*colors); element.check->setColors(*result);
setWaiting(element, false); setWaiting(element, false);
});
});
} }
void CloudList::subscribeToDownloadFinished() { void CloudList::subscribeToDownloadFinished() {

View file

@ -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 {