mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Use lottie instead of webp in bottom info reactions.
This commit is contained in:
parent
82523978c9
commit
409a3357da
2 changed files with 49 additions and 28 deletions
|
@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_document.h"
|
#include "data/data_document.h"
|
||||||
#include "data/data_document_media.h"
|
#include "data/data_document_media.h"
|
||||||
#include "data/data_changes.h"
|
#include "data/data_changes.h"
|
||||||
|
#include "lottie/lottie_icon.h"
|
||||||
#include "base/timer_rpl.h"
|
#include "base/timer_rpl.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "styles/style_chat.h"
|
#include "styles/style_chat.h"
|
||||||
|
@ -25,6 +26,7 @@ namespace {
|
||||||
|
|
||||||
constexpr auto kRefreshFullListEach = 60 * 60 * crl::time(1000);
|
constexpr auto kRefreshFullListEach = 60 * 60 * crl::time(1000);
|
||||||
constexpr auto kPollEach = 20 * crl::time(1000);
|
constexpr auto kPollEach = 20 * crl::time(1000);
|
||||||
|
constexpr auto kSizeForDownscale = 128;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -49,6 +51,8 @@ Reactions::Reactions(not_null<Session*> owner)
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reactions::~Reactions() = default;
|
||||||
|
|
||||||
void Reactions::refresh() {
|
void Reactions::refresh() {
|
||||||
request();
|
request();
|
||||||
}
|
}
|
||||||
|
@ -82,7 +86,7 @@ void Reactions::preloadImageFor(const QString &emoji) {
|
||||||
auto &set = _images.emplace(emoji).first->second;
|
auto &set = _images.emplace(emoji).first->second;
|
||||||
const auto i = ranges::find(_available, emoji, &Reaction::emoji);
|
const auto i = ranges::find(_available, emoji, &Reaction::emoji);
|
||||||
const auto document = (i != end(_available))
|
const auto document = (i != end(_available))
|
||||||
? i->staticIcon.get()
|
? i->centerIcon.get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (document) {
|
if (document) {
|
||||||
loadImage(set, document);
|
loadImage(set, document);
|
||||||
|
@ -100,6 +104,20 @@ QImage Reactions::resolveImageFor(
|
||||||
preloadImageFor(emoji);
|
preloadImageFor(emoji);
|
||||||
}
|
}
|
||||||
auto &set = (i != end(_images)) ? i->second : _images[emoji];
|
auto &set = (i != end(_images)) ? i->second : _images[emoji];
|
||||||
|
const auto resolve = [&](QImage &image, int size) {
|
||||||
|
const auto factor = style::DevicePixelRatio();
|
||||||
|
image = set.icon->frame().scaled(
|
||||||
|
size * factor,
|
||||||
|
size * factor,
|
||||||
|
Qt::IgnoreAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
image.setDevicePixelRatio(factor);
|
||||||
|
};
|
||||||
|
if (set.bottomInfo.isNull() && set.icon) {
|
||||||
|
resolve(set.bottomInfo, st::reactionInfoSize);
|
||||||
|
resolve(set.inlineList, st::reactionBottomSize);
|
||||||
|
crl::async([icon = std::move(set.icon)]{});
|
||||||
|
}
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case ImageSize::BottomInfo: return set.bottomInfo;
|
case ImageSize::BottomInfo: return set.bottomInfo;
|
||||||
case ImageSize::InlineList: return set.inlineList;
|
case ImageSize::InlineList: return set.inlineList;
|
||||||
|
@ -109,12 +127,12 @@ QImage Reactions::resolveImageFor(
|
||||||
|
|
||||||
void Reactions::resolveImages() {
|
void Reactions::resolveImages() {
|
||||||
for (auto &[emoji, set] : _images) {
|
for (auto &[emoji, set] : _images) {
|
||||||
if (!set.bottomInfo.isNull() || set.media) {
|
if (!set.bottomInfo.isNull() || set.icon || set.media) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto i = ranges::find(_available, emoji, &Reaction::emoji);
|
const auto i = ranges::find(_available, emoji, &Reaction::emoji);
|
||||||
const auto document = (i != end(_available))
|
const auto document = (i != end(_available))
|
||||||
? i->staticIcon.get()
|
? i->centerIcon.get()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
if (document) {
|
if (document) {
|
||||||
loadImage(set, document);
|
loadImage(set, document);
|
||||||
|
@ -128,13 +146,14 @@ void Reactions::resolveImages() {
|
||||||
void Reactions::loadImage(
|
void Reactions::loadImage(
|
||||||
ImageSet &set,
|
ImageSet &set,
|
||||||
not_null<DocumentData*> document) {
|
not_null<DocumentData*> document) {
|
||||||
if (!set.bottomInfo.isNull()) {
|
if (!set.bottomInfo.isNull() || set.icon) {
|
||||||
return;
|
return;
|
||||||
} else if (!set.media) {
|
} else if (!set.media) {
|
||||||
set.media = document->createMediaView();
|
set.media = document->createMediaView();
|
||||||
|
set.media->checkStickerLarge();
|
||||||
}
|
}
|
||||||
if (const auto image = set.media->getStickerLarge()) {
|
if (set.media->loaded()) {
|
||||||
setImage(set, image->original());
|
setLottie(set);
|
||||||
} else if (!_imagesLoadLifetime) {
|
} else if (!_imagesLoadLifetime) {
|
||||||
document->session().downloaderTaskFinished(
|
document->session().downloaderTaskFinished(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
|
@ -143,20 +162,15 @@ void Reactions::loadImage(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reactions::setImage(ImageSet &set, QImage large) {
|
void Reactions::setLottie(ImageSet &set) {
|
||||||
|
const auto size = kSizeForDownscale / style::DevicePixelRatio();
|
||||||
|
set.icon = std::make_unique<Lottie::Icon>(Lottie::IconDescriptor{
|
||||||
|
.path = set.media->owner()->filepath(true),
|
||||||
|
.json = set.media->bytes(),
|
||||||
|
.sizeOverride = QSize(size, size),
|
||||||
|
.frame = -1,
|
||||||
|
});
|
||||||
set.media = nullptr;
|
set.media = nullptr;
|
||||||
const auto scale = [&](int size) {
|
|
||||||
const auto factor = style::DevicePixelRatio();
|
|
||||||
return Images::prepare(
|
|
||||||
large,
|
|
||||||
size * factor,
|
|
||||||
size * factor,
|
|
||||||
Images::Option::Smooth,
|
|
||||||
size,
|
|
||||||
size);
|
|
||||||
};
|
|
||||||
set.bottomInfo = scale(st::reactionInfoSize);
|
|
||||||
set.inlineList = scale(st::reactionBottomSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reactions::downloadTaskFinished() {
|
void Reactions::downloadTaskFinished() {
|
||||||
|
@ -164,8 +178,8 @@ void Reactions::downloadTaskFinished() {
|
||||||
for (auto &[emoji, set] : _images) {
|
for (auto &[emoji, set] : _images) {
|
||||||
if (!set.media) {
|
if (!set.media) {
|
||||||
continue;
|
continue;
|
||||||
} else if (const auto image = set.media->getStickerLarge()) {
|
} else if (set.media->loaded()) {
|
||||||
setImage(set, image->original());
|
setLottie(set);
|
||||||
} else {
|
} else {
|
||||||
hasOne = true;
|
hasOne = true;
|
||||||
}
|
}
|
||||||
|
@ -249,6 +263,8 @@ std::optional<Reaction> Reactions::parse(const MTPAvailableReaction &entry) {
|
||||||
if (!known) {
|
if (!known) {
|
||||||
LOG(("API Error: Unknown emoji in reactions: %1").arg(emoji));
|
LOG(("API Error: Unknown emoji in reactions: %1").arg(emoji));
|
||||||
}
|
}
|
||||||
|
const auto selectAnimation = _owner->processDocument(
|
||||||
|
data.vselect_animation());
|
||||||
return known
|
return known
|
||||||
? std::make_optional(Reaction{
|
? std::make_optional(Reaction{
|
||||||
.emoji = emoji,
|
.emoji = emoji,
|
||||||
|
@ -256,19 +272,18 @@ std::optional<Reaction> Reactions::parse(const MTPAvailableReaction &entry) {
|
||||||
.staticIcon = _owner->processDocument(data.vstatic_icon()),
|
.staticIcon = _owner->processDocument(data.vstatic_icon()),
|
||||||
.appearAnimation = _owner->processDocument(
|
.appearAnimation = _owner->processDocument(
|
||||||
data.vappear_animation()),
|
data.vappear_animation()),
|
||||||
.selectAnimation = _owner->processDocument(
|
.selectAnimation = selectAnimation,
|
||||||
data.vselect_animation()),
|
|
||||||
.activateAnimation = _owner->processDocument(
|
.activateAnimation = _owner->processDocument(
|
||||||
data.vactivate_animation()),
|
data.vactivate_animation()),
|
||||||
.activateEffects = _owner->processDocument(
|
.activateEffects = _owner->processDocument(
|
||||||
data.veffect_animation()),
|
data.veffect_animation()),
|
||||||
|
.centerIcon = (data.vcenter_icon()
|
||||||
|
? _owner->processDocument(*data.vcenter_icon())
|
||||||
|
: selectAnimation),
|
||||||
.aroundAnimation = (data.varound_animation()
|
.aroundAnimation = (data.varound_animation()
|
||||||
? _owner->processDocument(
|
? _owner->processDocument(
|
||||||
*data.varound_animation()).get()
|
*data.varound_animation()).get()
|
||||||
: nullptr),
|
: nullptr),
|
||||||
.centerIcon = (data.vcenter_icon()
|
|
||||||
? _owner->processDocument(*data.vcenter_icon()).get()
|
|
||||||
: nullptr),
|
|
||||||
.active = !data.is_inactive(),
|
.active = !data.is_inactive(),
|
||||||
})
|
})
|
||||||
: std::nullopt;
|
: std::nullopt;
|
||||||
|
|
|
@ -9,6 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
|
|
||||||
|
namespace Lottie {
|
||||||
|
class Icon;
|
||||||
|
} // namespace Lottie
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
class DocumentMedia;
|
class DocumentMedia;
|
||||||
|
@ -22,14 +26,15 @@ struct Reaction {
|
||||||
not_null<DocumentData*> selectAnimation;
|
not_null<DocumentData*> selectAnimation;
|
||||||
not_null<DocumentData*> activateAnimation;
|
not_null<DocumentData*> activateAnimation;
|
||||||
not_null<DocumentData*> activateEffects;
|
not_null<DocumentData*> activateEffects;
|
||||||
|
not_null<DocumentData*> centerIcon;
|
||||||
DocumentData *aroundAnimation = nullptr;
|
DocumentData *aroundAnimation = nullptr;
|
||||||
DocumentData *centerIcon = nullptr;
|
|
||||||
bool active = false;
|
bool active = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Reactions final {
|
class Reactions final {
|
||||||
public:
|
public:
|
||||||
explicit Reactions(not_null<Session*> owner);
|
explicit Reactions(not_null<Session*> owner);
|
||||||
|
~Reactions();
|
||||||
|
|
||||||
void refresh();
|
void refresh();
|
||||||
|
|
||||||
|
@ -72,6 +77,7 @@ private:
|
||||||
QImage bottomInfo;
|
QImage bottomInfo;
|
||||||
QImage inlineList;
|
QImage inlineList;
|
||||||
std::shared_ptr<DocumentMedia> media;
|
std::shared_ptr<DocumentMedia> media;
|
||||||
|
std::unique_ptr<Lottie::Icon> icon;
|
||||||
};
|
};
|
||||||
|
|
||||||
void request();
|
void request();
|
||||||
|
@ -80,7 +86,7 @@ private:
|
||||||
const MTPAvailableReaction &entry);
|
const MTPAvailableReaction &entry);
|
||||||
|
|
||||||
void loadImage(ImageSet &set, not_null<DocumentData*> document);
|
void loadImage(ImageSet &set, not_null<DocumentData*> document);
|
||||||
void setImage(ImageSet &set, QImage large);
|
void setLottie(ImageSet &set);
|
||||||
void resolveImages();
|
void resolveImages();
|
||||||
void downloadTaskFinished();
|
void downloadTaskFinished();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue