From 371f1a51c35140044b39d278f413fd1076ec7b16 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 24 May 2019 15:06:17 +0200 Subject: [PATCH] Preload blocked users slice in Settings. --- Telegram/SourceFiles/apiwrap.cpp | 90 ++++++++++++++++++- Telegram/SourceFiles/apiwrap.h | 23 +++++ .../settings/settings_privacy_controllers.cpp | 39 ++++---- .../settings/settings_privacy_security.cpp | 15 +++- 4 files changed, 149 insertions(+), 18 deletions(-) diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index f80ebd13a0..25fc210bb4 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -90,6 +90,7 @@ constexpr auto kStickersByEmojiInvalidateTimeout = crl::time(60 * 60 * 1000); constexpr auto kNotifySettingSaveTimeout = crl::time(1000); constexpr auto kDialogsFirstLoad = 20; constexpr auto kDialogsPerPage = 500; +constexpr auto kBlockedFirstSlice = 16; using PhotoFileLocationId = Data::PhotoFileLocationId; using DocumentFileLocationId = Data::DocumentFileLocationId; @@ -208,6 +209,22 @@ std::optional ApiWrap::Privacy::KeyFromMTP( return std::nullopt; } +bool ApiWrap::BlockedUsersSlice::Item::operator==(const Item &other) const { + return (user == other.user) && (date == other.date); +} + +bool ApiWrap::BlockedUsersSlice::Item::operator!=(const Item &other) const { + return !(*this == other); +} + +bool ApiWrap::BlockedUsersSlice::operator==(const BlockedUsersSlice &other) const { + return (total == other.total) && (list == other.list); +} + +bool ApiWrap::BlockedUsersSlice::operator!=(const BlockedUsersSlice &other) const { + return !(*this == other); +} + ApiWrap::ApiWrap(not_null session) : _session(session) , _messageDataResolveDelayed([=] { resolveMessageDatas(); }) @@ -2168,9 +2185,16 @@ void ApiWrap::blockUser(not_null user) { if (user->isBlocked()) { Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserIsBlocked); } else if (_blockRequests.find(user) == end(_blockRequests)) { - auto requestId = request(MTPcontacts_Block(user->inputUser)).done([this, user](const MTPBool &result) { + const auto requestId = request(MTPcontacts_Block(user->inputUser)).done([this, user](const MTPBool &result) { _blockRequests.erase(user); user->setBlockStatus(UserData::BlockStatus::Blocked); + if (_blockedUsersSlice) { + _blockedUsersSlice->list.insert( + _blockedUsersSlice->list.begin(), + { user, unixtime() }); + ++_blockedUsersSlice->total; + _blockedUsersChanges.fire_copy(*_blockedUsersSlice); + } }).fail([this, user](const RPCError &error) { _blockRequests.erase(user); }).send(); @@ -2190,6 +2214,19 @@ void ApiWrap::unblockUser(not_null user) { )).done([=](const MTPBool &result) { _blockRequests.erase(user); user->setBlockStatus(UserData::BlockStatus::NotBlocked); + if (_blockedUsersSlice) { + auto &list = _blockedUsersSlice->list; + for (auto i = list.begin(); i != list.end(); ++i) { + if (i->user == user) { + list.erase(i); + break; + } + } + if (_blockedUsersSlice->total > list.size()) { + --_blockedUsersSlice->total; + } + _blockedUsersChanges.fire_copy(*_blockedUsersSlice); + } if (user->isBot() && !user->isSupport()) { sendBotStart(user); } @@ -5714,6 +5751,57 @@ auto ApiWrap::privacyValue(Privacy::Key key) -> rpl::producer { } } +void ApiWrap::reloadBlockedUsers() { + if (_blockedUsersRequestId) { + return; + } + _blockedUsersRequestId = request(MTPcontacts_GetBlocked( + MTP_int(0), + MTP_int(kBlockedFirstSlice) + )).done([=](const MTPcontacts_Blocked &result) { + _blockedUsersRequestId = 0; + const auto push = [&]( + int count, + const QVector &list) { + auto slice = BlockedUsersSlice(); + slice.total = std::max(count, list.size()); + slice.list.reserve(list.size()); + for (const auto &contact : list) { + contact.match([&](const MTPDcontactBlocked &data) { + const auto user = _session->data().userLoaded( + data.vuser_id.v); + if (user) { + user->setBlockStatus(UserData::BlockStatus::Blocked); + slice.list.push_back({ user, data.vdate.v }); + } + }); + } + if (!_blockedUsersSlice || *_blockedUsersSlice != slice) { + _blockedUsersSlice = slice; + _blockedUsersChanges.fire(std::move(slice)); + } + }; + result.match([&](const MTPDcontacts_blockedSlice &data) { + _session->data().processUsers(data.vusers); + push(data.vcount.v, data.vblocked.v); + }, [&](const MTPDcontacts_blocked &data) { + _session->data().processUsers(data.vusers); + push(0, data.vblocked.v); + }); + }).fail([=](const RPCError &error) { + _blockedUsersRequestId = 0; + }).send(); +} + +auto ApiWrap::blockedUsersSlice() -> rpl::producer { + if (!_blockedUsersSlice) { + reloadBlockedUsers(); + } + return _blockedUsersSlice + ? _blockedUsersChanges.events_starting_with_copy(*_blockedUsersSlice) + : (_blockedUsersChanges.events() | rpl::type_erased()); +} + void ApiWrap::reloadSelfDestruct() { if (_selfDestructRequestId) { return; diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 51bcbeaa6f..2db4513ec9 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -83,6 +83,22 @@ public: static std::optional KeyFromMTP(mtpTypeId type); }; + struct BlockedUsersSlice { + struct Item { + UserData *user = nullptr; + TimeId date = 0; + + bool operator==(const Item &other) const; + bool operator!=(const Item &other) const; + }; + + QVector list; + int total = 0; + + bool operator==(const BlockedUsersSlice &other) const; + bool operator!=(const BlockedUsersSlice &other) const; + }; + ApiWrap(not_null session); void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0); @@ -431,6 +447,9 @@ public: void reloadPrivacy(Privacy::Key key); rpl::producer privacyValue(Privacy::Key key); + void reloadBlockedUsers(); + rpl::producer blockedUsersSlice(); + void reloadSelfDestruct(); rpl::producer selfDestructValue() const; void saveSelfDestruct(int days); @@ -842,6 +861,10 @@ private: base::flat_map _privacyValues; std::map> _privacyChanges; + mtpRequestId _blockedUsersRequestId = 0; + std::optional _blockedUsersSlice; + rpl::event_stream _blockedUsersChanges; + mtpRequestId _selfDestructRequestId = 0; std::optional _selfDestructDays; rpl::event_stream _selfDestructChanges; diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index 1f26eebae3..473231e581 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -164,7 +164,21 @@ void BlockedBoxController::prepare() { } })); - loadMoreRows(); + _loadRequestId = -1; + Auth().api().blockedUsersSlice( + ) | rpl::take( + 1 + ) | rpl::start_with_next([=](const ApiWrap::BlockedUsersSlice &result) { + setDescriptionText(lang(lng_blocked_list_about)); + _loadRequestId = 0; + _offset = result.list.size(); + _allLoaded = (_offset >= result.total); + for (const auto item : result.list) { + appendRow(item.user); + }; + delegate()->peerListRefreshRows(); + loadMoreRows(); + }, lifetime()); } void BlockedBoxController::loadMoreRows() { @@ -178,10 +192,6 @@ void BlockedBoxController::loadMoreRows() { )).done([=](const MTPcontacts_Blocked &result) { _loadRequestId = 0; - if (!_offset) { - setDescriptionText(lang(lng_blocked_list_about)); - } - auto handleContactsBlocked = [](auto &list) { Auth().data().processUsers(list.vusers); return list.vblocked.v; @@ -219,17 +229,14 @@ void BlockedBoxController::receivedUsers(const QVector &resul _allLoaded = true; } - for_const (auto &item, result) { - ++_offset; - if (item.type() != mtpc_contactBlocked) { - continue; - } - auto &contactBlocked = item.c_contactBlocked(); - auto userId = contactBlocked.vuser_id.v; - if (auto user = Auth().data().userLoaded(userId)) { - appendRow(user); - user->setBlockStatus(UserData::BlockStatus::Blocked); - } + _offset += result.size(); + for (const auto &item : result) { + item.match([&](const MTPDcontactBlocked &data) { + if (const auto user = Auth().data().userLoaded(data.vuser_id.v)) { + appendRow(user); + user->setBlockStatus(UserData::BlockStatus::Blocked); + } + }); } delegate()->peerListRefreshRows(); } diff --git a/Telegram/SourceFiles/settings/settings_privacy_security.cpp b/Telegram/SourceFiles/settings/settings_privacy_security.cpp index 961e01ad95..c2693bf3cd 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_security.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_security.cpp @@ -96,13 +96,26 @@ rpl::producer PrivacyString(Privacy::Key key) { }); } +rpl::producer BlockedUsersCount() { + Auth().api().reloadBlockedUsers(); + return Auth().api().blockedUsersSlice( + ) | rpl::map([=](const ApiWrap::BlockedUsersSlice &data) { + return data.total; + }); +} + void SetupPrivacy(not_null container) { AddSkip(container, st::settingsPrivacySkip); AddSubsectionTitle(container, lng_settings_privacy_title); - AddButton( + auto count = BlockedUsersCount( + ) | rpl::map([](int count) { + return count ? QString::number(count) : QString(); + }); + AddButtonWithLabel( container, lng_settings_blocked_users, + std::move(count), st::settingsButton )->addClickHandler([] { const auto initBox = [](not_null box) {