2
0
mirror of https://github.com/kotatogram/kotatogram-desktop synced 2025-08-31 06:35:14 +00:00

Move background to global settings.

This commit is contained in:
John Preston
2020-06-19 19:14:55 +04:00
parent 5433c16244
commit 2635ca33f8
16 changed files with 359 additions and 264 deletions

View File

@@ -43,6 +43,11 @@ namespace {
constexpr auto kThemeFileSizeLimit = 5 * 1024 * 1024;
constexpr auto kFileLoaderQueueStopTimeout = crl::time(5000);
constexpr auto kSavedBackgroundFormat = QImage::Format_ARGB32_Premultiplied;
constexpr auto kWallPaperLegacySerializeTagId = int32(-111);
constexpr auto kWallPaperSerializeTagId = int32(-112);
constexpr auto kWallPaperSidesLimit = 10'000;
const auto kThemeNewPathRelativeTag = qstr("special://new_tag");
using namespace Storage::details;
@@ -70,7 +75,14 @@ FileKey _themeKeyLegacy = 0;
FileKey _langPackKey = 0;
FileKey _languagesKey = 0;
FileKey _backgroundKeyDay = 0;
FileKey _backgroundKeyNight = 0;
bool _useGlobalBackgroundKeys = false;
bool _backgroundCanWrite = true;
bool _backgroundMigrated = false;
int32 _oldSettingsVersion = 0;
bool _settingsRewritten;
enum class WriteMapWhen {
Now,
@@ -120,8 +132,16 @@ void applyReadContext(ReadSettingsContext &&context) {
_themeKeyLegacy = context.themeKeyLegacy;
_themeKeyDay = context.themeKeyDay;
_themeKeyNight = context.themeKeyNight;
_backgroundKeyDay = context.backgroundKeyDay;
_backgroundKeyNight = context.backgroundKeyNight;
_useGlobalBackgroundKeys = context.backgroundKeysRead;
_langPackKey = context.langPackKey;
_languagesKey = context.languagesKey;
if (context.tileRead && _useGlobalBackgroundKeys) {
Window::Theme::Background()->setTileDayValue(context.tileDay);
Window::Theme::Background()->setTileNightValue(context.tileNight);
}
}
bool _readOldSettings(bool remove, ReadSettingsContext &context) {
@@ -436,6 +456,7 @@ void writeSettings() {
// Theme keys and night mode.
size += sizeof(quint32) + sizeof(quint64) * 2 + sizeof(quint32);
size += sizeof(quint32) + sizeof(quint64) * 2;
if (_langPackKey) {
size += sizeof(quint32) + sizeof(quint64);
}
@@ -471,6 +492,16 @@ void writeSettings() {
<< quint64(_themeKeyDay)
<< quint64(_themeKeyNight)
<< quint32(Window::Theme::IsNightMode() ? 1 : 0);
if (_useGlobalBackgroundKeys) {
data.stream
<< quint32(dbiBackgroundKey)
<< quint64(_backgroundKeyDay)
<< quint64(_backgroundKeyNight);
data.stream
<< quint32(dbiTileBackground)
<< qint32(Window::Theme::Background()->tileDay() ? 1 : 0)
<< qint32(Window::Theme::Background()->tileNight() ? 1 : 0);
}
if (_langPackKey) {
data.stream << quint32(dbiLangPackKey) << quint64(_langPackKey);
}
@@ -487,6 +518,15 @@ void writeSettings() {
settings.writeEncrypted(data, SettingsKey);
}
void rewriteSettingsIfNeeded() {
if (_settingsRewritten
|| (_oldSettingsVersion == AppVersion && !_backgroundMigrated)) {
return;
}
_settingsRewritten = true;
writeSettings();
}
const QString &AutoupdatePrefix(const QString &replaceWith = {}) {
Expects(!Core::UpdaterDisabled());
@@ -547,6 +587,207 @@ QString readAutoupdatePrefix() {
return result.replace(QRegularExpression("/+$"), QString());
}
void writeBackground(const Data::WallPaper &paper, const QImage &image) {
if (!_backgroundCanWrite) {
return;
}
_useGlobalBackgroundKeys = true;
auto &backgroundKey = Window::Theme::IsNightMode()
? _backgroundKeyNight
: _backgroundKeyDay;
auto imageData = QByteArray();
if (!image.isNull()) {
const auto width = qint32(image.width());
const auto height = qint32(image.height());
const auto perpixel = (image.depth() >> 3);
const auto srcperline = image.bytesPerLine();
const auto srcsize = srcperline * height;
const auto dstperline = width * perpixel;
const auto dstsize = dstperline * height;
const auto copy = (image.format() != kSavedBackgroundFormat)
? image.convertToFormat(kSavedBackgroundFormat)
: image;
imageData.resize(2 * sizeof(qint32) + dstsize);
auto dst = bytes::make_detached_span(imageData);
bytes::copy(dst, bytes::object_as_span(&width));
dst = dst.subspan(sizeof(qint32));
bytes::copy(dst, bytes::object_as_span(&height));
dst = dst.subspan(sizeof(qint32));
const auto src = bytes::make_span(image.constBits(), srcsize);
if (srcsize == dstsize) {
bytes::copy(dst, src);
} else {
for (auto y = 0; y != height; ++y) {
bytes::copy(dst, src.subspan(y * srcperline, dstperline));
dst = dst.subspan(dstperline);
}
}
}
if (!backgroundKey) {
backgroundKey = GenerateKey(_basePath);
writeSettings();
}
const auto serialized = paper.serialize();
quint32 size = sizeof(qint32)
+ Serialize::bytearraySize(serialized)
+ Serialize::bytearraySize(imageData);
EncryptedDescriptor data(size);
data.stream
<< qint32(kWallPaperSerializeTagId)
<< serialized
<< imageData;
FileWriteDescriptor file(backgroundKey, _basePath);
file.writeEncrypted(data, SettingsKey);
}
bool readBackground() {
FileReadDescriptor bg;
auto &backgroundKey = Window::Theme::IsNightMode()
? _backgroundKeyNight
: _backgroundKeyDay;
if (!ReadEncryptedFile(bg, backgroundKey, _basePath, SettingsKey)) {
if (backgroundKey) {
ClearKey(backgroundKey, _basePath);
backgroundKey = 0;
writeSettings();
}
return false;
}
qint32 legacyId = 0;
bg.stream >> legacyId;
const auto paper = [&] {
if (legacyId == kWallPaperLegacySerializeTagId) {
quint64 id = 0;
quint64 accessHash = 0;
quint32 flags = 0;
QString slug;
bg.stream
>> id
>> accessHash
>> flags
>> slug;
return Data::WallPaper::FromLegacySerialized(
id,
accessHash,
flags,
slug);
} else if (legacyId == kWallPaperSerializeTagId) {
QByteArray serialized;
bg.stream >> serialized;
return Data::WallPaper::FromSerialized(serialized);
} else {
return Data::WallPaper::FromLegacyId(legacyId);
}
}();
if (bg.stream.status() != QDataStream::Ok || !paper) {
return false;
}
QByteArray imageData;
bg.stream >> imageData;
const auto isOldEmptyImage = (bg.stream.status() != QDataStream::Ok);
if (isOldEmptyImage
|| Data::IsLegacy1DefaultWallPaper(*paper)
|| Data::IsDefaultWallPaper(*paper)) {
_backgroundCanWrite = false;
if (isOldEmptyImage || bg.version < 8005) {
Window::Theme::Background()->set(Data::DefaultWallPaper());
Window::Theme::Background()->setTile(false);
} else {
Window::Theme::Background()->set(*paper);
}
_backgroundCanWrite = true;
return true;
} else if (Data::IsThemeWallPaper(*paper) && imageData.isEmpty()) {
_backgroundCanWrite = false;
Window::Theme::Background()->set(*paper);
_backgroundCanWrite = true;
return true;
}
auto image = QImage();
if (legacyId == kWallPaperSerializeTagId) {
const auto perpixel = 4;
auto src = bytes::make_span(imageData);
auto width = qint32();
auto height = qint32();
if (src.size() > 2 * sizeof(qint32)) {
bytes::copy(
bytes::object_as_span(&width),
src.subspan(0, sizeof(qint32)));
src = src.subspan(sizeof(qint32));
bytes::copy(
bytes::object_as_span(&height),
src.subspan(0, sizeof(qint32)));
src = src.subspan(sizeof(qint32));
if (width + height <= kWallPaperSidesLimit
&& src.size() == width * height * perpixel) {
image = QImage(
width,
height,
QImage::Format_ARGB32_Premultiplied);
if (!image.isNull()) {
const auto srcperline = width * perpixel;
const auto srcsize = srcperline * height;
const auto dstperline = image.bytesPerLine();
const auto dstsize = dstperline * height;
Assert(srcsize == dstsize);
bytes::copy(
bytes::make_span(image.bits(), dstsize),
src);
}
}
}
} else {
auto buffer = QBuffer(&imageData);
auto reader = QImageReader(&buffer);
#ifndef OS_MAC_OLD
reader.setAutoTransform(true);
#endif // OS_MAC_OLD
if (!reader.read(&image)) {
image = QImage();
}
}
if (!image.isNull() || paper->backgroundColor()) {
_backgroundCanWrite = false;
Window::Theme::Background()->set(*paper, std::move(image));
_backgroundCanWrite = true;
return true;
}
return false;
}
void moveLegacyBackground(
const QString &fromBasePath,
const MTP::AuthKeyPtr &fromLocalKey,
uint64 legacyBackgroundKeyDay,
uint64 legacyBackgroundKeyNight) {
if (_useGlobalBackgroundKeys
|| (!legacyBackgroundKeyDay && !legacyBackgroundKeyNight)) {
return;
}
const auto move = [&](uint64 from, FileKey &to) {
if (!from || to) {
return;
}
to = GenerateKey(_basePath);
FileReadDescriptor read;
if (!ReadEncryptedFile(read, from, fromBasePath, fromLocalKey)) {
return;
}
EncryptedDescriptor data;
data.data = read.data;
FileWriteDescriptor write(to, _basePath);
write.writeEncrypted(data, SettingsKey);
};
move(legacyBackgroundKeyDay, _backgroundKeyDay);
move(legacyBackgroundKeyNight, _backgroundKeyNight);
_backgroundMigrated = true;
}
void reset() {
if (_localLoader) {
_localLoader->stop();