diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 0e415984b..6af6a2753 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -154,6 +154,10 @@ QPixmap PrepareStaticImage(const QString &path) { return App::pixmapFromImageInPlace(std::move(image)); } +[[nodiscard]] QString CachedThemePath(uint64 documentId) { + return QString::fromLatin1("special://cached-%1").arg(documentId); +} + } // namespace struct OverlayWidget::SharedMedia { @@ -2198,6 +2202,8 @@ void OverlayWidget::playbackWaitingChange(bool waiting) { } void OverlayWidget::initThemePreview() { + using namespace Window::Theme; + Assert(_doc && _doc->isTheme()); const auto bytes = _doc->data(); @@ -2208,10 +2214,10 @@ void OverlayWidget::initThemePreview() { } _themePreviewShown = true; - Window::Theme::CurrentData current; - current.backgroundId = Window::Theme::Background()->id(); - current.backgroundImage = Window::Theme::Background()->createCurrentImage(); - current.backgroundTiled = Window::Theme::Background()->tile(); + auto current = CurrentData(); + current.backgroundId = Background()->id(); + current.backgroundImage = Background()->createCurrentImage(); + current.backgroundTiled = Background()->tile(); const auto &cloudList = _doc->session().data().cloudThemes().list(); const auto i = ranges::find( @@ -2221,15 +2227,14 @@ void OverlayWidget::initThemePreview() { const auto cloud = (i != end(cloudList)) ? *i : Data::CloudTheme(); const auto isTrusted = (cloud.documentId != 0); - const auto path = _doc->location().name(); + const auto realPath = _doc->location().name(); + const auto path = realPath.isEmpty() + ? CachedThemePath(_doc->id) + : realPath; const auto id = _themePreviewId = rand_value(); const auto weak = make_weak(this); crl::async([=, data = std::move(current)]() mutable { - auto preview = Window::Theme::GeneratePreview( - path, - bytes, - cloud, - std::move(data)); + auto preview = GeneratePreview(bytes, path, cloud, std::move(data)); crl::on_main(weak, [=, result = std::move(preview)]() mutable { if (id != _themePreviewId) { return; @@ -2243,15 +2248,14 @@ void OverlayWidget::initThemePreview() { st::themePreviewApplyButton); _themeApply->show(); _themeApply->setClickedCallback([=] { - const auto &object = Window::Theme::Background()->themeObject(); - const auto currentlyIsCustom = !object.pathAbsolute.isEmpty() - && !object.pathAbsolute.startsWith(qstr(":/gui/")) - && !object.cloud.id; + const auto &object = Background()->themeObject(); + const auto currentlyIsCustom = !object.cloud.id + && !IsEmbeddedTheme(object.pathAbsolute); auto preview = std::move(_themePreview); close(); - Window::Theme::Apply(std::move(preview)); + Apply(std::move(preview)); if (isTrusted && !currentlyIsCustom) { - Window::Theme::KeepApplied(); + KeepApplied(); } }); _themeCancel.create( diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 72d482ea4..a75495380 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -4221,7 +4221,7 @@ Window::Theme::Saved readThemeUsingKey(FileKey key) { auto ignoreCache = false; if (!object.cloud.id) { - QFile file(object.pathRelative); + auto file = QFile(object.pathRelative); if (object.pathRelative.isEmpty() || !file.exists()) { file.setFileName(object.pathAbsolute); } @@ -4480,9 +4480,8 @@ std::vector readRecentLanguages() { } bool copyThemeColorsToPalette(const QString &destination) { - auto &themeKey = Window::Theme::IsNightMode() - ? _themeKeyNight - : _themeKeyDay; + using namespace Window::Theme; + auto &themeKey = IsNightMode() ? _themeKeyNight : _themeKeyDay; if (!themeKey) { return false; } @@ -4499,10 +4498,7 @@ bool copyThemeColorsToPalette(const QString &destination) { return false; } - return Window::Theme::CopyColorsToPalette( - destination, - pathAbsolute, - themeContent); + return CopyColorsToPalette(destination, pathAbsolute, themeContent); } void writeRecentHashtagsAndBots() { diff --git a/Telegram/SourceFiles/window/themes/window_theme.cpp b/Telegram/SourceFiles/window/themes/window_theme.cpp index 831d648ac..5a081d8c5 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme.cpp @@ -856,6 +856,7 @@ void ChatBackground::setTileNightValue(bool tile) { void ChatBackground::setThemeObject(const Object &object) { _themeObject = object; + _themeObject.content = QByteArray(); } const Object &ChatBackground::themeObject() const { @@ -1100,6 +1101,10 @@ ChatBackground *Background() { return GlobalBackground.data(); } +bool IsEmbeddedTheme(const QString &path) { + return path.isEmpty() || path.startsWith(qstr(":/gui/")); +} + bool Initialize(Saved &&saved) { if (InitializeFromSaved(std::move(saved))) { Background()->setThemeObject(saved.object); @@ -1116,7 +1121,7 @@ void Uninitialize() { bool Apply( const QString &filepath, const Data::CloudTheme &cloud) { - if (auto preview = PreviewFromFile(filepath, {}, cloud)) { + if (auto preview = PreviewFromFile(QByteArray(), filepath, cloud)) { return Apply(std::move(preview)); } return false; @@ -1134,7 +1139,7 @@ bool Apply(std::unique_ptr preview) { void ApplyDefaultWithPath(const QString &themePath) { if (!themePath.isEmpty()) { - if (auto preview = PreviewFromFile(themePath, {}, {})) { + if (auto preview = PreviewFromFile(QByteArray(), themePath, {})) { Apply(std::move(preview)); } } else { diff --git a/Telegram/SourceFiles/window/themes/window_theme.h b/Telegram/SourceFiles/window/themes/window_theme.h index 3d55e7e65..75ee9dee2 100644 --- a/Telegram/SourceFiles/window/themes/window_theme.h +++ b/Telegram/SourceFiles/window/themes/window_theme.h @@ -19,6 +19,8 @@ namespace Theme { inline constexpr auto kThemeSchemeSizeLimit = 1024 * 1024; +[[nodiscard]] bool IsEmbeddedTheme(const QString &path); + struct Object { QString pathRelative; QString pathAbsolute; diff --git a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp index a113adab7..0a050e53e 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_editor_box.cpp @@ -216,11 +216,13 @@ void ImportFromFile( qsl("Theme files (*.tdesktop-theme *.tdesktop-palette)")); filters.push_back(FileDialog::AllFilesFilter()); const auto callback = crl::guard(session, [=]( - const FileDialog::OpenResult &result) { - if (result.paths.isEmpty()) { - return; + const FileDialog::OpenResult &result) { + const auto path = result.paths.isEmpty() + ? QString() + : result.paths.front(); + if (!path.isEmpty()) { + Window::Theme::Apply(path); } - Window::Theme::Apply(result.paths.front()); }); FileDialog::GetOpenPath( parent.get(), diff --git a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp index 33ad9ff91..c01031222 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_preview.cpp +++ b/Telegram/SourceFiles/window/themes/window_theme_preview.cpp @@ -909,9 +909,11 @@ void Generator::restoreTextPalette() { } // namespace std::unique_ptr PreviewFromFile( - const QString &filepath, const QByteArray &bytes, + const QString &filepath, const Data::CloudTheme &cloud) { + Expects(!filepath.isEmpty()); // Use + auto result = std::make_unique(); auto &object = result->object; object.cloud = cloud; @@ -935,11 +937,11 @@ std::unique_ptr PreviewFromFile( } std::unique_ptr GeneratePreview( - const QString &filepath, const QByteArray &bytes, + const QString &filepath, const Data::CloudTheme &cloud, CurrentData &&data) { - auto result = PreviewFromFile(filepath, bytes, cloud); + auto result = PreviewFromFile(bytes, filepath, cloud); if (!result) { return nullptr; } diff --git a/Telegram/SourceFiles/window/themes/window_theme_preview.h b/Telegram/SourceFiles/window/themes/window_theme_preview.h index b38d350b3..fd32ccd2b 100644 --- a/Telegram/SourceFiles/window/themes/window_theme_preview.h +++ b/Telegram/SourceFiles/window/themes/window_theme_preview.h @@ -23,12 +23,12 @@ struct CurrentData { }; std::unique_ptr PreviewFromFile( - const QString &filepath, const QByteArray &bytes, + const QString &filepath, const Data::CloudTheme &cloud); std::unique_ptr GeneratePreview( - const QString &filepath, const QByteArray &bytes, + const QString &filepath, const Data::CloudTheme &cloud, CurrentData &&data); diff --git a/Telegram/SourceFiles/window/themes/window_themes_cloud_list.cpp b/Telegram/SourceFiles/window/themes/window_themes_cloud_list.cpp index 10aaa4334..fc758e83b 100644 --- a/Telegram/SourceFiles/window/themes/window_themes_cloud_list.cpp +++ b/Telegram/SourceFiles/window/themes/window_themes_cloud_list.cpp @@ -61,7 +61,7 @@ constexpr auto kShowPerRow = 4; takeh * to.width() / to.height(), 1); return (small.width() != takew) - ? small.copy(0, (small.width() - takew) / 2, takew, takeh) + ? small.copy((small.width() - takew) / 2, 0, takew, takeh) : small; } } @@ -181,8 +181,7 @@ void CloudList::setup() { std::vector CloudList::collectAll() const { const auto &object = Background()->themeObject(); - const auto isDefault = object.pathAbsolute.isEmpty() - || object.pathAbsolute.startsWith(qstr(":/gui/")); + const auto isDefault = IsEmbeddedTheme(object.pathAbsolute); auto result = _window->session().data().cloudThemes().list(); if (!isDefault) { const auto i = ranges::find( diff --git a/Telegram/SourceFiles/window/themes/window_themes_embedded.cpp b/Telegram/SourceFiles/window/themes/window_themes_embedded.cpp index 06341eb2f..54d004154 100644 --- a/Telegram/SourceFiles/window/themes/window_themes_embedded.cpp +++ b/Telegram/SourceFiles/window/themes/window_themes_embedded.cpp @@ -166,7 +166,7 @@ Colorizer ColorizerFrom(const EmbeddedScheme &scheme, const QColor &color) { } Colorizer ColorizerForTheme(const QString &absolutePath) { - if (!absolutePath.startsWith(qstr(":/gui"))) { + if (absolutePath.isEmpty() || !IsEmbeddedTheme(absolutePath)) { return Colorizer(); } const auto schemes = EmbeddedThemes();