Preload blocked users slice in Settings.

This commit is contained in:
John Preston 2019-05-24 15:06:17 +02:00
parent 8aaaef3ff4
commit 371f1a51c3
4 changed files with 149 additions and 18 deletions

View File

@ -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::Key> 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<AuthSession*> session)
: _session(session)
, _messageDataResolveDelayed([=] { resolveMessageDatas(); })
@ -2168,9 +2185,16 @@ void ApiWrap::blockUser(not_null<UserData*> 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<UserData*> 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<Privacy> {
}
}
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<MTPContactBlocked> &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<BlockedUsersSlice> {
if (!_blockedUsersSlice) {
reloadBlockedUsers();
}
return _blockedUsersSlice
? _blockedUsersChanges.events_starting_with_copy(*_blockedUsersSlice)
: (_blockedUsersChanges.events() | rpl::type_erased());
}
void ApiWrap::reloadSelfDestruct() {
if (_selfDestructRequestId) {
return;

View File

@ -83,6 +83,22 @@ public:
static std::optional<Key> 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<Item> list;
int total = 0;
bool operator==(const BlockedUsersSlice &other) const;
bool operator!=(const BlockedUsersSlice &other) const;
};
ApiWrap(not_null<AuthSession*> session);
void applyUpdates(const MTPUpdates &updates, uint64 sentMessageRandomId = 0);
@ -431,6 +447,9 @@ public:
void reloadPrivacy(Privacy::Key key);
rpl::producer<Privacy> privacyValue(Privacy::Key key);
void reloadBlockedUsers();
rpl::producer<BlockedUsersSlice> blockedUsersSlice();
void reloadSelfDestruct();
rpl::producer<int> selfDestructValue() const;
void saveSelfDestruct(int days);
@ -842,6 +861,10 @@ private:
base::flat_map<Privacy::Key, Privacy> _privacyValues;
std::map<Privacy::Key, rpl::event_stream<Privacy>> _privacyChanges;
mtpRequestId _blockedUsersRequestId = 0;
std::optional<BlockedUsersSlice> _blockedUsersSlice;
rpl::event_stream<BlockedUsersSlice> _blockedUsersChanges;
mtpRequestId _selfDestructRequestId = 0;
std::optional<int> _selfDestructDays;
rpl::event_stream<int> _selfDestructChanges;

View File

@ -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<MTPContactBlocked> &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();
}

View File

@ -96,13 +96,26 @@ rpl::producer<QString> PrivacyString(Privacy::Key key) {
});
}
rpl::producer<int> BlockedUsersCount() {
Auth().api().reloadBlockedUsers();
return Auth().api().blockedUsersSlice(
) | rpl::map([=](const ApiWrap::BlockedUsersSlice &data) {
return data.total;
});
}
void SetupPrivacy(not_null<Ui::VerticalLayout*> 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<PeerListBox*> box) {