diff --git a/Telegram/SourceFiles/api/api_invite_links.cpp b/Telegram/SourceFiles/api/api_invite_links.cpp index f39e609aa1..f072876c60 100644 --- a/Telegram/SourceFiles/api/api_invite_links.cpp +++ b/Telegram/SourceFiles/api/api_invite_links.cpp @@ -759,6 +759,15 @@ void InviteLinks::requestMoreLinks( }).send(); } +void InviteLinks::pushRecentRequests(RecentRequests &&requests) { + _recentRequestsLocal.fire(std::move(requests)); +} + +auto InviteLinks::recentRequestsLocal() const +-> rpl::producer { + return _recentRequestsLocal.events(); +} + void InviteLinks::editPermanentLink( not_null peer, const QString &link) { diff --git a/Telegram/SourceFiles/api/api_invite_links.h b/Telegram/SourceFiles/api/api_invite_links.h index 0ade698563..01eee58ee5 100644 --- a/Telegram/SourceFiles/api/api_invite_links.h +++ b/Telegram/SourceFiles/api/api_invite_links.h @@ -132,6 +132,13 @@ public: bool revoked, Fn done); + struct RecentRequests { + not_null peer; + std::vector> users; + }; + void pushRecentRequests(RecentRequests &&requests); + [[nodiscard]] rpl::producer recentRequestsLocal() const; + private: struct LinkKey { not_null peer; @@ -216,6 +223,7 @@ private: base::flat_map< std::pair, not_null>, ProcessRequest> _processRequests; + rpl::event_stream _recentRequestsLocal; rpl::event_stream _updates; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp index 87ede518d0..68dad14955 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/peer_list_controllers.h" #include "boxes/peers/edit_participants_box.h" // SubscribeToMigration #include "boxes/peers/edit_peer_invite_link.h" // PrepareRequestedRowStatus +#include "history/view/history_view_requests_bar.h" // kRecentRequestsLimit #include "data/data_peer.h" #include "data/data_user.h" #include "data/data_chat.h" @@ -382,6 +383,7 @@ void RequestsBoxController::processRequest( Ui::Text::WithEntities) }); } + pushRecentRequests(); }); const auto fail = [] {}; session().api().inviteLinks().processRequest( @@ -393,6 +395,24 @@ void RequestsBoxController::processRequest( fail); } +void RequestsBoxController::pushRecentRequests() { + const auto count = std::min( + delegate()->peerListFullRowsCount(), + HistoryView::kRecentRequestsLimit); + if (!count) { + return; + } + auto requests = std::vector>(); + requests.reserve(count); + for (auto i = 0; i != count; ++i) { + requests.push_back(delegate()->peerListRowAt(i)->peer()->asUser()); + } + session().api().inviteLinks().pushRecentRequests({ + .peer = _peer, + .users = std::move(requests), + }); +} + void RequestsBoxController::appendRow( not_null user, TimeId date) { diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.h index cedba9e318..ed87e944a5 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.h +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_requests_box.h @@ -58,6 +58,7 @@ private: void appendRow(not_null user, TimeId date); void refreshDescription(); void processRequest(not_null user, bool approved); + void pushRecentRequests(); void subscribeToMigration(); void migrate(not_null chat, not_null channel); diff --git a/Telegram/SourceFiles/history/view/history_view_requests_bar.cpp b/Telegram/SourceFiles/history/view/history_view_requests_bar.cpp index fa4b8eaac5..b5fc4fff9b 100644 --- a/Telegram/SourceFiles/history/view/history_view_requests_bar.cpp +++ b/Telegram/SourceFiles/history/view/history_view_requests_bar.cpp @@ -17,12 +17,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/group_call_userpics.h" #include "info/profile/info_profile_values.h" #include "apiwrap.h" +#include "api/api_invite_links.h" namespace HistoryView { namespace { // If less than 10 requests we request userpics each time the count changes. -constexpr auto kRequestAgainThreshold = 10; +constexpr auto kRequestExactThreshold = 10; } // namespace @@ -31,27 +32,25 @@ rpl::producer RequestsBarContentByPeer( int userpicSize) { struct State { explicit State(not_null peer) - : api(&peer->session().api()) { + : peer(peer) { current.isGroup = !peer->isBroadcast(); } ~State() { if (requestId) { - api->request(requestId).cancel(); + peer->session().api().request(requestId).cancel(); } } - not_null api; + not_null peer; std::vector userpics; std::vector> users; Ui::RequestsBarContent current; base::has_weak_ptr guard; mtpRequestId requestId = 0; - Fn requestUsers; bool someUserpicsNotLoaded = false; bool pushScheduled = false; }; - static constexpr auto kLimit = 3; static const auto FillUserpics = []( not_null state) { const auto &users = state->users; @@ -114,6 +113,60 @@ rpl::producer RequestsBarContentByPeer( return true; }; + static const auto RequestExact = []( + not_null state, + int userpicSize, + Fn push, + auto requestExact) { + if (state->requestId) { + return; + } + using Flag = MTPmessages_GetChatInviteImporters::Flag; + state->requestId = state->peer->session().api().request( + MTPmessages_GetChatInviteImporters( + MTP_flags(Flag::f_requested), + state->peer->input, + MTPstring(), // link + MTPstring(), // q + MTP_int(0), // offset_date + MTP_inputUserEmpty(), // offset_user + MTP_int(kRecentRequestsLimit)) + ).done([=](const MTPmessages_ChatInviteImporters &result) { + state->requestId = 0; + + result.match([&]( + const MTPDmessages_chatInviteImporters &data) { + const auto count = data.vcount().v; + const auto changed = (state->current.count != count); + const auto &importers = data.vimporters().v; + auto &owner = state->peer->owner(); + state->users = std::vector>(); + const auto use = std::min( + importers.size(), + HistoryView::kRecentRequestsLimit); + state->users.reserve(use); + for (auto i = 0; i != use; ++i) { + importers[i].match([&]( + const MTPDchatInviteImporter &data) { + state->users.push_back( + owner.user(data.vuser_id())); + }); + } + if (changed) { + state->current.count = count; + } + if (RegenerateUserpics(state, userpicSize) || changed) { + push(); + } + if (state->userpics.size() > state->current.count) { + requestExact(state, userpicSize, push, requestExact); + } + }); + }).fail([=](const MTP::Error &error) { + state->requestId = 0; + }).send(); + }; + return [=](auto consumer) { const auto api = &peer->session().api(); @@ -121,7 +174,9 @@ rpl::producer RequestsBarContentByPeer( auto state = lifetime.make_state(peer); const auto pushNext = [=] { - if (state->pushScheduled) { + if (state->pushScheduled + || (std::min(state->current.count, kRecentRequestsLimit) + != state->users.size())) { return; } state->pushScheduled = true; @@ -131,53 +186,6 @@ rpl::producer RequestsBarContentByPeer( }); }; - state->requestUsers = [=] { - if (state->requestId) { - return; - } - using Flag = MTPmessages_GetChatInviteImporters::Flag; - state->requestId = state->api->request( - MTPmessages_GetChatInviteImporters( - MTP_flags(Flag::f_requested), - peer->input, - MTPstring(), // link - MTPstring(), // q - MTP_int(0), // offset_date - MTP_inputUserEmpty(), // offset_user - MTP_int(kLimit)) - ).done([=](const MTPmessages_ChatInviteImporters &result) { - state->requestId = 0; - - result.match([&]( - const MTPDmessages_chatInviteImporters &data) { - const auto count = data.vcount().v; - const auto changed = (state->current.count != count); - const auto &importers = data.vimporters().v; - auto &owner = peer->owner(); - state->users = std::vector>(); - state->users.reserve(importers.size()); - for (const auto &importer : importers) { - importer.match([&]( - const MTPDchatInviteImporter &data) { - state->users.push_back( - owner.user(data.vuser_id())); - }); - } - if (changed) { - state->current.count = count; - } - if (RegenerateUserpics(state, userpicSize) || changed) { - pushNext(); - } - if (state->userpics.size() > state->current.count) { - state->requestUsers(); - } - }); - }).fail([=](const MTP::Error &error) { - state->requestId = 0; - }).send(); - }; - peer->session().downloaderTaskFinished( ) | rpl::filter([=] { return state->someUserpicsNotLoaded; @@ -198,15 +206,28 @@ rpl::producer RequestsBarContentByPeer( return (state->current.count != count); }) | rpl::start_with_next([=](int count) { const auto was = state->current.count; - const auto requestUsersNeeded = (was < kRequestAgainThreshold) - || (count < kRequestAgainThreshold); + const auto requestUsersNeeded = (was < kRequestExactThreshold) + || (count < kRequestExactThreshold); state->current.count = count; if (requestUsersNeeded) { - state->requestUsers(); + RequestExact(state, userpicSize, pushNext, RequestExact); } pushNext(); }, lifetime); + using RecentRequests = Api::InviteLinks::RecentRequests; + api->inviteLinks().recentRequestsLocal( + ) | rpl::filter([=](const RecentRequests &value) { + return (value.peer == peer) + && (state->current.count >= kRequestExactThreshold) + && (value.users.size() == kRecentRequestsLimit); + }) | rpl::start_with_next([=](RecentRequests &&value) { + state->users = std::move(value.users); + if (RegenerateUserpics(state, userpicSize)) { + pushNext(); + } + }, lifetime); + return lifetime; }; } diff --git a/Telegram/SourceFiles/history/view/history_view_requests_bar.h b/Telegram/SourceFiles/history/view/history_view_requests_bar.h index 772214df1e..1fa4a289f8 100644 --- a/Telegram/SourceFiles/history/view/history_view_requests_bar.h +++ b/Telegram/SourceFiles/history/view/history_view_requests_bar.h @@ -15,6 +15,8 @@ struct RequestsBarContent; namespace HistoryView { +inline constexpr auto kRecentRequestsLimit = 3; + [[nodiscard]] rpl::producer RequestsBarContentByPeer( not_null peer, int userpicSize);