diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 2c124769b..14cc25536 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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"; diff --git a/Telegram/SourceFiles/api/api_user_privacy.cpp b/Telegram/SourceFiles/api/api_user_privacy.cpp index d0c17fa6b..78f863bed 100644 --- a/Telegram/SourceFiles/api/api_user_privacy.cpp +++ b/Telegram/SourceFiles/api/api_user_privacy.cpp @@ -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(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 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; } diff --git a/Telegram/SourceFiles/api/api_user_privacy.h b/Telegram/SourceFiles/api/api_user_privacy.h index 471f41f48..a1f66189f 100644 --- a/Telegram/SourceFiles/api/api_user_privacy.h +++ b/Telegram/SourceFiles/api/api_user_privacy.h @@ -31,6 +31,7 @@ public: Voices, About, Birthday, + GiftsAutoSave, }; enum class Option { Everyone, @@ -41,6 +42,7 @@ public: struct Exceptions { std::vector> peers; bool premiums = false; + bool miniapps = false; }; struct Rule { Option option = Option::Everyone; diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp index c9a9055e1..d90059cb9 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -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 widget, const style::Checkbox &st) { @@ -102,7 +153,7 @@ public: not_null session, rpl::producer title, const Exceptions &selected, - bool allowChoosePremiums); + std::optional allowChooseSpecial); Main::Session &session() const override; void rowClicked(not_null 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 createRow(not_null history) override; private: - [[nodiscard]] object_ptr preparePremiumsRowList(); + [[nodiscard]] object_ptr prepareSpecialRowList( + SpecialRowType type); const not_null _session; rpl::producer _title; Exceptions _selected; - bool _allowChoosePremiums = false; + std::optional _allowChooseSpecial; PeerListContentDelegate *_typesDelegate = nullptr; Fn _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 session, bool premiums); + TypesController(not_null session, SpecialRowType type); Main::Session &session() const override; void prepare() override; void rowClicked(not_null row) override; - [[nodiscard]] bool premiumsSelected() const; - [[nodiscard]] rpl::producer premiumsChanges() const; + [[nodiscard]] bool specialSelected() const; + [[nodiscard]] rpl::producer specialChanges() const; [[nodiscard]] auto rowSelectionChanges() const -> rpl::producer; private: const not_null _session; + const SpecialRowType _type; rpl::event_stream<> _selectionChanged; rpl::event_stream _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 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()); + delegate()->peerListAppendRow(std::make_unique(_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 row) { _rowSelectionChanges.fire({ row, checked }); } -rpl::producer TypesController::premiumsChanges() const { +rpl::producer TypesController::specialChanges() const { return _rowSelectionChanges.events( ) | rpl::map([=] { - return premiumsSelected(); + return specialSelected(); }); } @@ -247,12 +301,12 @@ PrivacyExceptionsBoxController::PrivacyExceptionsBoxController( not_null session, rpl::producer title, const Exceptions &selected, - bool allowChoosePremiums) + std::optional 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 { auto result = object_ptr((QWidget*)nullptr); const auto container = result.data(); @@ -291,30 +350,39 @@ auto PrivacyExceptionsBoxController::preparePremiumsRowList() _typesDelegate = lifetime.make_state(); const auto controller = lifetime.make_state( &session(), - _selected.premiums); + type); const auto content = result->add(object_ptr( 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 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())); auto initBox = [=, controller = controller.get()]( not_null 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, diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.h b/Telegram/SourceFiles/boxes/edit_privacy_box.h index 3aae28403..bd87e90f2 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.h +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.h @@ -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 value) { diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index 6b2a753ce..db18d216e 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -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 = InputPrivac inputPrivacyValueDisallowChatParticipants#e94f0f86 chats:Vector = 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 = PrivacyRule; privacyValueDisallowChatParticipants#41c87565 chats:Vector = PrivacyRule; privacyValueAllowCloseFriends#f7e8d89b = PrivacyRule; privacyValueAllowPremium#ece9814b = PrivacyRule; +privacyValueAllowBots#21461b5d = PrivacyRule; +privacyValueDisallowBots#f6a5f82f = PrivacyRule; account.privacyRules#50a04e45 rules:Vector chats:Vector users:Vector = account.PrivacyRules; diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index dc9a7bcc3..c93c50aae 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -380,11 +380,13 @@ void BlockedBoxController::rowClicked(not_null row) { }); } -void BlockedBoxController::rowRightActionClicked(not_null row) { +void BlockedBoxController::rowRightActionClicked( + not_null 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 PhoneNumberPrivacyController::title() const { return tr::lng_edit_privacy_phone_number_title(); } -rpl::producer PhoneNumberPrivacyController::optionsTitleKey() const { +auto PhoneNumberPrivacyController::optionsTitleKey() const +-> rpl::producer { return tr::lng_edit_privacy_phone_number_header(); } @@ -731,7 +734,8 @@ void LastSeenPrivacyController::handleExceptionsChange( void LastSeenPrivacyController::confirmSave( bool someAreDisallowed, Fn 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 GroupsInvitePrivacyController::optionsTitleKey( return tr::lng_edit_privacy_groups_header(); } -rpl::producer GroupsInvitePrivacyController::exceptionButtonTextKey( - Exception exception) const { +auto GroupsInvitePrivacyController::exceptionButtonTextKey( + Exception exception) const +-> rpl::producer { 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 GroupsInvitePrivacyController::exceptionButtonTextKey( rpl::producer 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 CallsPrivacyController::optionsTitleKey() const { rpl::producer 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 CallsPrivacyController::exceptionButtonTextKey( rpl::producer 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 CallsPeer2PeerPrivacyController::title() const { return tr::lng_edit_privacy_calls_p2p_title(); } -rpl::producer CallsPeer2PeerPrivacyController::optionsTitleKey() const { +auto CallsPeer2PeerPrivacyController::optionsTitleKey() const +-> rpl::producer { 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 CallsPeer2PeerPrivacyController::exceptionButtonTextKey( - Exception exception) const { +auto CallsPeer2PeerPrivacyController::exceptionButtonTextKey( + Exception exception) const +-> rpl::producer { switch (exception) { case Exception::Always: { return tr::lng_edit_privacy_calls_p2p_always_empty(); @@ -1121,7 +1135,8 @@ rpl::producer ProfilePhotoPrivacyController::title() const { return tr::lng_edit_privacy_profile_photo_title(); } -rpl::producer ProfilePhotoPrivacyController::optionsTitleKey() const { +auto ProfilePhotoPrivacyController::optionsTitleKey() const +-> rpl::producer { return tr::lng_edit_privacy_profile_photo_header(); } @@ -1234,7 +1249,8 @@ object_ptr 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 ProfilePhotoPrivacyController::exceptionButtonTextKey( - Exception exception) const { +auto ProfilePhotoPrivacyController::exceptionButtonTextKey( + Exception exception) const +-> rpl::producer { switch (exception) { case Exception::Always: { return tr::lng_edit_privacy_profile_photo_always_empty(); @@ -1363,8 +1380,10 @@ rpl::producer VoicesPrivacyController::optionsTitleKey() const { rpl::producer 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 VoicesPrivacyController::exceptionButtonTextKey( rpl::producer 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 AboutPrivacyController::optionsTitleKey() const { rpl::producer 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 AboutPrivacyController::exceptionButtonTextKey( rpl::producer 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 AboutPrivacyController::exceptionBoxTitle( auto AboutPrivacyController::exceptionsDescription() const -> rpl::producer { - 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 BirthdayPrivacyController::optionsTitleKey() const { rpl::producer 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 BirthdayPrivacyController::exceptionButtonTextKey( rpl::producer 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 BirthdayPrivacyController::setupAboveWidget( return result; } +UserPrivacy::Key GiftsAutoSavePrivacyController::key() const { + return Key::GiftsAutoSave; +} + +rpl::producer GiftsAutoSavePrivacyController::title() const { + return tr::lng_edit_privacy_gifts_title(); +} + +auto GiftsAutoSavePrivacyController::optionsTitleKey() const +-> rpl::producer { + return tr::lng_edit_privacy_gifts_header(); +} + +auto GiftsAutoSavePrivacyController::exceptionButtonTextKey( + Exception exception) const +-> rpl::producer { + 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 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 { + return tr::lng_edit_privacy_lastseen_exceptions(); +} + +bool GiftsAutoSavePrivacyController::allowMiniAppsToggle( + Exception exception) const { + return true; +} + } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.h b/Telegram/SourceFiles/settings/settings_privacy_controllers.h index d058649d2..88a61d9cd 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.h +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.h @@ -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 title() const override; + rpl::producer optionsTitleKey() const override; + rpl::producer exceptionButtonTextKey( + Exception exception) const override; + rpl::producer exceptionBoxTitle( + Exception exception) const override; + rpl::producer exceptionsDescription() const override; + bool allowMiniAppsToggle(Exception exception) const override; + +}; + } // namespace Settings diff --git a/Telegram/SourceFiles/settings/settings_privacy_security.cpp b/Telegram/SourceFiles/settings/settings_privacy_security.cpp index f71134c3c..3222bc248 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_security.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_security.cpp @@ -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(session); }); + [=] { return std::make_unique( + 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(); }); + add( + tr::lng_settings_gifts_privacy(), + Key::GiftsAutoSave, + [=] { return std::make_unique(); }); 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);