Add td_api::updateProfileAccentColors.

This commit is contained in:
levlam 2023-11-27 18:08:45 +03:00
parent fbcd4c7198
commit 60eb989657
4 changed files with 347 additions and 1 deletions

View File

@ -750,6 +750,18 @@ premiumGiveawayInfoCompleted creation_date:int32 actual_winners_selection_date:i
//@dark_theme_colors The list of 1-3 colors in RGB format, describing the accent color, as expected to be shown in dark themes
accentColor id:int32 built_in_accent_color_id:int32 light_theme_colors:vector<int32> dark_theme_colors:vector<int32> = AccentColor;
//@description Contains information about supported accent colors for user profile photo background in RGB format
//@palette_colors The list of 1-2 colors in RGB format, describing the colors, as expected to be shown in the color palette settings
//@background_colors The list of 1-2 colors in RGB format, describing the colors, as expected to be used for the profile photo background
//@story_colors The list of 2 colors in RGB format, describing the colors of the gradient to be used for the unread active story indicator around profile photo
profileAccentColors palette_colors:vector<int32> background_colors:vector<int32> story_colors:vector<int32> = ProfileAccentColors;
//@description Contains information about supported accent color for user profile photo background
//@id Profile accent color identifier
//@light_theme_colors The list of 1-3 colors in RGB format, describing the accent color, as expected to be shown in light themes
//@dark_theme_colors The list of 1-3 colors in RGB format, describing the accent color, as expected to be shown in dark themes
profileAccentColor id:int32 light_theme_colors:profileAccentColors dark_theme_colors:profileAccentColors = ProfileAccentColor;
//@description Describes a custom emoji to be shown instead of the Telegram Premium badge
//@custom_emoji_id Identifier of the custom emoji in stickerFormatTgs format
//@expiration_date Point in time (Unix timestamp) when the status will expire; 0 if never
@ -4522,7 +4534,7 @@ premiumFeatureUpgradedStories = PremiumFeature;
//@description The ability to boost chats
premiumFeatureChatBoost = PremiumFeature;
//@description The ability to choose accent color
//@description The ability to choose accent color for replies and user profile
premiumFeatureAccentColor = PremiumFeature;
@ -6389,6 +6401,11 @@ updateChatThemes chat_themes:vector<chatTheme> = Update;
//@available_accent_color_ids The list of accent color identifiers, which can be set through setAccentColor and setChatAccentColor. The colors must be shown in the specififed order
updateAccentColors colors:vector<accentColor> available_accent_color_ids:vector<int32> = Update;
//@description The list of supported accent colors for user profiles has changed
//@colors Information about supported colors
//@available_accent_color_ids The list of accent color identifiers, which can be set through setProfileAccentColor. The colors must be shown in the specififed order
updateProfileAccentColors colors:vector<profileAccentColor> available_accent_color_ids:vector<int32> = Update;
//@description Some language pack strings have been updated @localization_target Localization target to which the language pack belongs @language_pack_id Identifier of the updated language pack @strings List of changed language pack strings; empty if all strings have changed
updateLanguagePackStrings localization_target:string language_pack_id:string strings:vector<languagePackString> = Update;

View File

@ -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

View File

@ -34,12 +34,16 @@ class ThemeManager final : public Actor {
void reload_accent_colors();
void reload_profile_accent_colors();
static string get_theme_parameters_json_string(const td_api::object_ptr<td_api::themeParameters> &theme,
bool for_web_view);
int32 get_accent_color_id_object(AccentColorId accent_color_id,
AccentColorId fallback_accent_color_id = AccentColorId()) const;
int32 get_profile_accent_color_id_object(AccentColorId accent_color_id) const;
void get_current_state(vector<td_api::object_ptr<td_api::Update>> &updates) const;
private:
@ -104,6 +108,39 @@ class ThemeManager final : public Actor {
void parse(ParserT &parser);
};
struct ProfileAccentColor {
vector<int32> palette_colors_;
vector<int32> background_colors_;
vector<int32> story_colors_;
td_api::object_ptr<td_api::profileAccentColors> get_profile_accent_colors_object() const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
friend bool operator==(const ProfileAccentColor &lhs, const ProfileAccentColor &rhs);
friend bool operator!=(const ProfileAccentColor &lhs, const ProfileAccentColor &rhs);
struct ProfileAccentColors {
FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> light_colors_;
FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> dark_colors_;
vector<AccentColorId> accent_color_ids_;
int32 hash_ = 0;
td_api::object_ptr<td_api::updateProfileAccentColors> get_update_profile_accent_colors_object() const;
template <class StorerT>
void store(StorerT &storer) const;
template <class ParserT>
void parse(ParserT &parser);
};
void start_up() final;
void tear_down() final;
@ -112,6 +149,8 @@ class ThemeManager final : public Actor {
void load_accent_colors();
void load_profile_accent_colors();
static bool is_dark_base_theme(BaseTheme base_theme);
void on_get_chat_themes(Result<telegram_api::object_ptr<telegram_api::account_Themes>> result);
@ -122,6 +161,15 @@ class ThemeManager final : public Actor {
void on_get_accent_colors(Result<telegram_api::object_ptr<telegram_api::help_PeerColors>> result);
bool on_update_profile_accent_colors(FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> light_colors,
FlatHashMap<AccentColorId, ProfileAccentColor, AccentColorIdHash> dark_colors,
vector<AccentColorId> accent_color_ids);
ProfileAccentColor get_profile_accent_color(
telegram_api::object_ptr<telegram_api::help_PeerColorSet> &&color_set) const;
void on_get_profile_accent_colors(Result<telegram_api::object_ptr<telegram_api::help_PeerColors>> result);
td_api::object_ptr<td_api::themeSettings> get_theme_settings_object(const ThemeSettings &settings) const;
td_api::object_ptr<td_api::chatTheme> get_chat_theme_object(const ChatTheme &theme) const;
@ -132,10 +180,14 @@ class ThemeManager final : public Actor {
string get_accent_colors_database_key();
string get_profile_accent_colors_database_key();
void save_chat_themes();
void save_accent_colors();
void save_profile_accent_colors();
void send_update_chat_themes() const;
static BaseTheme get_base_theme(const telegram_api::object_ptr<telegram_api::BaseTheme> &base_theme);
@ -144,12 +196,18 @@ class ThemeManager final : public Actor {
td_api::object_ptr<td_api::updateAccentColors> get_update_accent_colors_object() const;
td_api::object_ptr<td_api::updateProfileAccentColors> get_update_profile_accent_colors_object() const;
void send_update_accent_colors() const;
void send_update_profile_accent_colors() const;
ChatThemes chat_themes_;
AccentColors accent_colors_;
ProfileAccentColors profile_accent_colors_;
Td *td_;
ActorShared<> parent_;
};

View File

@ -2263,6 +2263,7 @@ void UpdatesManager::try_reload_data() {
td_->story_manager_->reload_all_read_stories();
td_->theme_manager_->reload_accent_colors();
td_->theme_manager_->reload_chat_themes();
td_->theme_manager_->reload_profile_accent_colors();
schedule_data_reload();
}