diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 0a0df1e1f0..c4a5eb26f7 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -2896,8 +2896,12 @@ void ApiWrap::refreshFileReference( MTPmessages_GetSavedGifs(MTP_int(0)), [=] { crl::on_main(_session, [=] { local().writeSavedGifs(); }); }); }, [&](Data::FileOriginWallpaper data) { - request(MTPaccount_GetWallPaper( - MTP_inputWallPaper( + const auto useSlug = data.ownerId + && (data.ownerId != session().userId()) + && !data.slug.isEmpty(); + request(MTPaccount_GetWallPaper(useSlug + ? MTP_inputWallPaperSlug(MTP_string(data.slug)) + : MTP_inputWallPaper( MTP_long(data.paperId), MTP_long(data.accessHash)))); }, [&](Data::FileOriginTheme data) { diff --git a/Telegram/SourceFiles/boxes/background_box.cpp b/Telegram/SourceFiles/boxes/background_box.cpp index 9ead668bb8..7f47d003a4 100644 --- a/Telegram/SourceFiles/boxes/background_box.cpp +++ b/Telegram/SourceFiles/boxes/background_box.cpp @@ -174,7 +174,7 @@ void BackgroundBox::removePaper(const Data::WallPaper &paper) { } session->data().removeWallpaper(paper); session->api().request(MTPaccount_SaveWallPaper( - paper.mtpInput(), + paper.mtpInput(session), MTP_bool(true), paper.mtpSettings() )).send(); diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp index 4d0a4c9937..fd63f3891e 100644 --- a/Telegram/SourceFiles/boxes/background_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp @@ -506,7 +506,7 @@ void BackgroundPreviewBox::apply() { _controller->content()->setChatBackground(_paper, std::move(_full)); if (install) { _controller->session().api().request(MTPaccount_InstallWallPaper( - _paper.mtpInput(), + _paper.mtpInput(&_controller->session()), _paper.mtpSettings() )).send(); } diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index 64c113fbe0..9305a5cc5a 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/send_files_box.h" #include "ui/widgets/input_fields.h" #include "storage/serialize_common.h" +#include "window/themes/window_theme.h" #include "facades.h" namespace Core { @@ -87,8 +88,9 @@ QByteArray Settings::serialize() const { stream << quint64(i); } stream - << qint32(_autoDownloadDictionaries.current() ? 1 : 0); - + << qint32(_autoDownloadDictionaries.current() ? 1 : 0) + << qint32(Window::Theme::Background()->tileDay() ? 1 : 0) + << qint32(Window::Theme::Background()->tileNight() ? 1 : 0); } return result; } diff --git a/Telegram/SourceFiles/data/data_file_origin.h b/Telegram/SourceFiles/data/data_file_origin.h index 6c8a0d5f7c..60936abe79 100644 --- a/Telegram/SourceFiles/data/data_file_origin.h +++ b/Telegram/SourceFiles/data/data_file_origin.h @@ -61,13 +61,21 @@ struct FileOriginSavedGifs { }; struct FileOriginWallpaper { - FileOriginWallpaper(uint64 paperId, uint64 accessHash) + FileOriginWallpaper( + uint64 paperId, + uint64 accessHash, + UserId ownerId, + const QString &slug) : paperId(paperId) - , accessHash(accessHash) { + , accessHash(accessHash) + , ownerId(ownerId) + , slug(slug) { } uint64 paperId = 0; uint64 accessHash = 0; + UserId ownerId = 0; + QString slug; inline bool operator<(const FileOriginWallpaper &other) const { return paperId < other.paperId; diff --git a/Telegram/SourceFiles/data/data_wall_paper.cpp b/Telegram/SourceFiles/data/data_wall_paper.cpp index e8437169c2..caa8fc5ec7 100644 --- a/Telegram/SourceFiles/data/data_wall_paper.cpp +++ b/Telegram/SourceFiles/data/data_wall_paper.cpp @@ -196,11 +196,17 @@ void WallPaper::loadDocument() const { } FileOrigin WallPaper::fileOrigin() const { - return FileOriginWallpaper(_id, _accessHash); + return FileOriginWallpaper(_id, _accessHash, _ownerId, _slug); } -MTPInputWallPaper WallPaper::mtpInput() const { - return MTP_inputWallPaper(MTP_long(_id), MTP_long(_accessHash)); +UserId WallPaper::ownerId() const { + return _ownerId; +} + +MTPInputWallPaper WallPaper::mtpInput(not_null session) const { + return (_ownerId && _ownerId != session->userId() && !_slug.isEmpty()) + ? MTP_inputWallPaperSlug(MTP_string(_slug)) + : MTP_inputWallPaper(MTP_long(_id), MTP_long(_accessHash)); } MTPWallPaperSettings WallPaper::mtpSettings() const { @@ -324,6 +330,7 @@ std::optional WallPaper::Create( } auto result = WallPaper(data.vid().v); result._accessHash = data.vaccess_hash().v; + result._ownerId = session->userId(); result._flags = data.vflags().v; result._slug = qs(data.vslug()); result._document = document; @@ -372,7 +379,8 @@ QByteArray WallPaper::serialize() const { << _slug << qint32(_settings) << SerializeMaybeColor(_backgroundColor) - << qint32(_intensity); + << qint32(_intensity) + << qint32(_ownerId); } return result; } @@ -385,6 +393,7 @@ std::optional WallPaper::FromSerialized( auto id = quint64(); auto accessHash = quint64(); + auto ownerId = qint32(); auto flags = qint32(); auto slug = QString(); auto settings = qint32(); @@ -401,6 +410,9 @@ std::optional WallPaper::FromSerialized( >> settings >> backgroundColor >> intensity; + if (!stream.atEnd()) { + stream >> ownerId; + } if (stream.status() != QDataStream::Ok) { return std::nullopt; } else if (intensity < 0 || intensity > 100) { @@ -408,6 +420,7 @@ std::optional WallPaper::FromSerialized( } auto result = WallPaper(id); result._accessHash = accessHash; + result._ownerId = ownerId; result._flags = MTPDwallPaper::Flags::from_raw(flags); result._slug = slug; result._settings = MTPDwallPaperSettings::Flags::from_raw(settings); diff --git a/Telegram/SourceFiles/data/data_wall_paper.h b/Telegram/SourceFiles/data/data_wall_paper.h index 98957c78e7..72147d02b9 100644 --- a/Telegram/SourceFiles/data/data_wall_paper.h +++ b/Telegram/SourceFiles/data/data_wall_paper.h @@ -41,7 +41,9 @@ public: void loadDocumentThumbnail() const; [[nodiscard]] FileOrigin fileOrigin() const; - [[nodiscard]] MTPInputWallPaper mtpInput() const; + [[nodiscard]] UserId ownerId() const; + [[nodiscard]] MTPInputWallPaper mtpInput( + not_null session) const; [[nodiscard]] MTPWallPaperSettings mtpSettings() const; [[nodiscard]] WallPaper withUrlParams( @@ -77,6 +79,7 @@ private: WallPaperId _id = WallPaperId(); uint64 _accessHash = 0; + UserId _ownerId = 0; MTPDwallPaper::Flags _flags; QString _slug; diff --git a/Telegram/SourceFiles/main/main_domain.cpp b/Telegram/SourceFiles/main/main_domain.cpp index ce9457fdcd..12c923237e 100644 --- a/Telegram/SourceFiles/main/main_domain.cpp +++ b/Telegram/SourceFiles/main/main_domain.cpp @@ -38,9 +38,7 @@ Storage::StartResult Domain::start(const QByteArray &passcode) { const auto result = _local->start(passcode); if (result == Storage::StartResult::Success) { activateAfterStarting(); - if (Local::oldSettingsVersion() < AppVersion) { - Local::writeSettings(); - } + Local::rewriteSettingsIfNeeded(); } else { Assert(!started()); } diff --git a/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp b/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp index 72637b07e7..50ffccaabe 100644 --- a/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp +++ b/Telegram/SourceFiles/storage/details/storage_settings_scheme.cpp @@ -577,6 +577,16 @@ bool ReadSetting( Window::Theme::SetNightModeValue(nightMode == 1); } break; + case dbiBackgroundKey: { + quint64 keyDay = 0, keyNight = 0; + stream >> keyDay >> keyNight; + if (!CheckStreamStatus(stream)) return false; + + context.backgroundKeyDay = keyDay; + context.backgroundKeyNight = keyNight; + context.backgroundKeysRead = true; + } break; + case dbiLangPackKey: { quint64 langPackKey = 0; stream >> langPackKey; @@ -733,14 +743,15 @@ bool ReadSetting( stream >> v; if (!CheckStreamStatus(stream)) return false; - bool tile = (version < 8005 && !context.hasCustomDayBackground) + bool tile = (version < 8005 && !context.legacyHasCustomDayBackground) ? false : (v == 1); if (Window::Theme::IsNightMode()) { - context.tileNight = tile; - } else { context.tileDay = tile; + } else { + context.tileNight = tile; } + context.tileRead = true; } break; case dbiTileBackground: { @@ -748,8 +759,9 @@ bool ReadSetting( stream >> tileDay >> tileNight; if (!CheckStreamStatus(stream)) return false; - context.tileDay = (tileDay == 1); - context.tileNight = (tileNight == 1); + context.tileDay = tileDay; + context.tileNight = tileNight; + context.tileRead = true; } break; case dbiAdaptiveForWideOld: { diff --git a/Telegram/SourceFiles/storage/details/storage_settings_scheme.h b/Telegram/SourceFiles/storage/details/storage_settings_scheme.h index 44e425543b..4a72b9e800 100644 --- a/Telegram/SourceFiles/storage/details/storage_settings_scheme.h +++ b/Telegram/SourceFiles/storage/details/storage_settings_scheme.h @@ -28,7 +28,7 @@ struct ReadSettingsContext { } // This field is read in ReadSetting. - bool hasCustomDayBackground = false; + bool legacyHasCustomDayBackground = false; // Those fields are written in ReadSetting. MTP::DcOptions fallbackConfigLegacyDcOptions @@ -51,6 +51,12 @@ struct ReadSettingsContext { FileKey themeKeyLegacy = 0; FileKey themeKeyDay = 0; FileKey themeKeyNight = 0; + FileKey backgroundKeyDay = 0; + FileKey backgroundKeyNight = 0; + bool backgroundKeysRead = false; + bool tileDay = false; + bool tileNight = true; + bool tileRead = false; FileKey langPackKey = 0; FileKey languagesKey = 0; @@ -58,9 +64,6 @@ struct ReadSettingsContext { std::vector> mtpLegacyKeys; qint32 mtpLegacyMainDcId = 0; qint32 mtpLegacyUserId = 0; - - bool tileDay = false; - bool tileNight = true; }; [[nodiscard]] bool ReadSetting( @@ -159,6 +162,7 @@ enum { dbiApplicationSettings = 0x5e, dbiDialogsFiltersOld = 0x5f, dbiFallbackProductionConfig = 0x60, + dbiBackgroundKey = 0x61, dbiEncryptedWithSalt = 333, dbiEncrypted = 444, diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 97fd4279cf..6563361f47 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -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(); diff --git a/Telegram/SourceFiles/storage/localstorage.h b/Telegram/SourceFiles/storage/localstorage.h index 50890a034f..576a718dbb 100644 --- a/Telegram/SourceFiles/storage/localstorage.h +++ b/Telegram/SourceFiles/storage/localstorage.h @@ -41,16 +41,30 @@ namespace Export { struct Settings; } // namespace Export +namespace MTP { +class AuthKey; +using AuthKeyPtr = std::shared_ptr; +} // namespace MTP + namespace Local { void start(); void finish(); void writeSettings(); +void rewriteSettingsIfNeeded(); void writeAutoupdatePrefix(const QString &prefix); QString readAutoupdatePrefix(); +void writeBackground(const Data::WallPaper &paper, const QImage &image); +bool readBackground(); +void moveLegacyBackground( + const QString &fromBasePath, + const MTP::AuthKeyPtr &fromLocalKey, + uint64 legacyBackgroundKeyDay, + uint64 legacyBackgroundKeyNight); + void reset(); enum ClearManagerTask { diff --git a/Telegram/SourceFiles/storage/storage_account.cpp b/Telegram/SourceFiles/storage/storage_account.cpp index 904b455ed9..e6cc277828 100644 --- a/Telegram/SourceFiles/storage/storage_account.cpp +++ b/Telegram/SourceFiles/storage/storage_account.cpp @@ -39,17 +39,12 @@ using namespace details; using Database = Cache::Database; constexpr auto kDelayedWriteTimeout = crl::time(1000); -constexpr auto kSavedBackgroundFormat = QImage::Format_ARGB32_Premultiplied; constexpr auto kStickersVersionTag = quint32(-1); constexpr auto kStickersSerializeVersion = 1; constexpr auto kMaxSavedStickerSetsCount = 1000; constexpr auto kDefaultStickerInstallDate = TimeId(1); -constexpr auto kWallPaperLegacySerializeTagId = int32(-111); -constexpr auto kWallPaperSerializeTagId = int32(-112); -constexpr auto kWallPaperSidesLimit = 10'000; - constexpr auto kSinglePeerTypeUser = qint32(1); constexpr auto kSinglePeerTypeChat = qint32(2); constexpr auto kSinglePeerTypeChannel = qint32(3); @@ -65,7 +60,7 @@ enum { // Local Storage Keys lskLegacyStickerImages = 0x05, // legacy lskLegacyAudios = 0x06, // legacy lskRecentStickersOld = 0x07, // no data - lskBackgroundOld = 0x08, // no data + lskBackgroundOldOld = 0x08, // no data lskUserSettings = 0x09, // no data lskRecentHashtagsAndBots = 0x0a, // no data lskStickersOld = 0x0b, // no data @@ -77,7 +72,7 @@ enum { // Local Storage Keys lskTrustedBots = 0x11, // no data lskFavedStickers = 0x12, // no data lskExportSettings = 0x13, // no data - lskBackground = 0x14, // no data + lskBackgroundOld = 0x14, // no data lskSelfSerialized = 0x15, // serialized self }; @@ -173,8 +168,8 @@ base::flat_set Account::collectGoodNames() const { _archivedStickersKey, _recentStickersKeyOld, _savedGifsKey, - _backgroundKeyNight, - _backgroundKeyDay, + _legacyBackgroundKeyNight, + _legacyBackgroundKeyDay, _recentHashtagsAndBotsKey, _exportSettingsKey, _trustedBotsKey, @@ -259,7 +254,7 @@ Account::ReadMapResult Account::readMapWith( quint64 recentStickersKeyOld = 0; quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, favedStickersKey = 0, archivedStickersKey = 0; quint64 savedGifsKey = 0; - quint64 backgroundKeyDay = 0, backgroundKeyNight = 0; + quint64 legacyBackgroundKeyDay = 0, legacyBackgroundKeyNight = 0; quint64 userSettingsKey = 0, recentHashtagsAndBotsKey = 0, exportSettingsKey = 0; while (!map.stream.atEnd()) { quint32 keyType; @@ -315,13 +310,13 @@ Account::ReadMapResult Account::readMapWith( case lskRecentStickersOld: { map.stream >> recentStickersKeyOld; } break; - case lskBackgroundOld: { + case lskBackgroundOldOld: { map.stream >> (Window::Theme::IsNightMode() - ? backgroundKeyNight - : backgroundKeyDay); + ? legacyBackgroundKeyNight + : legacyBackgroundKeyDay); } break; - case lskBackground: { - map.stream >> backgroundKeyDay >> backgroundKeyNight; + case lskBackgroundOld: { + map.stream >> legacyBackgroundKeyDay >> legacyBackgroundKeyNight; } break; case lskUserSettings: { map.stream >> userSettingsKey; @@ -376,8 +371,8 @@ Account::ReadMapResult Account::readMapWith( _favedStickersKey = favedStickersKey; _archivedStickersKey = archivedStickersKey; _savedGifsKey = savedGifsKey; - _backgroundKeyDay = backgroundKeyDay; - _backgroundKeyNight = backgroundKeyNight; + _legacyBackgroundKeyDay = legacyBackgroundKeyDay; + _legacyBackgroundKeyNight = legacyBackgroundKeyNight; _settingsKey = userSettingsKey; _recentHashtagsAndBotsKey = recentHashtagsAndBotsKey; _exportSettingsKey = exportSettingsKey; @@ -392,6 +387,13 @@ Account::ReadMapResult Account::readMapWith( if (_locationsKey) { readLocations(); } + if (_legacyBackgroundKeyDay || _legacyBackgroundKeyNight) { + Local::moveLegacyBackground( + _basePath, + _localKey, + _legacyBackgroundKeyDay, + _legacyBackgroundKeyNight); + } auto stored = readSessionSettings(); readMtpData(); @@ -403,6 +405,7 @@ Account::ReadMapResult Account::readMapWith( _oldMapVersion); LOG(("Map read time: %1").arg(crl::now() - ms)); + return ReadMapResult::Success; } @@ -469,7 +472,6 @@ void Account::writeMap() { } if (_favedStickersKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64); - if (_backgroundKeyDay || _backgroundKeyNight) mapSize += sizeof(quint32) + sizeof(quint64) + sizeof(quint64); if (_settingsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_recentHashtagsAndBotsKey) mapSize += sizeof(quint32) + sizeof(quint64); if (_exportSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64); @@ -509,12 +511,6 @@ void Account::writeMap() { if (_savedGifsKey) { mapData.stream << quint32(lskSavedGifs) << quint64(_savedGifsKey); } - if (_backgroundKeyDay || _backgroundKeyNight) { - mapData.stream - << quint32(lskBackground) - << quint64(_backgroundKeyDay) - << quint64(_backgroundKeyNight); - } if (_settingsKey) { mapData.stream << quint32(lskUserSettings) << quint64(_settingsKey); } @@ -542,7 +538,7 @@ void Account::reset() { _favedStickersKey = 0; _archivedStickersKey = 0; _savedGifsKey = 0; - _backgroundKeyDay = _backgroundKeyNight = 0; + _legacyBackgroundKeyDay = _legacyBackgroundKeyNight = 0; _settingsKey = _recentHashtagsAndBotsKey = _exportSettingsKey = 0; _oldMapVersion = 0; _fileLocations.clear(); @@ -764,10 +760,6 @@ void Account::writeSessionSettings(Main::SessionSettings *stored) { } EncryptedDescriptor data(size); - data.stream - << quint32(dbiTileBackground) - << qint32(Window::Theme::Background()->tileDay() ? 1 : 0) - << qint32(Window::Theme::Background()->tileNight() ? 1 : 0); data.stream << quint32(dbiUseExternalVideoPlayer) << qint32(cUseExternalVideoPlayer()); data.stream << quint32(dbiCacheSettings) << qint64(_cacheTotalSizeLimit) << qint32(_cacheTotalTimeLimit) << qint64(_cacheBigFileTotalSizeLimit) << qint32(_cacheBigFileTotalTimeLimit); if (!userData.isEmpty()) { @@ -783,7 +775,7 @@ void Account::writeSessionSettings(Main::SessionSettings *stored) { ReadSettingsContext Account::prepareReadSettingsContext() const { return ReadSettingsContext{ - .hasCustomDayBackground = (_backgroundKeyDay != 0) + .legacyHasCustomDayBackground = (_legacyBackgroundKeyDay != 0) }; } @@ -845,9 +837,10 @@ std::unique_ptr Account::applyReadContext( } } - // #TODO multi - //Window::Theme::Background()->setTileDayValue(context.tileDay); - //Window::Theme::Background()->setTileNightValue(context.tileNight); + if (context.tileRead) { + Window::Theme::Background()->setTileDayValue(context.tileDay); + Window::Theme::Background()->setTileNightValue(context.tileNight); + } return std::move(context.sessionSettingsStorage); } @@ -1955,185 +1948,6 @@ void Account::readSavedGifs() { } } -void Account::writeBackground( - const Data::WallPaper &paper, - const QImage &image) { - if (!_backgroundCanWrite) { - return; - } - - if (!_localKey) { - LOG(("App Error: localkey not created in writeBackground()")); - return; - } - - 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); - writeMapQueued(); - } - 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, _localKey); -} - -bool Account::readBackground() { - FileReadDescriptor bg; - auto &backgroundKey = Window::Theme::IsNightMode() - ? _backgroundKeyNight - : _backgroundKeyDay; - if (!ReadEncryptedFile(bg, backgroundKey, _basePath, _localKey)) { - if (backgroundKey) { - ClearKey(backgroundKey, _basePath); - backgroundKey = 0; - writeMapDelayed(); - } - 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 Account::writeRecentHashtagsAndBots() { const auto &write = cRecentWriteHashtags(); const auto &search = cRecentSearchHashtags(); diff --git a/Telegram/SourceFiles/storage/storage_account.h b/Telegram/SourceFiles/storage/storage_account.h index eb922fb64e..6c65fd4081 100644 --- a/Telegram/SourceFiles/storage/storage_account.h +++ b/Telegram/SourceFiles/storage/storage_account.h @@ -71,9 +71,6 @@ public: void writeMtpData(); void writeMtpConfig(); - void writeBackground(const Data::WallPaper &paper, const QImage &image); - bool readBackground(); - void writeDrafts(not_null history); void writeDrafts( const PeerId &peer, @@ -232,8 +229,8 @@ private: FileKey _archivedStickersKey = 0; FileKey _savedGifsKey = 0; FileKey _recentStickersKeyOld = 0; - FileKey _backgroundKeyDay = 0; - FileKey _backgroundKeyNight = 0; + FileKey _legacyBackgroundKeyDay = 0; + FileKey _legacyBackgroundKeyNight = 0; FileKey _settingsKey = 0; FileKey _recentHashtagsAndBotsKey = 0; FileKey _exportSettingsKey = 0; @@ -245,7 +242,6 @@ private: base::flat_set _trustedBots; bool _trustedBotsRead = false; - bool _backgroundCanWrite = true; bool _readingUserSettings = false; bool _recentHashtagsAndBotsWereRead = false; diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index f5f8bbc8de..2f170c3b46 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -14,7 +14,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "apiwrap.h" #include "storage/localstorage.h" -#include "storage/storage_account.h" #include "storage/localimageloader.h" #include "storage/file_upload.h" #include "base/parse_helper.h" @@ -531,10 +530,6 @@ ChatBackground::ChatBackground() : _adjustableColors({ }); } -Storage::Account &ChatBackground::local() const { - return Core::App().activeAccount().local(); -} - void ChatBackground::setThemeData(QImage &&themeImage, bool themeTile) { _themeImage = validateBackgroundImage(std::move(themeImage)); _themeTile = themeTile; @@ -544,7 +539,7 @@ void ChatBackground::start() { if (!Data::details::IsUninitializedWallPaper(_paper)) { return; } - if (!local().readBackground()) { + if (!Local::readBackground()) { set(Data::ThemeWallPaper()); } @@ -659,7 +654,7 @@ void ChatBackground::set(const Data::WallPaper &paper, QImage image) { setPaper(Data::DefaultWallPaper().withParamsFrom(_paper)); image.load(qsl(":/gui/art/bg.jpg")); } - local().writeBackground( + Local::writeBackground( _paper, ((Data::IsDefaultWallPaper(_paper) || Data::IsLegacy1DefaultWallPaper(_paper)) @@ -875,7 +870,7 @@ void ChatBackground::setTile(bool tile) { if (this->tile() != old) { if (!Data::details::IsTestingThemeWallPaper(_paper) && !Data::details::IsTestingDefaultWallPaper(_paper)) { - local().writeSessionSettings(); + Local::writeSettings(); } notify(BackgroundUpdate(BackgroundUpdate::Type::Changed, tile)); } @@ -1030,9 +1025,9 @@ bool ChatBackground::isNonDefaultBackground() { void ChatBackground::writeNewBackgroundSettings() { if (tile() != _tileForRevert) { - local().writeSessionSettings(); + Local::writeSettings(); } - local().writeBackground( + Local::writeBackground( _paper, ((Data::IsThemeWallPaper(_paper) || Data::IsDefaultWallPaper(_paper)) @@ -1116,13 +1111,10 @@ void ChatBackground::reapplyWithNightMode( } ClearApplying(); keepApplied(saved.object, settingExactTheme); - if (tile() != _tileForRevert) { - local().writeSessionSettings(); - } - if (nightModeChanged) { + if (tile() != _tileForRevert || nightModeChanged) { Local::writeSettings(); } - if (!settingExactTheme && !local().readBackground()) { + if (!settingExactTheme && !Local::readBackground()) { set(Data::ThemeWallPaper()); } }; diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index 109111573c..be9833fb9a 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -14,10 +14,6 @@ namespace Main { class Session; } // namespace Main -namespace Storage { -class Account; -} // namespace Storage - namespace Window { namespace Theme { @@ -181,8 +177,6 @@ private: QColor original; }; - Storage::Account &local() const; - void ensureStarted(); void saveForRevert(); void setPreparedImage(QImage original, QImage prepared);