2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-30 22:16:14 +00:00

Implement animated stickerset thumbnails.

This commit is contained in:
John Preston
2019-07-02 13:46:37 +02:00
parent db2d24ff32
commit 3b645422ff
11 changed files with 381 additions and 63 deletions

View File

@@ -1093,6 +1093,36 @@ RecentStickerPack &GetRecentPack() {
return cRefRecentStickers();
}
template <typename Method>
auto LottieCachedFromContent(
Method &&method,
Storage::Cache::Key baseKey,
LottieSize sizeTag,
not_null<AuthSession*> session,
const QByteArray &content,
QSize box) {
const auto key = Storage::Cache::Key{
baseKey.high,
baseKey.low + int(sizeTag)
};
const auto get = [=](FnMut<void(QByteArray &&cached)> handler) {
session->data().cacheBigFile().get(
key,
std::move(handler));
};
const auto weak = base::make_weak(session.get());
const auto put = [=](QByteArray &&cached) {
crl::on_main(weak, [=, data = std::move(cached)]() mutable {
weak->data().cacheBigFile().put(key, std::move(data));
});
};
return method(
get,
put,
content,
Lottie::FrameRequest{ box });
}
template <typename Method>
auto LottieFromDocument(
Method &&method,
@@ -1108,26 +1138,13 @@ auto LottieFromDocument(
Lottie::FrameRequest{ box });
}
if (const auto baseKey = document->bigFileBaseCacheKey()) {
const auto key = Storage::Cache::Key{
baseKey->high,
baseKey->low + int(sizeTag)
};
const auto get = [=](FnMut<void(QByteArray &&cached)> handler) {
document->session().data().cacheBigFile().get(
key,
std::move(handler));
};
const auto weak = base::make_weak(&document->session());
const auto put = [=](QByteArray &&cached) {
crl::on_main(weak, [=, data = std::move(cached)]() mutable {
weak->data().cacheBigFile().put(key, std::move(data));
});
};
return method(
get,
put,
return LottieCachedFromContent(
std::forward<Method>(method),
*baseKey,
sizeTag,
&document->session(),
Lottie::ReadContent(data, filepath),
Lottie::FrameRequest{ box });
box);
}
return method(
Lottie::ReadContent(data, filepath),
@@ -1156,4 +1173,98 @@ not_null<Lottie::Animation*> LottieAnimationFromDocument(
return LottieFromDocument(method, document, sizeTag, box);
}
bool HasLottieThumbnail(
ImagePtr thumbnail,
not_null<DocumentData*> sticker) {
if (thumbnail) {
if (!thumbnail->loaded()) {
return false;
}
const auto &location = thumbnail->location();
const auto &bytes = thumbnail->bytesForCache();
return location.valid()
&& location.type() == StorageFileLocation::Type::StickerSetThumb
&& !bytes.isEmpty();
} else if (const auto info = sticker->sticker()) {
if (!info->animated) {
return false;
}
sticker->automaticLoad(sticker->stickerSetOrigin(), nullptr);
if (!sticker->loaded()) {
return false;
}
return sticker->bigFileBaseCacheKey().has_value();
}
return false;
}
std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
ImagePtr thumbnail,
not_null<DocumentData*> sticker,
LottieSize sizeTag,
QSize box,
std::shared_ptr<Lottie::FrameRenderer> renderer) {
const auto baseKey = thumbnail
? thumbnail->location().file().bigFileBaseCacheKey()
: sticker->bigFileBaseCacheKey();
if (!baseKey) {
return nullptr;
}
const auto content = (thumbnail
? thumbnail->bytesForCache()
: Lottie::ReadContent(sticker->data(), sticker->filepath()));
if (content.isEmpty()) {
return nullptr;
}
const auto method = [](auto &&...args) {
return std::make_unique<Lottie::SinglePlayer>(
std::forward<decltype(args)>(args)...);
};
return LottieCachedFromContent(
method,
*baseKey,
sizeTag,
&sticker->session(),
content,
box);
}
ThumbnailSource::ThumbnailSource(
const StorageImageLocation &location,
int size)
: StorageSource(location, size) {
}
QImage ThumbnailSource::takeLoaded() {
if (_bytesForAnimated.isEmpty()
&& _loader
&& _loader->finished()
&& !_loader->cancelled()) {
_bytesForAnimated = _loader->bytes();
}
auto result = StorageSource::takeLoaded();
if (!_bytesForAnimated.isEmpty()
&& !result.isNull()
&& result.size() != Image::Empty()->original().size()) {
_bytesForAnimated = QByteArray();
}
return result;
}
QByteArray ThumbnailSource::bytesForCache() {
return _bytesForAnimated;
}
std::unique_ptr<FileLoader> ThumbnailSource::createLoader(
Data::FileOrigin origin,
LoadFromCloudSetting fromCloud,
bool autoLoading) {
auto result = StorageSource::createLoader(
origin,
fromCloud,
autoLoading);
_loader = result.get();
return result;
}
} // namespace Stickers