&&promise) final {
+ dialog_ids_ = td->messages_manager_->get_recently_opened_dialogs(limit_, std::move(promise));
+ }
+
+ void do_send_result() final {
+ send_result(MessagesManager::get_chats_object(dialog_ids_));
+ }
+
+ public:
+ GetRecentlyOpenedChatsRequest(ActorShared td, uint64 request_id, int32 limit)
+ : RequestActor(std::move(td), request_id), limit_(limit) {
+ }
+};
+
class GetMessageRequest final : public RequestOnceActor {
FullMessageId full_message_id_;
@@ -4369,6 +4388,7 @@ void Td::send_update(tl_object_ptr &&object) {
}
switch (object_id) {
+ case td_api::updateChatThemes::ID:
case td_api::updateFavoriteStickers::ID:
case td_api::updateInstalledStickerSets::ID:
case td_api::updateRecentStickers::ID:
@@ -5435,6 +5455,11 @@ void Td::on_request(uint64 id, const td_api::clearRecentlyFoundChats &request) {
send_closure(actor_id(this), &Td::send_result, id, make_tl_object());
}
+void Td::on_request(uint64 id, const td_api::getRecentlyOpenedChats &request) {
+ CHECK_IS_USER();
+ CREATE_REQUEST(GetRecentlyOpenedChatsRequest, request.limit_);
+}
+
void Td::on_request(uint64 id, const td_api::openChat &request) {
CHECK_IS_USER();
answer_ok_query(id, messages_manager_->open_dialog(DialogId(request.chat_id_)));
@@ -8135,12 +8160,6 @@ void Td::on_request(uint64 id, const td_api::resetBackgrounds &request) {
background_manager_->reset_backgrounds(std::move(promise));
}
-void Td::on_request(uint64 id, const td_api::getChatThemes &request) {
- CHECK_IS_USER();
- CREATE_REQUEST_PROMISE();
- theme_manager_->get_chat_themes(std::move(promise));
-}
-
void Td::on_request(uint64 id, td_api::getRecentlyVisitedTMeUrls &request) {
CHECK_IS_USER();
CLEAN_INPUT_STRING(request.referrer_);
diff --git a/td/telegram/Td.h b/td/telegram/Td.h
index a5db5e26b..f13407019 100644
--- a/td/telegram/Td.h
+++ b/td/telegram/Td.h
@@ -595,6 +595,8 @@ class Td final : public Actor {
void on_request(uint64 id, const td_api::clearRecentlyFoundChats &request);
+ void on_request(uint64 id, const td_api::getRecentlyOpenedChats &request);
+
void on_request(uint64 id, const td_api::getGroupsInCommon &request);
void on_request(uint64 id, td_api::checkChatUsername &request);
@@ -1195,8 +1197,6 @@ class Td final : public Actor {
void on_request(uint64 id, const td_api::resetBackgrounds &request);
- void on_request(uint64 id, const td_api::getChatThemes &request);
-
void on_request(uint64 id, td_api::getRecentlyVisitedTMeUrls &request);
void on_request(uint64 id, td_api::setBotUpdatesStatus &request);
diff --git a/td/telegram/ThemeManager.cpp b/td/telegram/ThemeManager.cpp
index e2de4ec03..1f7ef974f 100644
--- a/td/telegram/ThemeManager.cpp
+++ b/td/telegram/ThemeManager.cpp
@@ -6,6 +6,7 @@
//
#include "td/telegram/ThemeManager.h"
+#include "td/telegram/AuthManager.h"
#include "td/telegram/BackgroundManager.h"
#include "td/telegram/Global.h"
#include "td/telegram/net/NetQueryCreator.h"
@@ -14,6 +15,7 @@
#include "td/utils/algorithm.h"
#include "td/utils/buffer.h"
#include "td/utils/logging.h"
+#include "td/utils/Random.h"
#include "td/utils/Time.h"
namespace td {
@@ -44,33 +46,73 @@ class GetChatThemesQuery final : public Td::ResultHandler {
}
};
+bool operator==(const ThemeManager::ThemeSettings &lhs, const ThemeManager::ThemeSettings &rhs) {
+ return lhs.accent_color == rhs.accent_color && lhs.background_id == rhs.background_id &&
+ lhs.background_type == rhs.background_type && lhs.base_theme == rhs.base_theme &&
+ lhs.message_colors == rhs.message_colors && lhs.animate_message_colors == rhs.animate_message_colors;
+}
+
+bool operator!=(const ThemeManager::ThemeSettings &lhs, const ThemeManager::ThemeSettings &rhs) {
+ return !(lhs == rhs);
+}
+
ThemeManager::ThemeManager(Td *td, ActorShared<> parent) : td_(td), parent_(std::move(parent)) {
- chat_themes_.next_reload_time = Time::now();
+}
+
+void ThemeManager::start_up() {
+ init();
+}
+
+void ThemeManager::init() {
+ if (!td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot()) {
+ return;
+ }
+
+ chat_themes_.next_reload_time = Time::now(); // TODO load chat themes from binlog
+ loop();
}
void ThemeManager::tear_down() {
parent_.reset();
}
-void ThemeManager::get_chat_themes(Promise> &&promise) {
+void ThemeManager::loop() {
+ if (!td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot()) {
+ return;
+ }
+
if (Time::now() < chat_themes_.next_reload_time) {
- return promise.set_value(get_chat_themes_object());
+ return set_timeout_at(chat_themes_.next_reload_time);
}
- if (!chat_themes_.themes.empty()) {
- promise.set_value(get_chat_themes_object());
- pending_get_chat_themes_queries_.push_back(Promise>());
- } else {
- pending_get_chat_themes_queries_.push_back(std::move(promise));
- }
- if (pending_get_chat_themes_queries_.size() == 1) {
- auto request_promise = PromiseCreator::lambda(
- [actor_id = actor_id(this)](Result> result) {
- send_closure(actor_id, &ThemeManager::on_get_chat_themes, std::move(result));
- });
+ auto request_promise = PromiseCreator::lambda(
+ [actor_id = actor_id(this)](Result> result) {
+ send_closure(actor_id, &ThemeManager::on_get_chat_themes, std::move(result));
+ });
- td_->create_handler(std::move(request_promise))->send(chat_themes_.hash);
+ td_->create_handler(std::move(request_promise))->send(chat_themes_.hash);
+}
+
+void ThemeManager::on_update_theme(telegram_api::object_ptr &&theme, Promise &&promise) {
+ CHECK(theme != nullptr);
+ bool is_changed = false;
+ for (auto &chat_theme : chat_themes_.themes) {
+ if (chat_theme.light_id == theme->id_ || chat_theme.dark_id == theme->id_) {
+ auto theme_settings = get_chat_theme_settings(std::move(theme->settings_));
+ if (chat_theme.light_id == theme->id_ && chat_theme.light_theme != theme_settings) {
+ chat_theme.light_theme = theme_settings;
+ is_changed = true;
+ }
+ if (chat_theme.dark_id == theme->id_ && chat_theme.dark_theme != theme_settings) {
+ chat_theme.dark_theme = theme_settings;
+ is_changed = true;
+ }
+ }
}
+ if (is_changed) {
+ send_update_chat_themes();
+ }
+ promise.set_value(Unit());
}
td_api::object_ptr ThemeManager::get_theme_settings_object(const ThemeSettings &settings) const {
@@ -97,54 +139,52 @@ td_api::object_ptr ThemeManager::get_chat_theme_object(const
get_theme_settings_object(theme.dark_theme));
}
-td_api::object_ptr ThemeManager::get_chat_themes_object() const {
- return td_api::make_object(
+td_api::object_ptr ThemeManager::get_update_chat_themes_object() const {
+ return td_api::make_object(
transform(chat_themes_.themes, [this](const ChatTheme &theme) { return get_chat_theme_object(theme); }));
}
+void ThemeManager::send_update_chat_themes() const {
+ send_closure(G()->td(), &Td::send_update, get_update_chat_themes_object());
+}
+
void ThemeManager::on_get_chat_themes(Result> result) {
- auto promises = std::move(pending_get_chat_themes_queries_);
- CHECK(!promises.empty());
- reset_to_empty(pending_get_chat_themes_queries_);
-
if (result.is_error()) {
- // do not clear chat_themes_
-
- auto error = result.move_as_error();
- for (auto &promise : promises) {
- promise.set_error(error.clone());
- }
+ set_timeout_in(Random::fast(40, 60));
return;
}
chat_themes_.next_reload_time = Time::now() + THEME_CACHE_TIME;
+ set_timeout_at(chat_themes_.next_reload_time);
auto chat_themes_ptr = result.move_as_ok();
LOG(DEBUG) << "Receive " << to_string(chat_themes_ptr);
- if (chat_themes_ptr->get_id() != telegram_api::account_chatThemesNotModified::ID) {
- CHECK(chat_themes_ptr->get_id() == telegram_api::account_chatThemes::ID);
- auto chat_themes = telegram_api::move_object_as(chat_themes_ptr);
- chat_themes_.hash = chat_themes->hash_;
- chat_themes_.themes.clear();
- for (auto &chat_theme : chat_themes->themes_) {
- if (chat_theme->emoticon_.empty()) {
- LOG(ERROR) << "Receive " << to_string(chat_theme);
- continue;
- }
-
- ChatTheme theme;
- theme.emoji = std::move(chat_theme->emoticon_);
- theme.light_theme = get_chat_theme_settings(std::move(chat_theme->theme_->settings_));
- theme.dark_theme = get_chat_theme_settings(std::move(chat_theme->dark_theme_->settings_));
- chat_themes_.themes.push_back(std::move(theme));
+ if (chat_themes_ptr->get_id() == telegram_api::account_chatThemesNotModified::ID) {
+ return;
+ }
+ CHECK(chat_themes_ptr->get_id() == telegram_api::account_chatThemes::ID);
+ auto chat_themes = telegram_api::move_object_as(chat_themes_ptr);
+ chat_themes_.hash = chat_themes->hash_;
+ chat_themes_.themes.clear();
+ for (auto &chat_theme : chat_themes->themes_) {
+ if (chat_theme->emoticon_.empty()) {
+ LOG(ERROR) << "Receive " << to_string(chat_theme);
+ continue;
}
+
+ ChatTheme theme;
+ theme.emoji = std::move(chat_theme->emoticon_);
+ theme.light_id = chat_theme->theme_->id_;
+ theme.dark_id = chat_theme->dark_theme_->id_;
+ theme.light_theme = get_chat_theme_settings(std::move(chat_theme->theme_->settings_));
+ theme.dark_theme = get_chat_theme_settings(std::move(chat_theme->dark_theme_->settings_));
+ if (theme.light_theme.message_colors.empty() || theme.dark_theme.message_colors.empty()) {
+ continue;
+ }
+ chat_themes_.themes.push_back(std::move(theme));
}
- for (auto &promise : promises) {
- if (promise) {
- promise.set_value(get_chat_themes_object());
- }
- }
+ send_update_chat_themes();
}
ThemeManager::BaseTheme ThemeManager::get_base_theme(
@@ -184,4 +224,12 @@ ThemeManager::ThemeSettings ThemeManager::get_chat_theme_settings(
return result;
}
+void ThemeManager::get_current_state(vector> &updates) const {
+ if (!td_->auth_manager_->is_authorized() || td_->auth_manager_->is_bot() || chat_themes_.themes.empty()) {
+ return;
+ }
+
+ updates.push_back(get_update_chat_themes_object());
+}
+
} // namespace td
diff --git a/td/telegram/ThemeManager.h b/td/telegram/ThemeManager.h
index f3a4dbc3a..dc8fcb93d 100644
--- a/td/telegram/ThemeManager.h
+++ b/td/telegram/ThemeManager.h
@@ -25,7 +25,11 @@ class ThemeManager final : public Actor {
public:
ThemeManager(Td *td, ActorShared<> parent);
- void get_chat_themes(Promise> &&promise);
+ void init();
+
+ void on_update_theme(telegram_api::object_ptr &&theme, Promise &&promise);
+
+ void get_current_state(vector> &updates) const;
private:
enum class BaseTheme : int32 { Classic, Day, Night, Tinted, Arctic };
@@ -41,8 +45,14 @@ class ThemeManager final : public Actor {
bool animate_message_colors = false;
};
+ friend bool operator==(const ThemeSettings &lhs, const ThemeSettings &rhs);
+
+ friend bool operator!=(const ThemeSettings &lhs, const ThemeSettings &rhs);
+
struct ChatTheme {
string emoji;
+ int64 light_id = 0;
+ int64 dark_id = 0;
ThemeSettings light_theme;
ThemeSettings dark_theme;
};
@@ -53,6 +63,10 @@ class ThemeManager final : public Actor {
vector themes;
};
+ void start_up() final;
+
+ void loop() final;
+
void tear_down() final;
void on_get_chat_themes(Result> result);
@@ -61,14 +75,14 @@ class ThemeManager final : public Actor {
td_api::object_ptr get_chat_theme_object(const ChatTheme &theme) const;
- td_api::object_ptr get_chat_themes_object() const;
+ td_api::object_ptr get_update_chat_themes_object() const;
+
+ void send_update_chat_themes() const;
static BaseTheme get_base_theme(const telegram_api::object_ptr &base_theme);
ThemeSettings get_chat_theme_settings(telegram_api::object_ptr settings);
- vector>> pending_get_chat_themes_queries_;
-
ChatThemes chat_themes_;
Td *td_;
diff --git a/td/telegram/UpdatesManager.cpp b/td/telegram/UpdatesManager.cpp
index 0739e4219..0ba36bbe7 100644
--- a/td/telegram/UpdatesManager.cpp
+++ b/td/telegram/UpdatesManager.cpp
@@ -47,6 +47,7 @@
#include "td/telegram/StickersManager.h"
#include "td/telegram/Td.h"
#include "td/telegram/TdDb.h"
+#include "td/telegram/ThemeManager.h"
#include "td/telegram/WebPagesManager.h"
#include "td/actor/MultiPromise.h"
@@ -3206,10 +3207,10 @@ void UpdatesManager::on_update(tl_object_ptr update, Promise &&promise) {
- promise.set_value(Unit());
+ td_->theme_manager_->on_update_theme(std::move(update->theme_), std::move(promise));
}
+// unsupported updates
+
} // namespace td
diff --git a/td/telegram/UpdatesManager.h b/td/telegram/UpdatesManager.h
index 86df374c7..7a3ef1312 100644
--- a/td/telegram/UpdatesManager.h
+++ b/td/telegram/UpdatesManager.h
@@ -486,9 +486,9 @@ class UpdatesManager final : public Actor {
void on_update(tl_object_ptr update, Promise &&promise);
void on_update(tl_object_ptr update, Promise &&promise);
- // unsupported updates
-
void on_update(tl_object_ptr update, Promise &&promise);
+
+ // unsupported updates
};
} // namespace td
diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp
index 318edc1f2..d96c78a1d 100644
--- a/td/telegram/cli.cpp
+++ b/td/telegram/cli.cpp
@@ -1535,20 +1535,22 @@ class CliClient final : public Actor {
static td_api::object_ptr get_solid_pattern_background(int32 color, int32 intensity,
bool is_moving) {
- return get_gradient_pattern_background(color, color, intensity, is_moving);
+ return get_gradient_pattern_background(color, color, intensity, false, is_moving);
}
static td_api::object_ptr get_gradient_pattern_background(int32 top_color, int32 bottom_color,
- int32 intensity, bool is_moving) {
+ int32 intensity, bool is_inverted,
+ bool is_moving) {
return td_api::make_object(get_background_fill(top_color, bottom_color), intensity,
- is_moving);
+ is_inverted, is_moving);
}
static td_api::object_ptr get_freeform_gradient_pattern_background(vector colors,
int32 intensity,
+ bool is_inverted,
bool is_moving) {
return td_api::make_object(get_background_fill(std::move(colors)), intensity,
- is_moving);
+ is_inverted, is_moving);
}
static td_api::object_ptr get_solid_background(int32 color) {
@@ -2229,14 +2231,16 @@ class CliClient final : public Actor {
send_get_background_url(get_solid_pattern_background(0, 0, false));
send_get_background_url(get_solid_pattern_background(0xFFFFFF, 100, true));
send_get_background_url(get_solid_pattern_background(0xABCDEF, 49, true));
- send_get_background_url(get_gradient_pattern_background(0, 0, 0, false));
- send_get_background_url(get_gradient_pattern_background(0xFFFFFF, 0, 100, true));
- send_get_background_url(get_gradient_pattern_background(0xABCDEF, 0xFEDCBA, 49, true));
- send_get_background_url(get_gradient_pattern_background(0, 0x1000000, 49, true));
- send_get_background_url(get_freeform_gradient_pattern_background({0xABCDEF, 0xFEDCBA}, 49, true));
- send_get_background_url(get_freeform_gradient_pattern_background({0xABCDEF, 0x111111, 0x222222}, 49, true));
+ send_get_background_url(get_gradient_pattern_background(0, 0, 0, false, false));
+ send_get_background_url(get_gradient_pattern_background(0, 0, 0, true, false));
+ send_get_background_url(get_gradient_pattern_background(0xFFFFFF, 0, 100, false, true));
+ send_get_background_url(get_gradient_pattern_background(0xFFFFFF, 0, 100, true, true));
+ send_get_background_url(get_gradient_pattern_background(0xABCDEF, 0xFEDCBA, 49, false, true));
+ send_get_background_url(get_gradient_pattern_background(0, 0x1000000, 49, false, true));
+ send_get_background_url(get_freeform_gradient_pattern_background({0xABCDEF, 0xFEDCBA}, 49, false, true));
+ send_get_background_url(get_freeform_gradient_pattern_background({0xABCDEF, 0x111111, 0x222222}, 49, true, true));
send_get_background_url(
- get_freeform_gradient_pattern_background({0xABCDEF, 0xFEDCBA, 0x111111, 0x222222}, 49, true));
+ get_freeform_gradient_pattern_background({0xABCDEF, 0xFEDCBA, 0x111111, 0x222222}, 49, false, true));
send_get_background_url(get_solid_background(-1));
send_get_background_url(get_solid_background(0xABCDEF));
send_get_background_url(get_solid_background(0x1000000));
@@ -2261,7 +2265,7 @@ class CliClient final : public Actor {
} else if (op == "sbggp" || op == "sbggpd") {
send_request(td_api::make_object(
td_api::make_object(as_input_file(args)),
- get_gradient_pattern_background(0xABCDEF, 0xFE, 51, false), op == "sbggpd"));
+ get_gradient_pattern_background(0xABCDEF, 0xFE, 51, op == "sbggpd", false), op == "sbggpd"));
} else if (op == "sbgs" || op == "sbgsd") {
int32 color;
get_args(args, color);
@@ -2296,8 +2300,6 @@ class CliClient final : public Actor {
send_request(td_api::make_object(to_integer(args)));
} else if (op == "rbgs") {
send_request(td_api::make_object());
- } else if (op == "gcts") {
- send_request(td_api::make_object());
} else if (op == "gcos") {
send_request(td_api::make_object());
} else if (op == "gcoc") {
@@ -4050,6 +4052,8 @@ class CliClient final : public Actor {
send_request(td_api::make_object(as_chat_id(args)));
} else if (op == "crfcs") {
send_request(td_api::make_object());
+ } else if (op == "groc") {
+ send_request(td_api::make_object(as_limit(args)));
} else if (op == "gwpp") {
send_request(td_api::make_object(as_caption(args)));
} else if (op == "gwpiv") {
diff --git a/td/telegram/net/DcOptions.h b/td/telegram/net/DcOptions.h
index 848ec6084..eee4fd10e 100644
--- a/td/telegram/net/DcOptions.h
+++ b/td/telegram/net/DcOptions.h
@@ -172,7 +172,7 @@ class DcOption {
friend bool operator==(const DcOption &lhs, const DcOption &rhs);
- friend StringBuilder &operator<<(StringBuilder &sb, const DcOption::PrintFlags &flags);
+ friend StringBuilder &operator<<(StringBuilder &sb, const PrintFlags &flags);
friend StringBuilder &operator<<(StringBuilder &sb, const DcOption &dc_option);
diff --git a/td/tl/tl_json.h b/td/tl/tl_json.h
index 2c77c8a9b..9b5b6f282 100644
--- a/td/tl/tl_json.h
+++ b/td/tl/tl_json.h
@@ -17,6 +17,7 @@
#include "td/utils/SliceBuilder.h"
#include "td/utils/Status.h"
#include "td/utils/tl_storers.h"
+#include "td/utils/TlDowncastHelper.h"
#include
@@ -149,21 +150,6 @@ Status from_json(std::vector &to, JsonValue from) {
return Status::OK();
}
-template
-class DowncastHelper final : public T {
- public:
- explicit DowncastHelper(int32 constructor) : constructor_(constructor) {
- }
- int32 get_id() const final {
- return constructor_;
- }
- void store(TlStorerToString &s, const char *field_name) const final {
- }
-
- private:
- int32 constructor_{0};
-};
-
template
std::enable_if_t::value, Status> from_json(tl_object_ptr &to, JsonValue from) {
if (from.type() != JsonValue::Type::Object) {
@@ -185,7 +171,7 @@ std::enable_if_t::value, Status> from_json(tl_object_p
return Status::Error(PSLICE() << "Expected String or Integer, got " << constructor_value.type());
}
- DowncastHelper helper(constructor);
+ TlDowncastHelper helper(constructor);
Status status;
bool ok = downcast_call(static_cast(helper), [&](auto &dummy) {
auto result = make_tl_object>();
diff --git a/tdutils/CMakeLists.txt b/tdutils/CMakeLists.txt
index cf4c9c4ee..528c8eb19 100644
--- a/tdutils/CMakeLists.txt
+++ b/tdutils/CMakeLists.txt
@@ -256,10 +256,10 @@ set(TDUTILS_SOURCE
td/utils/Time.h
td/utils/TimedStat.h
td/utils/Timer.h
- td/utils/TsFileLog.h
td/utils/tl_helpers.h
td/utils/tl_parsers.h
td/utils/tl_storers.h
+ td/utils/TlDowncastHelper.h
td/utils/translit.h
td/utils/TsCerr.h
td/utils/TsFileLog.h
diff --git a/tdutils/td/utils/TlDowncastHelper.h b/tdutils/td/utils/TlDowncastHelper.h
new file mode 100644
index 000000000..c573683af
--- /dev/null
+++ b/tdutils/td/utils/TlDowncastHelper.h
@@ -0,0 +1,26 @@
+//
+// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+#pragma once
+
+namespace td {
+
+template
+class TlDowncastHelper final : public T {
+ public:
+ explicit TlDowncastHelper(int32 constructor) : constructor_(constructor) {
+ }
+ int32 get_id() const final {
+ return constructor_;
+ }
+ void store(TlStorerToString &s, const char *field_name) const final {
+ }
+
+ private:
+ int32 constructor_{0};
+};
+
+} // namespace td
diff --git a/tdutils/td/utils/port/wstring_convert.cpp b/tdutils/td/utils/port/wstring_convert.cpp
index 45ad32065..c81d0695f 100644
--- a/tdutils/td/utils/port/wstring_convert.cpp
+++ b/tdutils/td/utils/port/wstring_convert.cpp
@@ -10,6 +10,8 @@ char disable_linker_warning_about_empty_file_wstring_convert_cpp TD_UNUSED;
#if TD_PORT_WINDOWS
+#include "td/utils/base64.h"
+#include "td/utils/SliceBuilder.h"
#include "td/utils/utf8.h"
#include
@@ -18,7 +20,7 @@ namespace td {
Result to_wstring(CSlice slice) {
if (!check_utf8(slice)) {
- return Status::Error("Wrong string encoding");
+ return Status::Error(PSLICE() << "String was expected to be encoded in UTF-8: " << base64_encode(slice));
}
size_t wstring_len = utf8_utf16_length(slice);
|