mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +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 kReactionsPerRow = 5;
|
||||||
constexpr auto kDisabledOpacity = 0.5;
|
constexpr auto kDisabledOpacity = 0.5;
|
||||||
constexpr auto kPreviewsCount = int(PremiumPreview::kCount);
|
constexpr auto kPreviewsCount = int(PremiumPreview::kCount);
|
||||||
|
constexpr auto kToggleStickerTimeout = 2 * crl::time(1000);
|
||||||
|
|
||||||
struct Descriptor {
|
struct Descriptor {
|
||||||
PremiumPreview section = PremiumPreview::Stickers;
|
PremiumPreview section = PremiumPreview::Stickers;
|
||||||
|
@ -168,7 +169,8 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
||||||
[[nodiscard]] not_null<Ui::RpWidget*> StickerPreview(
|
[[nodiscard]] not_null<Ui::RpWidget*> StickerPreview(
|
||||||
not_null<Ui::RpWidget*> parent,
|
not_null<Ui::RpWidget*> parent,
|
||||||
not_null<Window::SessionController*> controller,
|
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;
|
using namespace HistoryView;
|
||||||
|
|
||||||
PreloadSticker(media);
|
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> lottie;
|
||||||
std::unique_ptr<Lottie::SinglePlayer> effect;
|
std::unique_ptr<Lottie::SinglePlayer> effect;
|
||||||
std::unique_ptr<Ui::PathShiftGradient> pathGradient;
|
std::unique_ptr<Ui::PathShiftGradient> pathGradient;
|
||||||
|
bool readyInvoked = false;
|
||||||
};
|
};
|
||||||
const auto state = lifetime.make_state<State>();
|
const auto state = lifetime.make_state<State>();
|
||||||
const auto createLottieIfReady = [=] {
|
const auto createLottieIfReady = [=] {
|
||||||
|
@ -220,11 +223,28 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
||||||
QString(),
|
QString(),
|
||||||
true);
|
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();
|
auto &lifetime = result->lifetime();
|
||||||
state->lottie->updates() | rpl::start_with_next(update, lifetime);
|
state->lottie->updates() | rpl::start_with_next(update, lifetime);
|
||||||
state->effect->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(
|
state->pathGradient = MakePathShiftGradient(
|
||||||
controller->chatStyle(),
|
controller->chatStyle(),
|
||||||
[=] { result->update(); });
|
[=] { result->update(); });
|
||||||
|
@ -294,23 +314,92 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
std::vector<std::shared_ptr<Data::DocumentMedia>> medias;
|
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 premium = &controller->session().api().premium();
|
||||||
const auto state = lifetime.make_state<State>();
|
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 fill = [=] {
|
||||||
const auto &list = premium->stickers();
|
const auto &list = premium->stickers();
|
||||||
for (const auto &document : list) {
|
for (const auto &document : list) {
|
||||||
state->medias.push_back(document->createMediaView());
|
state->medias.push_back(document->createMediaView());
|
||||||
}
|
}
|
||||||
if (state->medias.empty()) {
|
if (!state->medias.empty()) {
|
||||||
return;
|
state->current = create(state->medias.front());
|
||||||
|
state->current->move(0, 0);
|
||||||
}
|
}
|
||||||
state->single = StickerPreview(
|
|
||||||
result,
|
|
||||||
controller,
|
|
||||||
state->medias.front());
|
|
||||||
};
|
};
|
||||||
|
|
||||||
fill();
|
fill();
|
||||||
if (state->medias.empty()) {
|
if (state->medias.empty()) {
|
||||||
premium->stickersUpdated(
|
premium->stickersUpdated(
|
||||||
|
@ -1101,7 +1190,12 @@ void PreviewBox(
|
||||||
state->leftFrom = start;
|
state->leftFrom = start;
|
||||||
state->content = GenerateDefaultPreview(outer, controller, now);
|
state->content = GenerateDefaultPreview(outer, controller, now);
|
||||||
state->animation.stop();
|
state->animation.stop();
|
||||||
state->animation.start(animationCallback, 0., 1., st::slideDuration);
|
state->animation.start(
|
||||||
|
animationCallback,
|
||||||
|
0.,
|
||||||
|
1.,
|
||||||
|
st::premiumSlideDuration,
|
||||||
|
anim::sineInOut);
|
||||||
}, outer->lifetime());
|
}, outer->lifetime());
|
||||||
|
|
||||||
auto title = state->selected.value(
|
auto title = state->selected.value(
|
||||||
|
|
|
@ -312,6 +312,7 @@ premiumPreviewButtonLabel: FlatLabel(defaultFlatLabel) {
|
||||||
textFg: premiumButtonFg;
|
textFg: premiumButtonFg;
|
||||||
style: semiboldTextStyle;
|
style: semiboldTextStyle;
|
||||||
}
|
}
|
||||||
|
premiumSlideDuration: 200;
|
||||||
|
|
||||||
stickersPremiumLock: icon{{ "emoji/premium_lock", premiumButtonFg }};
|
stickersPremiumLock: icon{{ "emoji/premium_lock", premiumButtonFg }};
|
||||||
|
|
||||||
|
|
|
@ -70,23 +70,23 @@ using Order = std::vector<QString>;
|
||||||
|
|
||||||
[[nodiscard]] Order FallbackOrder() {
|
[[nodiscard]] Order FallbackOrder() {
|
||||||
return Order{
|
return Order{
|
||||||
QString("double_limits"),
|
u"double_limits"_q,
|
||||||
QString("more_upload"),
|
u"more_upload"_q,
|
||||||
QString("faster_download"),
|
u"faster_download"_q,
|
||||||
QString("voice_to_text"),
|
u"voice_to_text"_q,
|
||||||
QString("no_ads"),
|
u"no_ads"_q,
|
||||||
QString("unique_reactions"),
|
u"unique_reactions"_q,
|
||||||
QString("premium_stickers"),
|
u"premium_stickers"_q,
|
||||||
QString("advanced_chat_management"),
|
u"advanced_chat_management"_q,
|
||||||
QString("profile_badge"),
|
u"profile_badge"_q,
|
||||||
QString("animated_userpics"),
|
u"animated_userpics"_q,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[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>{
|
||||||
{
|
{
|
||||||
QString("double_limits"),
|
u"double_limits"_q,
|
||||||
Entry{
|
Entry{
|
||||||
&st::settingsPremiumIconDouble,
|
&st::settingsPremiumIconDouble,
|
||||||
tr::lng_premium_summary_subtitle_double_limits(),
|
tr::lng_premium_summary_subtitle_double_limits(),
|
||||||
|
@ -94,7 +94,7 @@ using Order = std::vector<QString>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
QString("more_upload"),
|
u"more_upload"_q,
|
||||||
Entry{
|
Entry{
|
||||||
&st::settingsPremiumIconFiles,
|
&st::settingsPremiumIconFiles,
|
||||||
tr::lng_premium_summary_subtitle_more_upload(),
|
tr::lng_premium_summary_subtitle_more_upload(),
|
||||||
|
@ -102,7 +102,7 @@ using Order = std::vector<QString>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
QString("faster_download"),
|
u"faster_download"_q,
|
||||||
Entry{
|
Entry{
|
||||||
&st::settingsPremiumIconSpeed,
|
&st::settingsPremiumIconSpeed,
|
||||||
tr::lng_premium_summary_subtitle_faster_download(),
|
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{
|
Entry{
|
||||||
&st::settingsPremiumIconVoice,
|
&st::settingsPremiumIconVoice,
|
||||||
tr::lng_premium_summary_subtitle_voice_to_text(),
|
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{
|
Entry{
|
||||||
&st::settingsPremiumIconChannelsOff,
|
&st::settingsPremiumIconChannelsOff,
|
||||||
tr::lng_premium_summary_subtitle_no_ads(),
|
tr::lng_premium_summary_subtitle_no_ads(),
|
||||||
|
@ -126,7 +126,7 @@ using Order = std::vector<QString>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
QString("unique_reactions"),
|
u"unique_reactions"_q,
|
||||||
Entry{
|
Entry{
|
||||||
&st::settingsPremiumIconLike,
|
&st::settingsPremiumIconLike,
|
||||||
tr::lng_premium_summary_subtitle_unique_reactions(),
|
tr::lng_premium_summary_subtitle_unique_reactions(),
|
||||||
|
@ -134,7 +134,7 @@ using Order = std::vector<QString>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
QString("premium_stickers"),
|
u"premium_stickers"_q,
|
||||||
Entry{
|
Entry{
|
||||||
&st::settingsIconStickers,
|
&st::settingsIconStickers,
|
||||||
tr::lng_premium_summary_subtitle_premium_stickers(),
|
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{
|
Entry{
|
||||||
&st::settingsIconChat,
|
&st::settingsIconChat,
|
||||||
tr::lng_premium_summary_subtitle_advanced_chat_management(),
|
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{
|
Entry{
|
||||||
&st::settingsPremiumIconStar,
|
&st::settingsPremiumIconStar,
|
||||||
tr::lng_premium_summary_subtitle_profile_badge(),
|
tr::lng_premium_summary_subtitle_profile_badge(),
|
||||||
|
@ -158,7 +158,7 @@ using Order = std::vector<QString>;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
QString("animated_userpics"),
|
u"animated_userpics"_q,
|
||||||
Entry{
|
Entry{
|
||||||
&st::settingsPremiumIconPlay,
|
&st::settingsPremiumIconPlay,
|
||||||
tr::lng_premium_summary_subtitle_animated_userpics(),
|
tr::lng_premium_summary_subtitle_animated_userpics(),
|
||||||
|
|
Loading…
Add table
Reference in a new issue