Add gifts-to-profile privacy.

This commit is contained in:
John Preston 2024-11-15 15:34:23 +04:00
parent 3cfbd6a93b
commit 572c074c42
9 changed files with 346 additions and 107 deletions

View File

@ -682,6 +682,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_settings_messages_privacy" = "Messages";
"lng_settings_voices_privacy" = "Voice messages";
"lng_settings_bio_privacy" = "Bio";
"lng_settings_gifts_privacy" = "Gifts";
"lng_settings_birthday_privacy" = "Date of Birth";
"lng_settings_privacy_premium" = "Only subscribers of {link} can restrict receiving voice messages.";
"lng_settings_privacy_premium_link" = "Telegram Premium";
@ -1162,19 +1163,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_blocked_list_subtitle#other" = "{count} blocked users";
"lng_edit_privacy_everyone" = "Everybody";
"lng_edit_privacy_no_miniapps" = "Not Mini Apps";
"lng_edit_privacy_contacts" = "My contacts";
"lng_edit_privacy_close_friends" = "Close friends";
"lng_edit_privacy_contacts_and_premium" = "Contacts & Premium";
"lng_edit_privacy_contacts_and_miniapps" = "Contacts & Mini Apps";
"lng_edit_privacy_nobody" = "Nobody";
"lng_edit_privacy_premium" = "Premium users";
"lng_edit_privacy_miniapps" = "Mini Apps";
"lng_edit_privacy_exceptions" = "Add exceptions";
"lng_edit_privacy_user_types" = "User types";
"lng_edit_privacy_users_and_groups" = "Users and groups";
"lng_edit_privacy_premium_status" = "all Telegram Premium subscribers";
"lng_edit_privacy_miniapps_status" = "web mini apps that you use";
"lng_edit_privacy_exceptions_count#one" = "{count} user";
"lng_edit_privacy_exceptions_count#other" = "{count} users";
"lng_edit_privacy_exceptions_premium_and" = "Premium & {users}";
"lng_edit_privacy_exceptions_miniapps_and" = "Mini Apps & {users}";
"lng_edit_privacy_exceptions_add" = "Add users";
"lng_edit_privacy_phone_number_title" = "Phone number privacy";
@ -1228,6 +1234,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_edit_privacy_birthday_yet" = "You haven't entered your date of birth yet.\n{link}";
"lng_edit_privacy_birthday_yet_link" = "Add my birthday >";
"lng_edit_privacy_gifts_title" = "Gifts";
"lng_edit_privacy_gifts_header" = "Who can display gifts on my profile";
"lng_edit_privacy_gifts_always_empty" = "Always allow";
"lng_edit_privacy_gifts_never_empty" = "Never allow";
"lng_edit_privacy_gifts_exceptions" = "Choose whether gifts from specific senders need your approval before they're visible to others on your profile.";
"lng_edit_privacy_gifts_always_title" = "Always allow";
"lng_edit_privacy_gifts_never_title" = "Never allow";
"lng_edit_privacy_calls_title" = "Calls";
"lng_edit_privacy_calls_header" = "Who can call me";
"lng_edit_privacy_calls_always_empty" = "Always allow";

View File

@ -69,6 +69,9 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) {
if (rule.always.premiums && (rule.option != Option::Everyone)) {
result.push_back(MTP_inputPrivacyValueAllowPremium());
}
if (rule.always.miniapps && (rule.option != Option::Everyone)) {
result.push_back(MTP_inputPrivacyValueAllowBots());
}
}
if (!rule.ignoreNever) {
const auto users = collectInputUsers(rule.never);
@ -83,6 +86,9 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) {
MTP_inputPrivacyValueDisallowChatParticipants(
MTP_vector<MTPlong>(chats)));
}
if (rule.never.miniapps && (rule.option != Option::Nobody)) {
result.push_back(MTP_inputPrivacyValueDisallowBots());
}
}
result.push_back([&] {
switch (rule.option) {
@ -124,6 +130,10 @@ UserPrivacy::Rule TLToRules(const TLRules &rules, Data::Session &owner) {
setOption(Option::CloseFriends);
}, [&](const MTPDprivacyValueAllowPremium &) {
result.always.premiums = true;
}, [&](const MTPDprivacyValueAllowBots &) {
result.always.miniapps = true;
}, [&](const MTPDprivacyValueDisallowBots &) {
result.never.miniapps = true;
}, [&](const MTPDprivacyValueAllowUsers &data) {
const auto &users = data.vusers().v;
always.reserve(always.size() + users.size());
@ -199,6 +209,7 @@ MTPInputPrivacyKey KeyToTL(UserPrivacy::Key key) {
case Key::Voices: return MTP_inputPrivacyKeyVoiceMessages();
case Key::About: return MTP_inputPrivacyKeyAbout();
case Key::Birthday: return MTP_inputPrivacyKeyBirthday();
case Key::GiftsAutoSave: return MTP_inputPrivacyKeyStarGiftsAutoSave();
}
Unexpected("Key in Api::UserPrivacy::KetToTL.");
}
@ -228,6 +239,8 @@ std::optional<UserPrivacy::Key> TLToKey(mtpTypeId type) {
case mtpc_inputPrivacyKeyAbout: return Key::About;
case mtpc_privacyKeyBirthday:
case mtpc_inputPrivacyKeyBirthday: return Key::Birthday;
case mtpc_privacyKeyStarGiftsAutoSave:
case mtpc_inputPrivacyKeyStarGiftsAutoSave: return Key::GiftsAutoSave;
}
return std::nullopt;
}

View File

@ -31,6 +31,7 @@ public:
Voices,
About,
Birthday,
GiftsAutoSave,
};
enum class Option {
Everyone,
@ -41,6 +42,7 @@ public:
struct Exceptions {
std::vector<not_null<PeerData*>> peers;
bool premiums = false;
bool miniapps = false;
};
struct Rule {
Option option = Option::Everyone;

View File

@ -36,13 +36,64 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_settings.h"
#include "styles/style_layers.h"
#include "styles/style_menu_icons.h"
#include "styles/style_window.h"
namespace {
constexpr auto kPremiumsRowId = PeerId(FakeChatId(BareId(1))).value;
constexpr auto kMiniAppsRowId = PeerId(FakeChatId(BareId(2))).value;
using Exceptions = Api::UserPrivacy::Exceptions;
enum class SpecialRowType {
Premiums,
MiniApps,
};
[[nodiscard]] PaintRoundImageCallback GeneratePremiumsUserpicCallback(
bool forceRound) {
return [=](QPainter &p, int x, int y, int outerWidth, int size) {
auto gradient = QLinearGradient(
QPointF(x, y),
QPointF(x + size, y + size));
gradient.setStops(Ui::Premium::ButtonGradientStops());
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(gradient);
if (forceRound) {
p.drawEllipse(x, y, size, size);
} else {
const auto radius = size * Ui::ForumUserpicRadiusMultiplier();
p.drawRoundedRect(x, y, size, size, radius, radius);
}
st::settingsPrivacyPremium.paintInCenter(p, QRect(x, y, size, size));
};
}
[[nodiscard]] PaintRoundImageCallback GenerateMiniAppsUserpicCallback(
bool forceRound) {
return [=](QPainter &p, int x, int y, int outerWidth, int size) {
const auto &color1 = st::historyPeer6UserpicBg;
const auto &color2 = st::historyPeer6UserpicBg2;
const auto rect = style::rtlrect(x, y, size, size, outerWidth);
auto hq = PainterHighQualityEnabler(p);
auto gradient = QLinearGradient(x, y, x, y + size);
gradient.setStops({ { 0., color1->c }, { 1., color2->c } });
p.setPen(Qt::NoPen);
p.setBrush(gradient);
if (forceRound) {
p.drawEllipse(x, y, size, size);
} else {
const auto radius = size * Ui::ForumUserpicRadiusMultiplier();
p.drawRoundedRect(x, y, size, size, radius, radius);
}
st::windowFilterTypeBots.paintInCenter(p, QRect(x, y, size, size));
};
}
void CreateRadiobuttonLock(
not_null<Ui::RpWidget*> widget,
const style::Checkbox &st) {
@ -102,7 +153,7 @@ public:
not_null<Main::Session*> session,
rpl::producer<QString> title,
const Exceptions &selected,
bool allowChoosePremiums);
std::optional<SpecialRowType> allowChooseSpecial);
Main::Session &session() const override;
void rowClicked(not_null<PeerListRow*> row) override;
@ -110,18 +161,20 @@ public:
bool handleDeselectForeignRow(PeerListRowId itemId) override;
[[nodiscard]] bool premiumsSelected() const;
[[nodiscard]] bool miniAppsSelected() const;
protected:
void prepareViewHook() override;
std::unique_ptr<Row> createRow(not_null<History*> history) override;
private:
[[nodiscard]] object_ptr<Ui::RpWidget> preparePremiumsRowList();
[[nodiscard]] object_ptr<Ui::RpWidget> prepareSpecialRowList(
SpecialRowType type);
const not_null<Main::Session*> _session;
rpl::producer<QString> _title;
Exceptions _selected;
bool _allowChoosePremiums = false;
std::optional<SpecialRowType> _allowChooseSpecial;
PeerListContentDelegate *_typesDelegate = nullptr;
Fn<void(PeerListRowId)> _deselectOption;
@ -133,9 +186,9 @@ struct RowSelectionChange {
bool checked = false;
};
class PremiumsRow final : public PeerListRow {
class SpecialRow final : public PeerListRow {
public:
PremiumsRow();
explicit SpecialRow(SpecialRowType type);
QString generateName() override;
QString generateShortName() override;
@ -143,70 +196,68 @@ public:
bool forceRound) override;
bool useForumLikeUserpic() const override;
private:
const SpecialRowType _type = SpecialRowType::Premiums;
};
class TypesController final : public PeerListController {
public:
TypesController(not_null<Main::Session*> session, bool premiums);
TypesController(not_null<Main::Session*> session, SpecialRowType type);
Main::Session &session() const override;
void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override;
[[nodiscard]] bool premiumsSelected() const;
[[nodiscard]] rpl::producer<bool> premiumsChanges() const;
[[nodiscard]] bool specialSelected() const;
[[nodiscard]] rpl::producer<bool> specialChanges() const;
[[nodiscard]] auto rowSelectionChanges() const
-> rpl::producer<RowSelectionChange>;
private:
const not_null<Main::Session*> _session;
const SpecialRowType _type;
rpl::event_stream<> _selectionChanged;
rpl::event_stream<RowSelectionChange> _rowSelectionChanges;
};
PremiumsRow::PremiumsRow() : PeerListRow(kPremiumsRowId) {
setCustomStatus(tr::lng_edit_privacy_premium_status(tr::now));
SpecialRow::SpecialRow(SpecialRowType type)
: PeerListRow((type == SpecialRowType::Premiums)
? kPremiumsRowId
: kMiniAppsRowId) {
setCustomStatus((id() == kPremiumsRowId)
? tr::lng_edit_privacy_premium_status(tr::now)
: tr::lng_edit_privacy_miniapps_status(tr::now));
}
QString PremiumsRow::generateName() {
return tr::lng_edit_privacy_premium(tr::now);
QString SpecialRow::generateName() {
return (id() == kPremiumsRowId)
? tr::lng_edit_privacy_premium(tr::now)
: tr::lng_edit_privacy_miniapps(tr::now);
}
QString PremiumsRow::generateShortName() {
QString SpecialRow::generateShortName() {
return generateName();
}
PaintRoundImageCallback PremiumsRow::generatePaintUserpicCallback(
PaintRoundImageCallback SpecialRow::generatePaintUserpicCallback(
bool forceRound) {
return [=](QPainter &p, int x, int y, int outerWidth, int size) {
auto gradient = QLinearGradient(
QPointF(x, y),
QPointF(x + size, y + size));
gradient.setStops(Ui::Premium::ButtonGradientStops());
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(gradient);
if (forceRound) {
p.drawEllipse(x, y, size, size);
} else {
const auto radius = size * Ui::ForumUserpicRadiusMultiplier();
p.drawRoundedRect(x, y, size, size, radius, radius);
}
st::settingsPrivacyPremium.paintInCenter(p, QRect(x, y, size, size));
};
return (id() == kPremiumsRowId)
? GeneratePremiumsUserpicCallback(forceRound)
: GenerateMiniAppsUserpicCallback(forceRound);
}
bool PremiumsRow::useForumLikeUserpic() const {
bool SpecialRow::useForumLikeUserpic() const {
return true;
}
TypesController::TypesController(
not_null<Main::Session*> session,
bool premiums)
: _session(session) {
SpecialRowType type)
: _session(session)
, _type(type) {
}
Main::Session &TypesController::session() const {
@ -214,12 +265,15 @@ Main::Session &TypesController::session() const {
}
void TypesController::prepare() {
delegate()->peerListAppendRow(std::make_unique<PremiumsRow>());
delegate()->peerListAppendRow(std::make_unique<SpecialRow>(_type));
delegate()->peerListRefreshRows();
}
bool TypesController::premiumsSelected() const {
const auto row = delegate()->peerListFindRow(kPremiumsRowId);
bool TypesController::specialSelected() const {
const auto premiums = (_type == SpecialRowType::Premiums);
const auto row = delegate()->peerListFindRow(premiums
? kPremiumsRowId
: kMiniAppsRowId);
Assert(row != nullptr);
return row->checked();
@ -231,10 +285,10 @@ void TypesController::rowClicked(not_null<PeerListRow*> row) {
_rowSelectionChanges.fire({ row, checked });
}
rpl::producer<bool> TypesController::premiumsChanges() const {
rpl::producer<bool> TypesController::specialChanges() const {
return _rowSelectionChanges.events(
) | rpl::map([=] {
return premiumsSelected();
return specialSelected();
});
}
@ -247,12 +301,12 @@ PrivacyExceptionsBoxController::PrivacyExceptionsBoxController(
not_null<Main::Session*> session,
rpl::producer<QString> title,
const Exceptions &selected,
bool allowChoosePremiums)
std::optional<SpecialRowType> allowChooseSpecial)
: ChatsListBoxController(session)
, _session(session)
, _title(std::move(title))
, _selected(selected)
, _allowChoosePremiums(allowChoosePremiums) {
, _allowChooseSpecial(allowChooseSpecial) {
}
Main::Session &PrivacyExceptionsBoxController::session() const {
@ -261,14 +315,18 @@ Main::Session &PrivacyExceptionsBoxController::session() const {
void PrivacyExceptionsBoxController::prepareViewHook() {
delegate()->peerListSetTitle(std::move(_title));
if (_allowChoosePremiums || _selected.premiums) {
delegate()->peerListSetAboveWidget(preparePremiumsRowList());
if (_allowChooseSpecial || _selected.premiums || _selected.miniapps) {
delegate()->peerListSetAboveWidget(prepareSpecialRowList(
_allowChooseSpecial.value_or(_selected.premiums
? SpecialRowType::Premiums
: SpecialRowType::MiniApps)));
}
delegate()->peerListAddSelectedPeers(_selected.peers);
}
bool PrivacyExceptionsBoxController::isForeignRow(PeerListRowId itemId) {
return (itemId == kPremiumsRowId);
return (itemId == kPremiumsRowId)
|| (itemId == kMiniAppsRowId);
}
bool PrivacyExceptionsBoxController::handleDeselectForeignRow(
@ -280,7 +338,8 @@ bool PrivacyExceptionsBoxController::handleDeselectForeignRow(
return false;
}
auto PrivacyExceptionsBoxController::preparePremiumsRowList()
auto PrivacyExceptionsBoxController::prepareSpecialRowList(
SpecialRowType type)
-> object_ptr<Ui::RpWidget> {
auto result = object_ptr<Ui::VerticalLayout>((QWidget*)nullptr);
const auto container = result.data();
@ -291,30 +350,39 @@ auto PrivacyExceptionsBoxController::preparePremiumsRowList()
_typesDelegate = lifetime.make_state<PeerListContentDelegateSimple>();
const auto controller = lifetime.make_state<TypesController>(
&session(),
_selected.premiums);
type);
const auto content = result->add(object_ptr<PeerListContent>(
container,
controller));
_typesDelegate->setContent(content);
controller->setDelegate(_typesDelegate);
const auto selectType = [&](PeerListRowId id) {
const auto row = _typesDelegate->peerListFindRow(id);
if (row) {
content->changeCheckState(row, true, anim::type::instant);
this->delegate()->peerListSetForeignRowChecked(
row,
true,
anim::type::instant);
}
};
if (_selected.premiums) {
const auto row = _typesDelegate->peerListFindRow(kPremiumsRowId);
Assert(row != nullptr);
content->changeCheckState(row, true, anim::type::instant);
this->delegate()->peerListSetForeignRowChecked(
row,
true,
anim::type::instant);
selectType(kPremiumsRowId);
} else if (_selected.miniapps) {
selectType(kMiniAppsRowId);
}
container->add(CreatePeerListSectionSubtitle(
container,
tr::lng_edit_privacy_users_and_groups()));
controller->premiumsChanges(
) | rpl::start_with_next([=](bool premiums) {
_selected.premiums = premiums;
controller->specialChanges(
) | rpl::start_with_next([=](bool chosen) {
if (type == SpecialRowType::Premiums) {
_selected.premiums = chosen;
} else {
_selected.miniapps = chosen;
}
}, lifetime);
controller->rowSelectionChanges(
@ -329,6 +397,8 @@ auto PrivacyExceptionsBoxController::preparePremiumsRowList()
if (const auto row = _typesDelegate->peerListFindRow(itemId)) {
if (itemId == kPremiumsRowId) {
_selected.premiums = false;
} else if (itemId == kMiniAppsRowId) {
_selected.miniapps = false;
}
_typesDelegate->peerListSetRowChecked(row, false);
}
@ -337,10 +407,14 @@ auto PrivacyExceptionsBoxController::preparePremiumsRowList()
return result;
}
[[nodiscard]] bool PrivacyExceptionsBoxController::premiumsSelected() const {
bool PrivacyExceptionsBoxController::premiumsSelected() const {
return _selected.premiums;
}
bool PrivacyExceptionsBoxController::miniAppsSelected() const {
return _selected.miniapps;
}
void PrivacyExceptionsBoxController::rowClicked(not_null<PeerListRow*> row) {
const auto peer = row->peer();
@ -412,6 +486,11 @@ EditPrivacyBox::EditPrivacyBox(
// If we switch from Everyone to Contacts or Nobody suggest Premiums.
_value.always.premiums = true;
}
if (_controller->allowMiniAppsToggle(Exception::Always)
&& _value.option == Option::Everyone) {
// If we switch from Everyone to Contacts or Nobody suggest MiniApps.
_value.always.miniapps = true;
}
}
void EditPrivacyBox::prepare() {
@ -427,12 +506,18 @@ void EditPrivacyBox::editExceptions(
&_window->session(),
_controller->exceptionBoxTitle(exception),
exceptions(exception),
_controller->allowPremiumsToggle(exception));
(_controller->allowPremiumsToggle(exception)
? SpecialRowType::Premiums
: _controller->allowMiniAppsToggle(exception)
? SpecialRowType::MiniApps
: std::optional<SpecialRowType>()));
auto initBox = [=, controller = controller.get()](
not_null<PeerListBox*> box) {
box->addButton(tr::lng_settings_save(), crl::guard(this, [=] {
exceptions(exception).peers = box->collectSelectedRows();
exceptions(exception).premiums = controller->premiumsSelected();
auto &setTo = exceptions(exception);
setTo.peers = box->collectSelectedRows();
setTo.premiums = controller->premiumsSelected();
setTo.miniapps = controller->miniAppsSelected();
const auto type = [&] {
switch (exception) {
case Exception::Always: return Exception::Never;
@ -440,11 +525,17 @@ void EditPrivacyBox::editExceptions(
}
Unexpected("Invalid exception value.");
}();
auto &removeFrom = exceptions(type).peers;
auto &removeFrom = exceptions(type);
for (const auto peer : exceptions(exception).peers) {
removeFrom.erase(
ranges::remove(removeFrom, peer),
end(removeFrom));
removeFrom.peers.erase(
ranges::remove(removeFrom.peers, peer),
end(removeFrom.peers));
}
if (setTo.premiums) {
removeFrom.premiums = false;
}
if (setTo.miniapps) {
removeFrom.miniapps = false;
}
done();
box->closeBox();
@ -566,14 +657,21 @@ void EditPrivacyBox::setupContent() {
lt_count,
count)
: tr::lng_edit_privacy_exceptions_add(tr::now);
return !value.premiums
? users
: !count
? tr::lng_edit_privacy_premium(tr::now)
: tr::lng_edit_privacy_exceptions_premium_and(
tr::now,
lt_users,
users);
return value.premiums
? (!count
? tr::lng_edit_privacy_premium(tr::now)
: tr::lng_edit_privacy_exceptions_premium_and(
tr::now,
lt_users,
users))
: value.miniapps
? (!count
? tr::lng_edit_privacy_miniapps(tr::now)
: tr::lng_edit_privacy_exceptions_miniapps_and(
tr::now,
lt_users,
users))
: users;
});
_controller->handleExceptionsChange(
exception,

View File

@ -61,6 +61,10 @@ public:
Exception exception) const {
return false;
}
[[nodiscard]] virtual bool allowMiniAppsToggle(
Exception exception) const {
return false;
}
virtual void handleExceptionsChange(
Exception exception,
rpl::producer<int> value) {

View File

@ -533,6 +533,7 @@ inputPrivacyKeyAddedByPhone#d1219bdd = InputPrivacyKey;
inputPrivacyKeyVoiceMessages#aee69d68 = InputPrivacyKey;
inputPrivacyKeyAbout#3823cc40 = InputPrivacyKey;
inputPrivacyKeyBirthday#d65a11cc = InputPrivacyKey;
inputPrivacyKeyStarGiftsAutoSave#e1732341 = InputPrivacyKey;
privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
privacyKeyChatInvite#500e6dfa = PrivacyKey;
@ -545,6 +546,7 @@ privacyKeyAddedByPhone#42ffd42b = PrivacyKey;
privacyKeyVoiceMessages#697f414 = PrivacyKey;
privacyKeyAbout#a486b761 = PrivacyKey;
privacyKeyBirthday#2000a518 = PrivacyKey;
privacyKeyStarGiftsAutoSave#2ca4fdf8 = PrivacyKey;
inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
@ -556,6 +558,8 @@ inputPrivacyValueAllowChatParticipants#840649cf chats:Vector<long> = InputPrivac
inputPrivacyValueDisallowChatParticipants#e94f0f86 chats:Vector<long> = InputPrivacyRule;
inputPrivacyValueAllowCloseFriends#2f453e49 = InputPrivacyRule;
inputPrivacyValueAllowPremium#77cdc9f1 = InputPrivacyRule;
inputPrivacyValueAllowBots#5a4fcce5 = InputPrivacyRule;
inputPrivacyValueDisallowBots#c4e57915 = InputPrivacyRule;
privacyValueAllowContacts#fffe1bac = PrivacyRule;
privacyValueAllowAll#65427b82 = PrivacyRule;
@ -567,6 +571,8 @@ privacyValueAllowChatParticipants#6b134e8e chats:Vector<long> = PrivacyRule;
privacyValueDisallowChatParticipants#41c87565 chats:Vector<long> = PrivacyRule;
privacyValueAllowCloseFriends#f7e8d89b = PrivacyRule;
privacyValueAllowPremium#ece9814b = PrivacyRule;
privacyValueAllowBots#21461b5d = PrivacyRule;
privacyValueDisallowBots#f6a5f82f = PrivacyRule;
account.privacyRules#50a04e45 rules:Vector<PrivacyRule> chats:Vector<Chat> users:Vector<User> = account.PrivacyRules;

View File

@ -380,11 +380,13 @@ void BlockedBoxController::rowClicked(not_null<PeerListRow*> row) {
});
}
void BlockedBoxController::rowRightActionClicked(not_null<PeerListRow*> row) {
void BlockedBoxController::rowRightActionClicked(
not_null<PeerListRow*> row) {
session().api().blockedPeers().unblock(row->peer());
}
void BlockedBoxController::applySlice(const Api::BlockedPeers::Slice &slice) {
void BlockedBoxController::applySlice(
const Api::BlockedPeers::Slice &slice) {
if (slice.list.empty()) {
_allLoaded = true;
}
@ -487,7 +489,8 @@ rpl::producer<QString> PhoneNumberPrivacyController::title() const {
return tr::lng_edit_privacy_phone_number_title();
}
rpl::producer<QString> PhoneNumberPrivacyController::optionsTitleKey() const {
auto PhoneNumberPrivacyController::optionsTitleKey() const
-> rpl::producer<QString> {
return tr::lng_edit_privacy_phone_number_header();
}
@ -731,7 +734,8 @@ void LastSeenPrivacyController::handleExceptionsChange(
void LastSeenPrivacyController::confirmSave(
bool someAreDisallowed,
Fn<void()> saveCallback) {
if (someAreDisallowed && !Core::App().settings().lastSeenWarningSeen()) {
if (someAreDisallowed
&& !Core::App().settings().lastSeenWarningSeen()) {
auto callback = [
=,
saveCallback = std::move(saveCallback)
@ -776,11 +780,14 @@ rpl::producer<QString> GroupsInvitePrivacyController::optionsTitleKey(
return tr::lng_edit_privacy_groups_header();
}
rpl::producer<QString> GroupsInvitePrivacyController::exceptionButtonTextKey(
Exception exception) const {
auto GroupsInvitePrivacyController::exceptionButtonTextKey(
Exception exception) const
-> rpl::producer<QString> {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_groups_always_empty();
case Exception::Never: return tr::lng_edit_privacy_groups_never_empty();
case Exception::Always:
return tr::lng_edit_privacy_groups_always_empty();
case Exception::Never:
return tr::lng_edit_privacy_groups_never_empty();
}
Unexpected("Invalid exception value.");
}
@ -788,8 +795,10 @@ rpl::producer<QString> GroupsInvitePrivacyController::exceptionButtonTextKey(
rpl::producer<QString> GroupsInvitePrivacyController::exceptionBoxTitle(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_groups_always_title();
case Exception::Never: return tr::lng_edit_privacy_groups_never_title();
case Exception::Always:
return tr::lng_edit_privacy_groups_always_title();
case Exception::Never:
return tr::lng_edit_privacy_groups_never_title();
}
Unexpected("Invalid exception value.");
}
@ -819,8 +828,10 @@ rpl::producer<QString> CallsPrivacyController::optionsTitleKey() const {
rpl::producer<QString> CallsPrivacyController::exceptionButtonTextKey(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_calls_always_empty();
case Exception::Never: return tr::lng_edit_privacy_calls_never_empty();
case Exception::Always:
return tr::lng_edit_privacy_calls_always_empty();
case Exception::Never:
return tr::lng_edit_privacy_calls_never_empty();
}
Unexpected("Invalid exception value.");
}
@ -828,7 +839,8 @@ rpl::producer<QString> CallsPrivacyController::exceptionButtonTextKey(
rpl::producer<QString> CallsPrivacyController::exceptionBoxTitle(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_calls_always_title();
case Exception::Always:
return tr::lng_edit_privacy_calls_always_title();
case Exception::Never: return tr::lng_edit_privacy_calls_never_title();
}
Unexpected("Invalid exception value.");
@ -871,7 +883,8 @@ rpl::producer<QString> CallsPeer2PeerPrivacyController::title() const {
return tr::lng_edit_privacy_calls_p2p_title();
}
rpl::producer<QString> CallsPeer2PeerPrivacyController::optionsTitleKey() const {
auto CallsPeer2PeerPrivacyController::optionsTitleKey() const
-> rpl::producer<QString> {
return tr::lng_edit_privacy_calls_p2p_header();
}
@ -895,8 +908,9 @@ auto CallsPeer2PeerPrivacyController::warning() const
return tr::lng_settings_peer_to_peer_about(Ui::Text::WithEntities);
}
rpl::producer<QString> CallsPeer2PeerPrivacyController::exceptionButtonTextKey(
Exception exception) const {
auto CallsPeer2PeerPrivacyController::exceptionButtonTextKey(
Exception exception) const
-> rpl::producer<QString> {
switch (exception) {
case Exception::Always: {
return tr::lng_edit_privacy_calls_p2p_always_empty();
@ -1121,7 +1135,8 @@ rpl::producer<QString> ProfilePhotoPrivacyController::title() const {
return tr::lng_edit_privacy_profile_photo_title();
}
rpl::producer<QString> ProfilePhotoPrivacyController::optionsTitleKey() const {
auto ProfilePhotoPrivacyController::optionsTitleKey() const
-> rpl::producer<QString> {
return tr::lng_edit_privacy_profile_photo_header();
}
@ -1234,7 +1249,8 @@ object_ptr<Ui::RpWidget> ProfilePhotoPrivacyController::setupMiddleWidget(
container,
&controller->window(),
{
.confirm = tr::lng_profile_set_photo_button(tr::now),
.confirm = tr::lng_profile_set_photo_button(
tr::now),
.cropType = EditorData::CropType::Ellipse,
.keepAspectRatio = true,
},
@ -1283,8 +1299,9 @@ void ProfilePhotoPrivacyController::saveAdditional() {
}
}
rpl::producer<QString> ProfilePhotoPrivacyController::exceptionButtonTextKey(
Exception exception) const {
auto ProfilePhotoPrivacyController::exceptionButtonTextKey(
Exception exception) const
-> rpl::producer<QString> {
switch (exception) {
case Exception::Always: {
return tr::lng_edit_privacy_profile_photo_always_empty();
@ -1363,8 +1380,10 @@ rpl::producer<QString> VoicesPrivacyController::optionsTitleKey() const {
rpl::producer<QString> VoicesPrivacyController::exceptionButtonTextKey(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_voices_always_empty();
case Exception::Never: return tr::lng_edit_privacy_voices_never_empty();
case Exception::Always:
return tr::lng_edit_privacy_voices_always_empty();
case Exception::Never:
return tr::lng_edit_privacy_voices_never_empty();
}
Unexpected("Invalid exception value.");
}
@ -1372,7 +1391,8 @@ rpl::producer<QString> VoicesPrivacyController::exceptionButtonTextKey(
rpl::producer<QString> VoicesPrivacyController::exceptionBoxTitle(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_voices_always_title();
case Exception::Always:
return tr::lng_edit_privacy_voices_always_title();
case Exception::Never: return tr::lng_edit_privacy_voices_never_title();
}
Unexpected("Invalid exception value.");
@ -1468,7 +1488,8 @@ rpl::producer<QString> AboutPrivacyController::optionsTitleKey() const {
rpl::producer<QString> AboutPrivacyController::exceptionButtonTextKey(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_about_always_empty();
case Exception::Always:
return tr::lng_edit_privacy_about_always_empty();
case Exception::Never: return tr::lng_edit_privacy_about_never_empty();
}
Unexpected("Invalid exception value.");
@ -1477,7 +1498,8 @@ rpl::producer<QString> AboutPrivacyController::exceptionButtonTextKey(
rpl::producer<QString> AboutPrivacyController::exceptionBoxTitle(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_about_always_title();
case Exception::Always:
return tr::lng_edit_privacy_about_always_title();
case Exception::Never: return tr::lng_edit_privacy_about_never_title();
}
Unexpected("Invalid exception value.");
@ -1485,7 +1507,7 @@ rpl::producer<QString> AboutPrivacyController::exceptionBoxTitle(
auto AboutPrivacyController::exceptionsDescription() const
-> rpl::producer<QString> {
return tr::lng_edit_privacy_birthday_exceptions();
return tr::lng_edit_privacy_about_exceptions();
}
UserPrivacy::Key BirthdayPrivacyController::key() const {
@ -1503,8 +1525,10 @@ rpl::producer<QString> BirthdayPrivacyController::optionsTitleKey() const {
rpl::producer<QString> BirthdayPrivacyController::exceptionButtonTextKey(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_birthday_always_empty();
case Exception::Never: return tr::lng_edit_privacy_birthday_never_empty();
case Exception::Always:
return tr::lng_edit_privacy_birthday_always_empty();
case Exception::Never:
return tr::lng_edit_privacy_birthday_never_empty();
}
Unexpected("Invalid exception value.");
}
@ -1512,8 +1536,10 @@ rpl::producer<QString> BirthdayPrivacyController::exceptionButtonTextKey(
rpl::producer<QString> BirthdayPrivacyController::exceptionBoxTitle(
Exception exception) const {
switch (exception) {
case Exception::Always: return tr::lng_edit_privacy_birthday_always_title();
case Exception::Never: return tr::lng_edit_privacy_birthday_never_title();
case Exception::Always:
return tr::lng_edit_privacy_birthday_always_title();
case Exception::Never:
return tr::lng_edit_privacy_birthday_never_title();
}
Unexpected("Invalid exception value.");
}
@ -1553,4 +1579,49 @@ object_ptr<Ui::RpWidget> BirthdayPrivacyController::setupAboveWidget(
return result;
}
UserPrivacy::Key GiftsAutoSavePrivacyController::key() const {
return Key::GiftsAutoSave;
}
rpl::producer<QString> GiftsAutoSavePrivacyController::title() const {
return tr::lng_edit_privacy_gifts_title();
}
auto GiftsAutoSavePrivacyController::optionsTitleKey() const
-> rpl::producer<QString> {
return tr::lng_edit_privacy_gifts_header();
}
auto GiftsAutoSavePrivacyController::exceptionButtonTextKey(
Exception exception) const
-> rpl::producer<QString> {
switch (exception) {
case Exception::Always:
return tr::lng_edit_privacy_gifts_always_empty();
case Exception::Never:
return tr::lng_edit_privacy_gifts_never_empty();
}
Unexpected("Invalid exception value.");
}
rpl::producer<QString> GiftsAutoSavePrivacyController::exceptionBoxTitle(
Exception exception) const {
switch (exception) {
case Exception::Always:
return tr::lng_edit_privacy_gifts_always_title();
case Exception::Never: return tr::lng_edit_privacy_gifts_never_title();
}
Unexpected("Invalid exception value.");
}
auto GiftsAutoSavePrivacyController::exceptionsDescription() const
-> rpl::producer<QString> {
return tr::lng_edit_privacy_lastseen_exceptions();
}
bool GiftsAutoSavePrivacyController::allowMiniAppsToggle(
Exception exception) const {
return true;
}
} // namespace Settings

View File

@ -194,7 +194,7 @@ public:
};
class ForwardsPrivacyController
class ForwardsPrivacyController final
: public EditPrivacyController
, private HistoryView::SimpleElementDelegate {
public:
@ -340,4 +340,22 @@ public:
};
class GiftsAutoSavePrivacyController final : public EditPrivacyController {
public:
using Option = EditPrivacyBox::Option;
using Exception = EditPrivacyBox::Exception;
Key key() const override;
rpl::producer<QString> title() const override;
rpl::producer<QString> optionsTitleKey() const override;
rpl::producer<QString> exceptionButtonTextKey(
Exception exception) const override;
rpl::producer<QString> exceptionBoxTitle(
Exception exception) const override;
rpl::producer<QString> exceptionsDescription() const override;
bool allowMiniAppsToggle(Exception exception) const override;
};
} // namespace Settings

View File

@ -185,16 +185,23 @@ QString PrivacyBase(Privacy::Key key, const Privacy::Rule &rule) {
[[fallthrough]];
default:
switch (rule.option) {
case Option::Everyone: return tr::lng_edit_privacy_everyone(tr::now);
case Option::Everyone:
return rule.never.miniapps
? tr::lng_edit_privacy_no_miniapps(tr::now)
: tr::lng_edit_privacy_everyone(tr::now);
case Option::Contacts:
return rule.always.premiums
? tr::lng_edit_privacy_contacts_and_premium(tr::now)
: rule.always.miniapps
? tr::lng_edit_privacy_contacts_and_miniapps(tr::now)
: tr::lng_edit_privacy_contacts(tr::now);
case Option::CloseFriends:
return tr::lng_edit_privacy_close_friends(tr::now);
case Option::Nobody:
return rule.always.premiums
? tr::lng_edit_privacy_premium(tr::now)
: rule.always.miniapps
? tr::lng_edit_privacy_miniapps(tr::now)
: tr::lng_edit_privacy_nobody(tr::now);
}
Unexpected("Value in Privacy::Option.");
@ -405,7 +412,8 @@ void SetupPrivacy(
add(
tr::lng_settings_last_seen(),
Key::LastSeen,
[=] { return std::make_unique<LastSeenPrivacyController>(session); });
[=] { return std::make_unique<LastSeenPrivacyController>(
session); });
add(
tr::lng_settings_profile_photo_privacy(),
Key::ProfilePhoto,
@ -414,6 +422,10 @@ void SetupPrivacy(
tr::lng_settings_bio_privacy(),
Key::About,
[] { return std::make_unique<AboutPrivacyController>(); });
add(
tr::lng_settings_gifts_privacy(),
Key::GiftsAutoSave,
[=] { return std::make_unique<GiftsAutoSavePrivacyController>(); });
add(
tr::lng_settings_birthday_privacy(),
Key::Birthday,
@ -442,7 +454,8 @@ void SetupPrivacy(
}
AddMessagesPrivacyButton(controller, container);
session->api().userPrivacy().reload(Api::UserPrivacy::Key::AddedByPhone);
session->api().userPrivacy().reload(
Api::UserPrivacy::Key::AddedByPhone);
Ui::AddSkip(container, st::settingsPrivacySecurityPadding);
Ui::AddDivider(container);