177 lines
4.3 KiB
C++
177 lines
4.3 KiB
C++
/*
|
|
This file is part of Telegram Desktop,
|
|
the official desktop application for the Telegram messaging service.
|
|
|
|
For license and copyright information please follow this link:
|
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|
*/
|
|
#include "api/api_blocked_peers.h"
|
|
|
|
#include "apiwrap.h"
|
|
#include "base/unixtime.h"
|
|
#include "data/data_changes.h"
|
|
#include "data/data_peer.h"
|
|
#include "data/data_peer_id.h"
|
|
#include "data/data_session.h"
|
|
#include "main/main_session.h"
|
|
|
|
namespace Api {
|
|
namespace {
|
|
|
|
constexpr auto kBlockedFirstSlice = 16;
|
|
constexpr auto kBlockedPerPage = 40;
|
|
|
|
BlockedPeers::Slice TLToSlice(
|
|
const MTPcontacts_Blocked &blocked,
|
|
Data::Session &owner) {
|
|
const auto create = [&](int count, const QVector<MTPPeerBlocked> &list) {
|
|
auto slice = BlockedPeers::Slice();
|
|
slice.total = std::max(count, int(list.size()));
|
|
slice.list.reserve(list.size());
|
|
for (const auto &contact : list) {
|
|
contact.match([&](const MTPDpeerBlocked &data) {
|
|
slice.list.push_back({
|
|
.id = peerFromMTP(data.vpeer_id()),
|
|
.date = data.vdate().v,
|
|
});
|
|
});
|
|
}
|
|
return slice;
|
|
};
|
|
return blocked.match([&](const MTPDcontacts_blockedSlice &data) {
|
|
owner.processUsers(data.vusers());
|
|
owner.processChats(data.vchats());
|
|
return create(data.vcount().v, data.vblocked().v);
|
|
}, [&](const MTPDcontacts_blocked &data) {
|
|
owner.processUsers(data.vusers());
|
|
owner.processChats(data.vchats());
|
|
return create(0, data.vblocked().v);
|
|
});
|
|
}
|
|
|
|
} // namespace
|
|
|
|
BlockedPeers::BlockedPeers(not_null<ApiWrap*> api)
|
|
: _session(&api->session())
|
|
, _api(&api->instance()) {
|
|
}
|
|
|
|
bool BlockedPeers::Slice::Item::operator==(const Item &other) const {
|
|
return (id == other.id) && (date == other.date);
|
|
}
|
|
|
|
bool BlockedPeers::Slice::Item::operator!=(const Item &other) const {
|
|
return !(*this == other);
|
|
}
|
|
|
|
bool BlockedPeers::Slice::operator==(const BlockedPeers::Slice &other) const {
|
|
return (total == other.total) && (list == other.list);
|
|
}
|
|
|
|
bool BlockedPeers::Slice::operator!=(const BlockedPeers::Slice &other) const {
|
|
return !(*this == other);
|
|
}
|
|
|
|
void BlockedPeers::block(not_null<PeerData*> peer) {
|
|
if (peer->isBlocked()) {
|
|
_session->changes().peerUpdated(
|
|
peer,
|
|
Data::PeerUpdate::Flag::IsBlocked);
|
|
} else if (_blockRequests.find(peer) == end(_blockRequests)) {
|
|
const auto requestId = _api.request(MTPcontacts_Block(
|
|
peer->input
|
|
)).done([=] {
|
|
_blockRequests.erase(peer);
|
|
peer->setIsBlocked(true);
|
|
if (_slice) {
|
|
_slice->list.insert(
|
|
_slice->list.begin(),
|
|
{ peer->id, base::unixtime::now() });
|
|
++_slice->total;
|
|
_changes.fire_copy(*_slice);
|
|
}
|
|
}).fail([=] {
|
|
_blockRequests.erase(peer);
|
|
}).send();
|
|
|
|
_blockRequests.emplace(peer, requestId);
|
|
}
|
|
}
|
|
|
|
void BlockedPeers::unblock(
|
|
not_null<PeerData*> peer,
|
|
Fn<void()> onDone,
|
|
bool force) {
|
|
if (!force && !peer->isBlocked()) {
|
|
_session->changes().peerUpdated(
|
|
peer,
|
|
Data::PeerUpdate::Flag::IsBlocked);
|
|
return;
|
|
} else if (_blockRequests.find(peer) != end(_blockRequests)) {
|
|
return;
|
|
}
|
|
const auto requestId = _api.request(MTPcontacts_Unblock(
|
|
peer->input
|
|
)).done([=] {
|
|
_blockRequests.erase(peer);
|
|
peer->setIsBlocked(false);
|
|
if (_slice) {
|
|
auto &list = _slice->list;
|
|
for (auto i = list.begin(); i != list.end(); ++i) {
|
|
if (i->id == peer->id) {
|
|
list.erase(i);
|
|
break;
|
|
}
|
|
}
|
|
if (_slice->total > list.size()) {
|
|
--_slice->total;
|
|
}
|
|
_changes.fire_copy(*_slice);
|
|
}
|
|
if (onDone) {
|
|
onDone();
|
|
}
|
|
}).fail([=] {
|
|
_blockRequests.erase(peer);
|
|
}).send();
|
|
_blockRequests.emplace(peer, requestId);
|
|
}
|
|
|
|
void BlockedPeers::reload() {
|
|
if (_requestId) {
|
|
return;
|
|
}
|
|
request(0, [=](Slice &&slice) {
|
|
if (!_slice || *_slice != slice) {
|
|
_slice = slice;
|
|
_changes.fire(std::move(slice));
|
|
}
|
|
});
|
|
}
|
|
|
|
auto BlockedPeers::slice() -> rpl::producer<BlockedPeers::Slice> {
|
|
if (!_slice) {
|
|
reload();
|
|
}
|
|
return _slice
|
|
? _changes.events_starting_with_copy(*_slice)
|
|
: (_changes.events() | rpl::type_erased());
|
|
}
|
|
|
|
void BlockedPeers::request(int offset, Fn<void(BlockedPeers::Slice)> onDone) {
|
|
if (_requestId) {
|
|
return;
|
|
}
|
|
_requestId = _api.request(MTPcontacts_GetBlocked(
|
|
MTP_int(offset),
|
|
MTP_int(offset ? kBlockedPerPage : kBlockedFirstSlice)
|
|
)).done([=](const MTPcontacts_Blocked &result) {
|
|
_requestId = 0;
|
|
onDone(TLToSlice(result, _session->data()));
|
|
}).fail([=] {
|
|
_requestId = 0;
|
|
}).send();
|
|
}
|
|
|
|
} // namespace Api
|