diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 73e147e65..43e2a02a5 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1909,12 +1909,6 @@ savedMessagesTopicSavedFromChat chat_id:int53 = SavedMessagesTopic; //@last_message Last message in the topic; may be null if none or unknown foundSavedMessagesTopic topic:SavedMessagesTopic is_pinned:Bool order:int64 last_message:message = FoundSavedMessagesTopic; -//@description Contains a list of Saved Messages topics -//@total_count Total number of Saved Messages topics found -//@topics List of Saved Messages topics -//@next_offset The offset for the next request. If empty, then there are no more results -foundSavedMessagesTopics total_count:int32 topics:vector next_offset:string = FoundSavedMessagesTopics; - //@description Describes a forum topic icon @color Color of the topic icon in RGB format @custom_emoji_id Unique identifier of the custom emoji shown on the topic icon; 0 if none forumTopicIcon color:int32 custom_emoji_id:int64 = ForumTopicIcon; @@ -7248,13 +7242,9 @@ getSuitableDiscussionChats = Chats; getInactiveSupergroupChats = Chats; -//@description Returns list of all pinned Saved Messages topics -getPinnedSavedMessagesTopics = FoundSavedMessagesTopics; - -//@description Returns list of non-pinned Saved Messages topics from the specified offset -//@offset Offset of the first entry to return as received from the previous request; use empty string to get the first chunk of results -//@limit The maximum number of Saved Messages topics to be returned; up to 100 -getSavedMessagesTopics offset:string limit:int32 = FoundSavedMessagesTopics; +//@description Loads more Saved Messages topics. The loaded topics will be sent through updateSavedMessagesTopic. Topics are sorted by their topic.order in descending order. Returns a 404 error if all topics have been loaded +//@limit The maximum number of topics to be loaded. For optimal performance, the number of loaded topics is chosen by TDLib and can be smaller than the specified limit, even if the end of the list is not reached +loadSavedMessagesTopics limit:int32 = Ok; //@description Returns messages in a Saved Messages topic. The messages are returned in a reverse chronological order (i.e., in order of decreasing message_id) //@saved_messages_topic Saved Messages topic which messages will be fetched diff --git a/td/telegram/SavedMessagesManager.cpp b/td/telegram/SavedMessagesManager.cpp index e05e4bfcd..7088a0085 100644 --- a/td/telegram/SavedMessagesManager.cpp +++ b/td/telegram/SavedMessagesManager.cpp @@ -29,14 +29,15 @@ namespace td { class GetPinnedSavedDialogsQuery final : public Td::ResultHandler { - Promise> promise_; + Promise promise_; + int32 limit_; public: - explicit GetPinnedSavedDialogsQuery(Promise> &&promise) - : promise_(std::move(promise)) { + explicit GetPinnedSavedDialogsQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send() { + void send(int32 limit) { + limit_ = limit; send_query(G()->net_query_creator().create(telegram_api::messages_getPinnedSavedDialogs())); } @@ -48,7 +49,7 @@ class GetPinnedSavedDialogsQuery final : public Td::ResultHandler { auto result = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for GetPinnedSavedDialogsQuery: " << to_string(result); - td_->saved_messages_manager_->on_get_saved_messages_topics(true, std::move(result), std::move(promise_)); + td_->saved_messages_manager_->on_get_saved_messages_topics(true, limit_, std::move(result), std::move(promise_)); } void on_error(Status status) final { @@ -57,14 +58,15 @@ class GetPinnedSavedDialogsQuery final : public Td::ResultHandler { }; class GetSavedDialogsQuery final : public Td::ResultHandler { - Promise> promise_; + Promise promise_; + int32 limit_; public: - explicit GetSavedDialogsQuery(Promise> &&promise) - : promise_(std::move(promise)) { + explicit GetSavedDialogsQuery(Promise &&promise) : promise_(std::move(promise)) { } void send(int32 offset_date, MessageId offset_message_id, DialogId offset_dialog_id, int32 limit) { + limit_ = limit; auto input_peer = DialogManager::get_input_peer_force(offset_dialog_id); CHECK(input_peer != nullptr); @@ -82,7 +84,7 @@ class GetSavedDialogsQuery final : public Td::ResultHandler { auto result = result_ptr.move_as_ok(); LOG(INFO) << "Receive result for GetSavedDialogsQuery: " << to_string(result); - td_->saved_messages_manager_->on_get_saved_messages_topics(false, std::move(result), std::move(promise_)); + td_->saved_messages_manager_->on_get_saved_messages_topics(false, limit_, std::move(result), std::move(promise_)); } void on_error(Status status) final { @@ -409,56 +411,34 @@ void SavedMessagesManager::on_topic_changed(SavedMessagesTopic *topic) { send_update_saved_messages_topic(topic); } -void SavedMessagesManager::get_pinned_saved_messages_topics( - Promise> &&promise) { - td_->create_handler(std::move(promise))->send(); -} - -void SavedMessagesManager::get_saved_messages_topics( - const string &offset, int32 limit, Promise> &&promise) { - int32 offset_date = std::numeric_limits::max(); - DialogId offset_dialog_id; - MessageId offset_message_id; - bool is_offset_valid = [&] { - if (offset.empty()) { - return true; - } - - auto parts = full_split(offset, ','); - if (parts.size() != 3) { - return false; - } - auto r_offset_date = to_integer_safe(parts[0]); - auto r_offset_dialog_id = to_integer_safe(parts[1]); - auto r_offset_message_id = to_integer_safe(parts[2]); - if (r_offset_date.is_error() || r_offset_date.ok() <= 0 || r_offset_message_id.is_error() || - r_offset_dialog_id.is_error()) { - return false; - } - offset_date = r_offset_date.ok(); - offset_message_id = MessageId(ServerMessageId(r_offset_message_id.ok())); - offset_dialog_id = DialogId(r_offset_dialog_id.ok()); - if (!offset_message_id.is_valid() || !offset_dialog_id.is_valid() || - DialogManager::get_input_peer_force(offset_dialog_id)->get_id() == telegram_api::inputPeerEmpty::ID) { - return false; - } - return true; - }(); - if (!is_offset_valid) { - return promise.set_error(Status::Error(400, "Invalid offset specified")); - } - +void SavedMessagesManager::load_saved_messages_topics(int32 limit, Promise &&promise) { if (limit < 0) { return promise.set_error(Status::Error(400, "Limit must be non-negative")); } + if (limit == 0) { + return promise.set_value(Unit()); + } + if (topic_list_.last_topic_date_ == MAX_TOPIC_DATE) { + return promise.set_error(Status::Error(404, "Not Found")); + } + if (!are_pinned_saved_messages_topics_inited_) { + return get_pinned_saved_dialogs(limit, std::move(promise)); + } + get_saved_dialogs(limit, std::move(promise)); +} +void SavedMessagesManager::get_pinned_saved_dialogs(int32 limit, Promise &&promise) { + td_->create_handler(std::move(promise))->send(limit); +} + +void SavedMessagesManager::get_saved_dialogs(int32 limit, Promise &&promise) { td_->create_handler(std::move(promise)) - ->send(offset_date, offset_message_id, offset_dialog_id, limit); + ->send(topic_list_.offset_date_, topic_list_.offset_message_id_, topic_list_.offset_dialog_id_, limit); } void SavedMessagesManager::on_get_saved_messages_topics( - bool is_pinned, telegram_api::object_ptr &&saved_dialogs_ptr, - Promise> &&promise) { + bool is_pinned, int32 limit, telegram_api::object_ptr &&saved_dialogs_ptr, + Promise &&promise) { CHECK(saved_dialogs_ptr != nullptr); int32 total_count = -1; vector> dialogs; @@ -492,6 +472,7 @@ void SavedMessagesManager::on_get_saved_messages_topics( messages = std::move(saved_dialogs->messages_); chats = std::move(saved_dialogs->chats_); users = std::move(saved_dialogs->users_); + is_last = dialogs.empty(); break; } default: @@ -514,7 +495,6 @@ void SavedMessagesManager::on_get_saved_messages_topics( MessageId last_message_id; DialogId last_dialog_id; vector added_saved_messages_topic_ids; - vector> found_saved_messages_topics; for (auto &dialog : dialogs) { auto peer_dialog_id = DialogId(dialog->peer_); if (!peer_dialog_id.is_valid()) { @@ -546,9 +526,8 @@ void SavedMessagesManager::on_get_saved_messages_topics( continue; } auto message_date = MessagesManager::get_message_date(it->second); - if (message_date > 0) { - if (!is_pinned && last_message_date != 0 && - (last_message_date < message_date || last_message_id < last_topic_message_id)) { + if (!is_pinned && message_date > 0) { + if (last_message_date != 0 && (last_message_date < message_date || last_message_id < last_topic_message_id)) { LOG(ERROR) << "Receive " << last_topic_message_id << " at " << message_date << " after " << last_message_id << " at " << last_message_date; } @@ -562,7 +541,7 @@ void SavedMessagesManager::on_get_saved_messages_topics( if (full_message_id.get_dialog_id() != td_->dialog_manager_->get_my_dialog_id()) { if (full_message_id.get_dialog_id() != DialogId()) { - LOG(ERROR) << "Can't add last " << last_message_id << " to " << saved_messages_topic_id; + LOG(ERROR) << "Can't add last " << last_topic_message_id << " to " << saved_messages_topic_id; } total_count--; continue; @@ -574,11 +553,13 @@ void SavedMessagesManager::on_get_saved_messages_topics( do_set_topic_last_message_id(topic, last_topic_message_id, message_date); } on_topic_changed(topic); - - found_saved_messages_topics.push_back(get_found_saved_messages_topic_object(topic)); } if (is_pinned) { + if (!are_pinned_saved_messages_topics_inited_ && total_count < limit) { + get_saved_dialogs(limit - total_count, std::move(promise)); + promise = Promise(); + } are_pinned_saved_messages_topics_inited_ = true; set_pinned_saved_messages_topics(std::move(added_saved_messages_topic_ids)); set_last_topic_date({MIN_PINNED_TOPIC_ORDER - 1, SavedMessagesTopicId()}); @@ -586,15 +567,21 @@ void SavedMessagesManager::on_get_saved_messages_topics( set_last_topic_date(MAX_TOPIC_DATE); } else if (last_message_date > 0) { set_last_topic_date({get_topic_order(last_message_date, last_message_id), SavedMessagesTopicId(last_dialog_id)}); + } else { + LOG(ERROR) << "Receive no suitable topics"; + set_last_topic_date(MAX_TOPIC_DATE); } - string next_offset; - if (last_message_date > 0 && !is_last) { - next_offset = PSTRING() << last_message_date << ',' << last_dialog_id.get() << ',' - << last_message_id.get_server_message_id().get(); + if (!is_pinned) { + topic_list_.offset_date_ = last_message_date; + topic_list_.offset_dialog_id_ = last_dialog_id; + topic_list_.offset_message_id_ = last_message_id; + + if (is_last && dialogs.empty()) { + return promise.set_error(Status::Error(404, "Not Found")); + } } - promise.set_value(td_api::make_object( - total_count, std::move(found_saved_messages_topics), next_offset)); + promise.set_value(Unit()); } td_api::object_ptr SavedMessagesManager::get_found_saved_messages_topic_object( @@ -888,7 +875,7 @@ void SavedMessagesManager::reload_pinned_saved_messages_topics() { return; } - td_->create_handler(Auto())->send(); + get_pinned_saved_dialogs(0, Auto()); } void SavedMessagesManager::get_current_state(vector> &updates) const { diff --git a/td/telegram/SavedMessagesManager.h b/td/telegram/SavedMessagesManager.h index e04b88e96..1528dd2ae 100644 --- a/td/telegram/SavedMessagesManager.h +++ b/td/telegram/SavedMessagesManager.h @@ -33,14 +33,11 @@ class SavedMessagesManager final : public Actor { void on_topic_message_deleted(SavedMessagesTopicId saved_messages_topic_id, MessageId message_id); - void get_pinned_saved_messages_topics(Promise> &&promise); + void load_saved_messages_topics(int32 limit, Promise &&promsie); - void get_saved_messages_topics(const string &offset, int32 limit, - Promise> &&promise); - - void on_get_saved_messages_topics(bool is_pinned, + void on_get_saved_messages_topics(bool is_pinned, int32 limit, telegram_api::object_ptr &&saved_dialogs_ptr, - Promise> &&promise); + Promise &&promise); void get_saved_messages_topic_history(SavedMessagesTopicId saved_messages_topic_id, MessageId from_message_id, int32 offset, int32 limit, @@ -95,6 +92,10 @@ class SavedMessagesManager final : public Actor { (order_ == other.order_ && topic_id_.get_unique_id() >= other.topic_id_.get_unique_id()); } + bool operator==(const TopicDate &other) const { + return order_ == other.order_ && topic_id_ == other.topic_id_; + } + SavedMessagesTopicId get_topic_id() const { return topic_id_; } @@ -107,6 +108,10 @@ class SavedMessagesManager final : public Actor { std::set ordered_topics_; TopicDate last_topic_date_ = MIN_TOPIC_DATE; // in memory + + int32 offset_date_ = std::numeric_limits::max(); + DialogId offset_dialog_id_; + MessageId offset_message_id_; }; void tear_down() final; @@ -115,6 +120,10 @@ class SavedMessagesManager final : public Actor { SavedMessagesTopic *add_topic(SavedMessagesTopicId saved_messages_topic_id); + void get_pinned_saved_dialogs(int32 limit, Promise &&promise); + + void get_saved_dialogs(int32 limit, Promise &&promise); + void on_get_saved_messages_topic_history(SavedMessagesTopicId saved_messages_topic_id, MessageId from_message_id, Result &&r_info, Promise> &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 2a622ba3f..8686bd501 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -5057,17 +5057,10 @@ void Td::on_request(uint64 id, const td_api::getChats &request) { messages_manager_->get_dialogs_from_list(DialogListId(request.chat_list_), request.limit_, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::getPinnedSavedMessagesTopics &request) { +void Td::on_request(uint64 id, const td_api::loadSavedMessagesTopics &request) { CHECK_IS_USER(); - CREATE_REQUEST_PROMISE(); - saved_messages_manager_->get_pinned_saved_messages_topics(std::move(promise)); -} - -void Td::on_request(uint64 id, const td_api::getSavedMessagesTopics &request) { - CHECK_IS_USER(); - // don't need to check offset UTF-8 correctness - CREATE_REQUEST_PROMISE(); - saved_messages_manager_->get_saved_messages_topics(request.offset_, request.limit_, std::move(promise)); + CREATE_OK_REQUEST_PROMISE(); + saved_messages_manager_->load_saved_messages_topics(request.limit_, std::move(promise)); } void Td::on_request(uint64 id, const td_api::getSavedMessagesTopicHistory &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 584f0ff4a..bb44d921b 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -676,9 +676,7 @@ class Td final : public Actor { void on_request(uint64 id, const td_api::getChats &request); - void on_request(uint64 id, const td_api::getPinnedSavedMessagesTopics &request); - - void on_request(uint64 id, const td_api::getSavedMessagesTopics &request); + void on_request(uint64 id, const td_api::loadSavedMessagesTopics &request); void on_request(uint64 id, const td_api::getSavedMessagesTopicHistory &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 314b0e198..8bf1ad22b 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2754,13 +2754,10 @@ class CliClient final : public Actor { send_request(td_api::make_object(nullptr, 1)); send_request(td_api::make_object(nullptr, 10)); send_request(td_api::make_object(nullptr, 5)); - } else if (op == "gpsmt") { - send_request(td_api::make_object()); - } else if (op == "gsmt") { + } else if (op == "lsmt") { string limit; - string offset; - get_args(args, limit, offset); - send_request(td_api::make_object(offset, as_limit(limit))); + get_args(args, limit); + send_request(td_api::make_object(as_limit(limit))); } else if (op == "gsmth") { MessageId from_message_id; int32 offset;