diff --git a/td/telegram/AccentColorId.h b/td/telegram/AccentColorId.h index ad307d90b..60cf29d76 100644 --- a/td/telegram/AccentColorId.h +++ b/td/telegram/AccentColorId.h @@ -43,6 +43,10 @@ class AccentColorId { return id >= 0; } + bool is_built_in() const { + return 0 <= id && id < 7; + } + int32 get() const { return id; } diff --git a/td/telegram/ConfigManager.cpp b/td/telegram/ConfigManager.cpp index 66721e9b5..dcd6b095b 100644 --- a/td/telegram/ConfigManager.cpp +++ b/td/telegram/ConfigManager.cpp @@ -6,6 +6,7 @@ // #include "td/telegram/ConfigManager.h" +#include "td/telegram/AccentColorId.h" #include "td/telegram/AuthManager.h" #include "td/telegram/ConnectionState.h" #include "td/telegram/ContactsManager.h" @@ -29,6 +30,7 @@ #include "td/telegram/Td.h" #include "td/telegram/TdDb.h" #include "td/telegram/telegram_api.h" +#include "td/telegram/ThemeManager.h" #include "td/mtproto/AuthData.h" #include "td/mtproto/AuthKey.h" @@ -1483,6 +1485,9 @@ void ConfigManager::process_app_config(tl_object_ptr &c // bool archive_all_stories = false; int32 story_viewers_expire_period = 86400; int64 stories_changelog_user_id = ContactsManager::get_service_notifications_user_id().get(); + FlatHashMap, AccentColorIdHash> light_colors; + FlatHashMap, AccentColorIdHash> dark_colors; + vector accent_color_ids; if (config->get_id() == telegram_api::jsonObject::ID) { for (auto &key_value : static_cast(config.get())->value_) { Slice key = key_value->key_; @@ -1949,6 +1954,62 @@ void ConfigManager::process_app_config(tl_object_ptr &c get_json_value_int(std::move(key_value->value_), key)); continue; } + if (key == "peer_colors" || key == "dark_peer_colors") { + auto &color_map = key == "peer_colors" ? light_colors : dark_colors; + if (value->get_id() == telegram_api::jsonObject::ID) { + auto peer_color_ids = std::move(static_cast(value)->value_); + for (auto &peer_color_id : peer_color_ids) { + CHECK(peer_color_id != nullptr); + auto r_accent_color_id = to_integer_safe(peer_color_id->key_); + if (r_accent_color_id.is_error()) { + LOG(ERROR) << "Receive " << to_string(peer_color_id); + continue; + } + auto accent_color_id = AccentColorId(r_accent_color_id.ok()); + if (!accent_color_id.is_valid() || accent_color_id.is_built_in() || + peer_color_id->value_->get_id() != telegram_api::jsonArray::ID) { + LOG(ERROR) << "Receive " << to_string(peer_color_id); + continue; + } + auto &colors = color_map[accent_color_id]; + if (!colors.empty()) { + LOG(ERROR) << "Receive duplicate " << accent_color_id; + continue; + } + auto colors_json = std::move(static_cast(peer_color_id->value_.get())->value_); + for (auto &color_json : colors_json) { + auto color_str = get_json_value_string(std::move(color_json), key); + auto r_color = hex_to_integer_safe(color_str); + if (r_color.is_ok() && r_color.ok() <= 0xFFFFFF) { + colors.push_back(static_cast(r_color.ok())); + } + } + if (colors.size() != colors_json.size()) { + LOG(ERROR) << "Receive invalid colors for " << accent_color_id; + color_map.erase(accent_color_id); + } + } + } else { + LOG(ERROR) << "Receive unexpected " << key << ' ' << to_string(*value); + } + continue; + } + if (key == "peer_colors_available") { + if (value->get_id() == telegram_api::jsonArray::ID) { + auto colors = std::move(static_cast(value)->value_); + for (auto &color : colors) { + auto accent_color_id = AccentColorId(get_json_value_int(std::move(color), key)); + if (accent_color_id.is_valid() && !td::contains(accent_color_ids, accent_color_id)) { + accent_color_ids.push_back(accent_color_id); + } else { + LOG(ERROR) << "Receive an invalid accent color identifier"; + } + } + } else { + LOG(ERROR) << "Receive unexpected peer_colors_available " << to_string(*value); + } + continue; + } new_values.push_back(std::move(key_value)); } @@ -1960,6 +2021,16 @@ void ConfigManager::process_app_config(tl_object_ptr &c send_closure(G()->link_manager(), &LinkManager::update_autologin_domains, std::move(autologin_domains), std::move(url_auth_domains), std::move(whitelisted_domains)); + td::remove_if(accent_color_ids, [&light_colors](AccentColorId accent_color_id) { + if (!accent_color_id.is_built_in() && light_colors.count(accent_color_id) == 0) { + LOG(ERROR) << "Receive unknown " << accent_color_id; + return true; + } + return false; + }); + send_closure(G()->theme_manager(), &ThemeManager::on_update_accent_colors, std::move(light_colors), + std::move(dark_colors), std::move(accent_color_ids)); + Global &options = *G(); if (ignored_restriction_reasons.empty()) { diff --git a/td/telegram/ConfigManager.h b/td/telegram/ConfigManager.h index 4f96a1f0a..55c67cd81 100644 --- a/td/telegram/ConfigManager.h +++ b/td/telegram/ConfigManager.h @@ -102,7 +102,7 @@ class ConfigManager final : public NetQueryCallback { private: struct AppConfig { - static constexpr int32 CURRENT_VERSION = 21; + static constexpr int32 CURRENT_VERSION = 22; int32 version_ = 0; int32 hash_ = 0; telegram_api::object_ptr config_; diff --git a/td/telegram/ThemeManager.cpp b/td/telegram/ThemeManager.cpp index 79aa526fd..0d143424a 100644 --- a/td/telegram/ThemeManager.cpp +++ b/td/telegram/ThemeManager.cpp @@ -239,6 +239,31 @@ void ThemeManager::on_update_theme(telegram_api::object_ptr promise.set_value(Unit()); } +void ThemeManager::on_update_accent_colors(FlatHashMap, AccentColorIdHash> light_colors, + FlatHashMap, AccentColorIdHash> dark_colors, + vector accent_color_ids) { + auto are_equal = [](const FlatHashMap, AccentColorIdHash> &lhs, + const FlatHashMap, AccentColorIdHash> &rhs) { + if (lhs.size() != rhs.size()) { + return false; + } + for (auto &lhs_it : lhs) { + auto rhs_it = rhs.find(lhs_it.first); + if (rhs_it == rhs.end() || rhs_it->second != lhs_it.second) { + return false; + } + } + return true; + }; + if (accent_color_ids == accent_colors_.accent_color_ids_ && are_equal(light_colors, accent_colors_.light_colors_) && + are_equal(dark_colors, accent_colors_.dark_colors_)) { + return; + } + accent_colors_.light_colors_ = std::move(light_colors); + accent_colors_.dark_colors_ = std::move(dark_colors); + accent_colors_.accent_color_ids_ = std::move(accent_color_ids); +} + namespace { template static auto get_color_json(int32 color); diff --git a/td/telegram/ThemeManager.h b/td/telegram/ThemeManager.h index 831bc53d8..115ca0783 100644 --- a/td/telegram/ThemeManager.h +++ b/td/telegram/ThemeManager.h @@ -6,6 +6,7 @@ // #pragma once +#include "td/telegram/AccentColorId.h" #include "td/telegram/BackgroundInfo.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" @@ -13,6 +14,7 @@ #include "td/actor/actor.h" #include "td/utils/common.h" +#include "td/utils/FlatHashMap.h" #include "td/utils/Promise.h" #include "td/utils/Status.h" @@ -28,6 +30,10 @@ class ThemeManager final : public Actor { void on_update_theme(telegram_api::object_ptr &&theme, Promise &&promise); + void on_update_accent_colors(FlatHashMap, AccentColorIdHash> light_colors, + FlatHashMap, AccentColorIdHash> dark_colors, + vector accent_color_ids); + static string get_theme_parameters_json_string(const td_api::object_ptr &theme, bool for_web_view); @@ -83,6 +89,12 @@ class ThemeManager final : public Actor { void parse(ParserT &parser); }; + struct AccentColors { + FlatHashMap, AccentColorIdHash> light_colors_; + FlatHashMap, AccentColorIdHash> dark_colors_; + vector accent_color_ids_; + }; + void start_up() final; void loop() final; @@ -111,6 +123,8 @@ class ThemeManager final : public Actor { ChatThemes chat_themes_; + AccentColors accent_colors_; + Td *td_; ActorShared<> parent_; };