diff --git a/Telegram/Resources/icons/limits/chats.png b/Telegram/Resources/icons/limits/chats.png new file mode 100644 index 0000000000..2c3815a8ed Binary files /dev/null and b/Telegram/Resources/icons/limits/chats.png differ diff --git a/Telegram/Resources/icons/limits/chats@2x.png b/Telegram/Resources/icons/limits/chats@2x.png new file mode 100644 index 0000000000..414acb1938 Binary files /dev/null and b/Telegram/Resources/icons/limits/chats@2x.png differ diff --git a/Telegram/Resources/icons/limits/chats@3x.png b/Telegram/Resources/icons/limits/chats@3x.png new file mode 100644 index 0000000000..c814dd1994 Binary files /dev/null and b/Telegram/Resources/icons/limits/chats@3x.png differ diff --git a/Telegram/Resources/icons/limits/files.png b/Telegram/Resources/icons/limits/files.png new file mode 100644 index 0000000000..48ed2f5d93 Binary files /dev/null and b/Telegram/Resources/icons/limits/files.png differ diff --git a/Telegram/Resources/icons/limits/files@2x.png b/Telegram/Resources/icons/limits/files@2x.png new file mode 100644 index 0000000000..368d56ca98 Binary files /dev/null and b/Telegram/Resources/icons/limits/files@2x.png differ diff --git a/Telegram/Resources/icons/limits/files@3x.png b/Telegram/Resources/icons/limits/files@3x.png new file mode 100644 index 0000000000..8b204778c9 Binary files /dev/null and b/Telegram/Resources/icons/limits/files@3x.png differ diff --git a/Telegram/Resources/icons/limits/folders.png b/Telegram/Resources/icons/limits/folders.png new file mode 100644 index 0000000000..6c94dab318 Binary files /dev/null and b/Telegram/Resources/icons/limits/folders.png differ diff --git a/Telegram/Resources/icons/limits/folders@2x.png b/Telegram/Resources/icons/limits/folders@2x.png new file mode 100644 index 0000000000..6372f5a9a7 Binary files /dev/null and b/Telegram/Resources/icons/limits/folders@2x.png differ diff --git a/Telegram/Resources/icons/limits/folders@3x.png b/Telegram/Resources/icons/limits/folders@3x.png new file mode 100644 index 0000000000..0c515302e0 Binary files /dev/null and b/Telegram/Resources/icons/limits/folders@3x.png differ diff --git a/Telegram/Resources/icons/limits/groups.png b/Telegram/Resources/icons/limits/groups.png new file mode 100644 index 0000000000..06948fb75b Binary files /dev/null and b/Telegram/Resources/icons/limits/groups.png differ diff --git a/Telegram/Resources/icons/limits/groups@2x.png b/Telegram/Resources/icons/limits/groups@2x.png new file mode 100644 index 0000000000..b4176982e7 Binary files /dev/null and b/Telegram/Resources/icons/limits/groups@2x.png differ diff --git a/Telegram/Resources/icons/limits/groups@3x.png b/Telegram/Resources/icons/limits/groups@3x.png new file mode 100644 index 0000000000..ba35f53981 Binary files /dev/null and b/Telegram/Resources/icons/limits/groups@3x.png differ diff --git a/Telegram/Resources/icons/limits/links.png b/Telegram/Resources/icons/limits/links.png new file mode 100644 index 0000000000..96d5761299 Binary files /dev/null and b/Telegram/Resources/icons/limits/links.png differ diff --git a/Telegram/Resources/icons/limits/links@2x.png b/Telegram/Resources/icons/limits/links@2x.png new file mode 100644 index 0000000000..90ac07fddc Binary files /dev/null and b/Telegram/Resources/icons/limits/links@2x.png differ diff --git a/Telegram/Resources/icons/limits/links@3x.png b/Telegram/Resources/icons/limits/links@3x.png new file mode 100644 index 0000000000..926a5ad409 Binary files /dev/null and b/Telegram/Resources/icons/limits/links@3x.png differ diff --git a/Telegram/Resources/icons/limits/pins.png b/Telegram/Resources/icons/limits/pins.png new file mode 100644 index 0000000000..572cffebfb Binary files /dev/null and b/Telegram/Resources/icons/limits/pins.png differ diff --git a/Telegram/Resources/icons/limits/pins@2x.png b/Telegram/Resources/icons/limits/pins@2x.png new file mode 100644 index 0000000000..a1f4bbd402 Binary files /dev/null and b/Telegram/Resources/icons/limits/pins@2x.png differ diff --git a/Telegram/Resources/icons/limits/pins@3x.png b/Telegram/Resources/icons/limits/pins@3x.png new file mode 100644 index 0000000000..a7bfe571a8 Binary files /dev/null and b/Telegram/Resources/icons/limits/pins@3x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index e7df50240e..fbc0f43bdf 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -177,6 +177,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_channels_leave_done" = "You've left the selected communities."; "lng_links_limit_title" = "Too Many Public Links"; +"lng_links_limit_subtitle" = "Your public communitites"; "lng_links_limit1#one" = "You have reserved **{count}** public link."; "lng_links_limit1#other" = "You have reserved **{count}** public links."; "lng_links_limit2#one" = "Try revoking the link from an older group or channel, or upgrade to **Telegram Premium** to double the limit to **{count}** public link."; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index 0966e90bac..4322190c7a 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -1081,7 +1081,16 @@ ringtonesBoxSkip: 7px; premiumBubblePadding: margins(14px, 0px, 14px, 0px); premiumBubbleHeight: 40px; premiumBubbleSkip: 5px; +premiumBubbleTextSkip: 3px; premiumBubbleSlideDuration: 500; premiumBubbleTailSize: size(21px, 7px); premiumBubbleFont: font(19px); premiumLineTextSkip: 11px; +premiumInfographicPadding: margins(0px, 10px, 0px, 15px); + +premiumIconChats: icon {{ "limits/chats", settingsIconFg }}; +premiumIconFiles: icon {{ "limits/files", settingsIconFg }}; +premiumIconFolders: icon {{ "limits/folders", settingsIconFg }}; +premiumIconGroups: icon {{ "limits/groups", settingsIconFg }}; +premiumIconLinks: icon {{ "limits/links", settingsIconFg }}; +premiumIconPins: icon {{ "limits/pins", settingsIconFg }}; diff --git a/Telegram/SourceFiles/boxes/premium_limits_box.cpp b/Telegram/SourceFiles/boxes/premium_limits_box.cpp index 02d20b6398..baaaa9b398 100644 --- a/Telegram/SourceFiles/boxes/premium_limits_box.cpp +++ b/Telegram/SourceFiles/boxes/premium_limits_box.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/boxes/confirm_box.h" #include "ui/controls/peer_list_dummy.h" +#include "ui/effects/premium_graphics.h" #include "ui/widgets/buttons.h" #include "ui/wrap/padding_wrap.h" #include "ui/text/text_utilities.h" @@ -23,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_session.h" #include "lang/lang_keys.h" +#include "settings/settings_common.h" #include "base/unixtime.h" #include "apiwrap.h" #include "styles/style_boxes.h" @@ -31,6 +33,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace { +struct InfographicDescriptor { + float64 defaultLimit = 0; + float64 current = 0; + float64 premiumLimit = 0; + const style::icon *icon; +}; + +[[nodiscard]] rpl::producer<> BoxShowFinishes(not_null box) { + const auto singleShot = box->lifetime().make_state(); + const auto showFinishes = singleShot->make_state>(); + + box->setShowFinishedCallback([=] { + showFinishes->fire({}); + singleShot->destroy(); + box->setShowFinishedCallback(nullptr); + }); + + return showFinishes->events(); +} + class InactiveController final : public PeerListController { public: explicit InactiveController(not_null session); @@ -371,6 +393,7 @@ void SimpleLimitBox( not_null session, rpl::producer title, rpl::producer text, + const InfographicDescriptor &descriptor, bool premium, bool fixed = false) { box->setWidth(st::boxWideWidth); @@ -378,36 +401,30 @@ void SimpleLimitBox( const auto top = fixed ? box->setPinnedToTopContent(object_ptr(box)) : box->verticalLayout(); + + Settings::AddSkip(top, st::premiumInfographicPadding.top()); + Ui::Premium::AddBubbleRow( + top, + BoxShowFinishes(box), + descriptor.defaultLimit, + descriptor.current, + descriptor.premiumLimit, + std::nullopt, + descriptor.icon); + Settings::AddSkip(top, st::premiumLineTextSkip); + Ui::Premium::AddLimitRow(top, descriptor.premiumLimit); + Settings::AddSkip(top, st::premiumInfographicPadding.bottom()); + + box->setTitle(std::move(title)); + + auto padding = st::boxPadding; + padding.setTop(padding.bottom()); top->add( - object_ptr>( + object_ptr( box, - object_ptr( - box, - std::move(title), - st::changePhoneTitle)), - st::changePhoneTitlePadding); - - top->add( - object_ptr>( - box, - object_ptr( - box, - std::move(text), - st::changePhoneDescription)), - st::changePhoneDescriptionPadding); - - box->setNoContentMargin(true); - - const auto close = Ui::CreateChild( - box.get(), - st::infoLayerTopBarClose); - close->addClickHandler([=] { box->closeBox(); }); - box->widthValue() | rpl::start_with_next([=](int width) { - close->moveToRight(0, 0, width); - }, close->lifetime()); - box->setFocusCallback([=] { - close->raise(); - }); + std::move(text), + st::aboutRevokePublicLabel), + padding); if (premium) { box->addButton(tr::lng_box_ok(), [=] { @@ -420,6 +437,15 @@ void SimpleLimitBox( }); }); } + + box->addButton(tr::lng_cancel(), [=] { + box->closeBox(); + }); + + if (fixed) { + Settings::AddSkip(top); + Settings::AddDivider(top); + } } void SimplePinsLimitBox( @@ -431,19 +457,19 @@ void SimplePinsLimitBox( int limitPremium) { const auto premium = session->user()->isPremium(); + const auto defaultLimit = Limit(session, keyDefault, limitDefault); + const auto premiumLimit = Limit(session, keyPremium, limitPremium); + auto text = rpl::combine( tr::lng_filter_pin_limit1( lt_count, - rpl::single(Limit( - session, - (premium ? keyPremium : keyDefault), - premium ? limitPremium : limitDefault)), + rpl::single(premium ? premiumLimit : defaultLimit), Ui::Text::RichLangValue), (premium ? rpl::single(TextWithEntities()) : tr::lng_filter_pin_limit2( lt_count, - rpl::single(Limit(session, keyPremium, limitPremium)), + rpl::single(premiumLimit), Ui::Text::RichLangValue)) ) | rpl::map([](TextWithEntities &&a, TextWithEntities &&b) { return b.text.isEmpty() @@ -455,6 +481,7 @@ void SimplePinsLimitBox( session, tr::lng_filter_pin_limit_title(), std::move(text), + { defaultLimit, defaultLimit, premiumLimit, &st::premiumIconPins }, premium); } @@ -465,21 +492,19 @@ void ChannelsLimitBox( not_null session) { const auto premium = session->user()->isPremium(); + const auto defaultLimit = Limit(session, "channels_limit_default", 500); + const auto premiumLimit = Limit(session, "channels_limit_premium", 1000); + auto text = rpl::combine( tr::lng_channels_limit1( lt_count, - rpl::single(Limit( - session, - (premium - ? "channels_limit_premium" - : "channels_limit_default"), - premium ? 1000 : 500)), + rpl::single(premium ? premiumLimit : defaultLimit), Ui::Text::RichLangValue), (premium ? tr::lng_channels_limit2_final(Ui::Text::RichLangValue) : tr::lng_channels_limit2( lt_count, - rpl::single(Limit(session, "channels_limit_premium", 1000)), + rpl::single(premiumLimit), Ui::Text::RichLangValue)) ) | rpl::map([](TextWithEntities &&a, TextWithEntities &&b) { return a.append(QChar(' ')).append(std::move(b)); @@ -490,6 +515,7 @@ void ChannelsLimitBox( session, tr::lng_channels_limit_title(), std::move(text), + { defaultLimit, defaultLimit, premiumLimit, &st::premiumIconGroups }, premium, true); @@ -553,24 +579,25 @@ void PublicLinksLimitBox( const auto session = &navigation->session(); const auto premium = session->user()->isPremium(); + const auto defaultLimit = Limit( + session, + "channels_public_limit_default", + 10); + const auto premiumLimit = Limit( + session, + "channels_public_limit_premium", + 20); + auto text = rpl::combine( tr::lng_links_limit1( lt_count, - rpl::single(Limit( - session, - (premium - ? "channels_public_limit_premium" - : "channels_public_limit_default"), - premium ? 20 : 10)), + rpl::single(premium ? premiumLimit : defaultLimit), Ui::Text::RichLangValue), (premium ? tr::lng_links_limit2_final(Ui::Text::RichLangValue) : tr::lng_links_limit2( lt_count, - rpl::single(Limit( - session, - "channels_public_limit_premium", - 20)), + rpl::single(premiumLimit), Ui::Text::RichLangValue)) ) | rpl::map([](TextWithEntities &&a, TextWithEntities &&b) { return a.append(QChar(' ')).append(std::move(b)); @@ -581,9 +608,14 @@ void PublicLinksLimitBox( session, tr::lng_links_limit_title(), std::move(text), + { defaultLimit, defaultLimit, premiumLimit, &st::premiumIconLinks }, premium, true); + Settings::AddSubsectionTitle( + box->verticalLayout(), + tr::lng_links_limit_subtitle()); + const auto delegate = box->lifetime().make_state(); const auto controller = box->lifetime().make_state( navigation, @@ -612,25 +644,25 @@ void FilterChatsLimitBox( not_null session) { const auto premium = session->user()->isPremium(); + const auto defaultLimit = Limit( + session, + "dialog_filters_chats_limit_default", + 100); + const auto premiumLimit = Limit( + session, + "dialog_filters_chats_limit_premium", + 200); + auto text = rpl::combine( tr::lng_filter_chats_limit1( lt_count, - rpl::single( - Limit( - session, - (premium - ? "dialog_filters_chats_limit_premium" - : "dialog_filters_chats_limit_default"), - premium ? 200 : 100)), + rpl::single(premium ? premiumLimit : defaultLimit), Ui::Text::RichLangValue), (premium ? rpl::single(TextWithEntities()) : tr::lng_filter_chats_limit2( lt_count, - rpl::single(Limit( - session, - "dialog_filters_chats_limit_premium", - 200)), + rpl::single(premiumLimit), Ui::Text::RichLangValue)) ) | rpl::map([](TextWithEntities &&a, TextWithEntities &&b) { return b.text.isEmpty() @@ -643,6 +675,7 @@ void FilterChatsLimitBox( session, tr::lng_filter_chats_limit_title(), std::move(text), + { defaultLimit, defaultLimit, premiumLimit, &st::premiumIconChats }, premium); } @@ -651,22 +684,25 @@ void FiltersLimitBox( not_null session) { const auto premium = session->user()->isPremium(); + const auto defaultLimit = Limit( + session, + "dialog_filters_limit_default", + 10); + const auto premiumLimit = Limit( + session, + "dialog_filters_limit_premium", + 20); + auto text = rpl::combine( tr::lng_filters_limit1( lt_count, - rpl::single(Limit( - session, - (premium - ? "dialog_filters_limit_premium" - : "dialog_filters_limit_default"), - premium ? 20 : 10)), + rpl::single(premium ? premiumLimit : defaultLimit), Ui::Text::RichLangValue), (premium ? rpl::single(TextWithEntities()) : tr::lng_filters_limit2( lt_count, - rpl::single( - Limit(session, "dialog_filters_limit_premium", 20)), + rpl::single(premiumLimit), Ui::Text::RichLangValue)) ) | rpl::map([](TextWithEntities &&a, TextWithEntities &&b) { return b.text.isEmpty() @@ -678,6 +714,7 @@ void FiltersLimitBox( session, tr::lng_filters_limit_title(), std::move(text), + { defaultLimit, defaultLimit, premiumLimit, &st::premiumIconFolders }, premium); } @@ -722,20 +759,23 @@ void CaptionLimitBox( not_null session) { const auto premium = session->user()->isPremium(); + const auto defaultLimit = Limit( + session, + "caption_length_limit_default", + 1024); + const auto premiumLimit = Limit( + session, + "caption_length_limit_premium", + 2048); + auto text = rpl::combine( tr::lng_caption_limit1( lt_count, - rpl::single(Limit( - session, - (premium - ? "caption_length_limit_premium" - : "caption_length_limit_default"), - premium ? 2048 : 1024)), + rpl::single(premium ? premiumLimit : defaultLimit), Ui::Text::RichLangValue), tr::lng_caption_limit2( lt_count, - rpl::single( - Limit(session, "caption_length_limit_premium", 2048)), + rpl::single(premiumLimit), Ui::Text::RichLangValue) ) | rpl::map([](TextWithEntities &&a, TextWithEntities &&b) { return a.append(QChar(' ')).append(std::move(b)); @@ -746,6 +786,7 @@ void CaptionLimitBox( session, tr::lng_caption_limit_title(), std::move(text), + { defaultLimit, defaultLimit, premiumLimit, &st::premiumIconChats }, premium); }