mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
Play premium sticker effects.
This commit is contained in:
parent
d87c9c72fb
commit
935fb79c52
15 changed files with 168 additions and 40 deletions
|
@ -254,6 +254,7 @@ void DocumentMedia::videoThumbnailWanted(Data::FileOrigin origin) {
|
||||||
|
|
||||||
void DocumentMedia::setVideoThumbnail(QByteArray content) {
|
void DocumentMedia::setVideoThumbnail(QByteArray content) {
|
||||||
_videoThumbnailBytes = std::move(content);
|
_videoThumbnailBytes = std::move(content);
|
||||||
|
_videoThumbnailBytes.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DocumentMedia::checkStickerLarge() {
|
void DocumentMedia::checkStickerLarge() {
|
||||||
|
|
|
@ -414,6 +414,7 @@ not_null<UserData*> Session::processUser(const MTPUser &data) {
|
||||||
| Flag::Scam
|
| Flag::Scam
|
||||||
| Flag::Fake
|
| Flag::Fake
|
||||||
| Flag::BotInlineGeo
|
| Flag::BotInlineGeo
|
||||||
|
| Flag::Premium
|
||||||
| Flag::Support
|
| Flag::Support
|
||||||
| (!minimal
|
| (!minimal
|
||||||
? Flag::Contact
|
? Flag::Contact
|
||||||
|
@ -2827,7 +2828,7 @@ void Session::documentApplyFields(
|
||||||
? Images::FromVideoSize(_session, data, *videoThumbnailSize)
|
? Images::FromVideoSize(_session, data, *videoThumbnailSize)
|
||||||
: ImageWithLocation();
|
: ImageWithLocation();
|
||||||
const auto isPremiumSticker = videoThumbnailSize
|
const auto isPremiumSticker = videoThumbnailSize
|
||||||
&& (videoThumbnailSize->c_videoSize().vtype().v == "fp");
|
&& (videoThumbnailSize->c_videoSize().vtype().v == "f");
|
||||||
documentApplyFields(
|
documentApplyFields(
|
||||||
document,
|
document,
|
||||||
data.vaccess_hash().v,
|
data.vaccess_hash().v,
|
||||||
|
|
|
@ -673,6 +673,9 @@ void InnerWidget::elementReplyTo(const FullMsgId &to) {
|
||||||
void InnerWidget::elementStartInteraction(not_null<const Element*> view) {
|
void InnerWidget::elementStartInteraction(not_null<const Element*> view) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InnerWidget::elementStartPremium(not_null<const Element*> view) {
|
||||||
|
}
|
||||||
|
|
||||||
void InnerWidget::elementShowSpoilerAnimation() {
|
void InnerWidget::elementShowSpoilerAnimation() {
|
||||||
_spoilerOpacity.stop();
|
_spoilerOpacity.stop();
|
||||||
_spoilerOpacity.start([=] { update(); }, 0., 1., st::fadeWrapDuration);
|
_spoilerOpacity.start([=] { update(); }, 0., 1., st::fadeWrapDuration);
|
||||||
|
|
|
@ -138,6 +138,8 @@ public:
|
||||||
void elementReplyTo(const FullMsgId &to) override;
|
void elementReplyTo(const FullMsgId &to) override;
|
||||||
void elementStartInteraction(
|
void elementStartInteraction(
|
||||||
not_null<const HistoryView::Element*> view) override;
|
not_null<const HistoryView::Element*> view) override;
|
||||||
|
void elementStartPremium(
|
||||||
|
not_null<const HistoryView::Element*> view) override;
|
||||||
void elementShowSpoilerAnimation() override;
|
void elementShowSpoilerAnimation() override;
|
||||||
|
|
||||||
~InnerWidget();
|
~InnerWidget();
|
||||||
|
|
|
@ -254,6 +254,11 @@ public:
|
||||||
_widget->elementStartInteraction(view);
|
_widget->elementStartInteraction(view);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void elementStartPremium(not_null<const Element*> view) override {
|
||||||
|
if (_widget) {
|
||||||
|
_widget->elementStartPremium(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
void elementShowSpoilerAnimation() override {
|
void elementShowSpoilerAnimation() override {
|
||||||
if (_widget) {
|
if (_widget) {
|
||||||
_widget->elementShowSpoilerAnimation();
|
_widget->elementShowSpoilerAnimation();
|
||||||
|
@ -3171,6 +3176,11 @@ void HistoryInner::elementStartInteraction(not_null<const Element*> view) {
|
||||||
_controller->emojiInteractions().startOutgoing(view);
|
_controller->emojiInteractions().startOutgoing(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HistoryInner::elementStartPremium(not_null<const Element*> view) {
|
||||||
|
_emojiInteractions->playPremiumEffect(view);
|
||||||
|
_animatedStickersPlayed.emplace(view->data());
|
||||||
|
}
|
||||||
|
|
||||||
void HistoryInner::elementShowSpoilerAnimation() {
|
void HistoryInner::elementShowSpoilerAnimation() {
|
||||||
_spoilerOpacity.stop();
|
_spoilerOpacity.stop();
|
||||||
_spoilerOpacity.start([=] { update(); }, 0., 1., st::fadeWrapDuration);
|
_spoilerOpacity.start([=] { update(); }, 0., 1., st::fadeWrapDuration);
|
||||||
|
|
|
@ -145,6 +145,7 @@ public:
|
||||||
not_null<Ui::PathShiftGradient*> elementPathShiftGradient();
|
not_null<Ui::PathShiftGradient*> elementPathShiftGradient();
|
||||||
void elementReplyTo(const FullMsgId &to);
|
void elementReplyTo(const FullMsgId &to);
|
||||||
void elementStartInteraction(not_null<const Element*> view);
|
void elementStartInteraction(not_null<const Element*> view);
|
||||||
|
void elementStartPremium(not_null<const Element*> view);
|
||||||
void elementShowSpoilerAnimation();
|
void elementShowSpoilerAnimation();
|
||||||
|
|
||||||
void updateBotInfo(bool recount = true);
|
void updateBotInfo(bool recount = true);
|
||||||
|
|
|
@ -205,6 +205,10 @@ void SimpleElementDelegate::elementStartInteraction(
|
||||||
not_null<const Element*> view) {
|
not_null<const Element*> view) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SimpleElementDelegate::elementStartPremium(
|
||||||
|
not_null<const Element*> view) {
|
||||||
|
}
|
||||||
|
|
||||||
void SimpleElementDelegate::elementShowSpoilerAnimation() {
|
void SimpleElementDelegate::elementShowSpoilerAnimation() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,7 @@ public:
|
||||||
virtual not_null<Ui::PathShiftGradient*> elementPathShiftGradient() = 0;
|
virtual not_null<Ui::PathShiftGradient*> elementPathShiftGradient() = 0;
|
||||||
virtual void elementReplyTo(const FullMsgId &to) = 0;
|
virtual void elementReplyTo(const FullMsgId &to) = 0;
|
||||||
virtual void elementStartInteraction(not_null<const Element*> view) = 0;
|
virtual void elementStartInteraction(not_null<const Element*> view) = 0;
|
||||||
|
virtual void elementStartPremium(not_null<const Element*> view) = 0;
|
||||||
virtual void elementShowSpoilerAnimation() = 0;
|
virtual void elementShowSpoilerAnimation() = 0;
|
||||||
|
|
||||||
virtual ~ElementDelegate() {
|
virtual ~ElementDelegate() {
|
||||||
|
@ -162,6 +163,7 @@ public:
|
||||||
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
|
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
|
||||||
void elementReplyTo(const FullMsgId &to) override;
|
void elementReplyTo(const FullMsgId &to) override;
|
||||||
void elementStartInteraction(not_null<const Element*> view) override;
|
void elementStartInteraction(not_null<const Element*> view) override;
|
||||||
|
void elementStartPremium(not_null<const Element*> view) override;
|
||||||
void elementShowSpoilerAnimation() override;
|
void elementShowSpoilerAnimation() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -24,8 +24,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace HistoryView {
|
namespace HistoryView {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kSizeMultiplier = 3;
|
constexpr auto kEmojiMultiplier = 3;
|
||||||
constexpr auto kCachesCount = 4;
|
constexpr auto kPremiumMultiplier = 2.25;
|
||||||
|
constexpr auto kEmojiCachesCount = 4;
|
||||||
|
constexpr auto kPremiumCachesCount = 8;
|
||||||
constexpr auto kMaxPlays = 5;
|
constexpr auto kMaxPlays = 5;
|
||||||
constexpr auto kMaxPlaysWithSmallDelay = 3;
|
constexpr auto kMaxPlaysWithSmallDelay = 3;
|
||||||
constexpr auto kSmallDelay = crl::time(200);
|
constexpr auto kSmallDelay = crl::time(200);
|
||||||
|
@ -55,6 +57,7 @@ EmojiInteractions::EmojiInteractions(not_null<Main::Session*> session)
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
|
|
||||||
_emojiSize = Sticker::EmojiSize();
|
_emojiSize = Sticker::EmojiSize();
|
||||||
|
_premiumSize = Sticker::Size();
|
||||||
}
|
}
|
||||||
|
|
||||||
EmojiInteractions::~EmojiInteractions() = default;
|
EmojiInteractions::~EmojiInteractions() = default;
|
||||||
|
@ -84,27 +87,63 @@ void EmojiInteractions::play(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmojiInteractions::playPremiumEffect(not_null<const Element*> view) {
|
||||||
|
if (const auto media = view->media()) {
|
||||||
|
if (const auto document = media->getDocument()) {
|
||||||
|
if (document->isPremiumSticker()) {
|
||||||
|
play(
|
||||||
|
QString(),
|
||||||
|
view,
|
||||||
|
document,
|
||||||
|
document->createMediaView()->videoThumbnailContent(),
|
||||||
|
QString(),
|
||||||
|
false,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void EmojiInteractions::play(
|
void EmojiInteractions::play(
|
||||||
QString emoticon,
|
QString emoticon,
|
||||||
not_null<Element*> view,
|
not_null<const Element*> view,
|
||||||
std::shared_ptr<Data::DocumentMedia> media,
|
std::shared_ptr<Data::DocumentMedia> media,
|
||||||
bool incoming) {
|
bool incoming) {
|
||||||
|
play(
|
||||||
|
std::move(emoticon),
|
||||||
|
view,
|
||||||
|
media->owner(),
|
||||||
|
media->bytes(),
|
||||||
|
media->owner()->filepath(),
|
||||||
|
incoming,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmojiInteractions::play(
|
||||||
|
QString emoticon,
|
||||||
|
not_null<const Element*> view,
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
QByteArray data,
|
||||||
|
QString filepath,
|
||||||
|
bool incoming,
|
||||||
|
bool premium) {
|
||||||
const auto top = view->block()->y() + view->y();
|
const auto top = view->block()->y() + view->y();
|
||||||
const auto bottom = top + view->height();
|
const auto bottom = top + view->height();
|
||||||
if (_visibleTop >= bottom
|
if (_visibleTop >= bottom
|
||||||
|| _visibleBottom <= top
|
|| _visibleBottom <= top
|
||||||
|| _visibleTop == _visibleBottom) {
|
|| _visibleTop == _visibleBottom
|
||||||
|
|| (data.isEmpty() && filepath.isEmpty())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lottie = preparePlayer(media.get());
|
auto lottie = preparePlayer(document, data, filepath, premium);
|
||||||
|
|
||||||
const auto shift = GenerateRandomShift(_emojiSize);
|
const auto shift = premium ? QPoint() : GenerateRandomShift(_emojiSize);
|
||||||
lottie->updates(
|
lottie->updates(
|
||||||
) | rpl::start_with_next([=](Lottie::Update update) {
|
) | rpl::start_with_next([=](Lottie::Update update) {
|
||||||
v::match(update.data, [&](const Lottie::Information &information) {
|
v::match(update.data, [&](const Lottie::Information &information) {
|
||||||
}, [&](const Lottie::DisplayFrameRequest &request) {
|
}, [&](const Lottie::DisplayFrameRequest &request) {
|
||||||
const auto rect = computeRect(view).translated(shift);
|
const auto rect = computeRect(view, premium).translated(shift);
|
||||||
if (rect.y() + rect.height() >= _visibleTop
|
if (rect.y() + rect.height() >= _visibleTop
|
||||||
&& rect.y() <= _visibleBottom) {
|
&& rect.y() <= _visibleBottom) {
|
||||||
_updateRequests.fire_copy(rect);
|
_updateRequests.fire_copy(rect);
|
||||||
|
@ -115,19 +154,30 @@ void EmojiInteractions::play(
|
||||||
.view = view,
|
.view = view,
|
||||||
.lottie = std::move(lottie),
|
.lottie = std::move(lottie),
|
||||||
.shift = shift,
|
.shift = shift,
|
||||||
|
.premium = premium,
|
||||||
});
|
});
|
||||||
if (incoming) {
|
if (incoming) {
|
||||||
_playStarted.fire(std::move(emoticon));
|
_playStarted.fire(std::move(emoticon));
|
||||||
}
|
}
|
||||||
if (const auto media = view->media()) {
|
if (const auto media = view->media()) {
|
||||||
media->stickerClearLoopPlayed();
|
if (!premium) {
|
||||||
|
media->stickerClearLoopPlayed();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize EmojiInteractions::sizeFor(bool premium) const {
|
||||||
|
return premium
|
||||||
|
? (_premiumSize * kPremiumMultiplier)
|
||||||
|
: (_emojiSize * kEmojiMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<Lottie::SinglePlayer> EmojiInteractions::preparePlayer(
|
std::unique_ptr<Lottie::SinglePlayer> EmojiInteractions::preparePlayer(
|
||||||
not_null<Data::DocumentMedia*> media) {
|
not_null<DocumentData*> document,
|
||||||
|
QByteArray data,
|
||||||
|
QString filepath,
|
||||||
|
bool premium) {
|
||||||
// Shortened copy from stickers_lottie module.
|
// Shortened copy from stickers_lottie module.
|
||||||
const auto document = media->owner();
|
|
||||||
const auto baseKey = document->bigFileBaseCacheKey();
|
const auto baseKey = document->bigFileBaseCacheKey();
|
||||||
const auto tag = uint8(0);
|
const auto tag = uint8(0);
|
||||||
const auto keyShift = ((tag << 4) & 0xF0)
|
const auto keyShift = ((tag << 4) & 0xF0)
|
||||||
|
@ -149,10 +199,8 @@ std::unique_ptr<Lottie::SinglePlayer> EmojiInteractions::preparePlayer(
|
||||||
std::move(data));
|
std::move(data));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const auto data = media->bytes();
|
|
||||||
const auto filepath = document->filepath();
|
|
||||||
const auto request = Lottie::FrameRequest{
|
const auto request = Lottie::FrameRequest{
|
||||||
_emojiSize * kSizeMultiplier * style::DevicePixelRatio(),
|
sizeFor(premium) * style::DevicePixelRatio(),
|
||||||
};
|
};
|
||||||
auto &weakProvider = _sharedProviders[document];
|
auto &weakProvider = _sharedProviders[document];
|
||||||
auto shared = [&] {
|
auto shared = [&] {
|
||||||
|
@ -160,7 +208,7 @@ std::unique_ptr<Lottie::SinglePlayer> EmojiInteractions::preparePlayer(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
const auto result = Lottie::SinglePlayer::SharedProvider(
|
const auto result = Lottie::SinglePlayer::SharedProvider(
|
||||||
kCachesCount,
|
premium ? kPremiumCachesCount : kEmojiCachesCount,
|
||||||
get,
|
get,
|
||||||
put,
|
put,
|
||||||
Lottie::ReadContent(data, filepath),
|
Lottie::ReadContent(data, filepath),
|
||||||
|
@ -179,19 +227,23 @@ void EmojiInteractions::visibleAreaUpdated(
|
||||||
_visibleBottom = visibleBottom;
|
_visibleBottom = visibleBottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect EmojiInteractions::computeRect(not_null<Element*> view) const {
|
QRect EmojiInteractions::computeRect(
|
||||||
|
not_null<const Element*> view,
|
||||||
|
bool premium) const {
|
||||||
const auto fullWidth = view->width();
|
const auto fullWidth = view->width();
|
||||||
const auto shift = (_emojiSize.width() * kSizeMultiplier) / 40;
|
const auto sticker = premium ? _premiumSize : _emojiSize;
|
||||||
|
const auto size = sizeFor(premium);
|
||||||
|
const auto shift = size.width() / 40;
|
||||||
const auto skip = (view->hasFromPhoto() ? st::msgPhotoSkip : 0)
|
const auto skip = (view->hasFromPhoto() ? st::msgPhotoSkip : 0)
|
||||||
+ st::msgMargin.left();
|
+ st::msgMargin.left();
|
||||||
const auto rightAligned = view->hasOutLayout()
|
const auto rightAligned = view->hasOutLayout()
|
||||||
&& !view->delegate()->elementIsChatWide();
|
&& !view->delegate()->elementIsChatWide();
|
||||||
const auto left = rightAligned
|
const auto left = rightAligned
|
||||||
? (fullWidth - skip + shift - _emojiSize.width() * kSizeMultiplier)
|
? (fullWidth - skip + shift - size.width())
|
||||||
: (skip - shift);
|
: (skip - shift);
|
||||||
const auto viewTop = view->block()->y() + view->y() + view->marginTop();
|
const auto viewTop = view->block()->y() + view->y() + view->marginTop();
|
||||||
const auto top = viewTop - _emojiSize.height();
|
const auto top = viewTop + (sticker.height() - size.height()) / 2;
|
||||||
return QRect(QPoint(left, top), _emojiSize * kSizeMultiplier);
|
return QRect(QPoint(left, top), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmojiInteractions::paint(QPainter &p) {
|
void EmojiInteractions::paint(QPainter &p) {
|
||||||
|
@ -201,7 +253,7 @@ void EmojiInteractions::paint(QPainter &p) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto request = Lottie::FrameRequest();
|
auto request = Lottie::FrameRequest();
|
||||||
request.box = _emojiSize * kSizeMultiplier * factor;
|
request.box = sizeFor(play.premium) * factor;
|
||||||
const auto rightAligned = play.view->hasOutLayout()
|
const auto rightAligned = play.view->hasOutLayout()
|
||||||
&& !play.view->delegate()->elementIsChatWide();
|
&& !play.view->delegate()->elementIsChatWide();
|
||||||
if (!rightAligned) {
|
if (!rightAligned) {
|
||||||
|
@ -217,7 +269,7 @@ void EmojiInteractions::paint(QPainter &p) {
|
||||||
if (play.frame + 1 == play.framesCount) {
|
if (play.frame + 1 == play.framesCount) {
|
||||||
play.finished = true;
|
play.finished = true;
|
||||||
}
|
}
|
||||||
const auto rect = computeRect(play.view);
|
const auto rect = computeRect(play.view, play.premium);
|
||||||
p.drawImage(
|
p.drawImage(
|
||||||
QRect(rect.topLeft() + play.shift, frame.image.size() / factor),
|
QRect(rect.topLeft() + play.shift, frame.image.size() / factor),
|
||||||
frame.image);
|
frame.image);
|
||||||
|
|
|
@ -36,6 +36,7 @@ public:
|
||||||
void play(
|
void play(
|
||||||
ChatHelpers::EmojiInteractionPlayRequest request,
|
ChatHelpers::EmojiInteractionPlayRequest request,
|
||||||
not_null<Element*> view);
|
not_null<Element*> view);
|
||||||
|
void playPremiumEffect(not_null<const Element*> view);
|
||||||
void visibleAreaUpdated(int visibleTop, int visibleBottom);
|
void visibleAreaUpdated(int visibleTop, int visibleBottom);
|
||||||
|
|
||||||
void paint(QPainter &p);
|
void paint(QPainter &p);
|
||||||
|
@ -44,39 +45,55 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Play {
|
struct Play {
|
||||||
not_null<Element*> view;
|
not_null<const Element*> view;
|
||||||
std::unique_ptr<Lottie::SinglePlayer> lottie;
|
std::unique_ptr<Lottie::SinglePlayer> lottie;
|
||||||
QPoint shift;
|
QPoint shift;
|
||||||
int frame = 0;
|
int frame = 0;
|
||||||
int framesCount = 0;
|
int framesCount = 0;
|
||||||
int frameRate = 0;
|
int frameRate = 0;
|
||||||
|
bool premium = false;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
};
|
};
|
||||||
struct Delayed {
|
struct Delayed {
|
||||||
QString emoticon;
|
QString emoticon;
|
||||||
not_null<Element*> view;
|
not_null<const Element*> view;
|
||||||
std::shared_ptr<Data::DocumentMedia> media;
|
std::shared_ptr<Data::DocumentMedia> media;
|
||||||
crl::time shouldHaveStartedAt = 0;
|
crl::time shouldHaveStartedAt = 0;
|
||||||
bool incoming = false;
|
bool incoming = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] QRect computeRect(not_null<Element*> view) const;
|
[[nodiscard]] QRect computeRect(
|
||||||
|
not_null<const Element*> view,
|
||||||
|
bool premium) const;
|
||||||
|
|
||||||
void play(
|
void play(
|
||||||
QString emoticon,
|
QString emoticon,
|
||||||
not_null<Element*> view,
|
not_null<const Element*> view,
|
||||||
std::shared_ptr<Data::DocumentMedia> media,
|
std::shared_ptr<Data::DocumentMedia> media,
|
||||||
bool incoming);
|
bool incoming);
|
||||||
|
void play(
|
||||||
|
QString emoticon,
|
||||||
|
not_null<const Element*> view,
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
QByteArray data,
|
||||||
|
QString filepath,
|
||||||
|
bool incoming,
|
||||||
|
bool premium);
|
||||||
void checkDelayed();
|
void checkDelayed();
|
||||||
|
|
||||||
|
[[nodiscard]] QSize sizeFor(bool premium) const;
|
||||||
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> preparePlayer(
|
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> preparePlayer(
|
||||||
not_null<Data::DocumentMedia*> media);
|
not_null<DocumentData*> document,
|
||||||
|
QByteArray data,
|
||||||
|
QString filepath,
|
||||||
|
bool premium);
|
||||||
|
|
||||||
const not_null<Main::Session*> _session;
|
const not_null<Main::Session*> _session;
|
||||||
|
|
||||||
int _visibleTop = 0;
|
int _visibleTop = 0;
|
||||||
int _visibleBottom = 0;
|
int _visibleBottom = 0;
|
||||||
QSize _emojiSize;
|
QSize _emojiSize;
|
||||||
|
QSize _premiumSize;
|
||||||
|
|
||||||
std::vector<Play> _plays;
|
std::vector<Play> _plays;
|
||||||
std::vector<Delayed> _delayed;
|
std::vector<Delayed> _delayed;
|
||||||
|
|
|
@ -1519,6 +1519,9 @@ void ListWidget::elementReplyTo(const FullMsgId &to) {
|
||||||
void ListWidget::elementStartInteraction(not_null<const Element*> view) {
|
void ListWidget::elementStartInteraction(not_null<const Element*> view) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ListWidget::elementStartPremium(not_null<const Element*> view) {
|
||||||
|
}
|
||||||
|
|
||||||
void ListWidget::elementShowSpoilerAnimation() {
|
void ListWidget::elementShowSpoilerAnimation() {
|
||||||
_spoilerOpacity.stop();
|
_spoilerOpacity.stop();
|
||||||
_spoilerOpacity.start([=] { update(); }, 0., 1., st::fadeWrapDuration);
|
_spoilerOpacity.start([=] { update(); }, 0., 1., st::fadeWrapDuration);
|
||||||
|
|
|
@ -292,6 +292,7 @@ public:
|
||||||
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
|
not_null<Ui::PathShiftGradient*> elementPathShiftGradient() override;
|
||||||
void elementReplyTo(const FullMsgId &to) override;
|
void elementReplyTo(const FullMsgId &to) override;
|
||||||
void elementStartInteraction(not_null<const Element*> view) override;
|
void elementStartInteraction(not_null<const Element*> view) override;
|
||||||
|
void elementStartPremium(not_null<const Element*> view) override;
|
||||||
void elementShowSpoilerAnimation() override;
|
void elementShowSpoilerAnimation() override;
|
||||||
|
|
||||||
void setEmptyInfoWidget(base::unique_qptr<Ui::RpWidget> &&w);
|
void setEmptyInfoWidget(base::unique_qptr<Ui::RpWidget> &&w);
|
||||||
|
|
|
@ -68,6 +68,9 @@ Sticker::Sticker(
|
||||||
dataMediaCreated();
|
dataMediaCreated();
|
||||||
} else {
|
} else {
|
||||||
_data->loadThumbnail(parent->data()->fullId());
|
_data->loadThumbnail(parent->data()->fullId());
|
||||||
|
if (_data->isPremiumSticker()) {
|
||||||
|
_data->loadVideoThumbnail(parent->data()->fullId());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (const auto media = replacing ? replacing->media() : nullptr) {
|
if (const auto media = replacing ? replacing->media() : nullptr) {
|
||||||
_lottie = media->stickerTakeLottie(_data, _replacements);
|
_lottie = media->stickerTakeLottie(_data, _replacements);
|
||||||
|
@ -123,7 +126,9 @@ bool Sticker::readyToDrawLottie() {
|
||||||
ensureDataMediaCreated();
|
ensureDataMediaCreated();
|
||||||
_dataMedia->checkStickerLarge();
|
_dataMedia->checkStickerLarge();
|
||||||
const auto loaded = _dataMedia->loaded();
|
const auto loaded = _dataMedia->loaded();
|
||||||
if (sticker->isLottie() && !_lottie && loaded) {
|
const auto waitingForPremium = _data->isPremiumSticker()
|
||||||
|
&& _dataMedia->videoThumbnailContent().isEmpty();
|
||||||
|
if (sticker->isLottie() && !_lottie && loaded && !waitingForPremium) {
|
||||||
setupLottie();
|
setupLottie();
|
||||||
}
|
}
|
||||||
return (_lottie && _lottie->ready());
|
return (_lottie && _lottie->ready());
|
||||||
|
@ -153,6 +158,19 @@ void Sticker::draw(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClickHandlerPtr Sticker::link() {
|
||||||
|
return _link;
|
||||||
|
}
|
||||||
|
|
||||||
|
DocumentData *Sticker::document() {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Sticker::stickerClearLoopPlayed() {
|
||||||
|
_lottieOncePlayed = false;
|
||||||
|
_premiumEffectPlayed = false;
|
||||||
|
}
|
||||||
|
|
||||||
void Sticker::paintLottie(
|
void Sticker::paintLottie(
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const PaintContext &context,
|
const PaintContext &context,
|
||||||
|
@ -162,6 +180,14 @@ void Sticker::paintLottie(
|
||||||
if (context.selected() && !_nextLastDiceFrame) {
|
if (context.selected() && !_nextLastDiceFrame) {
|
||||||
request.colored = context.st->msgStickerOverlay()->c;
|
request.colored = context.st->msgStickerOverlay()->c;
|
||||||
}
|
}
|
||||||
|
const auto premium = _data->isPremiumSticker();
|
||||||
|
if (premium) {
|
||||||
|
const auto rightAligned = _parent->hasOutLayout()
|
||||||
|
&& !_parent->delegate()->elementIsChatWide();
|
||||||
|
if (!rightAligned) {
|
||||||
|
request.mirrorHorizontal = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
const auto frame = _lottie
|
const auto frame = _lottie
|
||||||
? _lottie->frameInfo(request)
|
? _lottie->frameInfo(request)
|
||||||
: Lottie::Animation::FrameInfo();
|
: Lottie::Animation::FrameInfo();
|
||||||
|
@ -201,10 +227,10 @@ void Sticker::paintLottie(
|
||||||
_framesCount = count;
|
_framesCount = count;
|
||||||
_nextLastDiceFrame = !paused
|
_nextLastDiceFrame = !paused
|
||||||
&& (_diceIndex > 0)
|
&& (_diceIndex > 0)
|
||||||
&& (frame.index + 2 == count);
|
&& (_frameIndex + 2 == count);
|
||||||
const auto lastDiceFrame = (_diceIndex > 0) && atTheEnd();
|
const auto lastDiceFrame = (_diceIndex > 0) && atTheEnd();
|
||||||
const auto switchToNext = !playOnce
|
const auto switchToNext = !playOnce
|
||||||
|| (!lastDiceFrame && (frame.index != 0 || !_lottieOncePlayed));
|
|| (!lastDiceFrame && (_frameIndex != 0 || !_lottieOncePlayed));
|
||||||
if (!paused
|
if (!paused
|
||||||
&& switchToNext
|
&& switchToNext
|
||||||
&& _lottie->markFrameShown()
|
&& _lottie->markFrameShown()
|
||||||
|
@ -338,6 +364,9 @@ void Sticker::dataMediaCreated() const {
|
||||||
if (_dataMedia->thumbnailPath().isEmpty()) {
|
if (_dataMedia->thumbnailPath().isEmpty()) {
|
||||||
_dataMedia->thumbnailWanted(_parent->data()->fullId());
|
_dataMedia->thumbnailWanted(_parent->data()->fullId());
|
||||||
}
|
}
|
||||||
|
if (_data->isPremiumSticker()) {
|
||||||
|
_data->loadVideoThumbnail(_parent->data()->fullId());
|
||||||
|
}
|
||||||
_parent->history()->owner().registerHeavyViewPart(_parent);
|
_parent->history()->owner().registerHeavyViewPart(_parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -355,6 +384,11 @@ void Sticker::setupLottie() {
|
||||||
ChatHelpers::StickerLottieSize::MessageHistory,
|
ChatHelpers::StickerLottieSize::MessageHistory,
|
||||||
size() * cIntRetinaFactor(),
|
size() * cIntRetinaFactor(),
|
||||||
Lottie::Quality::High);
|
Lottie::Quality::High);
|
||||||
|
if (_data->isPremiumSticker()
|
||||||
|
&& !_premiumEffectPlayed) {
|
||||||
|
_premiumEffectPlayed = true;
|
||||||
|
_parent->delegate()->elementStartPremium(_parent);
|
||||||
|
}
|
||||||
lottieCreated();
|
lottieCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,16 +43,10 @@ public:
|
||||||
Painter &p,
|
Painter &p,
|
||||||
const PaintContext &context,
|
const PaintContext &context,
|
||||||
const QRect &r) override;
|
const QRect &r) override;
|
||||||
ClickHandlerPtr link() override {
|
ClickHandlerPtr link() override;
|
||||||
return _link;
|
|
||||||
}
|
|
||||||
|
|
||||||
DocumentData *document() override {
|
DocumentData *document() override;
|
||||||
return _data;
|
void stickerClearLoopPlayed() override;
|
||||||
}
|
|
||||||
void stickerClearLoopPlayed() override {
|
|
||||||
_lottieOncePlayed = false;
|
|
||||||
}
|
|
||||||
std::unique_ptr<Lottie::SinglePlayer> stickerTakeLottie(
|
std::unique_ptr<Lottie::SinglePlayer> stickerTakeLottie(
|
||||||
not_null<DocumentData*> data,
|
not_null<DocumentData*> data,
|
||||||
const Lottie::ColorReplacements *replacements) override;
|
const Lottie::ColorReplacements *replacements) override;
|
||||||
|
@ -111,6 +105,7 @@ private:
|
||||||
mutable int _frameIndex = -1;
|
mutable int _frameIndex = -1;
|
||||||
mutable int _framesCount = -1;
|
mutable int _framesCount = -1;
|
||||||
mutable bool _lottieOncePlayed = false;
|
mutable bool _lottieOncePlayed = false;
|
||||||
|
mutable bool _premiumEffectPlayed = false;
|
||||||
mutable bool _nextLastDiceFrame = false;
|
mutable bool _nextLastDiceFrame = false;
|
||||||
|
|
||||||
rpl::lifetime _lifetime;
|
rpl::lifetime _lifetime;
|
||||||
|
|
|
@ -45,7 +45,9 @@ void Document::writeToStream(QDataStream &stream, DocumentData *document) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stream << qint32(document->getDuration());
|
stream << qint32(document->getDuration());
|
||||||
stream << qint32(document->isPremiumSticker() ? 1 : 0);
|
if (document->type == StickerDocument) {
|
||||||
|
stream << qint32(document->isPremiumSticker() ? 1 : 0);
|
||||||
|
}
|
||||||
writeImageLocation(stream, document->thumbnailLocation());
|
writeImageLocation(stream, document->thumbnailLocation());
|
||||||
stream << qint32(document->thumbnailByteSize());
|
stream << qint32(document->thumbnailByteSize());
|
||||||
writeImageLocation(stream, document->videoThumbnailLocation());
|
writeImageLocation(stream, document->videoThumbnailLocation());
|
||||||
|
|
Loading…
Add table
Reference in a new issue