diff --git a/Telegram/Resources/icons/settings/premium/stories_caption.png b/Telegram/Resources/icons/settings/premium/stories_caption.png new file mode 100644 index 0000000000..d73bc90686 Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_caption.png differ diff --git a/Telegram/Resources/icons/settings/premium/stories_caption@2x.png b/Telegram/Resources/icons/settings/premium/stories_caption@2x.png new file mode 100644 index 0000000000..e67594df0d Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_caption@2x.png differ diff --git a/Telegram/Resources/icons/settings/premium/stories_caption@3x.png b/Telegram/Resources/icons/settings/premium/stories_caption@3x.png new file mode 100644 index 0000000000..373884acea Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_caption@3x.png differ diff --git a/Telegram/Resources/icons/settings/premium/stories_links.png b/Telegram/Resources/icons/settings/premium/stories_links.png new file mode 100644 index 0000000000..da8497860b Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_links.png differ diff --git a/Telegram/Resources/icons/settings/premium/stories_links@2x.png b/Telegram/Resources/icons/settings/premium/stories_links@2x.png new file mode 100644 index 0000000000..26dfa285ef Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_links@2x.png differ diff --git a/Telegram/Resources/icons/settings/premium/stories_links@3x.png b/Telegram/Resources/icons/settings/premium/stories_links@3x.png new file mode 100644 index 0000000000..fef135b0db Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_links@3x.png differ diff --git a/Telegram/Resources/icons/settings/premium/stories_order.png b/Telegram/Resources/icons/settings/premium/stories_order.png new file mode 100644 index 0000000000..3051561dfe Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_order.png differ diff --git a/Telegram/Resources/icons/settings/premium/stories_order@2x.png b/Telegram/Resources/icons/settings/premium/stories_order@2x.png new file mode 100644 index 0000000000..4b4f64ceb6 Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_order@2x.png differ diff --git a/Telegram/Resources/icons/settings/premium/stories_order@3x.png b/Telegram/Resources/icons/settings/premium/stories_order@3x.png new file mode 100644 index 0000000000..d550ddcef7 Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/stories_order@3x.png differ diff --git a/Telegram/Resources/icons/settings/premium/timer.png b/Telegram/Resources/icons/settings/premium/timer.png new file mode 100644 index 0000000000..5fe0383b45 Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/timer.png differ diff --git a/Telegram/Resources/icons/settings/premium/timer@2x.png b/Telegram/Resources/icons/settings/premium/timer@2x.png new file mode 100644 index 0000000000..28d3d14807 Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/timer@2x.png differ diff --git a/Telegram/Resources/icons/settings/premium/timer@3x.png b/Telegram/Resources/icons/settings/premium/timer@3x.png new file mode 100644 index 0000000000..173ad913dc Binary files /dev/null and b/Telegram/Resources/icons/settings/premium/timer@3x.png differ diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 70306ad8ff..a5cf29ecd0 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1828,6 +1828,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_premium_summary_subtitle_gift#other" = "{user} has gifted you a {count}-months subscription for Telegram Premium."; "lng_premium_summary_subtitle_gift_me#one" = "You gifted {user} a {count}-month subscription for Telegram Premium."; "lng_premium_summary_subtitle_gift_me#other" = "You gifted {user} a {count}-months subscription for Telegram Premium."; +"lng_premium_summary_subtitle_stories" = "Upgraded Stories"; +"lng_premium_summary_about_stories" = "Priority order, stealth mode, permanent views history and more."; "lng_premium_summary_subtitle_double_limits" = "Doubled Limits"; "lng_premium_summary_about_double_limits" = "Up to 1000 channels, 20 folders, 10 pins, 20 public links, 4 accounts and more."; "lng_premium_summary_subtitle_more_upload" = "4Gb Upload Size"; @@ -1861,6 +1863,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_premium_success" = "You've successfully subscribed to Telegram Premium!"; "lng_premium_unavailable" = "This feature requires subscription to **Telegram Premium**.\n\nUnfortunately, **Telegram Premium** is not available in your region."; +// Upgraded Stories. +"lng_premium_stories_subtitle_order" = "Priority Order"; +"lng_premium_stories_about_order" = "Get more views as your stories are always displayed first."; + +"lng_premium_stories_subtitle_stealth" = "Stealth Mode"; +"lng_premium_stories_about_stealth" = "Hide the fact that you viewed other people's stories."; + +"lng_premium_stories_subtitle_views" = "Permanent Views History"; +"lng_premium_stories_about_views" = "Check who opens your stories – even after they expire."; + +"lng_premium_stories_subtitle_expiration" = "Expiration Durations*"; +"lng_premium_stories_about_expiration" = "Set custom expiration durations like 6 or 48 hours for your stories."; + +"lng_premium_stories_subtitle_download" = "Download Stories"; +"lng_premium_stories_about_download" = "Save other people's unprotected stories to your disk."; + +"lng_premium_stories_subtitle_caption" = "Longer Captions*"; +"lng_premium_stories_about_caption" = "Add ten times longer captions to your stories – up to 2048 symbols."; + +"lng_premium_stories_subtitle_links" = "Links and Formatting*"; +"lng_premium_stories_about_links" = "Add links and formatting in captions of your stories."; + +"lng_premium_stories_about_mobile" = "* Available when posting stories from Telegram apps for iOS and Android."; + // Doubled Limits. "lng_premium_double_limits_subtitle_channels" = "Groups and Channels"; "lng_premium_double_limits_about_channels#one" = "Join up to {count} channels and large groups"; diff --git a/Telegram/SourceFiles/boxes/premium_preview_box.cpp b/Telegram/SourceFiles/boxes/premium_preview_box.cpp index 20581a7260..6505e31e60 100644 --- a/Telegram/SourceFiles/boxes/premium_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/premium_preview_box.cpp @@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/wrap/padding_wrap.h" #include "ui/boxes/confirm_box.h" #include "ui/painter.h" +#include "settings/settings_common.h" #include "settings/settings_premium.h" #include "lottie/lottie_single_player.h" #include "history/view/media/history_view_sticker.h" @@ -92,6 +93,10 @@ void PreloadSticker(const std::shared_ptr &media) { [[nodiscard]] rpl::producer SectionTitle(PremiumPreview section) { switch (section) { + case PremiumPreview::Stories: + return tr::lng_premium_summary_subtitle_stories(); + case PremiumPreview::DoubleLimits: + return tr::lng_premium_summary_subtitle_double_limits(); case PremiumPreview::MoreUpload: return tr::lng_premium_summary_subtitle_more_upload(); case PremiumPreview::FasterDownload: @@ -122,6 +127,10 @@ void PreloadSticker(const std::shared_ptr &media) { [[nodiscard]] rpl::producer SectionAbout(PremiumPreview section) { switch (section) { + case PremiumPreview::Stories: + return tr::lng_premium_summary_about_stories(); + case PremiumPreview::DoubleLimits: + return tr::lng_premium_summary_about_double_limits(); case PremiumPreview::MoreUpload: return tr::lng_premium_summary_about_more_upload(); case PremiumPreview::FasterDownload: @@ -1117,6 +1126,56 @@ void Show(std::shared_ptr show, QImage back) { } } +void DecorateListPromoBox( + not_null box, + std::shared_ptr show, + const Descriptor &descriptor) { + const auto session = &show->session(); + + box->addTopButton(st::boxTitleClose, [=] { + box->closeBox(); + }); + + Data::AmPremiumValue( + session + ) | rpl::skip(1) | rpl::start_with_next([=] { + box->closeBox(); + }, box->lifetime()); + + if (const auto &hidden = descriptor.hiddenCallback) { + box->boxClosing() | rpl::start_with_next(hidden, box->lifetime()); + } + + if (session->premium()) { + box->addButton(tr::lng_close(), [=] { + box->closeBox(); + }); + } else { + const auto button = Settings::CreateSubscribeButton({ + .parent = box, + .computeRef = [] { return u"double_limits"_q; }, + .show = show, + }); + + box->setShowFinishedCallback([=] { + button->startGlareAnimation(); + }); + + box->setStyle(st::premiumPreviewDoubledLimitsBox); + box->widthValue( + ) | rpl::start_with_next([=](int width) { + const auto &padding = + st::premiumPreviewDoubledLimitsBox.buttonPadding; + button->resizeToWidth(width + - padding.left() + - padding.right()); + button->moveToLeft(padding.left(), padding.top()); + }, button->lifetime()); + box->addButton( + object_ptr::fromRaw(button)); + } +} + void Show( std::shared_ptr show, Descriptor &&descriptor) { @@ -1128,6 +1187,18 @@ void Show( descriptor.shownCallback(raw); } return; + } else if (descriptor.section == PremiumPreview::DoubleLimits) { + show->showBox(Box([=](not_null box) { + DoubledLimitsPreviewBox(box, &show->session()); + DecorateListPromoBox(box, show, descriptor); + })); + return; + } else if (descriptor.section == PremiumPreview::Stories) { + show->showBox(Box([=](not_null box) { + UpgradedStoriesPreviewBox(box, &show->session()); + DecorateListPromoBox(box, show, descriptor); + })); + return; } auto &list = Preloads(); for (auto i = begin(list); i != end(list);) { @@ -1240,11 +1311,13 @@ void PremiumUnavailableBox(not_null box) { void DoubledLimitsPreviewBox( not_null box, not_null session) { + box->setTitle(tr::lng_premium_summary_subtitle_double_limits()); + const auto limits = Data::PremiumLimits(session); auto entries = std::vector(); { const auto premium = limits.channelsPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_channels(), tr::lng_premium_double_limits_about_channels( lt_count, @@ -1256,7 +1329,7 @@ void DoubledLimitsPreviewBox( } { const auto premium = limits.dialogsPinnedPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_pins(), tr::lng_premium_double_limits_about_pins( lt_count, @@ -1268,7 +1341,7 @@ void DoubledLimitsPreviewBox( } { const auto premium = limits.channelsPublicPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_links(), tr::lng_premium_double_limits_about_links( lt_count, @@ -1280,7 +1353,7 @@ void DoubledLimitsPreviewBox( } { const auto premium = limits.gifsPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_gifs(), tr::lng_premium_double_limits_about_gifs( lt_count, @@ -1292,7 +1365,7 @@ void DoubledLimitsPreviewBox( } { const auto premium = limits.stickersFavedPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_stickers(), tr::lng_premium_double_limits_about_stickers( lt_count, @@ -1304,7 +1377,7 @@ void DoubledLimitsPreviewBox( } { const auto premium = limits.aboutLengthPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_bio(), tr::lng_premium_double_limits_about_bio( Ui::Text::RichLangValue), @@ -1314,7 +1387,7 @@ void DoubledLimitsPreviewBox( } { const auto premium = limits.captionLengthPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_captions(), tr::lng_premium_double_limits_about_captions( Ui::Text::RichLangValue), @@ -1324,7 +1397,7 @@ void DoubledLimitsPreviewBox( } { const auto premium = limits.dialogFiltersPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_folders(), tr::lng_premium_double_limits_about_folders( lt_count, @@ -1336,7 +1409,7 @@ void DoubledLimitsPreviewBox( } { const auto premium = limits.dialogFiltersChatsPremium(); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_folder_chats(), tr::lng_premium_double_limits_about_folder_chats( lt_count, @@ -1350,7 +1423,7 @@ void DoubledLimitsPreviewBox( const auto till = (nextMax >= Main::Domain::kPremiumMaxAccounts) ? QString::number(Main::Domain::kPremiumMaxAccounts) : (QString::number(nextMax) + QChar('+')); - entries.push_back(Ui::Premium::ListEntry{ + entries.push_back({ tr::lng_premium_double_limits_subtitle_accounts(), tr::lng_premium_double_limits_about_accounts( lt_count, @@ -1366,6 +1439,60 @@ void DoubledLimitsPreviewBox( std::move(entries)); } +void UpgradedStoriesPreviewBox( + not_null box, + not_null session) { + using namespace Ui::Text; + + box->setTitle(tr::lng_premium_summary_subtitle_stories()); + + auto entries = std::vector(); + entries.push_back({ + .title = tr::lng_premium_stories_subtitle_order(), + .about = tr::lng_premium_stories_about_order(WithEntities), + .icon = &st::settingsStoriesIconOrder, + }); + entries.push_back({ + .title = tr::lng_premium_stories_subtitle_stealth(), + .about = tr::lng_premium_stories_about_stealth(WithEntities), + .icon = &st::settingsStoriesIconStealth, + }); + entries.push_back({ + .title = tr::lng_premium_stories_subtitle_views(), + .about = tr::lng_premium_stories_about_views(WithEntities), + .icon = &st::settingsStoriesIconViews, + }); + entries.push_back({ + .title = tr::lng_premium_stories_subtitle_expiration(), + .about = tr::lng_premium_stories_about_expiration(WithEntities), + .icon = &st::settingsStoriesIconExpiration, + }); + entries.push_back({ + .title = tr::lng_premium_stories_subtitle_download(), + .about = tr::lng_premium_stories_about_download(WithEntities), + .icon = &st::settingsStoriesIconDownload, + }); + entries.push_back({ + .title = tr::lng_premium_stories_subtitle_caption(), + .about = tr::lng_premium_stories_about_caption(WithEntities), + .icon = &st::settingsStoriesIconCaption, + }); + entries.push_back({ + .title = tr::lng_premium_stories_subtitle_links(), + .about = tr::lng_premium_stories_about_links(WithEntities), + .icon = &st::settingsStoriesIconLinks, + }); + + Ui::Premium::ShowListBox( + box, + st::defaultPremiumLimits, + std::move(entries)); + + Settings::AddDividerText( + box->verticalLayout(), + tr::lng_premium_stories_about_mobile()); +} + object_ptr CreateUnlockButton( QWidget *parent, rpl::producer text) { diff --git a/Telegram/SourceFiles/boxes/premium_preview_box.h b/Telegram/SourceFiles/boxes/premium_preview_box.h index 51f9bcfbde..dbe2be446f 100644 --- a/Telegram/SourceFiles/boxes/premium_preview_box.h +++ b/Telegram/SourceFiles/boxes/premium_preview_box.h @@ -41,7 +41,13 @@ void DoubledLimitsPreviewBox( not_null box, not_null session); +void UpgradedStoriesPreviewBox( + not_null box, + not_null session); + enum class PremiumPreview { + Stories, + DoubleLimits, MoreUpload, FasterDownload, VoiceToText, diff --git a/Telegram/SourceFiles/media/stories/media_stories_stealth.cpp b/Telegram/SourceFiles/media/stories/media_stories_stealth.cpp index 8bacca224f..04a78c7f28 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_stealth.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_stealth.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/timer_rpl.h" #include "base/unixtime.h" +#include "boxes/premium_preview_box.h" #include "chat_helpers/compose/compose_show.h" #include "data/data_peer_values.h" #include "data/data_session.h" @@ -295,7 +296,7 @@ struct Feature { label->resizeToWidth(width); label->move(added / 2, top); const auto inner = std::min(label->textMaxWidth(), width); - const auto right = (added / 2) + (width - inner) / 2 + inner; + const auto right = (added / 2) + (outer - inner) / 2 + inner; const auto lockTop = (label->height() - lock->height()) / 2; lock->move(right + lockLeft, top + lockTop); }; @@ -351,9 +352,7 @@ struct Feature { data->requested = false; const auto usage = ChatHelpers::WindowUsage::PremiumPromo; if (const auto window = show->resolveWindow(usage)) { - Settings::ShowPremium( - window, - u"stories__stealth_mode"_q); + ShowPremiumPreviewBox(window, PremiumPreview::Stories); window->window().activate(); } } else if (now.mode.cooldownTill > now.now) { diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 1c010e0f0b..990936b29d 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_peer_photo.h" #include "lang/lang_keys.h" #include "mainwindow.h" +#include "boxes/premium_preview_box.h" #include "core/application.h" #include "core/click_handler_types.h" #include "core/file_utilities.h" @@ -1252,8 +1253,8 @@ void OverlayWidget::showPremiumDownloadPromo() { const auto filter = [=](const auto &...) { const auto usage = ChatHelpers::WindowUsage::PremiumPromo; if (const auto window = uiShow()->resolveWindow(usage)) { - const auto ref = u"stories__save_stories_to_gallery"_q; - Settings::ShowPremium(window, ref); + ShowPremiumPreviewBox(window, PremiumPreview::Stories); + window->window().activate(); } return false; }; diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index 2fd6327a4d..ebb44cf0a4 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -109,6 +109,7 @@ settingsIconTopics: icon {{ "settings/topics", settingsIconFg }}; settingsIconTTL: icon {{ "settings/ttl", settingsIconFg }}; settingsIconPhoto: icon {{ "settings/photo", settingsIconFg }}; +settingsPremiumIconStories: icon {{ "settings/stories", settingsIconFg }}; settingsPremiumIconChannelsOff: icon {{ "settings/premium/channels_off", settingsIconFg }}; settingsPremiumIconDouble: icon {{ "settings/premium/double", settingsIconFg }}; settingsPremiumIconStatus: icon {{ "settings/premium/status", settingsIconFg }}; @@ -120,6 +121,14 @@ settingsPremiumIconVoice: icon {{ "settings/premium/voice", settingsIconFg }}; settingsPremiumIconFiles: icon {{ "settings/premium/files", settingsIconFg }}; settingsPremiumIconTranslations: icon {{ "settings/premium/translations", settingsIconFg }}; +settingsStoriesIconOrder: icon {{ "settings/premium/stories_order", premiumButtonBg1 }}; +settingsStoriesIconStealth: icon {{ "menu/stealth", premiumButtonBg1 }}; +settingsStoriesIconViews: icon {{ "menu/show_in_chat", premiumButtonBg1 }}; +settingsStoriesIconExpiration: icon {{ "settings/premium/timer", premiumButtonBg1 }}; +settingsStoriesIconDownload: icon {{ "menu/download", premiumButtonBg1 }}; +settingsStoriesIconCaption: icon {{ "settings/premium/stories_caption", premiumButtonBg1 }}; +settingsStoriesIconLinks: icon {{ "settings/premium/stories_links", premiumButtonBg1 }}; + settingsTTLChatsOff: icon {{ "settings/ttl/autodelete_off", windowSubTextFg }}; settingsTTLChatsOn: icon {{ "settings/ttl/autodelete_on", windowActiveTextFg }}; @@ -473,6 +482,9 @@ settingsPremiumRowAboutPadding: margins(59px, 0px, 46px, 6px); settingsPremiumPreviewTitlePadding: margins(24px, 13px, 24px, 3px); settingsPremiumPreviewAboutPadding: margins(24px, 0px, 24px, 11px); settingsPremiumPreviewLinePadding: margins(18px, 0px, 18px, 8px); +settingsPremiumPreviewIconTitlePadding: margins(62px, 13px, 24px, 1px); +settingsPremiumPreviewIconAboutPadding: margins(62px, 0px, 24px, 0px); +settingsPremiumPreviewIconPosition: point(20px, 7px); settingsPremiumTitlePadding: margins(0px, 18px, 0px, 11px); settingsPremiumAboutTextStyle: TextStyle(defaultTextStyle) { diff --git a/Telegram/SourceFiles/settings/settings_premium.cpp b/Telegram/SourceFiles/settings/settings_premium.cpp index 2b359b984e..75eb85370c 100644 --- a/Telegram/SourceFiles/settings/settings_premium.cpp +++ b/Telegram/SourceFiles/settings/settings_premium.cpp @@ -203,13 +203,14 @@ struct Entry { const style::icon *icon; rpl::producer title; rpl::producer description; - std::optional section; + PremiumPreview section = PremiumPreview::DoubleLimits; }; using Order = std::vector; [[nodiscard]] Order FallbackOrder() { return Order{ + u"stories"_q, u"double_limits"_q, u"more_upload"_q, u"faster_download"_q, @@ -228,12 +229,22 @@ using Order = std::vector; [[nodiscard]] base::flat_map EntryMap() { return base::flat_map{ + { + u"stories"_q, + Entry{ + &st::settingsPremiumIconStories, + tr::lng_premium_summary_subtitle_stories(), + tr::lng_premium_summary_about_stories(), + PremiumPreview::Stories, + }, + }, { u"double_limits"_q, Entry{ &st::settingsPremiumIconDouble, tr::lng_premium_summary_subtitle_double_limits(), tr::lng_premium_summary_about_double_limits(), + PremiumPreview::DoubleLimits, }, }, { @@ -1318,55 +1329,7 @@ void Premium::setupContent() { _setPaused(false); }); - if (section) { - ShowPremiumPreviewToBuy(controller, *section, hidden); - return; - } - controller->show(Box([=](not_null box) { - DoubledLimitsPreviewBox(box, &controller->session()); - - box->addTopButton(st::boxTitleClose, [=] { - box->closeBox(); - }); - - Data::AmPremiumValue( - &controller->session() - ) | rpl::skip(1) | rpl::start_with_next([=] { - box->closeBox(); - }, box->lifetime()); - - box->boxClosing( - ) | rpl::start_with_next(hidden, box->lifetime()); - - if (controller->session().premium()) { - box->addButton(tr::lng_close(), [=] { - box->closeBox(); - }); - } else { - const auto button = CreateSubscribeButton({ - controller, - box, - [] { return u"double_limits"_q; } - }); - - box->setShowFinishedCallback([=] { - button->startGlareAnimation(); - }); - - box->setStyle(st::premiumPreviewDoubledLimitsBox); - box->widthValue( - ) | rpl::start_with_next([=](int width) { - const auto &padding = - st::premiumPreviewDoubledLimitsBox.buttonPadding; - button->resizeToWidth(width - - padding.left() - - padding.right()); - button->moveToLeft(padding.left(), padding.top()); - }, button->lifetime()); - box->addButton( - object_ptr::fromRaw(button)); - } - })); + ShowPremiumPreviewToBuy(controller, section, hidden); }); iconContainers.push_back(dummy); diff --git a/Telegram/SourceFiles/ui/effects/premium_graphics.cpp b/Telegram/SourceFiles/ui/effects/premium_graphics.cpp index a7ce3f922b..6932795374 100644 --- a/Telegram/SourceFiles/ui/effects/premium_graphics.cpp +++ b/Telegram/SourceFiles/ui/effects/premium_graphics.cpp @@ -1018,79 +1018,123 @@ QGradientStops GiftGradientStops() { }; } +QGradientStops StoriesIconsGradientStops() { + return { + { 0., st::premiumButtonBg1->c }, + { .33, st::premiumButtonBg2->c }, + { .66, st::premiumButtonBg3->c }, + { 1., st::premiumIconBg1->c }, + }; +} + void ShowListBox( not_null box, const style::PremiumLimits &st, std::vector entries) { + box->setWidth(st::boxWideWidth); const auto &stLabel = st::defaultFlatLabel; const auto &titlePadding = st::settingsPremiumPreviewTitlePadding; - const auto &descriptionPadding = st::settingsPremiumPreviewAboutPadding; + const auto &aboutPadding = st::settingsPremiumPreviewAboutPadding; + const auto iconTitlePadding = st::settingsPremiumPreviewIconTitlePadding; + const auto iconAboutPadding = st::settingsPremiumPreviewIconAboutPadding; auto lines = std::vector(); lines.reserve(int(entries.size())); + auto icons = std::shared_ptr>(); + const auto content = box->verticalLayout(); for (auto &entry : entries) { - content->add( + const auto title = content->add( object_ptr( content, - base::take(entry.subtitle) | rpl::map(Ui::Text::Bold), + base::take(entry.title) | rpl::map(Ui::Text::Bold), stLabel), - titlePadding); + entry.icon ? iconTitlePadding : titlePadding); content->add( object_ptr( content, - base::take(entry.description), + base::take(entry.about), st::boxDividerLabel), - descriptionPadding); - - const auto limitRow = content->add( - object_ptr( - content, - st, - entry.rightNumber, - TextFactory([=, text = ProcessTextFactory(std::nullopt)]( - int n) { - if (entry.customRightText && (n == entry.rightNumber)) { - return *entry.customRightText; - } else { - return text(n); - } - }), - entry.leftNumber, - kLimitRowRatio), - st::settingsPremiumPreviewLinePadding); - lines.push_back(limitRow); + entry.icon ? iconAboutPadding : aboutPadding); + if (const auto outlined = entry.icon) { + if (!icons) { + icons = std::make_shared>(); + } + const auto index = int(icons->size()); + icons->push_back(QColor()); + const auto icon = Ui::CreateChild(content.get()); + icon->resize(outlined->size()); + title->topValue() | rpl::start_with_next([=](int y) { + const auto shift = st::settingsPremiumPreviewIconPosition; + icon->move(QPoint(0, y) + shift); + }, icon->lifetime()); + icon->paintRequest() | rpl::start_with_next([=] { + auto p = QPainter(icon); + outlined->paintInCenter(p, icon->rect(), (*icons)[index]); + }, icon->lifetime()); + } + if (entry.leftNumber || entry.rightNumber) { + auto factory = [=, text = ProcessTextFactory({})](int n) { + if (entry.customRightText && (n == entry.rightNumber)) { + return *entry.customRightText; + } else { + return text(n); + } + }; + const auto limitRow = content->add( + object_ptr( + content, + st, + entry.rightNumber, + TextFactory(std::move(factory)), + entry.leftNumber, + kLimitRowRatio), + st::settingsPremiumPreviewLinePadding); + lines.push_back(limitRow); + } } content->resizeToWidth(content->height()); - // Color lines. - Assert(lines.size() > 2); - const auto from = lines.front()->y(); - const auto to = lines.back()->y() + lines.back()->height(); + // Colors for icons. + if (icons) { + box->addSkip(st::settingsPremiumPreviewLinePadding.bottom()); - const auto partialGradient = [&] { - auto stops = Ui::Premium::FullHeightGradientStops(); - // Reverse. - for (auto &stop : stops) { - stop.first = std::abs(stop.first - 1.); + const auto stops = Ui::Premium::StoriesIconsGradientStops(); + for (auto i = 0, count = int(icons->size()); i != count; ++i) { + (*icons)[i] = anim::gradient_color_at( + stops, + (count > 1) ? (i / float64(count - 1)) : 0.); } - return PartialGradient(from, to, std::move(stops)); - }(); - - for (auto i = 0; i < int(lines.size()); i++) { - const auto &line = lines[i]; - - const auto brush = QBrush( - partialGradient.compute(line->y(), line->height())); - line->setColorOverride(brush); } - box->addSkip(st::settingsPremiumPreviewLinePadding.bottom()); - box->setTitle(tr::lng_premium_summary_subtitle_double_limits()); - box->setWidth(st::boxWideWidth); + // Color lines. + if (!lines.empty()) { + box->addSkip(st::settingsPremiumPreviewLinePadding.bottom()); + + const auto from = lines.front()->y(); + const auto to = lines.back()->y() + lines.back()->height(); + + const auto partialGradient = [&] { + auto stops = Ui::Premium::FullHeightGradientStops(); + // Reverse. + for (auto &stop : stops) { + stop.first = std::abs(stop.first - 1.); + } + return PartialGradient(from, to, std::move(stops)); + }(); + + for (auto i = 0; i < int(lines.size()); i++) { + const auto &line = lines[i]; + + const auto brush = QBrush( + partialGradient.compute(line->y(), line->height())); + line->setColorOverride(brush); + } + box->addSkip(st::settingsPremiumPreviewLinePadding.bottom()); + } } void AddGiftOptions( diff --git a/Telegram/SourceFiles/ui/effects/premium_graphics.h b/Telegram/SourceFiles/ui/effects/premium_graphics.h index 089758d932..7f932a9bdf 100644 --- a/Telegram/SourceFiles/ui/effects/premium_graphics.h +++ b/Telegram/SourceFiles/ui/effects/premium_graphics.h @@ -88,11 +88,12 @@ void AddAccountsRow( [[nodiscard]] QGradientStops GiftGradientStops(); struct ListEntry final { - rpl::producer subtitle; - rpl::producer description; + rpl::producer title; + rpl::producer about; int leftNumber = 0; int rightNumber = 0; std::optional customRightText; + const style::icon *icon = nullptr; }; void ShowListBox( not_null box,