mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Toggle premium stickers previews.
This commit is contained in:
parent
afb7f2e9a6
commit
50926acab9
3 changed files with 125 additions and 30 deletions
|
@ -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<Data::DocumentMedia> &media) {
|
|||
[[nodiscard]] not_null<Ui::RpWidget*> StickerPreview(
|
||||
not_null<Ui::RpWidget*> parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
const std::shared_ptr<Data::DocumentMedia> &media) {
|
||||
const std::shared_ptr<Data::DocumentMedia> &media,
|
||||
Fn<void()> readyCallback = nullptr) {
|
||||
using namespace HistoryView;
|
||||
|
||||
PreloadSticker(media);
|
||||
|
@ -193,6 +195,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
|||
std::unique_ptr<Lottie::SinglePlayer> lottie;
|
||||
std::unique_ptr<Lottie::SinglePlayer> effect;
|
||||
std::unique_ptr<Ui::PathShiftGradient> pathGradient;
|
||||
bool readyInvoked = false;
|
||||
};
|
||||
const auto state = lifetime.make_state<State>();
|
||||
const auto createLottieIfReady = [=] {
|
||||
|
@ -220,11 +223,28 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &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<Data::DocumentMedia> &media) {
|
|||
|
||||
struct State {
|
||||
std::vector<std::shared_ptr<Data::DocumentMedia>> 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<void()> 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<State>();
|
||||
const auto create = [=](std::shared_ptr<Data::DocumentMedia> media) {
|
||||
const auto outer = Ui::CreateChild<Ui::RpWidget>(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(
|
||||
|
|
|
@ -312,6 +312,7 @@ premiumPreviewButtonLabel: FlatLabel(defaultFlatLabel) {
|
|||
textFg: premiumButtonFg;
|
||||
style: semiboldTextStyle;
|
||||
}
|
||||
premiumSlideDuration: 200;
|
||||
|
||||
stickersPremiumLock: icon{{ "emoji/premium_lock", premiumButtonFg }};
|
||||
|
||||
|
|
|
@ -70,23 +70,23 @@ using Order = std::vector<QString>;
|
|||
|
||||
[[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<QString, Entry> EntryMap() {
|
||||
return base::flat_map<QString, Entry>{
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
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>;
|
|||
},
|
||||
},
|
||||
{
|
||||
QString("animated_userpics"),
|
||||
u"animated_userpics"_q,
|
||||
Entry{
|
||||
&st::settingsPremiumIconPlay,
|
||||
tr::lng_premium_summary_subtitle_animated_userpics(),
|
||||
|
|
Loading…
Add table
Reference in a new issue