diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index f080928c0..706824f92 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1107,9 +1107,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_edit_privacy_nobody" = "Nobody"; "lng_edit_privacy_premium" = "Premium users"; "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_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_add" = "Add users or groups"; "lng_edit_privacy_phone_number_title" = "Phone number privacy"; diff --git a/Telegram/SourceFiles/api/api_user_privacy.cpp b/Telegram/SourceFiles/api/api_user_privacy.cpp index ce9dc91f9..dd5693cee 100644 --- a/Telegram/SourceFiles/api/api_user_privacy.cpp +++ b/Telegram/SourceFiles/api/api_user_privacy.cpp @@ -26,7 +26,9 @@ using TLInputRules = MTPVector; using TLRules = MTPVector; TLInputRules RulesToTL(const UserPrivacy::Rule &rule) { - const auto collectInputUsers = [](const auto &peers) { + using Exceptions = UserPrivacy::Exceptions; + const auto collectInputUsers = [](const Exceptions &exceptions) { + const auto &peers = exceptions.peers; auto result = QVector(); result.reserve(peers.size()); for (const auto &peer : peers) { @@ -36,7 +38,8 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) { } return result; }; - const auto collectInputChats = [](const auto &peers) { + const auto collectInputChats = [](const Exceptions &exceptions) { + const auto &peers = exceptions.peers; auto result = QVector(); result.reserve(peers.size()); for (const auto &peer : peers) { @@ -47,6 +50,7 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) { return result; }; + using Option = UserPrivacy::Option; auto result = QVector(); result.reserve(kMaxRules); if (!rule.ignoreAlways) { @@ -62,6 +66,9 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) { MTP_inputPrivacyValueAllowChatParticipants( MTP_vector(chats))); } + if (rule.always.premiums && (rule.option != Option::Everyone)) { + result.push_back(MTP_inputPrivacyValueAllowPremium()); + } } if (!rule.ignoreNever) { const auto users = collectInputUsers(rule.never); @@ -78,14 +85,11 @@ TLInputRules RulesToTL(const UserPrivacy::Rule &rule) { } } result.push_back([&] { - using Option = UserPrivacy::Option; switch (rule.option) { case Option::Everyone: return MTP_inputPrivacyValueAllowAll(); case Option::Contacts: return MTP_inputPrivacyValueAllowContacts(); case Option::CloseFriends: return MTP_inputPrivacyValueAllowCloseFriends(); - case Option::ContactsAndPremium: - return MTP_inputPrivacyValueAllowPremium(); case Option::Nobody: return MTP_inputPrivacyValueDisallowAll(); } Unexpected("Option value in Api::UserPrivacy::RulesToTL."); @@ -102,6 +106,7 @@ UserPrivacy::Rule TLToRules(const TLRules &rules, Data::Session &owner) { using Option = UserPrivacy::Option; auto result = UserPrivacy::Rule(); auto optionSet = false; + auto allowPremium = false; const auto setOption = [&](Option option) { if (optionSet) { return; @@ -109,8 +114,8 @@ UserPrivacy::Rule TLToRules(const TLRules &rules, Data::Session &owner) { optionSet = true; result.option = option; }; - auto &always = result.always; - auto &never = result.never; + auto &always = result.always.peers; + auto &never = result.never.peers; const auto feed = [&](const MTPPrivacyRule &rule) { rule.match([&](const MTPDprivacyValueAllowAll &) { setOption(Option::Everyone); @@ -119,7 +124,7 @@ UserPrivacy::Rule TLToRules(const TLRules &rules, Data::Session &owner) { }, [&](const MTPDprivacyValueAllowCloseFriends &) { setOption(Option::CloseFriends); }, [&](const MTPDprivacyValueAllowPremium &) { - setOption(Option::ContactsAndPremium); + result.always.premiums = true; }, [&](const MTPDprivacyValueAllowUsers &data) { const auto &users = data.vusers().v; always.reserve(always.size() + users.size()); diff --git a/Telegram/SourceFiles/api/api_user_privacy.h b/Telegram/SourceFiles/api/api_user_privacy.h index 884000fb7..471f41f48 100644 --- a/Telegram/SourceFiles/api/api_user_privacy.h +++ b/Telegram/SourceFiles/api/api_user_privacy.h @@ -36,13 +36,16 @@ public: Everyone, Contacts, CloseFriends, - ContactsAndPremium, Nobody, }; + struct Exceptions { + std::vector> peers; + bool premiums = false; + }; struct Rule { Option option = Option::Everyone; - std::vector> always; - std::vector> never; + Exceptions always; + Exceptions never; bool ignoreAlways = false; bool ignoreNever = false; }; diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp index 9dfcf5ade..031fe5ee6 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/edit_privacy_box.h" #include "api/api_global_privacy.h" +#include "boxes/filters/edit_filter_chats_list.h" +#include "ui/effects/premium_graphics.h" #include "ui/layers/generic_box.h" #include "ui/widgets/checkbox.h" #include "ui/widgets/shadow.h" @@ -30,12 +32,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_peer_values.h" #include "window/window_session_controller.h" +#include "styles/style_boxes.h" #include "styles/style_settings.h" #include "styles/style_layers.h" #include "styles/style_menu_icons.h" namespace { -namespace { + +constexpr auto kPremiumsRowId = PeerId(FakeChatId(BareId(1))).value; + +using Exceptions = Api::UserPrivacy::Exceptions; void CreateRadiobuttonLock( not_null widget, @@ -90,37 +96,167 @@ void AddPremiumRequiredRow( }, row->lifetime()); } -} // namespace - class PrivacyExceptionsBoxController : public ChatsListBoxController { public: PrivacyExceptionsBoxController( not_null session, rpl::producer title, - const std::vector> &selected); + const Exceptions &selected, + bool allowChoosePremiums); Main::Session &session() const override; void rowClicked(not_null row) override; + bool isForeignRow(PeerListRowId itemId) override; + bool handleDeselectForeignRow(PeerListRowId itemId) override; + + [[nodiscard]] bool premiumsSelected() const; protected: void prepareViewHook() override; std::unique_ptr createRow(not_null history) override; private: + [[nodiscard]] object_ptr preparePremiumsRowList(); + const not_null _session; rpl::producer _title; - std::vector> _selected; + Exceptions _selected; + bool _allowChoosePremiums = false; + + PeerListContentDelegate *_typesDelegate = nullptr; + Fn _deselectOption; }; +struct RowSelectionChange { + not_null row; + bool checked = false; +}; + +class PremiumsRow final : public PeerListRow { +public: + PremiumsRow(); + + QString generateName() override; + QString generateShortName() override; + PaintRoundImageCallback generatePaintUserpicCallback( + bool forceRound) override; + bool useForumLikeUserpic() const override; + +}; + +class TypesController final : public PeerListController { +public: + TypesController(not_null session, bool premiums); + + Main::Session &session() const override; + void prepare() override; + void rowClicked(not_null row) override; + + [[nodiscard]] bool premiumsSelected() const; + [[nodiscard]] rpl::producer premiumsChanges() const; + [[nodiscard]] auto rowSelectionChanges() const + -> rpl::producer; + +private: + [[nodiscard]] std::unique_ptr createRow() const; + + const not_null _session; + bool _premiums = false; + + rpl::event_stream<> _selectionChanged; + rpl::event_stream _rowSelectionChanges; + +}; + +PremiumsRow::PremiumsRow() : PeerListRow(kPremiumsRowId) { + setCustomStatus(tr::lng_edit_privacy_premium_status(tr::now)); +} + +QString PremiumsRow::generateName() { + return tr::lng_edit_privacy_premium(tr::now); +} + +QString PremiumsRow::generateShortName() { + return generateName(); +} + +PaintRoundImageCallback PremiumsRow::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, { x, y, size, size }); + }; +} + +bool PremiumsRow::useForumLikeUserpic() const { + return true; +} + +TypesController::TypesController( + not_null session, + bool premiums) +: _session(session) +, _premiums(premiums) { +} + +Main::Session &TypesController::session() const { + return *_session; +} + +void TypesController::prepare() { + delegate()->peerListAppendRow(std::make_unique()); + delegate()->peerListRefreshRows(); +} + +bool TypesController::premiumsSelected() const { + const auto row = delegate()->peerListFindRow(kPremiumsRowId); + Assert(row != nullptr); + + return row->checked(); +} + +void TypesController::rowClicked(not_null row) { + const auto checked = !row->checked(); + delegate()->peerListSetRowChecked(row, checked); + _rowSelectionChanges.fire({ row, checked }); +} + +rpl::producer TypesController::premiumsChanges() const { + return _rowSelectionChanges.events( + ) | rpl::map([=] { + return premiumsSelected(); + }); +} + +auto TypesController::rowSelectionChanges() const +-> rpl::producer { + return _rowSelectionChanges.events(); +} + PrivacyExceptionsBoxController::PrivacyExceptionsBoxController( not_null session, rpl::producer title, - const std::vector> &selected) + const Exceptions &selected, + bool allowChoosePremiums) : ChatsListBoxController(session) , _session(session) , _title(std::move(title)) -, _selected(selected) { +, _selected(selected) +, _allowChoosePremiums(allowChoosePremiums) { } Main::Session &PrivacyExceptionsBoxController::session() const { @@ -129,7 +265,81 @@ Main::Session &PrivacyExceptionsBoxController::session() const { void PrivacyExceptionsBoxController::prepareViewHook() { delegate()->peerListSetTitle(std::move(_title)); - delegate()->peerListAddSelectedPeers(_selected); + if (_allowChoosePremiums || _selected.premiums) { + delegate()->peerListSetAboveWidget(preparePremiumsRowList()); + } + delegate()->peerListAddSelectedPeers(_selected.peers); +} + +bool PrivacyExceptionsBoxController::isForeignRow(PeerListRowId itemId) { + return (itemId == kPremiumsRowId); +} + +bool PrivacyExceptionsBoxController::handleDeselectForeignRow( + PeerListRowId itemId) { + if (isForeignRow(itemId)) { + _deselectOption(itemId); + return true; + } + return false; +} + +auto PrivacyExceptionsBoxController::preparePremiumsRowList() +-> object_ptr { + auto result = object_ptr((QWidget*)nullptr); + const auto container = result.data(); + container->add(CreatePeerListSectionSubtitle( + container, + tr::lng_edit_privacy_user_types())); + auto &lifetime = container->lifetime(); + _typesDelegate = lifetime.make_state(); + const auto controller = lifetime.make_state( + &session(), + _selected.premiums); + const auto content = result->add(object_ptr( + container, + controller)); + _typesDelegate->setContent(content); + controller->setDelegate(_typesDelegate); + + 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); + } + container->add(CreatePeerListSectionSubtitle( + container, + tr::lng_edit_privacy_users_and_groups())); + + controller->premiumsChanges( + ) | rpl::start_with_next([=](bool premiums) { + _selected.premiums = premiums; + }, lifetime); + + controller->rowSelectionChanges( + ) | rpl::start_with_next([=](RowSelectionChange update) { + this->delegate()->peerListSetForeignRowChecked( + update.row, + update.checked, + anim::type::normal); + }, lifetime); + + _deselectOption = [=](PeerListRowId itemId) { + if (const auto row = _typesDelegate->peerListFindRow(itemId)) { + _typesDelegate->peerListSetRowChecked(row, false); + } + }; + + return result; +} + +[[nodiscard]] bool PrivacyExceptionsBoxController::premiumsSelected() const { + return _selected.premiums; } void PrivacyExceptionsBoxController::rowClicked(not_null row) { @@ -145,7 +355,8 @@ void PrivacyExceptionsBoxController::rowClicked(not_null row) { } } -std::unique_ptr PrivacyExceptionsBoxController::createRow(not_null history) { +auto PrivacyExceptionsBoxController::createRow(not_null history) +-> std::unique_ptr { if (history->peer->isSelf() || history->peer->isRepliesChat()) { return nullptr; } else if (!history->peer->isUser() @@ -210,11 +421,13 @@ void EditPrivacyBox::editExceptions( auto controller = std::make_unique( &_window->session(), _controller->exceptionBoxTitle(exception), - exceptions(exception)); + exceptions(exception), + _controller->allowPremiumsToggle(exception)); auto initBox = [=, controller = controller.get()]( not_null box) { box->addButton(tr::lng_settings_save(), crl::guard(this, [=] { - exceptions(exception) = box->collectSelectedRows(); + exceptions(exception).peers = box->collectSelectedRows(); + exceptions(exception).premiums = controller->premiumsSelected(); const auto type = [&] { switch (exception) { case Exception::Always: return Exception::Never; @@ -222,8 +435,8 @@ void EditPrivacyBox::editExceptions( } Unexpected("Invalid exception value."); }(); - auto &removeFrom = exceptions(type); - for (const auto peer : exceptions(exception)) { + auto &removeFrom = exceptions(type).peers; + for (const auto peer : exceptions(exception).peers) { removeFrom.erase( ranges::remove(removeFrom, peer), end(removeFrom)); @@ -237,7 +450,7 @@ void EditPrivacyBox::editExceptions( Box(std::move(controller), std::move(initBox))); } -std::vector> &EditPrivacyBox::exceptions(Exception exception) { +EditPrivacyBox::Exceptions &EditPrivacyBox::exceptions(Exception exception) { switch (exception) { case Exception::Always: return _value.always; case Exception::Never: return _value.never; @@ -340,16 +553,28 @@ void EditPrivacyBox::setupContent() { const auto addExceptionLink = [=](Exception exception) { const auto update = Ui::CreateChild>(content); auto label = update->events_starting_with({}) | rpl::map([=] { - return Settings::ExceptionUsersCount(exceptions(exception)); - }) | rpl::map([](int count) { - return count - ? tr::lng_edit_privacy_exceptions_count(tr::now, lt_count, count) + const auto &value = exceptions(exception); + const auto count = Settings::ExceptionUsersCount(value.peers); + const auto users = count + ? tr::lng_edit_privacy_exceptions_count( + tr::now, + 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); }); _controller->handleExceptionsChange( exception, update->events_starting_with({}) | rpl::map([=] { - return Settings::ExceptionUsersCount(exceptions(exception)); + return Settings::ExceptionUsersCount( + exceptions(exception).peers); })); auto text = _controller->exceptionButtonTextKey(exception); const auto button = content->add( @@ -448,7 +673,7 @@ void EditPrivacyBox::setupContent() { addButton(tr::lng_settings_save(), [=] { const auto someAreDisallowed = (_value.option != Option::Everyone) - || !_value.never.empty(); + || !_value.never.peers.empty(); _controller->confirmSave(someAreDisallowed, crl::guard(this, [=] { _value.ignoreAlways = !showExceptionLink(Exception::Always); _value.ignoreNever = !showExceptionLink(Exception::Never); diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.h b/Telegram/SourceFiles/boxes/edit_privacy_box.h index da8bc98cf..3aae28403 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.h +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.h @@ -48,7 +48,8 @@ public: [[nodiscard]] virtual rpl::producer warning() const { return nullptr; } - virtual void prepareWarningLabel(not_null warning) const { + virtual void prepareWarningLabel( + not_null warning) const { } [[nodiscard]] virtual rpl::producer exceptionButtonTextKey( Exception exception) const = 0; @@ -56,6 +57,10 @@ public: Exception exception) const = 0; [[nodiscard]] virtual auto exceptionsDescription() const -> rpl::producer = 0; + [[nodiscard]] virtual bool allowPremiumsToggle( + Exception exception) const { + return false; + } virtual void handleExceptionsChange( Exception exception, rpl::producer value) { @@ -117,6 +122,7 @@ class EditPrivacyBox final : public Ui::BoxContent { public: using Value = Api::UserPrivacy::Rule; using Option = Api::UserPrivacy::Option; + using Exceptions = Api::UserPrivacy::Exceptions; using Exception = EditPrivacyController::Exception; EditPrivacyBox( @@ -148,7 +154,7 @@ private: int topSkip); void editExceptions(Exception exception, Fn done); - std::vector> &exceptions(Exception exception); + Exceptions &exceptions(Exception exception); const not_null _window; std::unique_ptr _controller; diff --git a/Telegram/SourceFiles/boxes/peer_list_box.cpp b/Telegram/SourceFiles/boxes/peer_list_box.cpp index fe3a3f28e..2430c583e 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.cpp +++ b/Telegram/SourceFiles/boxes/peer_list_box.cpp @@ -506,6 +506,22 @@ int PeerListBox::peerListSelectedRowsCount() { return _select ? _select->entity()->getItemsCount() : 0; } +std::vector PeerListBox::collectSelectedIds() { + auto result = std::vector(); + auto items = _select + ? _select->entity()->getItems() + : QVector(); + if (!items.empty()) { + result.reserve(items.size()); + for (const auto itemId : items) { + if (!_controller->isForeignRow(itemId)) { + result.push_back(itemId); + } + } + } + return result; +} + auto PeerListBox::collectSelectedRows() -> std::vector> { auto result = std::vector>(); @@ -887,11 +903,15 @@ void PeerListRow::lazyInitialize(const style::PeerListItem &st) { refreshStatus(); } +bool PeerListRow::useForumLikeUserpic() const { + return !special() && peer()->isForum(); +} + void PeerListRow::createCheckbox( const style::RoundImageCheckbox &st, Fn updateCallback) { const auto generateRadius = [=](int size) { - return (!special() && peer()->isForum()) + return useForumLikeUserpic() ? int(size * Ui::ForumUserpicRadiusMultiplier()) : std::optional(); }; diff --git a/Telegram/SourceFiles/boxes/peer_list_box.h b/Telegram/SourceFiles/boxes/peer_list_box.h index 50a37263e..ea7f73b67 100644 --- a/Telegram/SourceFiles/boxes/peer_list_box.h +++ b/Telegram/SourceFiles/boxes/peer_list_box.h @@ -166,6 +166,8 @@ public: return _name; } + virtual bool useForumLikeUserpic() const; + enum class StatusType { Online, LastSeen, @@ -1042,6 +1044,7 @@ public: std::unique_ptr controller, Fn)> init); + [[nodiscard]] std::vector collectSelectedIds(); [[nodiscard]] std::vector> collectSelectedRows(); void peerListSetTitle(rpl::producer title) override { diff --git a/Telegram/SourceFiles/data/data_birthday.h b/Telegram/SourceFiles/data/data_birthday.h index ebf4060c8..e728cce42 100644 --- a/Telegram/SourceFiles/data/data_birthday.h +++ b/Telegram/SourceFiles/data/data_birthday.h @@ -30,7 +30,7 @@ public: friend inline constexpr auto operator<=>(Birthday, Birthday) = default; friend inline constexpr bool operator==(Birthday, Birthday) = default; - static constexpr auto kYearMin = 1900; + static constexpr auto kYearMin = 1875; static constexpr auto kYearMax = 2100; private: diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index 9c1c98d22..d931f1df7 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -161,6 +161,7 @@ settingsPrivacyOption: Checkbox(settingsCheckbox) { settingsPrivacySecurityPadding: 12px; settingsPrivacySkip: 14px; settingsPrivacySkipTop: 4px; +settingsPrivacyPremium: icon{{ "profile_premium", premiumButtonFg }}; settingsPrivacyAddBirthday: FlatLabel(defaultFlatLabel) { minWidth: 256px; diff --git a/Telegram/SourceFiles/settings/settings_information.cpp b/Telegram/SourceFiles/settings/settings_information.cpp index bf6989647..b6b75b589 100644 --- a/Telegram/SourceFiles/settings/settings_information.cpp +++ b/Telegram/SourceFiles/settings/settings_information.cpp @@ -392,8 +392,9 @@ void SetupBirthday( key ) | rpl::map([=](const Api::UserPrivacy::Rule &value) { return (value.option == Api::UserPrivacy::Option::Contacts) - && value.always.empty() - && value.never.empty(); + && value.always.peers.empty() + && !value.always.premiums + && value.never.peers.empty(); }) | rpl::distinct_until_changed(); Ui::AddSkip(container); diff --git a/Telegram/SourceFiles/settings/settings_main.cpp b/Telegram/SourceFiles/settings/settings_main.cpp index d7005fd9d..ffa288223 100644 --- a/Telegram/SourceFiles/settings/settings_main.cpp +++ b/Telegram/SourceFiles/settings/settings_main.cpp @@ -440,10 +440,7 @@ void SetupPremium( button->addClickHandler([=] { showOther(BusinessId()); }); - constexpr auto kNewExpiresAt = int(1711958400); - if (base::unixtime::now() < kNewExpiresAt) { - Ui::NewBadge::AddToRight(button); - } + Ui::NewBadge::AddToRight(button); if (controller->session().premiumCanBuy()) { const auto button = AddButtonWithIcon( diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index 5308b9cf4..b3829efeb 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -795,6 +795,11 @@ auto GroupsInvitePrivacyController::exceptionsDescription() const return tr::lng_edit_privacy_groups_exceptions(); } +bool GroupsInvitePrivacyController::allowPremiumsToggle( + Exception exception) const { + return (exception == Exception::Always); +} + UserPrivacy::Key CallsPrivacyController::key() const { return Key::Calls; } diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.h b/Telegram/SourceFiles/settings/settings_privacy_controllers.h index 5e1083c20..d058649d2 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.h +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.h @@ -149,6 +149,7 @@ public: rpl::producer exceptionBoxTitle( Exception exception) const override; rpl::producer exceptionsDescription() const override; + bool allowPremiumsToggle(Exception exception) const override; }; diff --git a/Telegram/SourceFiles/settings/settings_privacy_security.cpp b/Telegram/SourceFiles/settings/settings_privacy_security.cpp index 404cb9d62..045457819 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_security.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_security.cpp @@ -114,31 +114,33 @@ void AddPremiumStar( }, badge->lifetime()); } -QString PrivacyBase(Privacy::Key key, Privacy::Option option) { +QString PrivacyBase(Privacy::Key key, const Privacy::Rule &rule) { using Key = Privacy::Key; using Option = Privacy::Option; switch (key) { case Key::CallsPeer2Peer: - switch (option) { + switch (rule.option) { case Option::Everyone: return tr::lng_edit_privacy_calls_p2p_everyone(tr::now); case Option::Contacts: return tr::lng_edit_privacy_calls_p2p_contacts(tr::now); - case Option::CloseFriends: - return tr::lng_edit_privacy_close_friends(tr::now); // unused case Option::Nobody: return tr::lng_edit_privacy_calls_p2p_nobody(tr::now); } - Unexpected("Value in Privacy::Option."); + [[fallthrough]]; default: - switch (option) { + switch (rule.option) { case Option::Everyone: return tr::lng_edit_privacy_everyone(tr::now); - case Option::Contacts: return tr::lng_edit_privacy_contacts(tr::now); + case Option::Contacts: + return rule.always.premiums + ? tr::lng_edit_privacy_contacts_and_premium(tr::now) + : tr::lng_edit_privacy_contacts(tr::now); case Option::CloseFriends: return tr::lng_edit_privacy_close_friends(tr::now); - case Option::ContactsAndPremium: - return tr::lng_edit_privacy_contacts_and_premium(tr::now); - case Option::Nobody: return tr::lng_edit_privacy_nobody(tr::now); + case Option::Nobody: + return rule.always.premiums + ? tr::lng_edit_privacy_premium(tr::now) + : tr::lng_edit_privacy_nobody(tr::now); } Unexpected("Value in Privacy::Option."); } @@ -152,17 +154,17 @@ rpl::producer PrivacyString( key ) | rpl::map([=](const Privacy::Rule &value) { auto add = QStringList(); - if (const auto never = ExceptionUsersCount(value.never)) { + if (const auto never = ExceptionUsersCount(value.never.peers)) { add.push_back("-" + QString::number(never)); } - if (const auto always = ExceptionUsersCount(value.always)) { + if (const auto always = ExceptionUsersCount(value.always.peers)) { add.push_back("+" + QString::number(always)); } if (!add.isEmpty()) { - return PrivacyBase(key, value.option) + return PrivacyBase(key, value) + " (" + add.join(", ") + ")"; } else { - return PrivacyBase(key, value.option); + return PrivacyBase(key, value); } }); }