diff --git a/td/telegram/Photo.cpp b/td/telegram/Photo.cpp index 17534742..06f3b659 100644 --- a/td/telegram/Photo.cpp +++ b/td/telegram/Photo.cpp @@ -135,9 +135,9 @@ tl_object_ptr get_profile_photo_object(FileManager *file_m if (profile_photo == nullptr || !profile_photo->small_file_id.is_valid()) { return nullptr; } - return make_tl_object(profile_photo->id, - file_manager->get_file_object(profile_photo->small_file_id), - file_manager->get_file_object(profile_photo->big_file_id)); + return td_api::make_object(profile_photo->id, + file_manager->get_file_object(profile_photo->small_file_id), + file_manager->get_file_object(profile_photo->big_file_id)); } bool operator==(const ProfilePhoto &lhs, const ProfilePhoto &rhs) { @@ -196,8 +196,8 @@ tl_object_ptr get_chat_photo_object(FileManager *file_manager if (dialog_photo == nullptr || !dialog_photo->small_file_id.is_valid()) { return nullptr; } - return make_tl_object(file_manager->get_file_object(dialog_photo->small_file_id), - file_manager->get_file_object(dialog_photo->big_file_id)); + return td_api::make_object(file_manager->get_file_object(dialog_photo->small_file_id), + file_manager->get_file_object(dialog_photo->big_file_id)); } bool operator==(const DialogPhoto &lhs, const DialogPhoto &rhs) { @@ -379,13 +379,17 @@ tl_object_ptr get_photo_size_object(FileManager *file_manager return nullptr; } - return make_tl_object( + return td_api::make_object( photo_size->type ? std::string(1, static_cast(photo_size->type)) : std::string(), // TODO replace string type with integer type file_manager->get_file_object(photo_size->file_id), photo_size->dimensions.width, photo_size->dimensions.height); } -void sort_photo_sizes(vector> &sizes) { +vector> get_photo_sizes_object(FileManager *file_manager, + const vector &photo_sizes) { + auto sizes = transform(photo_sizes, [file_manager](const PhotoSize &photo_size) { + return get_photo_size_object(file_manager, &photo_size); + }); std::sort(sizes.begin(), sizes.end(), [](const auto &lhs, const auto &rhs) { if (lhs->photo_->expected_size_ != rhs->photo_->expected_size_) { return lhs->photo_->expected_size_ < rhs->photo_->expected_size_; @@ -393,6 +397,7 @@ void sort_photo_sizes(vector> &sizes) { return static_cast(lhs->width_) * static_cast(lhs->height_) < static_cast(rhs->width_) * static_cast(rhs->height_); }); + return sizes; } bool operator==(const PhotoSize &lhs, const PhotoSize &rhs) { @@ -488,12 +493,7 @@ tl_object_ptr get_photo_object(FileManager *file_manager, const P return nullptr; } - vector> photos; - for (auto &photo_size : photo->photos) { - photos.push_back(get_photo_size_object(file_manager, &photo_size)); - } - sort_photo_sizes(photos); - return make_tl_object(photo->has_stickers, std::move(photos)); + return td_api::make_object(photo->has_stickers, get_photo_sizes_object(file_manager, photo->photos)); } tl_object_ptr get_user_profile_photo_object(FileManager *file_manager, const Photo *photo) { @@ -501,12 +501,8 @@ tl_object_ptr get_user_profile_photo_object(FileManage return nullptr; } - vector> photos; - for (auto &photo_size : photo->photos) { - photos.push_back(get_photo_size_object(file_manager, &photo_size)); - } - sort_photo_sizes(photos); - return make_tl_object(photo->id, photo->date, std::move(photos)); + return td_api::make_object(photo->id, photo->date, + get_photo_sizes_object(file_manager, photo->photos)); } void photo_delete_thumbnail(Photo &photo) { diff --git a/td/telegram/Photo.h b/td/telegram/Photo.h index ebfa266a..ce34117e 100644 --- a/td/telegram/Photo.h +++ b/td/telegram/Photo.h @@ -84,8 +84,9 @@ PhotoSize get_photo_size(FileManager *file_manager, FileType file_type, int64 id DialogId owner_dialog_id, tl_object_ptr &&size_ptr, bool is_webp); PhotoSize get_web_document_photo_size(FileManager *file_manager, FileType file_type, DialogId owner_dialog_id, tl_object_ptr web_document_ptr); -tl_object_ptr get_photo_size_object(FileManager *file_manager, const PhotoSize *photo_size); -void sort_photo_sizes(vector> &sizes); +td_api::object_ptr get_photo_size_object(FileManager *file_manager, const PhotoSize *photo_size); +vector> get_photo_sizes_object(FileManager *file_manager, + const vector &photo_sizes); bool operator==(const PhotoSize &lhs, const PhotoSize &rhs); bool operator!=(const PhotoSize &lhs, const PhotoSize &rhs); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index ce38c8fc..6be2655f 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2841,6 +2841,20 @@ class GetSupportUserRequest : public RequestActor<> { } }; +class GetWallpapersRequest : public RequestOnceActor { + void do_run(Promise &&promise) override { + td->wallpaper_manager_->get_wallpapers(std::move(promise)); + } + + void do_send_result() override { + send_result(td->wallpaper_manager_->get_wallpapers_object()); + } + + public: + GetWallpapersRequest(ActorShared td, uint64 request_id) : RequestOnceActor(std::move(td), request_id) { + } +}; + class GetRecentlyVisitedTMeUrlsRequest : public RequestActor> { string referrer_; @@ -6647,8 +6661,7 @@ void Td::on_request(uint64 id, const td_api::getSupportUser &request) { void Td::on_request(uint64 id, const td_api::getWallpapers &request) { CHECK_IS_USER(); - CREATE_REQUEST_PROMISE(); - send_closure(wallpaper_manager_actor_, &WallpaperManager::get_wallpapers, std::move(promise)); + CREATE_NO_ARGS_REQUEST(GetWallpapersRequest); } void Td::on_request(uint64 id, td_api::getRecentlyVisitedTMeUrls &request) { diff --git a/td/telegram/WallpaperManager.cpp b/td/telegram/WallpaperManager.cpp index 95422e03..3aa6378b 100644 --- a/td/telegram/WallpaperManager.cpp +++ b/td/telegram/WallpaperManager.cpp @@ -13,13 +13,15 @@ #include "td/telegram/Photo.h" #include "td/telegram/Td.h" +#include "td/utils/misc.h" + namespace td { class GetWallpapersQuery : public Td::ResultHandler { - Promise> promise_; + Promise>> promise_; public: - explicit GetWallpapersQuery(Promise> &&promise) + explicit GetWallpapersQuery(Promise>> &&promise) : promise_(std::move(promise)) { } @@ -33,38 +35,7 @@ class GetWallpapersQuery : public Td::ResultHandler { return on_error(id, result_ptr.move_as_error()); } - auto wallpapers = result_ptr.move_as_ok(); - - auto results = td_api::make_object(); - results->wallpapers_.reserve(wallpapers.size()); - for (auto &wallpaper_ptr : wallpapers) { - CHECK(wallpaper_ptr != nullptr); - switch (wallpaper_ptr->get_id()) { - case telegram_api::wallPaper::ID: { - auto wallpaper = move_tl_object_as(wallpaper_ptr); - vector> sizes; - sizes.reserve(wallpaper->sizes_.size()); - for (auto &size_ptr : wallpaper->sizes_) { - auto photo_size = get_photo_size(td->file_manager_.get(), FileType::Wallpaper, 0, 0, DialogId(), - std::move(size_ptr), false); - sizes.push_back(get_photo_size_object(td->file_manager_.get(), &photo_size)); - } - sort_photo_sizes(sizes); - results->wallpapers_.push_back( - td_api::make_object(wallpaper->id_, std::move(sizes), wallpaper->color_)); - break; - } - case telegram_api::wallPaperSolid::ID: { - auto wallpaper = move_tl_object_as(wallpaper_ptr); - results->wallpapers_.push_back(td_api::make_object( - wallpaper->id_, vector>(), wallpaper->bg_color_)); - break; - } - default: - UNREACHABLE(); - } - } - promise_.set_value(std::move(results)); + promise_.set_value(result_ptr.move_as_ok()); } void on_error(uint64 id, Status status) override { @@ -79,8 +50,70 @@ void WallpaperManager::tear_down() { parent_.reset(); } -void WallpaperManager::get_wallpapers(Promise> &&promise) { - td_->create_handler(std::move(promise))->send(); +void WallpaperManager::get_wallpapers(Promise &&promise) { + if (!wallpapers_.empty()) { + return promise.set_value(Unit()); + } + + pending_get_wallpapers_queries_.push_back(std::move(promise)); + if (pending_get_wallpapers_queries_.size() == 1) { + auto request_promise = PromiseCreator::lambda( + [actor_id = actor_id(this)](Result>> result) { + send_closure(actor_id, &WallpaperManager::on_get_wallpapers, std::move(result)); + }); + + td_->create_handler(std::move(request_promise))->send(); + } +} + +void WallpaperManager::on_get_wallpapers(Result>> result) { + CHECK(wallpapers_.empty()); + + auto promises = std::move(pending_get_wallpapers_queries_); + CHECK(!promises.empty()); + reset_to_empty(pending_get_wallpapers_queries_); + + if (result.is_error()) { + auto error = result.move_as_error(); + for (auto &promise : promises) { + promise.set_error(error.clone()); + } + return; + } + + wallpapers_ = transform(result.move_as_ok(), [file_manager = td_->file_manager_.get()]( + tl_object_ptr &&wallpaper_ptr) { + CHECK(wallpaper_ptr != nullptr); + switch (wallpaper_ptr->get_id()) { + case telegram_api::wallPaper::ID: { + auto wallpaper = move_tl_object_as(wallpaper_ptr); + vector sizes = transform( + std::move(wallpaper->sizes_), [file_manager](tl_object_ptr &&photo_size) { + return get_photo_size(file_manager, FileType::Wallpaper, 0, 0, DialogId(), std::move(photo_size), false); + }); + return Wallpaper{wallpaper->id_, std::move(sizes), wallpaper->color_}; + } + case telegram_api::wallPaperSolid::ID: { + auto wallpaper = move_tl_object_as(wallpaper_ptr); + return Wallpaper{wallpaper->id_, {}, wallpaper->bg_color_}; + } + default: + UNREACHABLE(); + return Wallpaper{0, {}, 0}; + } + }); + + for (auto &promise : promises) { + promise.set_value(Unit()); + } +} + +td_api::object_ptr WallpaperManager::get_wallpapers_object() const { + return td_api::make_object( + transform(wallpapers_, [file_manager = td_->file_manager_.get()](const Wallpaper &wallpaper) { + return td_api::make_object( + wallpaper.id, get_photo_sizes_object(file_manager, wallpaper.sizes), wallpaper.color); + })); } } // namespace td diff --git a/td/telegram/WallpaperManager.h b/td/telegram/WallpaperManager.h index d6702f54..6f3d1fc4 100644 --- a/td/telegram/WallpaperManager.h +++ b/td/telegram/WallpaperManager.h @@ -6,11 +6,14 @@ // #pragma once +#include "td/telegram/Photo.h" #include "td/telegram/td_api.h" #include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" +#include "td/utils/Status.h" + namespace td { class Td; @@ -19,11 +22,27 @@ class WallpaperManager : public Actor { public: WallpaperManager(Td *td, ActorShared<> parent); - void get_wallpapers(Promise> &&promise); + void get_wallpapers(Promise<> &&promise); + + td_api::object_ptr get_wallpapers_object() const; private: void tear_down() override; + void on_get_wallpapers(Result>> result); + + struct Wallpaper { + int32 id = 0; + vector sizes; + int32 color = 0; + + Wallpaper(int32 id, vector sizes, int32 color) : id(id), sizes(std::move(sizes)), color(color) { + } + }; + vector wallpapers_; + + vector> pending_get_wallpapers_queries_; + Td *td_; ActorShared<> parent_; };