diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index b8025092f..be5e8e8b6 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1218,6 +1218,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_edit_privacy_contacts" = "My contacts"; "lng_edit_privacy_close_friends" = "Close friends"; "lng_edit_privacy_contacts_and_premium" = "Contacts & Premium"; +"lng_edit_privacy_paid" = "Paid"; "lng_edit_privacy_contacts_and_miniapps" = "Contacts & Mini Apps"; "lng_edit_privacy_nobody" = "Nobody"; "lng_edit_privacy_premium" = "Premium users"; @@ -1356,6 +1357,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_messages_privacy_premium_about" = "Subscribe now to change this setting and get access to other exclusive features of Telegram Premium."; "lng_messages_privacy_premium" = "Only subscribers of {link} can select this option."; "lng_messages_privacy_premium_link" = "Telegram Premium"; +"lng_messages_privacy_charge" = "Charge for messages"; +"lng_messages_privacy_charge_about" = "Charge a fee for messages from people outside your contacts or those you haven't messaged first."; +"lng_messages_privacy_price" = "Set your price per message"; +"lng_messages_privacy_price_about" = "You will receive {percent} of the selected fee ({amount}) for each incoming message."; +"lng_messages_privacy_exceptions" = "Exceptions"; +"lng_messages_privacy_remove_fee" = "Remove Fee"; +"lng_messages_privacy_remove_about" = "Add users or entire groups who won't be charged for sending messages to you."; "lng_self_destruct_title" = "Account self-destruction"; "lng_self_destruct_description" = "If you don't come online at least once within this period, your account will be deleted along with all groups, messages and contacts."; @@ -2158,6 +2166,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_action_boost_apply#other" = "{from} boosted the group {count} times"; "lng_action_set_chat_intro" = "{from} added the message below for all empty chats. How?"; "lng_action_payment_refunded" = "{peer} refunded {amount}"; +"lng_action_paid_message_sent#one" = "You paid {count} Star to send a message"; +"lng_action_paid_message_sent#other" = "You paid {count} Stars to send a message"; +"lng_action_paid_message_got#one" = "You received {count} Star from {name}"; +"lng_action_paid_message_got#other" = "You received {count} Stars from {name}"; "lng_similar_channels_title" = "Similar channels"; "lng_similar_channels_view_all" = "View all"; @@ -4798,6 +4810,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_rights_boosts_no_restrict" = "Do not restrict boosters"; "lng_rights_boosts_about" = "Turn this on to always allow users who boosted your group to send messages and media."; "lng_rights_boosts_about_on" = "Choose how many boosts a user must give to the group to bypass restrictions on sending messages."; +"lng_rights_charge_stars" = "Charge Stars for Messages"; +"lng_rights_charge_stars_about" = "If you turn this on, regular members of the group will have to pay Stars to send messages."; +"lng_rights_charge_price" = "Set price per message"; +"lng_rights_charge_price_about" = "Your group will receive {percent} of the selected fee ({amount}) for each incoming message."; "lng_slowmode_enabled" = "Slow Mode is active.\nYou can send your next message in {left}."; "lng_slowmode_no_many" = "Slow mode is enabled. You can't send more than one message at a time."; @@ -4805,6 +4821,24 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_slowmode_seconds#one" = "{count} second"; "lng_slowmode_seconds#other" = "{count} seconds"; +"lng_payment_for_message#one" = "Pay {star}{count} for 1 Message"; +"lng_payment_for_message#other" = "Pay {star}{count} for 1 Message"; +"lng_payment_confirm_title" = "Confirm payment"; +"lng_payment_confirm_text#one" = "{name} charges **{count}** Star per message."; +"lng_payment_confirm_text#other" = "{name} charges **{count}** Stars per message."; +"lng_payment_confirm_sure#one" = "Would you like to pay **{count}** Star to send one message?"; +"lng_payment_confirm_sure#other" = "Would you like to pay **{count}** Stars to send one message?"; +"lng_payment_confirm_dont_ask" = "Don't ask me again"; +"lng_payment_confirm_button" = "Pay for 1 Message"; +"lng_payment_bar_text#one" = "{name} must pay {star}{count} for each message to you."; +"lng_payment_bar_text#other" = "{name} must pay {star}{count} for each message to you."; +"lng_payment_bar_button" = "Remove Fee"; +"lng_payment_refund_title" = "Remove Fee"; +"lng_payment_refund_text" = "Are you sure you want to allow {name} to message you for free?"; +"lng_payment_refund_also#one" = "Refund already paid {count} Star"; +"lng_payment_refund_also#other" = "Refund already paid {count} Stars"; +"lng_payment_refund_confirm" = "Confirm"; + "lng_rights_gigagroup_title" = "Broadcast group"; "lng_rights_gigagroup_convert" = "Convert to Broadcast Group"; "lng_rights_gigagroup_about" = "Broadcast groups can have over 200,000 members, but only admins can send messages in them."; diff --git a/Telegram/SourceFiles/api/api_global_privacy.cpp b/Telegram/SourceFiles/api/api_global_privacy.cpp index fbd4a4530..90c56ae4e 100644 --- a/Telegram/SourceFiles/api/api_global_privacy.cpp +++ b/Telegram/SourceFiles/api/api_global_privacy.cpp @@ -114,7 +114,8 @@ void GlobalPrivacy::updateHideReadTime(bool hide) { archiveAndMuteCurrent(), unarchiveOnNewMessageCurrent(), hide, - newRequirePremiumCurrent()); + newRequirePremiumCurrent(), + newChargeStarsCurrent()); } bool GlobalPrivacy::hideReadTimeCurrent() const { @@ -125,14 +126,6 @@ rpl::producer GlobalPrivacy::hideReadTime() const { return _hideReadTime.value(); } -void GlobalPrivacy::updateNewRequirePremium(bool value) { - update( - archiveAndMuteCurrent(), - unarchiveOnNewMessageCurrent(), - hideReadTimeCurrent(), - value); -} - bool GlobalPrivacy::newRequirePremiumCurrent() const { return _newRequirePremium.current(); } @@ -141,6 +134,25 @@ rpl::producer GlobalPrivacy::newRequirePremium() const { return _newRequirePremium.value(); } +int GlobalPrivacy::newChargeStarsCurrent() const { + return _newChargeStars.current(); +} + +rpl::producer GlobalPrivacy::newChargeStars() const { + return _newChargeStars.value(); +} + +void GlobalPrivacy::updateMessagesPrivacy( + bool requirePremium, + int chargeStars) { + update( + archiveAndMuteCurrent(), + unarchiveOnNewMessageCurrent(), + hideReadTimeCurrent(), + requirePremium, + chargeStars); +} + void GlobalPrivacy::loadPaidReactionShownPeer() { if (_paidReactionShownPeerLoaded) { return; @@ -169,7 +181,8 @@ void GlobalPrivacy::updateArchiveAndMute(bool value) { value, unarchiveOnNewMessageCurrent(), hideReadTimeCurrent(), - newRequirePremiumCurrent()); + newRequirePremiumCurrent(), + newChargeStarsCurrent()); } void GlobalPrivacy::updateUnarchiveOnNewMessage( @@ -178,14 +191,16 @@ void GlobalPrivacy::updateUnarchiveOnNewMessage( archiveAndMuteCurrent(), value, hideReadTimeCurrent(), - newRequirePremiumCurrent()); + newRequirePremiumCurrent(), + newChargeStarsCurrent()); } void GlobalPrivacy::update( bool archiveAndMute, UnarchiveOnNewMessage unarchiveOnNewMessage, bool hideReadTime, - bool newRequirePremium) { + bool newRequirePremium, + int newChargeStars) { using Flag = MTPDglobalPrivacySettings::Flag; _api.request(_requestId).cancel(); @@ -204,38 +219,44 @@ void GlobalPrivacy::update( | (hideReadTime ? Flag::f_hide_read_marks : Flag()) | ((newRequirePremium && newRequirePremiumAllowed) ? Flag::f_new_noncontact_peers_require_premium - : Flag()); - auto nonContactPaidStars = int64(0); + : Flag()) + | Flag::f_noncontact_peers_paid_stars; _requestId = _api.request(MTPaccount_SetGlobalPrivacySettings( MTP_globalPrivacySettings( MTP_flags(flags), - MTP_long(nonContactPaidStars)) + MTP_long(newChargeStars)) )).done([=](const MTPGlobalPrivacySettings &result) { _requestId = 0; apply(result); }).fail([=](const MTP::Error &error) { _requestId = 0; if (error.type() == u"PREMIUM_ACCOUNT_REQUIRED"_q) { - update(archiveAndMute, unarchiveOnNewMessage, hideReadTime, {}); + update( + archiveAndMute, + unarchiveOnNewMessage, + hideReadTime, + false, + 0); } }).send(); _archiveAndMute = archiveAndMute; _unarchiveOnNewMessage = unarchiveOnNewMessage; _hideReadTime = hideReadTime; _newRequirePremium = newRequirePremium; + _newChargeStars = newChargeStars; } -void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &data) { - data.match([&](const MTPDglobalPrivacySettings &data) { - _archiveAndMute = data.is_archive_and_mute_new_noncontact_peers(); - _unarchiveOnNewMessage = data.is_keep_archived_unmuted() - ? UnarchiveOnNewMessage::None - : data.is_keep_archived_folders() - ? UnarchiveOnNewMessage::NotInFoldersUnmuted - : UnarchiveOnNewMessage::AnyUnmuted; - _hideReadTime = data.is_hide_read_marks(); - _newRequirePremium = data.is_new_noncontact_peers_require_premium(); - }); +void GlobalPrivacy::apply(const MTPGlobalPrivacySettings &settings) { + const auto &data = settings.data(); + _archiveAndMute = data.is_archive_and_mute_new_noncontact_peers(); + _unarchiveOnNewMessage = data.is_keep_archived_unmuted() + ? UnarchiveOnNewMessage::None + : data.is_keep_archived_folders() + ? UnarchiveOnNewMessage::NotInFoldersUnmuted + : UnarchiveOnNewMessage::AnyUnmuted; + _hideReadTime = data.is_hide_read_marks(); + _newRequirePremium = data.is_new_noncontact_peers_require_premium(); + _newChargeStars = data.vnoncontact_peers_paid_stars().value_or_empty(); } } // namespace Api diff --git a/Telegram/SourceFiles/api/api_global_privacy.h b/Telegram/SourceFiles/api/api_global_privacy.h index 6c5848961..6b0fc064b 100644 --- a/Telegram/SourceFiles/api/api_global_privacy.h +++ b/Telegram/SourceFiles/api/api_global_privacy.h @@ -49,23 +49,28 @@ public: [[nodiscard]] bool hideReadTimeCurrent() const; [[nodiscard]] rpl::producer hideReadTime() const; - void updateNewRequirePremium(bool value); [[nodiscard]] bool newRequirePremiumCurrent() const; [[nodiscard]] rpl::producer newRequirePremium() const; + [[nodiscard]] int newChargeStarsCurrent() const; + [[nodiscard]] rpl::producer newChargeStars() const; + + void updateMessagesPrivacy(bool requirePremium, int chargeStars); + void loadPaidReactionShownPeer(); void updatePaidReactionShownPeer(PeerId shownPeer); [[nodiscard]] PeerId paidReactionShownPeerCurrent() const; [[nodiscard]] rpl::producer paidReactionShownPeer() const; private: - void apply(const MTPGlobalPrivacySettings &data); + void apply(const MTPGlobalPrivacySettings &settings); void update( bool archiveAndMute, UnarchiveOnNewMessage unarchiveOnNewMessage, bool hideReadTime, - bool newRequirePremium); + bool newRequirePremium, + int newChargeStars); const not_null _session; MTP::Sender _api; @@ -76,6 +81,7 @@ private: rpl::variable _showArchiveAndMute = false; rpl::variable _hideReadTime = false; rpl::variable _newRequirePremium = false; + rpl::variable _newChargeStars = 0; rpl::variable _paidReactionShownPeer = false; std::vector> _callbacks; bool _paidReactionShownPeerLoaded = false; diff --git a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp index 94c4af054..818ed5c35 100644 --- a/Telegram/SourceFiles/boxes/edit_privacy_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_privacy_box.cpp @@ -12,7 +12,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/premium_graphics.h" #include "ui/layers/generic_box.h" #include "ui/widgets/checkbox.h" +#include "ui/widgets/continuous_sliders.h" #include "ui/widgets/shadow.h" +#include "ui/text/format_values.h" #include "ui/text/text_utilities.h" #include "ui/toast/toast.h" #include "ui/wrap/slide_wrap.h" @@ -42,6 +44,10 @@ namespace { constexpr auto kPremiumsRowId = PeerId(FakeChatId(BareId(1))).value; constexpr auto kMiniAppsRowId = PeerId(FakeChatId(BareId(2))).value; +constexpr auto kGetPercent = 85; +constexpr auto kStarsMin = 10; +constexpr auto kStarsMax = 9000; +constexpr auto kDefaultChargeStars = 200; using Exceptions = Api::UserPrivacy::Exceptions; @@ -452,6 +458,109 @@ auto PrivacyExceptionsBoxController::createRow(not_null history) return result; } +[[nodiscard]] object_ptr MakeChargeStarsSlider( + QWidget *parent, + not_null sliderStyle, + not_null labelStyle, + int valuesCount, + Fn valueByIndex, + int value, + Fn valueProgress, + Fn valueFinished) { + auto result = object_ptr(parent); + const auto raw = result.data(); + + const auto labels = raw->add(object_ptr(raw)); + const auto min = Ui::CreateChild( + raw, + QString::number(kStarsMin), + *labelStyle); + const auto max = Ui::CreateChild( + raw, + QString::number(kStarsMax), + *labelStyle); + const auto current = Ui::CreateChild( + raw, + QString::number(value), + *labelStyle); + min->setTextColorOverride(st::windowSubTextFg->c); + max->setTextColorOverride(st::windowSubTextFg->c); + const auto slider = raw->add(object_ptr( + raw, + *sliderStyle)); + labels->resize( + labels->width(), + current->height() + st::defaultVerticalListSkip); + struct State { + int indexMin = 0; + int index = 0; + }; + const auto state = raw->lifetime().make_state(); + const auto updateByIndex = [=] { + const auto outer = labels->width(); + const auto minWidth = min->width(); + const auto maxWidth = max->width(); + const auto currentWidth = current->width(); + if (minWidth + maxWidth + currentWidth > outer) { + return; + } + + min->moveToLeft(0, 0, outer); + max->moveToRight(0, 0, outer); + current->moveToLeft((outer - current->width()) / 2, 0, outer); + }; + const auto updateByValue = [=](int value) { + current->setText( + tr::lng_action_gift_for_stars(tr::now, lt_count, value)); + + state->index = 0; + auto maxIndex = valuesCount - 1; + while (state->index < maxIndex) { + const auto mid = (state->index + maxIndex) / 2; + const auto midValue = valueByIndex(mid); + if (midValue == value) { + state->index = mid; + break; + } else if (midValue < value) { + state->index = mid + 1; + } else { + maxIndex = mid - 1; + } + } + updateByIndex(); + }; + const auto progress = [=](int value) { + updateByValue(value); + valueProgress(value); + }; + const auto finished = [=](int value) { + updateByValue(value); + valueFinished(value); + }; + style::PaletteChanged() | rpl::start_with_next([=] { + min->setTextColorOverride(st::windowSubTextFg->c); + max->setTextColorOverride(st::windowSubTextFg->c); + }, raw->lifetime()); + updateByValue(value); + state->indexMin = 0; + + slider->setPseudoDiscrete( + valuesCount, + valueByIndex, + value, + progress, + finished, + state->indexMin); + slider->resize(slider->width(), sliderStyle->seekSize.height()); + + raw->widthValue() | rpl::start_with_next([=](int width) { + labels->resizeToWidth(width); + updateByIndex(); + }, slider->lifetime()); + + return result; +} + } // namespace bool EditPrivacyController::hasOption(Option option) const { @@ -812,6 +921,7 @@ void EditMessagesPrivacyBox( constexpr auto kOptionAll = 0; constexpr auto kOptionPremium = 1; + constexpr auto kOptionCharge = 2; const auto allowed = [=] { return controller->session().premium() @@ -824,7 +934,11 @@ void EditMessagesPrivacyBox( Ui::AddSkip(inner, st::messagePrivacyTopSkip); Ui::AddSubsectionTitle(inner, tr::lng_messages_privacy_subtitle()); const auto group = std::make_shared( - privacy->newRequirePremiumCurrent() ? kOptionPremium : kOptionAll); + (privacy->newRequirePremiumCurrent() + ? kOptionPremium + : privacy->newChargeStarsCurrent() + ? kOptionCharge + : kOptionAll)); inner->add( object_ptr( inner, @@ -846,6 +960,107 @@ void EditMessagesPrivacyBox( 0, st::messagePrivacyBottomSkip)); + Ui::AddDividerText(inner, tr::lng_messages_privacy_about()); + + const auto charged = inner->add( + object_ptr( + inner, + group, + kOptionCharge, + tr::lng_messages_privacy_charge(tr::now), + st::messagePrivacyCheck), + st::settingsSendTypePadding + style::margins( + 0, + st::messagePrivacyBottomSkip, + 0, + st::messagePrivacyBottomSkip)); + + Ui::AddDividerText(inner, tr::lng_messages_privacy_charge_about()); + + const auto chargeWrap = inner->add( + object_ptr>( + inner, + object_ptr(inner))); + const auto chargeInner = chargeWrap->entity(); + + Ui::AddSkip(chargeInner); + Ui::AddSubsectionTitle(chargeInner, tr::lng_messages_privacy_price()); + + struct State { + rpl::variable stars; + }; + const auto state = std::make_shared(); + const auto savedValue = privacy->newChargeStarsCurrent(); + const auto chargeStars = savedValue ? savedValue : kDefaultChargeStars; + state->stars = chargeStars; + + auto values = std::vector(); + if (chargeStars < kStarsMin) { + values.push_back(chargeStars); + } + for (auto i = kStarsMin; i < 100; ++i) { + values.push_back(i); + } + for (auto i = 100; i < 1000; i += 10) { + if (i < chargeStars + 10 && chargeStars < i) { + values.push_back(chargeStars); + } + values.push_back(i); + } + for (auto i = 1000; i < kStarsMax + 1; i += 100) { + if (i < chargeStars + 100 && chargeStars < i) { + values.push_back(chargeStars); + } + values.push_back(i); + } + const auto valuesCount = int(values.size()); + const auto setStars = [=](int value) { + state->stars = value; + }; + chargeInner->add( + MakeChargeStarsSlider( + chargeInner, + &st::settingsScale, + &st::settingsScaleLabel, + valuesCount, + [=](int index) { return values[index]; }, + chargeStars, + setStars, + setStars), + st::boxRowPadding); + Ui::AddSkip(chargeInner); + + auto dollars = state->stars.value() | rpl::map([=](int stars) { + const auto ratio = controller->session().appConfig().get( + u"stars_usd_withdraw_rate_x1000"_q, + 1200); + const auto dollars = int(base::SafeRound(stars * (ratio / 1000.))); + return '~' + Ui::FillAmountAndCurrency(dollars, u"USD"_q); + }); + Ui::AddDividerText( + chargeInner, + tr::lng_messages_privacy_price_about( + lt_percent, + rpl::single(QString::number(kGetPercent) + '%'), + lt_amount, + std::move(dollars))); + + Ui::AddSkip(chargeInner); + Ui::AddSubsectionTitle( + chargeInner, + tr::lng_messages_privacy_exceptions()); + const auto exceptions = Settings::AddButtonWithLabel( + chargeInner, + tr::lng_messages_privacy_remove_fee(), + rpl::single(u""_q), + st::settingsButtonNoIcon); + Ui::AddSkip(chargeInner); + Ui::AddDividerText(chargeInner, tr::lng_messages_privacy_remove_about()); + + using namespace rpl::mappers; + chargeWrap->toggleOn(group->value() | rpl::map(_1 == kOptionCharge)); + chargeWrap->finishAnimating(); + using WeakToast = base::weak_ptr; const auto toast = std::make_shared(); const auto showToast = [=] { @@ -875,19 +1090,18 @@ void EditMessagesPrivacyBox( }), }); }; + if (!allowed()) { CreateRadiobuttonLock(restricted, st::messagePrivacyCheck); + CreateRadiobuttonLock(charged, st::messagePrivacyCheck); group->setChangedCallback([=](int value) { - if (value == kOptionPremium) { + if (value == kOptionPremium || value == kOptionCharge) { group->setValue(kOptionAll); showToast(); } }); - } - Ui::AddDividerText(inner, tr::lng_messages_privacy_about()); - if (!allowed()) { Ui::AddSkip(inner); Settings::AddButtonWithIcon( inner, @@ -907,8 +1121,12 @@ void EditMessagesPrivacyBox( } else { box->addButton(tr::lng_settings_save(), [=] { if (allowed()) { - privacy->updateNewRequirePremium( - group->current() == kOptionPremium); + const auto value = group->current(); + const auto premiumRequired = (value == kOptionPremium); + const auto chargeStars = (value == kOptionCharge) + ? state->stars.current() + : 0; + privacy->updateMessagesPrivacy(premiumRequired, chargeStars); box->closeBox(); } else { showToast(); diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 7b53de283..0c36d9945 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -610,7 +610,6 @@ void UserData::setCallsStatus(CallsStatus callsStatus) { } } - Data::Birthday UserData::birthday() const { return _birthday; } diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp index 9656bd08a..898125cf3 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_widget.cpp @@ -630,7 +630,7 @@ void Widget::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) { }); }, filter.skipUnique ? nullptr : &st::mediaPlayerMenuCheck); - if (_inner->peer()->canManageGifts() && _inner->peer()->isChannel()) { + if (_inner->peer()->canManageGifts()) { addAction({ .isSeparator = true }); addAction(tr::lng_peer_gifts_filter_saved(tr::now), [=] { diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index 568d449f4..3de238c6b 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -535,6 +535,7 @@ inputPrivacyKeyVoiceMessages#aee69d68 = InputPrivacyKey; inputPrivacyKeyAbout#3823cc40 = InputPrivacyKey; inputPrivacyKeyBirthday#d65a11cc = InputPrivacyKey; inputPrivacyKeyStarGiftsAutoSave#e1732341 = InputPrivacyKey; +inputPrivacyKeyNoPaidMessages#bdc597b4 = InputPrivacyKey; privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey; privacyKeyChatInvite#500e6dfa = PrivacyKey; diff --git a/Telegram/SourceFiles/settings/settings_privacy_security.cpp b/Telegram/SourceFiles/settings/settings_privacy_security.cpp index 09ae65ad8..c605ed28d 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_security.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_security.cpp @@ -356,10 +356,16 @@ void AddMessagesPrivacyButton( not_null container) { const auto session = &controller->session(); const auto privacy = &session->api().globalPrivacy(); - auto label = rpl::conditional( + auto label = rpl::combine( privacy->newRequirePremium(), - tr::lng_edit_privacy_contacts_and_premium(), - tr::lng_edit_privacy_everyone()); + privacy->newChargeStars() + ) | rpl::map([=](bool requirePremium, int chargeStars) { + return chargeStars + ? tr::lng_edit_privacy_paid() + : requirePremium + ? tr::lng_edit_privacy_contacts_and_premium() + : tr::lng_edit_privacy_everyone(); + }) | rpl::flatten_latest(); const auto &st = st::settingsButtonNoIcon; const auto button = AddButtonWithLabel( container,