Save privacy in ApiWrap. Handle privacy updates.

This commit is contained in:
John Preston 2017-03-17 20:19:46 +03:00
parent 346daee421
commit fc77b0a51c
9 changed files with 168 additions and 29 deletions

View File

@ -923,6 +923,140 @@ bool ApiWrap::hasUnsavedDrafts() const {
return !_draftsSaveRequestIds.isEmpty();
}
void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacyRule> &&rules) {
auto keyTypeId = key.type();
auto it = _privacySaveRequests.find(keyTypeId);
if (it != _privacySaveRequests.cend()) {
MTP::cancel(it.value());
_privacySaveRequests.erase(it);
}
auto requestId = MTP::send(MTPaccount_SetPrivacy(key, MTP_vector<MTPInputPrivacyRule>(std::move(rules))), rpcDone(&ApiWrap::savePrivacyDone, keyTypeId), rpcFail(&ApiWrap::savePrivacyFail, keyTypeId));
_privacySaveRequests.insert(keyTypeId, requestId);
}
void ApiWrap::savePrivacyDone(mtpTypeId keyTypeId, const MTPaccount_PrivacyRules &result) {
Expects(result.type() == mtpc_account_privacyRules);
auto &rules = result.c_account_privacyRules();
App::feedUsers(rules.vusers);
_privacySaveRequests.remove(keyTypeId);
handlePrivacyChange(keyTypeId, rules.vrules);
}
bool ApiWrap::savePrivacyFail(mtpTypeId keyTypeId, const RPCError &error) {
if (MTP::isDefaultHandledError(error)) {
return false;
}
_privacySaveRequests.remove(keyTypeId);
return true;
}
void ApiWrap::handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules) {
if (keyTypeId == mtpc_privacyKeyStatusTimestamp) {
enum class Rule {
Unknown,
Allow,
Disallow,
};
auto userRules = QMap<UserId, Rule>();
auto contactsRule = Rule::Unknown;
auto everyoneRule = Rule::Unknown;
for (auto &rule : rules.v) {
auto type = rule.type();
if (type != mtpc_privacyValueAllowAll && type != mtpc_privacyValueDisallowAll && contactsRule != Rule::Unknown) {
// This is simplified: we ignore per-user rules that come after a contacts rule.
// But none of the official apps provide such complicated rule sets, so its fine.
continue;
}
switch (type) {
case mtpc_privacyValueAllowAll: everyoneRule = Rule::Allow; break;
case mtpc_privacyValueDisallowAll: everyoneRule = Rule::Disallow; break;
case mtpc_privacyValueAllowContacts: contactsRule = Rule::Allow; break;
case mtpc_privacyValueDisallowContacts: contactsRule = Rule::Disallow; break;
case mtpc_privacyValueAllowUsers: {
for_const (auto &userId, rule.c_privacyValueAllowUsers().vusers.v) {
if (!userRules.contains(userId.v)) {
userRules.insert(userId.v, Rule::Allow);
}
}
} break;
case mtpc_privacyValueDisallowUsers: {
for_const (auto &userId, rule.c_privacyValueDisallowUsers().vusers.v) {
if (!userRules.contains(userId.v)) {
userRules.insert(userId.v, Rule::Disallow);
}
}
} break;
}
if (everyoneRule != Rule::Unknown) {
break;
}
}
auto now = unixtime();
App::enumerateUsers([&userRules, contactsRule, everyoneRule, now](UserData *user) {
if (user->isSelf() || user->loadedStatus != PeerData::FullLoaded) {
return;
}
if (user->onlineTill <= 0) {
return;
}
if (user->onlineTill + 3 * 86400 >= now) {
user->onlineTill = -2; // recently
} else if (user->onlineTill + 7 * 86400 >= now) {
user->onlineTill = -3; // last week
} else if (user->onlineTill + 30 * 86400 >= now) {
user->onlineTill = -4; // last month
} else {
user->onlineTill = 0;
}
Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserOnlineChanged);
});
if (_contactsStatusesRequestId) {
MTP::cancel(_contactsStatusesRequestId);
}
_contactsStatusesRequestId = MTP::send(MTPcontacts_GetStatuses(), rpcDone(&ApiWrap::contactsStatusesDone), rpcFail(&ApiWrap::contactsStatusesFail));
}
}
int ApiWrap::onlineTillFromStatus(const MTPUserStatus &status, int currentOnlineTill) {
switch (status.type()) {
case mtpc_userStatusEmpty: return 0;
case mtpc_userStatusRecently: return (currentOnlineTill > -10) ? -2 : currentOnlineTill; // don't modify pseudo-online
case mtpc_userStatusLastWeek: return -3;
case mtpc_userStatusLastMonth: return -4;
case mtpc_userStatusOffline: return status.c_userStatusOffline().vwas_online.v;
case mtpc_userStatusOnline: return status.c_userStatusOnline().vexpires.v;
}
Unexpected("Bad UserStatus type.");
}
void ApiWrap::contactsStatusesDone(const MTPVector<MTPContactStatus> &result) {
_contactsStatusesRequestId = 0;
for_const (auto &item, result.v) {
t_assert(item.type() == mtpc_contactStatus);
auto &data = item.c_contactStatus();
if (auto user = App::userLoaded(data.vuser_id.v)) {
auto oldOnlineTill = user->onlineTill;
auto newOnlineTill = onlineTillFromStatus(data.vstatus, oldOnlineTill);
if (oldOnlineTill != newOnlineTill) {
user->onlineTill = newOnlineTill;
Notify::peerUpdatedDelayed(user, Notify::PeerUpdate::Flag::UserOnlineChanged);
}
}
}
}
bool ApiWrap::contactsStatusesFail(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) {
return false;
}
_contactsStatusesRequestId = 0;
return true;
}
void ApiWrap::saveDraftsToCloud() {
for (auto i = _draftsSaveRequestIds.begin(), e = _draftsSaveRequestIds.end(); i != e; ++i) {
if (i.value()) continue; // sent already

View File

@ -76,6 +76,10 @@ public:
void saveDraftToCloudDelayed(History *history);
bool hasUnsavedDrafts() const;
void savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacyRule> &&rules);
void handlePrivacyChange(mtpTypeId keyTypeId, const MTPVector<MTPPrivacyRule> &rules);
int onlineTillFromStatus(const MTPUserStatus &status, int currentOnlineTill);
~ApiWrap();
signals:
@ -179,4 +183,12 @@ private:
void stickersClearRecentDone(const MTPBool &result);
bool stickersClearRecentFail(const RPCError &result);
QMap<mtpTypeId, mtpRequestId> _privacySaveRequests;
void savePrivacyDone(mtpTypeId keyTypeId, const MTPaccount_PrivacyRules &result);
bool savePrivacyFail(mtpTypeId keyTypeId, const RPCError &error);
mtpRequestId _contactsStatusesRequestId = 0;
void contactsStatusesDone(const MTPVector<MTPContactStatus> &result);
bool contactsStatusesFail(const RPCError &error);
};

View File

@ -535,21 +535,13 @@ namespace {
data->loadedStatus = PeerData::FullLoaded;
}
auto oldOnlineTill = data->onlineTill;
if (status && !minimal) switch (status->type()) {
case mtpc_userStatusEmpty: data->onlineTill = 0; break;
case mtpc_userStatusRecently:
if (data->onlineTill > -10) { // don't modify pseudo-online
data->onlineTill = -2;
}
break;
case mtpc_userStatusLastWeek: data->onlineTill = -3; break;
case mtpc_userStatusLastMonth: data->onlineTill = -4; break;
case mtpc_userStatusOffline: data->onlineTill = status->c_userStatusOffline().vwas_online.v; break;
case mtpc_userStatusOnline: data->onlineTill = status->c_userStatusOnline().vexpires.v; break;
}
if (oldOnlineTill != data->onlineTill) {
update.flags |= UpdateFlag::UserOnlineChanged;
if (status && !minimal) {
auto oldOnlineTill = data->onlineTill;
auto newOnlineTill = App::api()->onlineTillFromStatus(*status, oldOnlineTill);
if (oldOnlineTill != newOnlineTill) {
data->onlineTill = newOnlineTill;
update.flags |= UpdateFlag::UserOnlineChanged;
}
}
if (data->contact < 0 && !data->phone().isEmpty() && data->id != AuthSession::CurrentUserPeerId()) {
@ -1560,6 +1552,14 @@ namespace {
return i.value();
}
void enumerateUsers(base::lambda<void(UserData*)> action) {
for_const (auto peer, peersData) {
if (auto user = peer->asUser()) {
action(user);
}
}
}
UserData *self() {
return ::self;
}

View File

@ -146,6 +146,7 @@ namespace App {
inline ChannelData *channelLoaded(ChannelId channelId) {
return channel(channelId, PeerData::FullLoaded);
}
void enumerateUsers(base::lambda<void(UserData*)> action);
UserData *self();
PeerData *peerByName(const QString &username);

View File

@ -26,6 +26,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "ui/widgets/buttons.h"
#include "ui/effects/widget_slide_wrap.h"
#include "boxes/peer_list_box.h"
#include "apiwrap.h"
#include "lang.h"
namespace {
@ -330,7 +331,10 @@ void EditPrivacyBox::createWidgets() {
_exceptionsDescription.create(this, _controller->exceptionsDescription(), Ui::FlatLabel::InitType::Simple, st::editPrivacyLabel);
clearButtons();
addButton(lang(lng_settings_save), [this] { _controller->save(collectResult()); });
addButton(lang(lng_settings_save), [this] {
App::api()->savePrivacy(_controller->key(), collectResult());
closeBox();
});
addButton(lang(lng_cancel), [this] { closeBox(); });
showChildren();

View File

@ -44,7 +44,6 @@ public:
class Controller {
public:
virtual MTPInputPrivacyKey key() = 0;
virtual void save(QVector<MTPInputPrivacyRule> &&result) = 0;
virtual QString title() = 0;
virtual QString optionDescription(Option option) {

View File

@ -5060,6 +5060,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updatePrivacy: {
auto &d = update.c_updatePrivacy();
App::api()->handlePrivacyChange(d.vkey.type(), d.vrules);
} break;
case mtpc_updatePinnedDialogs: {

View File

@ -223,11 +223,6 @@ MTPInputPrivacyKey LastSeenPrivacyController::key() {
return MTP_inputPrivacyKeyStatusTimestamp();
}
void LastSeenPrivacyController::save(QVector<MTPInputPrivacyRule> &&result) {
MTP::send(MTPaccount_SetPrivacy(MTP_inputPrivacyKeyStatusTimestamp(), MTP_vector<MTPInputPrivacyRule>(result)));
view()->closeBox();
}
QString LastSeenPrivacyController::title() {
return lang(lng_edit_privacy_lastseen_title);
}
@ -269,11 +264,6 @@ MTPInputPrivacyKey GroupsInvitePrivacyController::key() {
return MTP_inputPrivacyKeyChatInvite();
}
void GroupsInvitePrivacyController::save(QVector<MTPInputPrivacyRule> &&result) {
MTP::send(MTPaccount_SetPrivacy(MTP_inputPrivacyKeyChatInvite(), MTP_vector<MTPInputPrivacyRule>(result)));
view()->closeBox();
}
QString GroupsInvitePrivacyController::title() {
return lang(lng_edit_privacy_groups_title);
}

View File

@ -53,7 +53,6 @@ public:
using Exception = EditPrivacyBox::Exception;
MTPInputPrivacyKey key() override;
void save(QVector<MTPInputPrivacyRule> &&result) override;
QString title() override;
QString optionDescription(Option option) override;
@ -70,7 +69,6 @@ public:
using Exception = EditPrivacyBox::Exception;
MTPInputPrivacyKey key() override;
void save(QVector<MTPInputPrivacyRule> &&result) override;
QString title() override;
QString optionDescription(Option option) override;