Show current privacy values in settings section.

This commit is contained in:
John Preston 2018-09-11 12:11:52 +03:00
parent 165511fb14
commit 12ebae01b0
8 changed files with 371 additions and 197 deletions

View File

@ -147,6 +147,16 @@ ApiWrap::MessageToSend::MessageToSend(not_null<History*> history)
: history(history) {
}
MTPInputPrivacyKey ApiWrap::Privacy::Input(Key key) {
switch (key) {
case Privacy::Key::Calls: return MTP_inputPrivacyKeyPhoneCall();
case Privacy::Key::Invites: return MTP_inputPrivacyKeyChatInvite();
case Privacy::Key::LastSeen:
return MTP_inputPrivacyKeyStatusTimestamp();
}
Unexpected("Key in ApiWrap::Privacy::Input.");
}
ApiWrap::ApiWrap(not_null<AuthSession*> session)
: _session(session)
, _messageDataResolveDelayed([=] { resolveMessageDatas(); })
@ -1880,112 +1890,139 @@ void ApiWrap::saveDraftToCloudDelayed(not_null<History*> history) {
}
void ApiWrap::savePrivacy(const MTPInputPrivacyKey &key, QVector<MTPInputPrivacyRule> &&rules) {
auto keyTypeId = key.type();
auto it = _privacySaveRequests.find(keyTypeId);
const auto keyTypeId = key.type();
const auto it = _privacySaveRequests.find(keyTypeId);
if (it != _privacySaveRequests.cend()) {
request(it->second).cancel();
_privacySaveRequests.erase(it);
}
auto requestId = request(MTPaccount_SetPrivacy(key, MTP_vector<MTPInputPrivacyRule>(std::move(rules)))).done([this, keyTypeId](const MTPaccount_PrivacyRules &result) {
const auto requestId = request(MTPaccount_SetPrivacy(
key,
MTP_vector<MTPInputPrivacyRule>(std::move(rules))
)).done([=](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);
}).fail([this, keyTypeId](const RPCError &error) {
}).fail([=](const RPCError &error) {
_privacySaveRequests.remove(keyTypeId);
}).send();
_privacySaveRequests.emplace(keyTypeId, requestId);
}
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;
}
void ApiWrap::handlePrivacyChange(
mtpTypeId keyTypeId,
const MTPVector<MTPPrivacyRule> &rules) {
using Key = Privacy::Key;
const auto key = [&]() -> base::optional<Key> {
switch (keyTypeId) {
case mtpc_privacyKeyStatusTimestamp:
case mtpc_inputPrivacyKeyStatusTimestamp: return Key::LastSeen;
case mtpc_privacyKeyChatInvite:
case mtpc_inputPrivacyKeyChatInvite: return Key::Invites;
case mtpc_privacyKeyPhoneCall:
case mtpc_inputPrivacyKeyPhoneCall: return Key::Calls;
}
auto now = unixtime();
App::enumerateUsers([&](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) {
request(_contactsStatusesRequestId).cancel();
}
_contactsStatusesRequestId = request(MTPcontacts_GetStatuses()).done([this](const MTPVector<MTPContactStatus> &result) {
_contactsStatusesRequestId = 0;
for_const (auto &item, result.v) {
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);
}
}
}
}).fail([this](const RPCError &error) {
_contactsStatusesRequestId = 0;
}).send();
return base::none;
}();
if (!key) {
return;
}
pushPrivacy(*key, rules.v);
if (*key == Key::LastSeen) {
updatePrivacyLastSeens(rules.v);
}
}
void ApiWrap::updatePrivacyLastSeens(const QVector<MTPPrivacyRule> &rules) {
enum class Rule {
Unknown,
Allow,
Disallow,
};
auto userRules = QMap<UserId, Rule>();
auto contactsRule = Rule::Unknown;
auto everyoneRule = Rule::Unknown;
for (auto &rule : rules) {
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([&](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) {
request(_contactsStatusesRequestId).cancel();
}
_contactsStatusesRequestId = request(MTPcontacts_GetStatuses()).done([this](const MTPVector<MTPContactStatus> &result) {
_contactsStatusesRequestId = 0;
for_const (auto &item, result.v) {
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);
}
}
}
}).fail([this](const RPCError &error) {
_contactsStatusesRequestId = 0;
}).send();
}
int ApiWrap::onlineTillFromStatus(const MTPUserStatus &status, int currentOnlineTill) {
@ -4977,6 +5014,95 @@ void ApiWrap::saveSelfBio(const QString &text, FnMut<void()> done) {
}).send();
}
void ApiWrap::reloadPrivacy(Privacy::Key key) {
if (_privacyRequestIds.contains(key)) {
return;
}
const auto requestId = request(MTPaccount_GetPrivacy(
Privacy::Input(key)
)).done([=](const MTPaccount_PrivacyRules &result) {
_privacyRequestIds.erase(key);
result.match([&](const MTPDaccount_privacyRules &data) {
App::feedUsers(data.vusers);
pushPrivacy(key, data.vrules.v);
});
}).fail([=](const RPCError &error) {
_privacyRequestIds.erase(key);
}).send();
}
auto ApiWrap::parsePrivacy(const QVector<MTPPrivacyRule> &rules)
-> Privacy {
using Option = Privacy::Option;
// This is simplified version of privacy rules interpretation.
// But it should be fine for all the apps
// that use the same subset of features.
auto result = Privacy();
auto optionSet = false;
const auto SetOption = [&](Option option) {
if (optionSet) return;
optionSet = true;
result.option = option;
};
auto &always = result.always;
auto &never = result.never;
const auto Feed = [&](const MTPPrivacyRule &rule) {
rule.match([&](const MTPDprivacyValueAllowAll &) {
SetOption(Option::Everyone);
}, [&](const MTPDprivacyValueAllowContacts &) {
SetOption(Option::Contacts);
}, [&](const MTPDprivacyValueAllowUsers &data) {
const auto &users = data.vusers.v;
always.reserve(always.size() + users.size());
for (const auto userId : users) {
const auto user = App::user(UserId(userId.v));
if (!base::contains(never, user)
&& !base::contains(always, user)) {
always.push_back(user);
}
}
}, [&](const MTPDprivacyValueDisallowContacts &) {
// not supported
}, [&](const MTPDprivacyValueDisallowAll &) {
SetOption(Option::Nobody);
}, [&](const MTPDprivacyValueDisallowUsers &data) {
const auto &users = data.vusers.v;
never.reserve(never.size() + users.size());
for (const auto userId : users) {
const auto user = App::user(UserId(userId.v));
if (!base::contains(always, user)
&& !base::contains(never, user)) {
never.push_back(user);
}
}
});
};
for (const auto &rule : rules) {
Feed(rule);
}
Feed(MTP_privacyValueDisallowAll()); // disallow by default.
return result;
}
void ApiWrap::pushPrivacy(
Privacy::Key key,
const QVector<MTPPrivacyRule> &rules) {
const auto &saved = (_privacyValues[key] = parsePrivacy(rules));
const auto i = _privacyChanges.find(key);
if (i != end(_privacyChanges)) {
i->second.fire_copy(saved);
}
}
auto ApiWrap::privacyValue(Privacy::Key key) -> rpl::producer<Privacy> {
if (const auto i = _privacyValues.find(key); i != end(_privacyValues)) {
return _privacyChanges[key].events_starting_with_copy(i->second);
} else {
return _privacyChanges[key].events();
}
}
void ApiWrap::readServerHistory(not_null<History*> history) {
if (history->unreadCount()) {
readServerHistoryForce(history);

View File

@ -338,6 +338,26 @@ public:
void saveSelfBio(const QString &text, FnMut<void()> done);
struct Privacy {
enum class Key {
LastSeen,
Calls,
Invites,
};
enum class Option {
Everyone,
Contacts,
Nobody,
};
Option option = Option::Everyone;
std::vector<not_null<UserData*>> always;
std::vector<not_null<UserData*>> never;
static MTPInputPrivacyKey Input(Key key);
};
void reloadPrivacy(Privacy::Key key);
rpl::producer<Privacy> privacyValue(Privacy::Key key);
~ApiWrap();
private:
@ -521,6 +541,12 @@ private:
void photoUploadReady(const FullMsgId &msgId, const MTPInputFile &file);
Privacy parsePrivacy(const QVector<MTPPrivacyRule> &rules);
void pushPrivacy(
Privacy::Key key,
const QVector<MTPPrivacyRule> &rules);
void updatePrivacyLastSeens(const QVector<MTPPrivacyRule> &rules);
not_null<AuthSession*> _session;
MessageDataRequests _messageDataRequests;
@ -678,4 +704,8 @@ private:
FnMut<void()> _saveBioDone;
QString _saveBioText;
base::flat_map<Privacy::Key, mtpRequestId> _privacyRequestIds;
base::flat_map<Privacy::Key, Privacy> _privacyValues;
std::map<Privacy::Key, rpl::event_stream<Privacy>> _privacyChanges;
};

View File

@ -14,9 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/slide_wrap.h"
#include "history/history.h"
#include "boxes/peer_list_controllers.h"
#include "base/binary_guard.h"
#include "lang/lang_keys.h"
#include "apiwrap.h"
#include "auth_session.h"
#include "lang/lang_keys.h"
namespace {
@ -77,9 +78,19 @@ std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxControl
} // namespace
EditPrivacyBox::EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller) : BoxContent()
, _controller(std::move(controller))
EditPrivacyBox::EditPrivacyBox(
QWidget*,
std::unique_ptr<Controller> controller,
rpl::producer<Value> preloaded)
: _controller(std::move(controller))
, _loading(this, lang(lng_contacts_loading), Ui::FlatLabel::InitType::Simple, st::membersAbout) {
std::move(
preloaded
) | rpl::take(
1
) | rpl::start_with_next([=](Value &&data) {
dataReady(std::move(data));
}, lifetime());
}
void EditPrivacyBox::prepare() {
@ -88,7 +99,11 @@ void EditPrivacyBox::prepare() {
setTitle([this] { return _controller->title(); });
addButton(langFactory(lng_cancel), [this] { closeBox(); });
loadData();
if (_loading) {
_prepared = true;
} else {
createWidgets();
}
setDimensions(st::boxWideWidth, countDefaultHeight(st::boxWideWidth));
}
@ -215,13 +230,13 @@ QVector<MTPInputPrivacyRule> EditPrivacyBox::collectResult() {
constexpr auto kMaxRules = 3; // allow users, disallow users, option
auto result = QVector<MTPInputPrivacyRule>();
result.reserve(kMaxRules);
if (showExceptionLink(Exception::Always) && !_alwaysUsers.empty()) {
result.push_back(MTP_inputPrivacyValueAllowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_alwaysUsers))));
if (showExceptionLink(Exception::Always) && !_value.always.empty()) {
result.push_back(MTP_inputPrivacyValueAllowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_value.always))));
}
if (showExceptionLink(Exception::Never) && !_neverUsers.empty()) {
result.push_back(MTP_inputPrivacyValueDisallowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_neverUsers))));
if (showExceptionLink(Exception::Never) && !_value.never.empty()) {
result.push_back(MTP_inputPrivacyValueDisallowUsers(MTP_vector<MTPInputUser>(collectInputUsers(_value.never))));
}
switch (_option) {
switch (_value.option) {
case Option::Everyone: result.push_back(MTP_inputPrivacyValueAllowAll()); break;
case Option::Contacts: result.push_back(MTP_inputPrivacyValueAllowContacts()); break;
case Option::Nobody: result.push_back(MTP_inputPrivacyValueDisallowAll()); break;
@ -236,8 +251,8 @@ style::margins EditPrivacyBox::exceptionLinkMargins() const {
std::vector<not_null<UserData*>> &EditPrivacyBox::exceptionUsers(Exception exception) {
switch (exception) {
case Exception::Always: return _alwaysUsers;
case Exception::Never: return _neverUsers;
case Exception::Always: return _value.always;
case Exception::Never: return _value.never;
}
Unexpected("Invalid exception value.");
}
@ -252,18 +267,18 @@ object_ptr<Ui::SlideWrap<Ui::LinkButton>> &EditPrivacyBox::exceptionLink(Excepti
bool EditPrivacyBox::showExceptionLink(Exception exception) const {
switch (exception) {
case Exception::Always: return (_option == Option::Contacts) || (_option == Option::Nobody);
case Exception::Never: return (_option == Option::Everyone) || (_option == Option::Contacts);
case Exception::Always: return (_value.option == Option::Contacts) || (_value.option == Option::Nobody);
case Exception::Never: return (_value.option == Option::Everyone) || (_value.option == Option::Contacts);
}
Unexpected("Invalid exception value.");
}
void EditPrivacyBox::createWidgets() {
_loading.destroy();
_optionGroup = std::make_shared<Ui::RadioenumGroup<Option>>(_option);
_optionGroup = std::make_shared<Ui::RadioenumGroup<Option>>(_value.option);
auto createOption = [this](object_ptr<Ui::Radioenum<Option>> &widget, Option option, const QString &label) {
if (_controller->hasOption(option) || (_option == option)) {
if (_controller->hasOption(option) || (_value.option == option)) {
widget.create(this, _optionGroup, option, label, st::defaultBoxCheckbox);
}
};
@ -294,16 +309,18 @@ void EditPrivacyBox::createWidgets() {
clearButtons();
addButton(langFactory(lng_settings_save), [this] {
auto someAreDisallowed = (_option != Option::Everyone) || !_neverUsers.empty();
auto someAreDisallowed = (_value.option != Option::Everyone) || !_value.never.empty();
_controller->confirmSave(someAreDisallowed, crl::guard(this, [this] {
Auth().api().savePrivacy(_controller->key(), collectResult());
Auth().api().savePrivacy(
_controller->apiKey(),
collectResult());
closeBox();
}));
});
addButton(langFactory(lng_cancel), [this] { closeBox(); });
_optionGroup->setChangedCallback([this](Option value) {
_option = value;
_value.option = value;
_alwaysLink->toggle(
showExceptionLink(Exception::Always),
anim::type::normal);
@ -323,54 +340,10 @@ void EditPrivacyBox::createWidgets() {
setDimensions(st::boxWideWidth, resizeGetHeight(st::boxWideWidth));
}
void EditPrivacyBox::loadData() {
request(MTPaccount_GetPrivacy(_controller->key())).done([this](const MTPaccount_PrivacyRules &result) {
Expects(result.type() == mtpc_account_privacyRules);
auto &rules = result.c_account_privacyRules();
App::feedUsers(rules.vusers);
// This is simplified version of privacy rules interpretation.
// But it should be fine for all the apps that use the same subset of features.
auto optionSet = false;
auto setOption = [this, &optionSet](Option option) {
if (optionSet) return;
optionSet = true;
_option = option;
};
auto feedRule = [this, &setOption](const MTPPrivacyRule &rule) {
switch (rule.type()) {
case mtpc_privacyValueAllowAll: setOption(Option::Everyone); break;
case mtpc_privacyValueAllowContacts: setOption(Option::Contacts); break;
case mtpc_privacyValueAllowUsers: {
auto &users = rule.c_privacyValueAllowUsers().vusers.v;
_alwaysUsers.reserve(_alwaysUsers.size() + users.size());
for (auto &userId : users) {
auto user = App::user(UserId(userId.v));
if (!base::contains(_neverUsers, user) && !base::contains(_alwaysUsers, user)) {
_alwaysUsers.push_back(user);
}
}
} break;
case mtpc_privacyValueDisallowContacts: // not supported, fall through
case mtpc_privacyValueDisallowAll: setOption(Option::Nobody); break;
case mtpc_privacyValueDisallowUsers: {
auto &users = rule.c_privacyValueDisallowUsers().vusers.v;
_neverUsers.reserve(_neverUsers.size() + users.size());
for (auto &userId : users) {
auto user = App::user(UserId(userId.v));
if (!base::contains(_alwaysUsers, user) && !base::contains(_neverUsers, user)) {
_neverUsers.push_back(user);
}
}
} break;
}
};
for (auto &rule : rules.vrules.v) {
feedRule(rule);
}
feedRule(MTP_privacyValueDisallowAll()); // disallow by default.
void EditPrivacyBox::dataReady(Value &&value) {
_value = std::move(value);
_loading.destroy();
if (_prepared) {
createWidgets();
}).send();
}
}

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h"
#include "mtproto/sender.h"
#include "apiwrap.h"
namespace Ui {
class FlatLabel;
@ -23,11 +24,8 @@ class SlideWrap;
class EditPrivacyBox : public BoxContent, private MTP::Sender {
public:
enum class Option {
Everyone,
Contacts,
Nobody,
};
using Value = ApiWrap::Privacy;
using Option = Value::Option;
enum class Exception {
Always,
Never,
@ -35,7 +33,10 @@ public:
class Controller {
public:
virtual MTPInputPrivacyKey key() = 0;
using Key = ApiWrap::Privacy::Key;
virtual Key key() = 0;
virtual MTPInputPrivacyKey apiKey() = 0;
virtual QString title() = 0;
virtual bool hasOption(Option option) {
@ -71,7 +72,10 @@ public:
};
EditPrivacyBox(QWidget*, std::unique_ptr<Controller> controller);
EditPrivacyBox(
QWidget*,
std::unique_ptr<Controller> controller,
rpl::producer<Value> preloaded);
protected:
void prepare() override;
@ -84,16 +88,18 @@ private:
bool showExceptionLink(Exception exception) const;
void createWidgets();
QVector<MTPInputPrivacyRule> collectResult();
void loadData();
void dataReady(Value &&value);
int countDefaultHeight(int newWidth);
void editExceptionUsers(Exception exception);
QString exceptionLinkText(Exception exception);
std::vector<not_null<UserData*>> &exceptionUsers(Exception exception);
object_ptr<Ui::SlideWrap<Ui::LinkButton>> &exceptionLink(Exception exception);
object_ptr<Ui::SlideWrap<Ui::LinkButton>> &exceptionLink(
Exception exception);
std::unique_ptr<Controller> _controller;
Option _option = Option::Everyone;
Value _value;
bool _prepared = false;
std::shared_ptr<Ui::RadioenumGroup<Option>> _optionGroup;
object_ptr<Ui::FlatLabel> _loading;
@ -107,7 +113,4 @@ private:
object_ptr<Ui::SlideWrap<Ui::LinkButton>> _neverLink = { nullptr };
object_ptr<Ui::FlatLabel> _exceptionsDescription = { nullptr };
std::vector<not_null<UserData*>> _alwaysUsers;
std::vector<not_null<UserData*>> _neverUsers;
};

View File

@ -220,7 +220,11 @@ std::unique_ptr<PeerListRow> BlockedBoxController::createRow(UserData *user) con
return std::move(row);
}
MTPInputPrivacyKey LastSeenPrivacyController::key() {
ApiWrap::Privacy::Key LastSeenPrivacyController::key() {
return Key::LastSeen;
}
MTPInputPrivacyKey LastSeenPrivacyController::apiKey() {
return MTP_inputPrivacyKeyStatusTimestamp();
}
@ -274,7 +278,11 @@ void LastSeenPrivacyController::confirmSave(bool someAreDisallowed, FnMut<void()
}
}
MTPInputPrivacyKey GroupsInvitePrivacyController::key() {
ApiWrap::Privacy::Key GroupsInvitePrivacyController::key() {
return Key::Invites;
}
MTPInputPrivacyKey GroupsInvitePrivacyController::apiKey() {
return MTP_inputPrivacyKeyChatInvite();
}
@ -310,7 +318,11 @@ QString GroupsInvitePrivacyController::exceptionsDescription() {
return lang(lng_edit_privacy_groups_exceptions);
}
MTPInputPrivacyKey CallsPrivacyController::key() {
ApiWrap::Privacy::Key CallsPrivacyController::key() {
return Key::Calls;
}
MTPInputPrivacyKey CallsPrivacyController::apiKey() {
return MTP_inputPrivacyKeyPhoneCall();
}

View File

@ -41,7 +41,8 @@ public:
using Option = EditPrivacyBox::Option;
using Exception = EditPrivacyBox::Exception;
MTPInputPrivacyKey key() override;
Key key() override;
MTPInputPrivacyKey apiKey() override;
QString title() override;
QString description() override;
@ -59,7 +60,8 @@ public:
using Option = EditPrivacyBox::Option;
using Exception = EditPrivacyBox::Exception;
MTPInputPrivacyKey key() override;
Key key() override;
MTPInputPrivacyKey apiKey() override;
QString title() override;
bool hasOption(Option option) override;
@ -75,7 +77,8 @@ public:
using Option = EditPrivacyBox::Option;
using Exception = EditPrivacyBox::Exception;
MTPInputPrivacyKey key() override;
Key key() override;
MTPInputPrivacyKey apiKey() override;
QString title() override;
QString description() override;

View File

@ -286,15 +286,12 @@ void PrivacyWidget::onBlockedUsers() {
}
void PrivacyWidget::onLastSeenPrivacy() {
Ui::show(Box<EditPrivacyBox>(std::make_unique<LastSeenPrivacyController>()));
}
void PrivacyWidget::onCallsPrivacy() {
Ui::show(Box<EditPrivacyBox>(std::make_unique<CallsPrivacyController>()));
}
void PrivacyWidget::onGroupsInvitePrivacy() {
Ui::show(Box<EditPrivacyBox>(std::make_unique<GroupsInvitePrivacyController>()));
}
void PrivacyWidget::onAutoLock() {

View File

@ -65,30 +65,60 @@ void SetupPrivacy(not_null<Ui::VerticalLayout*> container) {
initBox));
});
AddButton(
container,
using Privacy = ApiWrap::Privacy;
const auto PrivacyString = [](Privacy::Key key) {
Auth().api().reloadPrivacy(key);
return Auth().api().privacyValue(
key
) | rpl::map([](const Privacy &value) {
const auto base = [&] {
using Option = Privacy::Option;
switch (value.option) {
case Option::Everyone: return lng_edit_privacy_everyone;
case Option::Contacts: return lng_edit_privacy_contacts;
case Option::Nobody: return lng_edit_privacy_nobody;
}
Unexpected("Value in Privacy::Option.");
}();
auto add = QStringList();
if (const auto never = value.never.size()) {
add.push_back("-" + QString::number(never));
}
if (const auto always = value.always.size()) {
add.push_back("+" + QString::number(always));
}
if (!add.isEmpty()) {
return lang(base) + " (" + add.join(", ") + ")";
} else {
return lang(base);
}
});
};
using namespace OldSettings;
const auto add = [&](LangKey label, Privacy::Key key, auto controller) {
AddButtonWithLabel(
container,
label,
PrivacyString(key),
st::settingsButton
)->addClickHandler([=] {
Ui::show(Box<EditPrivacyBox>(
controller(),
Auth().api().privacyValue(key)));
});
};
add(
lng_settings_last_seen,
st::settingsButton
)->addClickHandler([] {
Ui::show(Box<EditPrivacyBox>(
std::make_unique<OldSettings::LastSeenPrivacyController>()));
});
AddButton(
container,
Privacy::Key::LastSeen,
[] { return std::make_unique<LastSeenPrivacyController>(); });
add(
lng_settings_calls,
st::settingsButton
)->addClickHandler([] {
Ui::show(Box<EditPrivacyBox>(
std::make_unique<OldSettings::CallsPrivacyController>()));
});
AddButton(
container,
Privacy::Key::Calls,
[] { return std::make_unique<CallsPrivacyController>(); });
add(
lng_settings_groups_invite,
st::settingsButton
)->addClickHandler([] {
Ui::show(Box<EditPrivacyBox>(
std::make_unique<OldSettings::GroupsInvitePrivacyController>()));
});
Privacy::Key::Invites,
[] { return std::make_unique<GroupsInvitePrivacyController>(); });
AddSkip(container, st::settingsPrivacySecurityPadding);
AddDividerText(