From 50926acab934fabb92ed182a30d16868505bbffd Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 13 Jun 2022 16:52:21 +0400 Subject: [PATCH] Toggle premium stickers previews. --- .../SourceFiles/boxes/premium_preview_box.cpp | 114 ++++++++++++++++-- .../chat_helpers/chat_helpers.style | 1 + .../SourceFiles/settings/settings_premium.cpp | 40 +++--- 3 files changed, 125 insertions(+), 30 deletions(-) diff --git a/Telegram/SourceFiles/boxes/premium_preview_box.cpp b/Telegram/SourceFiles/boxes/premium_preview_box.cpp index 2a5777c8e..ca4b77d36 100644 --- a/Telegram/SourceFiles/boxes/premium_preview_box.cpp +++ b/Telegram/SourceFiles/boxes/premium_preview_box.cpp @@ -50,6 +50,7 @@ constexpr auto kShiftDuration = crl::time(200); constexpr auto kReactionsPerRow = 5; constexpr auto kDisabledOpacity = 0.5; constexpr auto kPreviewsCount = int(PremiumPreview::kCount); +constexpr auto kToggleStickerTimeout = 2 * crl::time(1000); struct Descriptor { PremiumPreview section = PremiumPreview::Stickers; @@ -168,7 +169,8 @@ void PreloadSticker(const std::shared_ptr &media) { [[nodiscard]] not_null StickerPreview( not_null parent, not_null controller, - const std::shared_ptr &media) { + const std::shared_ptr &media, + Fn readyCallback = nullptr) { using namespace HistoryView; PreloadSticker(media); @@ -193,6 +195,7 @@ void PreloadSticker(const std::shared_ptr &media) { std::unique_ptr lottie; std::unique_ptr effect; std::unique_ptr pathGradient; + bool readyInvoked = false; }; const auto state = lifetime.make_state(); const auto createLottieIfReady = [=] { @@ -220,11 +223,28 @@ void PreloadSticker(const std::shared_ptr &media) { QString(), true); - const auto update = [=] { result->update(); }; + const auto update = [=] { + if (!state->readyInvoked + && readyCallback + && state->lottie->ready() + && state->effect->ready()) { + state->readyInvoked = true; + readyCallback(); + } + result->update(); + }; auto &lifetime = result->lifetime(); state->lottie->updates() | rpl::start_with_next(update, lifetime); state->effect->updates() | rpl::start_with_next(update, lifetime); }; + createLottieIfReady(); + if (!state->lottie || !state->effect) { + controller->session().downloaderTaskFinished( + ) | rpl::take_while([=] { + createLottieIfReady(); + return !state->lottie || !state->effect; + }) | rpl::start(result->lifetime()); + } state->pathGradient = MakePathShiftGradient( controller->chatStyle(), [=] { result->update(); }); @@ -294,23 +314,92 @@ void PreloadSticker(const std::shared_ptr &media) { struct State { std::vector> medias; - Ui::RpWidget *single = nullptr; + Ui::RpWidget *previous = nullptr; + Ui::RpWidget *current = nullptr; + Ui::RpWidget *next = nullptr; + Ui::Animations::Simple slide; + base::Timer toggleTimer; + Fn readyCallback; + bool singleReady = false; + bool timerFired = false; + bool nextReady = false; + int index = 0; }; const auto premium = &controller->session().api().premium(); const auto state = lifetime.make_state(); + const auto create = [=](std::shared_ptr media) { + const auto outer = Ui::CreateChild(result); + outer->show(); + + result->sizeValue( + ) | rpl::start_with_next([=](QSize size) { + outer->resize(size); + }, outer->lifetime()); + + [[maybe_unused]] const auto sticker = StickerPreview( + outer, + controller, + media, + state->readyCallback); + + return outer; + }; + const auto createNext = [=] { + state->nextReady = false; + state->next = create(state->medias[state->index]); + state->next->move(0, state->current->height()); + }; + const auto check = [=] { + if (!state->timerFired || !state->nextReady) { + return; + } + const auto animationCallback = [=] { + const auto top = int(base::SafeRound(state->slide.value(0.))); + state->previous->move(0, top - state->current->height()); + state->current->move(0, top); + if (!state->slide.animating()) { + delete base::take(state->previous); + state->timerFired = false; + state->toggleTimer.callOnce(kToggleStickerTimeout); + } + }; + state->index = (++state->index) % state->medias.size(); + delete std::exchange(state->previous, state->current); + state->current = state->next; + createNext(); + state->slide.stop(); + state->slide.start( + animationCallback, + state->current->height(), + 0, + st::premiumSlideDuration, + anim::sineInOut); + }; + state->toggleTimer.setCallback([=] { + state->timerFired = true; + check(); + }); + state->readyCallback = [=] { + if (!state->next) { + createNext(); + state->toggleTimer.callOnce(kToggleStickerTimeout); + } else { + state->nextReady = true; + check(); + } + }; + const auto fill = [=] { const auto &list = premium->stickers(); for (const auto &document : list) { state->medias.push_back(document->createMediaView()); } - if (state->medias.empty()) { - return; + if (!state->medias.empty()) { + state->current = create(state->medias.front()); + state->current->move(0, 0); } - state->single = StickerPreview( - result, - controller, - state->medias.front()); }; + fill(); if (state->medias.empty()) { premium->stickersUpdated( @@ -1101,7 +1190,12 @@ void PreviewBox( state->leftFrom = start; state->content = GenerateDefaultPreview(outer, controller, now); state->animation.stop(); - state->animation.start(animationCallback, 0., 1., st::slideDuration); + state->animation.start( + animationCallback, + 0., + 1., + st::premiumSlideDuration, + anim::sineInOut); }, outer->lifetime()); auto title = state->selected.value( diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style index 28052a8fe..b3641e4b4 100644 --- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style +++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style @@ -312,6 +312,7 @@ premiumPreviewButtonLabel: FlatLabel(defaultFlatLabel) { textFg: premiumButtonFg; style: semiboldTextStyle; } +premiumSlideDuration: 200; stickersPremiumLock: icon{{ "emoji/premium_lock", premiumButtonFg }}; diff --git a/Telegram/SourceFiles/settings/settings_premium.cpp b/Telegram/SourceFiles/settings/settings_premium.cpp index d453d5b57..78627f0f4 100644 --- a/Telegram/SourceFiles/settings/settings_premium.cpp +++ b/Telegram/SourceFiles/settings/settings_premium.cpp @@ -70,23 +70,23 @@ using Order = std::vector; [[nodiscard]] Order FallbackOrder() { return Order{ - QString("double_limits"), - QString("more_upload"), - QString("faster_download"), - QString("voice_to_text"), - QString("no_ads"), - QString("unique_reactions"), - QString("premium_stickers"), - QString("advanced_chat_management"), - QString("profile_badge"), - QString("animated_userpics"), + u"double_limits"_q, + u"more_upload"_q, + u"faster_download"_q, + u"voice_to_text"_q, + u"no_ads"_q, + u"unique_reactions"_q, + u"premium_stickers"_q, + u"advanced_chat_management"_q, + u"profile_badge"_q, + u"animated_userpics"_q, }; } [[nodiscard]] base::flat_map EntryMap() { return base::flat_map{ { - QString("double_limits"), + u"double_limits"_q, Entry{ &st::settingsPremiumIconDouble, tr::lng_premium_summary_subtitle_double_limits(), @@ -94,7 +94,7 @@ using Order = std::vector; }, }, { - QString("more_upload"), + u"more_upload"_q, Entry{ &st::settingsPremiumIconFiles, tr::lng_premium_summary_subtitle_more_upload(), @@ -102,7 +102,7 @@ using Order = std::vector; }, }, { - QString("faster_download"), + u"faster_download"_q, Entry{ &st::settingsPremiumIconSpeed, tr::lng_premium_summary_subtitle_faster_download(), @@ -110,7 +110,7 @@ using Order = std::vector; }, }, { - QString("voice_to_text"), + u"voice_to_text"_q, Entry{ &st::settingsPremiumIconVoice, tr::lng_premium_summary_subtitle_voice_to_text(), @@ -118,7 +118,7 @@ using Order = std::vector; }, }, { - QString("no_ads"), + u"no_ads"_q, Entry{ &st::settingsPremiumIconChannelsOff, tr::lng_premium_summary_subtitle_no_ads(), @@ -126,7 +126,7 @@ using Order = std::vector; }, }, { - QString("unique_reactions"), + u"unique_reactions"_q, Entry{ &st::settingsPremiumIconLike, tr::lng_premium_summary_subtitle_unique_reactions(), @@ -134,7 +134,7 @@ using Order = std::vector; }, }, { - QString("premium_stickers"), + u"premium_stickers"_q, Entry{ &st::settingsIconStickers, tr::lng_premium_summary_subtitle_premium_stickers(), @@ -142,7 +142,7 @@ using Order = std::vector; }, }, { - QString("advanced_chat_management"), + u"advanced_chat_management"_q, Entry{ &st::settingsIconChat, tr::lng_premium_summary_subtitle_advanced_chat_management(), @@ -150,7 +150,7 @@ using Order = std::vector; }, }, { - QString("profile_badge"), + u"profile_badge"_q, Entry{ &st::settingsPremiumIconStar, tr::lng_premium_summary_subtitle_profile_badge(), @@ -158,7 +158,7 @@ using Order = std::vector; }, }, { - QString("animated_userpics"), + u"animated_userpics"_q, Entry{ &st::settingsPremiumIconPlay, tr::lng_premium_summary_subtitle_animated_userpics(),