diff --git a/Telegram/SourceFiles/data/data_cloud_themes.cpp b/Telegram/SourceFiles/data/data_cloud_themes.cpp index 978bab8ca7..043b9cc249 100644 --- a/Telegram/SourceFiles/data/data_cloud_themes.cpp +++ b/Telegram/SourceFiles/data/data_cloud_themes.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_premium.h" #include "window/themes/window_theme.h" +#include "window/themes/window_themes_chat.h" #include "window/themes/window_theme_preview.h" #include "window/themes/window_theme_editor_box.h" #include "window/window_controller.h" @@ -29,6 +30,36 @@ constexpr auto kFirstReloadTimeout = 10 * crl::time(1000); constexpr auto kReloadTimeout = 3600 * crl::time(1000); constexpr auto kGiftThemesLimit = 24; +[[nodiscard]] bool SamePaper( + const std::optional &was, + const std::optional &now) { + return (was.has_value() == now.has_value()) + && (!was || was->key() == now->key()); +} + +[[nodiscard]] bool SameThemeSettings( + const base::flat_map &was, + const base::flat_map &now) { + if (was.size() != now.size()) { + return false; + } + for (const auto &[type, settings] : was) { + const auto i = now.find(type); + if (i == end(now)) { + return false; + } + const auto &other = i->second; + if (settings.accentColor != other.accentColor + || settings.outgoingAccentColor != other.outgoingAccentColor + || (settings.outgoingMessagesColors + != other.outgoingMessagesColors) + || !SamePaper(settings.paper, other.paper)) { + return false; + } + } + return true; +} + bool IsTestingColors/* = false*/; } // namespace @@ -206,6 +237,8 @@ void CloudThemes::setupReload() { if (needReload()) { _reloadCurrentTimer.callOnce(kFirstReloadTimeout); + } else if (!Background()->themeObject().cloud.emoticon.isEmpty()) { + _reloadCurrentTimer.callOnce(kFirstReloadTimeout); } Background()->updates( ) | rpl::filter([](const BackgroundUpdate &update) { @@ -253,6 +286,10 @@ void CloudThemes::install() { void CloudThemes::reloadCurrent() { if (!needReload()) { + const auto &cloud = Window::Theme::Background()->themeObject().cloud; + if (!cloud.emoticon.isEmpty() && !cloud.settings.empty()) { + refreshChatThemes(); + } return; } const auto &fields = Window::Theme::Background()->themeObject().cloud; @@ -437,6 +474,7 @@ void CloudThemes::refreshChatThemes() { _chatThemesHash = data.vhash().v; parseChatThemes(data.vthemes().v); _chatThemesUpdates.fire({}); + checkAppliedChatTheme(); }, [](const MTPDaccount_themesNotModified &) { }); }).fail([=] { @@ -745,6 +783,39 @@ void CloudThemes::checkCurrentTheme() { } } +void CloudThemes::checkAppliedChatTheme() { + using namespace Window::Theme; + + const auto &object = Background()->themeObject(); + const auto &cloud = object.cloud; + if (cloud.emoticon.isEmpty() || cloud.settings.empty()) { + return; + } + const auto fresh = themeForToken(cloud.emoticon); + if (!fresh) { + return; + } + const auto &windows = _session->windows(); + if (windows.empty()) { + return; + } + const auto primary = ranges::find_if(windows, []( + not_null window) { + return window->isPrimary(); + }); + const auto controller = (primary != end(windows)) + ? *primary + : windows.front(); + if (!SameThemeSettings(cloud.settings, fresh->settings)) { + ApplyChatTheme(controller, *fresh, IsNightMode()); + return; + } + auto updated = object; + updated.cloud = *fresh; + Background()->setThemeObject(updated); + CheckChatThemeWallPaper(controller); +} + rpl::producer<> CloudThemes::updated() const { return _updates.events(); } diff --git a/Telegram/SourceFiles/data/data_cloud_themes.h b/Telegram/SourceFiles/data/data_cloud_themes.h index 445c171f3e..0f6a3a8011 100644 --- a/Telegram/SourceFiles/data/data_cloud_themes.h +++ b/Telegram/SourceFiles/data/data_cloud_themes.h @@ -125,6 +125,7 @@ private: void parseThemes(const QVector &list); void checkCurrentTheme(); + void checkAppliedChatTheme(); void install(); void setupReload(); diff --git a/Telegram/SourceFiles/window/themes/window_themes_chat.cpp b/Telegram/SourceFiles/window/themes/window_themes_chat.cpp index acb795cc96..f44a6fd79b 100644 --- a/Telegram/SourceFiles/window/themes/window_themes_chat.cpp +++ b/Telegram/SourceFiles/window/themes/window_themes_chat.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/themes/window_themes_chat.h" #include "base/crc32hash.h" +#include "data/data_session.h" +#include "main/main_session.h" #include "mainwidget.h" #include "mainwindow.h" #include "ui/chat/chat_theme.h" @@ -135,27 +137,50 @@ void CheckChatThemeWallPaper(not_null controller) { if (!controller->widget()->sessionContent()) { return; } - const auto &cloud = Background()->themeObject().cloud; + const auto background = Background(); + auto cloud = background->themeObject().cloud; if (cloud.emoticon.isEmpty() || cloud.settings.empty()) { return; } - const auto used = ChatThemeVariant(cloud, IsNightMode()); + auto used = ChatThemeVariant(cloud, IsNightMode()); if (!used) { return; } - const auto &paper = cloud.settings.find(*used)->second.paper; + auto paper = cloud.settings.find(*used)->second.paper; if (!paper) { return; } - const auto ¤t = Background()->paper(); - if (current.equals(*paper)) { + if (!paper->document() && paper->isPattern()) { + const auto &themes = controller->session().data().cloudThemes(); + const auto fresh = themes.themeForToken(cloud.emoticon); + if (fresh) { + auto updated = background->themeObject(); + updated.cloud = *fresh; + background->setThemeObject(updated); + cloud = *fresh; + used = ChatThemeVariant(cloud, IsNightMode()); + if (!used) { + return; + } + const auto &live = cloud.settings.find(*used)->second.paper; + if (live) { + paper = live; + } + } + } + const auto ¤t = background->paper(); + const auto degraded = current.isPattern() + && !current.document() + && background->prepared().isNull() + && (paper->document() != nullptr); + if (!degraded && current.key() == paper->key()) { return; } const auto owned = Data::IsDefaultWallPaper(current) || Data::IsThemeWallPaper(current) || ranges::any_of(cloud.settings, [&](const auto &entry) { return entry.second.paper - && entry.second.paper->equals(current); + && (entry.second.paper->key() == current.key()); }); if (owned) { controller->content()->setChatBackground(*paper);