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."));
});
}
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 {

View File

@ -56,6 +56,7 @@ private:
};
void parseThemes(const QVector<MTPTheme> &list);
void checkCurrentTheme();
void install();
void setupReload();

View File

@ -259,13 +259,20 @@ bool loadBackground(zlib::FileToRead &file, QByteArray *outBackground, bool *out
return true;
}
bool loadTheme(
bool LoadTheme(
const QByteArray &content,
const std::optional<QByteArray> &editedPalette,
Cached &cache,
const Colorizer &colorizer,
const std::optional<QByteArray> &editedPalette,
Cached *cache = 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);
const auto emptyColorizer = Colorizer();
@ -289,7 +296,9 @@ bool loadTheme(
if (!loadColorScheme(schemeContent, paletteColorizer, out)) {
return false;
}
Background()->saveAdjustableColors();
if (!out) {
Background()->saveAdjustableColors();
}
auto backgroundTiled = false;
auto backgroundContent = QByteArray();
@ -314,30 +323,37 @@ bool loadTheme(
if (colorizer) {
Colorize(background, colorizer);
}
auto buffer = QBuffer(&cache.background);
if (!background.save(&buffer, "BMP")) {
LOG(("Theme Error: could not write background image as a BMP to cache."));
return false;
if (cache) {
auto buffer = QBuffer(&cache->background);
if (!background.save(&buffer, "BMP")) {
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), cache.tiled, out);
applyBackground(std::move(background), backgroundTiled, out);
}
} else {
// Looks like it is not a .zip theme.
if (!loadColorScheme(editedPalette.value_or(content), paletteColorizer, out)) {
return false;
}
Background()->saveAdjustableColors();
if (!out) {
Background()->saveAdjustableColors();
}
}
if (out) {
cache.colors = out->palette.save();
} else {
cache.colors = style::main_palette::save();
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());
}
cache.paletteChecksum = style::palette::Checksum();
cache.contentChecksum = hashCrc32(content.constData(), content.size());
return true;
}
@ -396,7 +412,7 @@ bool InitializeFromSaved(Saved &&saved) {
}
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;
}
if (editing) {
@ -1046,11 +1062,11 @@ void ChatBackground::reapplyWithNightMode(
auto preview = std::make_unique<Preview>();
preview->object = std::move(read.object);
preview->instance.cached = std::move(read.cache);
const auto loaded = loadTheme(
const auto loaded = LoadTheme(
preview->object.content,
std::nullopt,
preview->instance.cached,
ColorizerForTheme(path),
std::nullopt,
&preview->instance.cached,
&preview->instance);
if (!loaded) {
return false;
@ -1252,28 +1268,21 @@ void ResetToSomeDefault() {
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(
const QString &path,
not_null<Instance*> out,
Cached *outCache,
not_null<QByteArray*> outContent) {
*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) {
return LoadFromContent(content, out, {});
bool LoadFromContent(
const QByteArray &content,
not_null<Instance*> out,
Cached *outCache) {
return LoadTheme(content, Colorizer(), std::nullopt, outCache, out);
}
QString EditingPalettePath() {

View File

@ -84,8 +84,12 @@ void Revert();
bool LoadFromFile(
const QString &file,
not_null<Instance*> out,
Cached *outCache,
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 AdjustedColor(QColor original, QColor background);
QImage ProcessBackgroundImage(QImage image);

View File

@ -925,13 +925,15 @@ std::unique_ptr<Preview> PreviewFromFile(
object.pathRelative = filepath.isEmpty()
? object.pathAbsolute
: QDir().relativeFilePath(filepath);
const auto instance = &result->instance;
const auto cache = &result->instance.cached;
if (bytes.isEmpty()) {
if (!LoadFromFile(filepath, &result->instance, &object.content)) {
if (!LoadFromFile(filepath, instance, cache, &object.content)) {
return nullptr;
}
} else {
object.content = bytes;
if (!LoadFromContent(bytes, &result->instance)) {
if (!LoadFromContent(bytes, instance, cache)) {
return nullptr;
}
}

View File

@ -91,7 +91,7 @@ constexpr auto kShowPerRow = 4;
return std::nullopt;
}
auto instance = Instance();
if (!LoadFromContent(content, &instance)) {
if (!LoadFromContent(content, &instance, nullptr)) {
return std::nullopt;
}
auto result = CloudListColors();
@ -519,10 +519,16 @@ void CloudList::refreshElementUsing(
}
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());
} else if (const auto documentId = element.theme.documentId) {
const auto document = _window->session().data().document(documentId);
} else if (document) {
document->save(Data::FileOrigin(), QString()); // #TODO themes
if (document->loaded()) {
refreshColorsFromDocument(element, document);
@ -598,17 +604,26 @@ bool CloudList::amCreator(const Data::CloudTheme &theme) const {
void CloudList::refreshColorsFromDocument(
Element &element,
not_null<DocumentData*> document) {
auto colors = ColorsFromTheme(
document->filepath(),
document->data());
if (!colors) {
return;
}
if (colors->background.isNull()) {
colors->background = ColorsFromCurrentTheme().background;
}
element.check->setColors(*colors);
setWaiting(element, false);
const auto id = element.id();
const auto path = document->filepath();
const auto data = document->data();
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;
}
auto &element = *i;
if (result->background.isNull()) {
result->background = ColorsFromCurrentTheme().background;
}
element.check->setColors(*result);
setWaiting(element, false);
});
});
}
void CloudList::subscribeToDownloadFinished() {

View File

@ -86,6 +86,7 @@ private:
Data::CloudTheme theme;
not_null<CloudListCheck*> check;
std::unique_ptr<Ui::Radiobutton> button;
base::binary_guard generating;
bool waiting = false;
uint64 id() const {