diff options
| author | levlam <levlam@telegram.org> | 2023-11-27 18:08:45 +0300 |
|---|---|---|
| committer | levlam <levlam@telegram.org> | 2023-11-27 18:08:45 +0300 |
| commit | 60eb98965754f4090ad67837e97e2625d498392d (patch) | |
| tree | ce723241f39af7cbc4e8680f5485c8b9fe40f451 /td/telegram/ThemeManager.cpp | |
| parent | fbcd4c71989763d7c89c313853528f9ca90a8c5b (diff) | |
Add td_api::updateProfileAccentColors.
Diffstat (limited to 'td/telegram/ThemeManager.cpp')
| -rw-r--r-- | td/telegram/ThemeManager.cpp | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/td/telegram/ThemeManager.cpp b/td/telegram/ThemeManager.cpp index 50bc7cc59..62ddb7a33 100644 --- a/td/telegram/ThemeManager.cpp +++ b/td/telegram/ThemeManager.cpp @@ -78,6 +78,32 @@ class GetPeerColorsQuery final : public Td::ResultHandler { } }; +class GetPeerProfileColorsQuery final : public Td::ResultHandler { + Promise<telegram_api::object_ptr<telegram_api::help_PeerColors>> promise_; + + public: + explicit GetPeerProfileColorsQuery(Promise<telegram_api::object_ptr<telegram_api::help_PeerColors>> &&promise) + : promise_(std::move(promise)) { + } + + void send(int32 hash) { + send_query(G()->net_query_creator().create(telegram_api::help_getPeerProfileColors(hash))); + } + + void on_result(BufferSlice packet) final { + auto result_ptr = fetch_result<telegram_api::help_getPeerProfileColors>(packet); + if (result_ptr.is_error()) { + return on_error(result_ptr.move_as_error()); + } + + promise_.set_value(result_ptr.move_as_ok()); + } + + void on_error(Status status) final { + promise_.set_error(std::move(status)); + } +}; + bool operator==(const ThemeManager::ThemeSettings &lhs, const ThemeManager::ThemeSettings &rhs) { return lhs.accent_color == rhs.accent_color && lhs.message_accent_color == rhs.message_accent_color && lhs.background_info == rhs.background_info && lhs.base_theme == rhs.base_theme && @@ -88,6 +114,15 @@ bool operator!=(const ThemeManager::ThemeSettings &lhs, const ThemeManager::Them return !(lhs == rhs); } +bool operator==(const ThemeManager::ProfileAccentColor &lhs, const ThemeManager::ProfileAccentColor &rhs) { + return lhs.palette_colors_ == rhs.palette_colors_ && lhs.background_colors_ == rhs.background_colors_ && + lhs.story_colors_ == rhs.story_colors_; +} + +bool operator!=(const ThemeManager::ProfileAccentColor &lhs, const ThemeManager::ProfileAccentColor &rhs) { + return !(lhs == rhs); +} + template <class StorerT> void ThemeManager::ThemeSettings::store(StorerT &storer) const { using td::store; @@ -217,8 +252,76 @@ void ThemeManager::AccentColors::parse(ParserT &parser) { } } +template <class StorerT> +void ThemeManager::ProfileAccentColor::store(StorerT &storer) const { + td::store(palette_colors_, storer); + td::store(background_colors_, storer); + td::store(story_colors_, storer); +} + +template <class ParserT> +void ThemeManager::ProfileAccentColor::parse(ParserT &parser) { + td::parse(palette_colors_, parser); + td::parse(background_colors_, parser); + td::parse(story_colors_, parser); +} + +template <class StorerT> +void ThemeManager::ProfileAccentColors::store(StorerT &storer) const { + bool has_hash = hash_ != 0; + BEGIN_STORE_FLAGS(); + STORE_FLAG(has_hash); + END_STORE_FLAGS(); + td::store(static_cast<int32>(light_colors_.size()), storer); + for (auto &it : light_colors_) { + td::store(it.first, storer); + td::store(it.second, storer); + } + td::store(static_cast<int32>(dark_colors_.size()), storer); + for (auto &it : dark_colors_) { + td::store(it.first, storer); + td::store(it.second, storer); + } + td::store(accent_color_ids_, storer); + if (has_hash) { + td::store(hash_, storer); + } +} + +template <class ParserT> +void ThemeManager::ProfileAccentColors::parse(ParserT &parser) { + bool has_hash; + BEGIN_PARSE_FLAGS(); + PARSE_FLAG(has_hash); + END_PARSE_FLAGS(); + int32 size; + td::parse(size, parser); + for (int32 i = 0; i < size; i++) { + AccentColorId accent_color_id; + ProfileAccentColor colors; + td::parse(accent_color_id, parser); + td::parse(colors, parser); + CHECK(accent_color_id.is_valid()); + light_colors_.emplace(accent_color_id, std::move(colors)); + } + td::parse(size, parser); + for (int32 i = 0; i < size; i++) { + AccentColorId accent_color_id; + ProfileAccentColor colors; + td::parse(accent_color_id, parser); + td::parse(colors, parser); + CHECK(accent_color_id.is_valid()); + dark_colors_.emplace(accent_color_id, std::move(colors)); + } + td::parse(accent_color_ids_, parser); + if (has_hash) { + td::parse(hash_, parser); + } +} + ThemeManager::ThemeManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) { load_accent_colors(); + load_profile_accent_colors(); } void ThemeManager::start_up() { @@ -259,6 +362,23 @@ void ThemeManager::load_accent_colors() { } } +void ThemeManager::load_profile_accent_colors() { + if (!td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot()) { + return; + } + + auto log_event_string = G()->td_db()->get_binlog_pmc()->get(get_profile_accent_colors_database_key()); + if (!log_event_string.empty()) { + auto status = log_event_parse(profile_accent_colors_, log_event_string); + if (status.is_ok()) { + send_update_profile_accent_colors(); + } else { + LOG(ERROR) << "Failed to parse profile accent colors from binlog: " << status; + profile_accent_colors_ = ProfileAccentColors(); + } + } +} + void ThemeManager::init() { load_chat_themes(); if (td_->auth_manager_->is_authorized() && !td_->auth_manager_->is_bot()) { @@ -268,6 +388,9 @@ void ThemeManager::init() { if (accent_colors_.hash_ == 0) { reload_accent_colors(); } + if (profile_accent_colors_.hash_ == 0) { + reload_profile_accent_colors(); + } } } @@ -359,6 +482,38 @@ bool ThemeManager::on_update_accent_colors(FlatHashMap<AccentColorId, vector<int return true; } +bool ThemeManager::on_update_profile_accent_colors( + FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> light_colors, + FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> dark_colors, + vector<AccentColorId> accent_color_ids) { + auto are_equal = [](const FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> &lhs, + const FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> &rhs) { + 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 == profile_accent_colors_.accent_color_ids_ && + are_equal(light_colors, profile_accent_colors_.light_colors_) && + are_equal(dark_colors, profile_accent_colors_.dark_colors_)) { + return false; + } + for (auto &it : light_colors) { + profile_accent_colors_.light_colors_[it.first] = std::move(it.second); + } + for (auto &it : dark_colors) { + profile_accent_colors_.dark_colors_[it.first] = std::move(it.second); + } + profile_accent_colors_.accent_color_ids_ = std::move(accent_color_ids); + + save_profile_accent_colors(); + send_update_profile_accent_colors(); + return true; +} + namespace { template <bool for_web_view> static auto get_color_json(int32 color); @@ -427,6 +582,14 @@ int32 ThemeManager::get_accent_color_id_object(AccentColorId accent_color_id, return fallback_accent_color_id.get(); } +int32 ThemeManager::get_profile_accent_color_id_object(AccentColorId accent_color_id) const { + CHECK(accent_color_id.is_valid()); + if (td_->auth_manager_->is_bot() || profile_accent_colors_.light_colors_.count(accent_color_id) != 0) { + return accent_color_id.get(); + } + return 5; // blue +} + td_api::object_ptr<td_api::themeSettings> ThemeManager::get_theme_settings_object(const ThemeSettings &settings) const { auto fill = [colors = settings.message_colors]() mutable -> td_api::object_ptr<td_api::BackgroundFill> { if (colors.size() >= 3) { @@ -492,6 +655,33 @@ td_api::object_ptr<td_api::updateAccentColors> ThemeManager::AccentColors::get_u return td_api::make_object<td_api::updateAccentColors>(std::move(colors), std::move(available_accent_color_ids)); } +td_api::object_ptr<td_api::updateProfileAccentColors> ThemeManager::get_update_profile_accent_colors_object() const { + return profile_accent_colors_.get_update_profile_accent_colors_object(); +} + +td_api::object_ptr<td_api::profileAccentColors> ThemeManager::ProfileAccentColor::get_profile_accent_colors_object() + const { + return td_api::make_object<td_api::profileAccentColors>( + vector<int32>(palette_colors_), vector<int32>(background_colors_), vector<int32>(story_colors_)); +} + +td_api::object_ptr<td_api::updateProfileAccentColors> +ThemeManager::ProfileAccentColors::get_update_profile_accent_colors_object() const { + vector<td_api::object_ptr<td_api::profileAccentColor>> colors; + for (auto &it : light_colors_) { + auto light_colors = it.second.get_profile_accent_colors_object(); + auto dark_it = dark_colors_.find(it.first); + auto dark_colors = dark_it != dark_colors_.end() ? dark_it->second.get_profile_accent_colors_object() + : it.second.get_profile_accent_colors_object(); + colors.push_back(td_api::make_object<td_api::profileAccentColor>(it.first.get(), std::move(light_colors), + std::move(dark_colors))); + } + auto available_accent_color_ids = + transform(accent_color_ids_, [](AccentColorId accent_color_id) { return accent_color_id.get(); }); + return td_api::make_object<td_api::updateProfileAccentColors>(std::move(colors), + std::move(available_accent_color_ids)); +} + string ThemeManager::get_chat_themes_database_key() { return "chat_themes"; } @@ -500,6 +690,10 @@ string ThemeManager::get_accent_colors_database_key() { return "accent_colors"; } +string ThemeManager::get_profile_accent_colors_database_key() { + return "profile_accent_colors"; +} + void ThemeManager::save_chat_themes() { G()->td_db()->get_binlog_pmc()->set(get_chat_themes_database_key(), log_event_store(chat_themes_).as_slice().str()); } @@ -509,6 +703,11 @@ void ThemeManager::save_accent_colors() { log_event_store(accent_colors_).as_slice().str()); } +void ThemeManager::save_profile_accent_colors() { + G()->td_db()->get_binlog_pmc()->set(get_profile_accent_colors_database_key(), + log_event_store(profile_accent_colors_).as_slice().str()); +} + void ThemeManager::send_update_chat_themes() const { send_closure(G()->td(), &Td::send_update, get_update_chat_themes_object()); } @@ -517,6 +716,10 @@ void ThemeManager::send_update_accent_colors() const { send_closure(G()->td(), &Td::send_update, get_update_accent_colors_object()); } +void ThemeManager::send_update_profile_accent_colors() const { + send_closure(G()->td(), &Td::send_update, get_update_profile_accent_colors_object()); +} + void ThemeManager::reload_chat_themes() { auto request_promise = PromiseCreator::lambda( [actor_id = actor_id(this)](Result<telegram_api::object_ptr<telegram_api::account_Themes>> result) { @@ -643,6 +846,70 @@ void ThemeManager::on_get_accent_colors(Result<telegram_api::object_ptr<telegram } } +void ThemeManager::reload_profile_accent_colors() { + auto request_promise = PromiseCreator::lambda( + [actor_id = actor_id(this)](Result<telegram_api::object_ptr<telegram_api::help_PeerColors>> result) { + send_closure(actor_id, &ThemeManager::on_get_profile_accent_colors, std::move(result)); + }); + + td_->create_handler<GetPeerProfileColorsQuery>(std::move(request_promise))->send(profile_accent_colors_.hash_); +} + +ThemeManager::ProfileAccentColor ThemeManager::get_profile_accent_color( + telegram_api::object_ptr<telegram_api::help_PeerColorSet> &&color_set) const { + CHECK(color_set != nullptr); + CHECK(color_set->get_id() == telegram_api::help_peerColorProfileSet::ID); + auto colors = telegram_api::move_object_as<telegram_api::help_peerColorProfileSet>(color_set); + ProfileAccentColor color; + color.palette_colors_ = std::move(colors->palette_colors_); + color.background_colors_ = std::move(colors->bg_colors_); + color.story_colors_ = std::move(colors->story_colors_); + return color; +} + +void ThemeManager::on_get_profile_accent_colors( + Result<telegram_api::object_ptr<telegram_api::help_PeerColors>> result) { + if (result.is_error()) { + return; + } + + auto peer_colors_ptr = result.move_as_ok(); + LOG(DEBUG) << "Receive " << to_string(peer_colors_ptr); + if (peer_colors_ptr->get_id() == telegram_api::help_peerColorsNotModified::ID) { + return; + } + CHECK(peer_colors_ptr->get_id() == telegram_api::help_peerColors::ID); + auto peer_colors = telegram_api::move_object_as<telegram_api::help_peerColors>(peer_colors_ptr); + FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> light_colors; + FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> dark_colors; + vector<AccentColorId> accent_color_ids; + for (auto &option : peer_colors->colors_) { + AccentColorId accent_color_id(option->color_id_); + if (option->colors_ == nullptr || option->colors_->get_id() != telegram_api::help_peerColorProfileSet::ID || + option->dark_colors_ == nullptr || + option->dark_colors_->get_id() != telegram_api::help_peerColorProfileSet::ID || !accent_color_id.is_valid() || + td::contains(accent_color_ids, accent_color_id)) { + LOG(ERROR) << "Receive " << to_string(option); + continue; + } + if (!option->hidden_) { + accent_color_ids.push_back(accent_color_id); + } + light_colors[accent_color_id] = get_profile_accent_color(std::move(option->colors_)); + dark_colors[accent_color_id] = get_profile_accent_color(std::move(option->dark_colors_)); + } + + bool is_changed = false; + if (profile_accent_colors_.hash_ != peer_colors->hash_) { + profile_accent_colors_.hash_ = peer_colors->hash_; + is_changed = true; + } + if (!on_update_profile_accent_colors(std::move(light_colors), std::move(dark_colors), std::move(accent_color_ids)) && + is_changed) { + save_profile_accent_colors(); + } +} + ThemeManager::BaseTheme ThemeManager::get_base_theme( const telegram_api::object_ptr<telegram_api::BaseTheme> &base_theme) { CHECK(base_theme != nullptr); @@ -689,6 +956,9 @@ void ThemeManager::get_current_state(vector<td_api::object_ptr<td_api::Update>> if (!accent_colors_.accent_color_ids_.empty()) { updates.push_back(get_update_accent_colors_object()); } + if (!profile_accent_colors_.accent_color_ids_.empty()) { + updates.push_back(get_update_profile_accent_colors_object()); + } } } // namespace td |
