Implement stories premium promo.

This commit is contained in:
John Preston 2023-08-04 08:07:37 +02:00
parent 40b274e1b4
commit 7877cb0b3a
21 changed files with 292 additions and 113 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -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#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#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_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_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_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"; "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_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."; "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. // Doubled Limits.
"lng_premium_double_limits_subtitle_channels" = "Groups and Channels"; "lng_premium_double_limits_subtitle_channels" = "Groups and Channels";
"lng_premium_double_limits_about_channels#one" = "Join up to {count} channels and large groups"; "lng_premium_double_limits_about_channels#one" = "Join up to {count} channels and large groups";

View File

@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/wrap/padding_wrap.h" #include "ui/wrap/padding_wrap.h"
#include "ui/boxes/confirm_box.h" #include "ui/boxes/confirm_box.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "settings/settings_common.h"
#include "settings/settings_premium.h" #include "settings/settings_premium.h"
#include "lottie/lottie_single_player.h" #include "lottie/lottie_single_player.h"
#include "history/view/media/history_view_sticker.h" #include "history/view/media/history_view_sticker.h"
@ -92,6 +93,10 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
[[nodiscard]] rpl::producer<QString> SectionTitle(PremiumPreview section) { [[nodiscard]] rpl::producer<QString> SectionTitle(PremiumPreview section) {
switch (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: case PremiumPreview::MoreUpload:
return tr::lng_premium_summary_subtitle_more_upload(); return tr::lng_premium_summary_subtitle_more_upload();
case PremiumPreview::FasterDownload: case PremiumPreview::FasterDownload:
@ -122,6 +127,10 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
[[nodiscard]] rpl::producer<QString> SectionAbout(PremiumPreview section) { [[nodiscard]] rpl::producer<QString> SectionAbout(PremiumPreview section) {
switch (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: case PremiumPreview::MoreUpload:
return tr::lng_premium_summary_about_more_upload(); return tr::lng_premium_summary_about_more_upload();
case PremiumPreview::FasterDownload: case PremiumPreview::FasterDownload:
@ -1117,6 +1126,56 @@ void Show(std::shared_ptr<ChatHelpers::Show> show, QImage back) {
} }
} }
void DecorateListPromoBox(
not_null<Ui::GenericBox*> box,
std::shared_ptr<ChatHelpers::Show> 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<Ui::AbstractButton>::fromRaw(button));
}
}
void Show( void Show(
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,
Descriptor &&descriptor) { Descriptor &&descriptor) {
@ -1128,6 +1187,18 @@ void Show(
descriptor.shownCallback(raw); descriptor.shownCallback(raw);
} }
return; return;
} else if (descriptor.section == PremiumPreview::DoubleLimits) {
show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
DoubledLimitsPreviewBox(box, &show->session());
DecorateListPromoBox(box, show, descriptor);
}));
return;
} else if (descriptor.section == PremiumPreview::Stories) {
show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
UpgradedStoriesPreviewBox(box, &show->session());
DecorateListPromoBox(box, show, descriptor);
}));
return;
} }
auto &list = Preloads(); auto &list = Preloads();
for (auto i = begin(list); i != end(list);) { for (auto i = begin(list); i != end(list);) {
@ -1240,11 +1311,13 @@ void PremiumUnavailableBox(not_null<Ui::GenericBox*> box) {
void DoubledLimitsPreviewBox( void DoubledLimitsPreviewBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session) { not_null<Main::Session*> session) {
box->setTitle(tr::lng_premium_summary_subtitle_double_limits());
const auto limits = Data::PremiumLimits(session); const auto limits = Data::PremiumLimits(session);
auto entries = std::vector<Ui::Premium::ListEntry>(); auto entries = std::vector<Ui::Premium::ListEntry>();
{ {
const auto premium = limits.channelsPremium(); 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_subtitle_channels(),
tr::lng_premium_double_limits_about_channels( tr::lng_premium_double_limits_about_channels(
lt_count, lt_count,
@ -1256,7 +1329,7 @@ void DoubledLimitsPreviewBox(
} }
{ {
const auto premium = limits.dialogsPinnedPremium(); 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_subtitle_pins(),
tr::lng_premium_double_limits_about_pins( tr::lng_premium_double_limits_about_pins(
lt_count, lt_count,
@ -1268,7 +1341,7 @@ void DoubledLimitsPreviewBox(
} }
{ {
const auto premium = limits.channelsPublicPremium(); 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_subtitle_links(),
tr::lng_premium_double_limits_about_links( tr::lng_premium_double_limits_about_links(
lt_count, lt_count,
@ -1280,7 +1353,7 @@ void DoubledLimitsPreviewBox(
} }
{ {
const auto premium = limits.gifsPremium(); 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_subtitle_gifs(),
tr::lng_premium_double_limits_about_gifs( tr::lng_premium_double_limits_about_gifs(
lt_count, lt_count,
@ -1292,7 +1365,7 @@ void DoubledLimitsPreviewBox(
} }
{ {
const auto premium = limits.stickersFavedPremium(); 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_subtitle_stickers(),
tr::lng_premium_double_limits_about_stickers( tr::lng_premium_double_limits_about_stickers(
lt_count, lt_count,
@ -1304,7 +1377,7 @@ void DoubledLimitsPreviewBox(
} }
{ {
const auto premium = limits.aboutLengthPremium(); 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_subtitle_bio(),
tr::lng_premium_double_limits_about_bio( tr::lng_premium_double_limits_about_bio(
Ui::Text::RichLangValue), Ui::Text::RichLangValue),
@ -1314,7 +1387,7 @@ void DoubledLimitsPreviewBox(
} }
{ {
const auto premium = limits.captionLengthPremium(); 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_subtitle_captions(),
tr::lng_premium_double_limits_about_captions( tr::lng_premium_double_limits_about_captions(
Ui::Text::RichLangValue), Ui::Text::RichLangValue),
@ -1324,7 +1397,7 @@ void DoubledLimitsPreviewBox(
} }
{ {
const auto premium = limits.dialogFiltersPremium(); 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_subtitle_folders(),
tr::lng_premium_double_limits_about_folders( tr::lng_premium_double_limits_about_folders(
lt_count, lt_count,
@ -1336,7 +1409,7 @@ void DoubledLimitsPreviewBox(
} }
{ {
const auto premium = limits.dialogFiltersChatsPremium(); 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_subtitle_folder_chats(),
tr::lng_premium_double_limits_about_folder_chats( tr::lng_premium_double_limits_about_folder_chats(
lt_count, lt_count,
@ -1350,7 +1423,7 @@ void DoubledLimitsPreviewBox(
const auto till = (nextMax >= Main::Domain::kPremiumMaxAccounts) const auto till = (nextMax >= Main::Domain::kPremiumMaxAccounts)
? QString::number(Main::Domain::kPremiumMaxAccounts) ? QString::number(Main::Domain::kPremiumMaxAccounts)
: (QString::number(nextMax) + QChar('+')); : (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_subtitle_accounts(),
tr::lng_premium_double_limits_about_accounts( tr::lng_premium_double_limits_about_accounts(
lt_count, lt_count,
@ -1366,6 +1439,60 @@ void DoubledLimitsPreviewBox(
std::move(entries)); std::move(entries));
} }
void UpgradedStoriesPreviewBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session) {
using namespace Ui::Text;
box->setTitle(tr::lng_premium_summary_subtitle_stories());
auto entries = std::vector<Ui::Premium::ListEntry>();
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<Ui::GradientButton> CreateUnlockButton( object_ptr<Ui::GradientButton> CreateUnlockButton(
QWidget *parent, QWidget *parent,
rpl::producer<QString> text) { rpl::producer<QString> text) {

View File

@ -41,7 +41,13 @@ void DoubledLimitsPreviewBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session); not_null<Main::Session*> session);
void UpgradedStoriesPreviewBox(
not_null<Ui::GenericBox*> box,
not_null<Main::Session*> session);
enum class PremiumPreview { enum class PremiumPreview {
Stories,
DoubleLimits,
MoreUpload, MoreUpload,
FasterDownload, FasterDownload,
VoiceToText, VoiceToText,

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer_rpl.h" #include "base/timer_rpl.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "boxes/premium_preview_box.h"
#include "chat_helpers/compose/compose_show.h" #include "chat_helpers/compose/compose_show.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_session.h" #include "data/data_session.h"
@ -295,7 +296,7 @@ struct Feature {
label->resizeToWidth(width); label->resizeToWidth(width);
label->move(added / 2, top); label->move(added / 2, top);
const auto inner = std::min(label->textMaxWidth(), width); 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; const auto lockTop = (label->height() - lock->height()) / 2;
lock->move(right + lockLeft, top + lockTop); lock->move(right + lockLeft, top + lockTop);
}; };
@ -351,9 +352,7 @@ struct Feature {
data->requested = false; data->requested = false;
const auto usage = ChatHelpers::WindowUsage::PremiumPromo; const auto usage = ChatHelpers::WindowUsage::PremiumPromo;
if (const auto window = show->resolveWindow(usage)) { if (const auto window = show->resolveWindow(usage)) {
Settings::ShowPremium( ShowPremiumPreviewBox(window, PremiumPreview::Stories);
window,
u"stories__stealth_mode"_q);
window->window().activate(); window->window().activate();
} }
} else if (now.mode.cooldownTill > now.now) { } else if (now.mode.cooldownTill > now.now) {

View File

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_peer_photo.h" #include "api/api_peer_photo.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "boxes/premium_preview_box.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
@ -1252,8 +1253,8 @@ void OverlayWidget::showPremiumDownloadPromo() {
const auto filter = [=](const auto &...) { const auto filter = [=](const auto &...) {
const auto usage = ChatHelpers::WindowUsage::PremiumPromo; const auto usage = ChatHelpers::WindowUsage::PremiumPromo;
if (const auto window = uiShow()->resolveWindow(usage)) { if (const auto window = uiShow()->resolveWindow(usage)) {
const auto ref = u"stories__save_stories_to_gallery"_q; ShowPremiumPreviewBox(window, PremiumPreview::Stories);
Settings::ShowPremium(window, ref); window->window().activate();
} }
return false; return false;
}; };

View File

@ -109,6 +109,7 @@ settingsIconTopics: icon {{ "settings/topics", settingsIconFg }};
settingsIconTTL: icon {{ "settings/ttl", settingsIconFg }}; settingsIconTTL: icon {{ "settings/ttl", settingsIconFg }};
settingsIconPhoto: icon {{ "settings/photo", settingsIconFg }}; settingsIconPhoto: icon {{ "settings/photo", settingsIconFg }};
settingsPremiumIconStories: icon {{ "settings/stories", settingsIconFg }};
settingsPremiumIconChannelsOff: icon {{ "settings/premium/channels_off", settingsIconFg }}; settingsPremiumIconChannelsOff: icon {{ "settings/premium/channels_off", settingsIconFg }};
settingsPremiumIconDouble: icon {{ "settings/premium/double", settingsIconFg }}; settingsPremiumIconDouble: icon {{ "settings/premium/double", settingsIconFg }};
settingsPremiumIconStatus: icon {{ "settings/premium/status", settingsIconFg }}; settingsPremiumIconStatus: icon {{ "settings/premium/status", settingsIconFg }};
@ -120,6 +121,14 @@ settingsPremiumIconVoice: icon {{ "settings/premium/voice", settingsIconFg }};
settingsPremiumIconFiles: icon {{ "settings/premium/files", settingsIconFg }}; settingsPremiumIconFiles: icon {{ "settings/premium/files", settingsIconFg }};
settingsPremiumIconTranslations: icon {{ "settings/premium/translations", 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 }}; settingsTTLChatsOff: icon {{ "settings/ttl/autodelete_off", windowSubTextFg }};
settingsTTLChatsOn: icon {{ "settings/ttl/autodelete_on", windowActiveTextFg }}; settingsTTLChatsOn: icon {{ "settings/ttl/autodelete_on", windowActiveTextFg }};
@ -473,6 +482,9 @@ settingsPremiumRowAboutPadding: margins(59px, 0px, 46px, 6px);
settingsPremiumPreviewTitlePadding: margins(24px, 13px, 24px, 3px); settingsPremiumPreviewTitlePadding: margins(24px, 13px, 24px, 3px);
settingsPremiumPreviewAboutPadding: margins(24px, 0px, 24px, 11px); settingsPremiumPreviewAboutPadding: margins(24px, 0px, 24px, 11px);
settingsPremiumPreviewLinePadding: margins(18px, 0px, 18px, 8px); 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); settingsPremiumTitlePadding: margins(0px, 18px, 0px, 11px);
settingsPremiumAboutTextStyle: TextStyle(defaultTextStyle) { settingsPremiumAboutTextStyle: TextStyle(defaultTextStyle) {

View File

@ -203,13 +203,14 @@ struct Entry {
const style::icon *icon; const style::icon *icon;
rpl::producer<QString> title; rpl::producer<QString> title;
rpl::producer<QString> description; rpl::producer<QString> description;
std::optional<PremiumPreview> section; PremiumPreview section = PremiumPreview::DoubleLimits;
}; };
using Order = std::vector<QString>; using Order = std::vector<QString>;
[[nodiscard]] Order FallbackOrder() { [[nodiscard]] Order FallbackOrder() {
return Order{ return Order{
u"stories"_q,
u"double_limits"_q, u"double_limits"_q,
u"more_upload"_q, u"more_upload"_q,
u"faster_download"_q, u"faster_download"_q,
@ -228,12 +229,22 @@ using Order = std::vector<QString>;
[[nodiscard]] base::flat_map<QString, Entry> EntryMap() { [[nodiscard]] base::flat_map<QString, Entry> EntryMap() {
return base::flat_map<QString, Entry>{ return base::flat_map<QString, Entry>{
{
u"stories"_q,
Entry{
&st::settingsPremiumIconStories,
tr::lng_premium_summary_subtitle_stories(),
tr::lng_premium_summary_about_stories(),
PremiumPreview::Stories,
},
},
{ {
u"double_limits"_q, u"double_limits"_q,
Entry{ Entry{
&st::settingsPremiumIconDouble, &st::settingsPremiumIconDouble,
tr::lng_premium_summary_subtitle_double_limits(), tr::lng_premium_summary_subtitle_double_limits(),
tr::lng_premium_summary_about_double_limits(), tr::lng_premium_summary_about_double_limits(),
PremiumPreview::DoubleLimits,
}, },
}, },
{ {
@ -1318,55 +1329,7 @@ void Premium::setupContent() {
_setPaused(false); _setPaused(false);
}); });
if (section) { ShowPremiumPreviewToBuy(controller, section, hidden);
ShowPremiumPreviewToBuy(controller, *section, hidden);
return;
}
controller->show(Box([=](not_null<Ui::GenericBox*> 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<Ui::AbstractButton>::fromRaw(button));
}
}));
}); });
iconContainers.push_back(dummy); iconContainers.push_back(dummy);

View File

@ -1018,56 +1018,102 @@ QGradientStops GiftGradientStops() {
}; };
} }
QGradientStops StoriesIconsGradientStops() {
return {
{ 0., st::premiumButtonBg1->c },
{ .33, st::premiumButtonBg2->c },
{ .66, st::premiumButtonBg3->c },
{ 1., st::premiumIconBg1->c },
};
}
void ShowListBox( void ShowListBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
const style::PremiumLimits &st, const style::PremiumLimits &st,
std::vector<ListEntry> entries) { std::vector<ListEntry> entries) {
box->setWidth(st::boxWideWidth);
const auto &stLabel = st::defaultFlatLabel; const auto &stLabel = st::defaultFlatLabel;
const auto &titlePadding = st::settingsPremiumPreviewTitlePadding; 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<Line*>(); auto lines = std::vector<Line*>();
lines.reserve(int(entries.size())); lines.reserve(int(entries.size()));
auto icons = std::shared_ptr<std::vector<QColor>>();
const auto content = box->verticalLayout(); const auto content = box->verticalLayout();
for (auto &entry : entries) { for (auto &entry : entries) {
content->add( const auto title = content->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
content, content,
base::take(entry.subtitle) | rpl::map(Ui::Text::Bold), base::take(entry.title) | rpl::map(Ui::Text::Bold),
stLabel), stLabel),
titlePadding); entry.icon ? iconTitlePadding : titlePadding);
content->add( content->add(
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
content, content,
base::take(entry.description), base::take(entry.about),
st::boxDividerLabel), st::boxDividerLabel),
descriptionPadding); entry.icon ? iconAboutPadding : aboutPadding);
if (const auto outlined = entry.icon) {
const auto limitRow = content->add( if (!icons) {
object_ptr<Line>( icons = std::make_shared<std::vector<QColor>>();
content, }
st, const auto index = int(icons->size());
entry.rightNumber, icons->push_back(QColor());
TextFactory([=, text = ProcessTextFactory(std::nullopt)]( const auto icon = Ui::CreateChild<Ui::RpWidget>(content.get());
int n) { 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)) { if (entry.customRightText && (n == entry.rightNumber)) {
return *entry.customRightText; return *entry.customRightText;
} else { } else {
return text(n); return text(n);
} }
}), };
const auto limitRow = content->add(
object_ptr<Line>(
content,
st,
entry.rightNumber,
TextFactory(std::move(factory)),
entry.leftNumber, entry.leftNumber,
kLimitRowRatio), kLimitRowRatio),
st::settingsPremiumPreviewLinePadding); st::settingsPremiumPreviewLinePadding);
lines.push_back(limitRow); lines.push_back(limitRow);
} }
}
content->resizeToWidth(content->height()); content->resizeToWidth(content->height());
// Colors for icons.
if (icons) {
box->addSkip(st::settingsPremiumPreviewLinePadding.bottom());
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.);
}
}
// Color lines. // Color lines.
Assert(lines.size() > 2); if (!lines.empty()) {
box->addSkip(st::settingsPremiumPreviewLinePadding.bottom());
const auto from = lines.front()->y(); const auto from = lines.front()->y();
const auto to = lines.back()->y() + lines.back()->height(); const auto to = lines.back()->y() + lines.back()->height();
@ -1088,9 +1134,7 @@ void ShowListBox(
line->setColorOverride(brush); line->setColorOverride(brush);
} }
box->addSkip(st::settingsPremiumPreviewLinePadding.bottom()); box->addSkip(st::settingsPremiumPreviewLinePadding.bottom());
}
box->setTitle(tr::lng_premium_summary_subtitle_double_limits());
box->setWidth(st::boxWideWidth);
} }
void AddGiftOptions( void AddGiftOptions(

View File

@ -88,11 +88,12 @@ void AddAccountsRow(
[[nodiscard]] QGradientStops GiftGradientStops(); [[nodiscard]] QGradientStops GiftGradientStops();
struct ListEntry final { struct ListEntry final {
rpl::producer<QString> subtitle; rpl::producer<QString> title;
rpl::producer<TextWithEntities> description; rpl::producer<TextWithEntities> about;
int leftNumber = 0; int leftNumber = 0;
int rightNumber = 0; int rightNumber = 0;
std::optional<QString> customRightText; std::optional<QString> customRightText;
const style::icon *icon = nullptr;
}; };
void ShowListBox( void ShowListBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,