/* This file is part of Telegram Desktop, the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "data/data_document_good_thumbnail.h" #include "data/data_session.h" #include "data/data_document.h" #include "data/data_file_origin.h" #include "media/media_clip_reader.h" #include "auth_session.h" namespace Data { namespace { constexpr auto kGoodThumbQuality = 87; } // namespace GoodThumbSource::GoodThumbSource(not_null document) : _document(document) { } void GoodThumbSource::generate(base::binary_guard &&guard) { if (!guard.alive()) { return; } const auto data = _document->data(); auto location = _document->location().isEmpty() ? nullptr : std::make_unique(_document->location()); if (data.isEmpty() && !location) { _empty = true; return; } crl::async([ =, guard = std::move(guard), location = std::move(location) ]() mutable { const auto filepath = (location && location->accessEnable()) ? location->name() : QString(); auto result = Media::Clip::PrepareForSending(filepath, data); auto bytes = QByteArray(); if (!result.thumbnail.isNull()) { QBuffer buffer(&bytes); result.thumbnail.save(&buffer, "JPG", kGoodThumbQuality); } if (!filepath.isEmpty()) { location->accessDisable(); } const auto bytesSize = bytes.size(); ready( std::move(guard), std::move(result.thumbnail), bytesSize, std::move(bytes)); }); } // NB: This method is called from crl::async(), 'this' is unreliable. void GoodThumbSource::ready( base::binary_guard &&guard, QImage &&image, int bytesSize, QByteArray &&bytesForCache) { crl::on_main([ =, guard = std::move(guard), image = std::move(image), bytes = std::move(bytesForCache) ]() mutable { if (!guard.alive()) { return; } if (image.isNull()) { _empty = true; return; } _loaded = std::move(image); _width = _loaded.width(); _height = _loaded.height(); _bytesSize = bytesSize; if (!bytes.isEmpty()) { Auth().data().cache().put( _document->goodThumbnailCacheKey(), Storage::Cache::Database::TaggedValue{ std::move(bytes), Data::kImageCacheTag }); } Auth().downloaderTaskFinished().notify(); }); } void GoodThumbSource::load( Data::FileOrigin origin, bool loadFirst, bool prior) { if (loading() || _empty) { return; } auto [left, right] = base::make_binary_guard(); _loading = std::move(left); auto callback = [=, guard = std::move(right)]( QByteArray &&value) mutable { if (value.isEmpty()) { crl::on_main([=, guard = std::move(guard)]() mutable { generate(std::move(guard)); }); return; } crl::async([ =, guard = std::move(guard), value = std::move(value) ]() mutable { ready(std::move(guard), App::readImage(value), value.size()); }); }; Auth().data().cache().get( _document->goodThumbnailCacheKey(), std::move(callback)); } void GoodThumbSource::loadEvenCancelled( Data::FileOrigin origin, bool loadFirst, bool prior) { _empty = false; load(origin, loadFirst, prior); } QImage GoodThumbSource::takeLoaded() { return std::move(_loaded); } void GoodThumbSource::unload() { _loaded = QImage(); cancel(); } void GoodThumbSource::automaticLoad( Data::FileOrigin origin, const HistoryItem *item) { } void GoodThumbSource::automaticLoadSettingsChanged() { } bool GoodThumbSource::loading() { return _loading.alive(); } bool GoodThumbSource::displayLoading() { return false; } void GoodThumbSource::cancel() { _loading.kill(); } float64 GoodThumbSource::progress() { return 1.; } int GoodThumbSource::loadOffset() { return 0; } const StorageImageLocation &GoodThumbSource::location() { return StorageImageLocation::Null; } void GoodThumbSource::refreshFileReference(const QByteArray &data) { } std::optional GoodThumbSource::cacheKey() { return _document->goodThumbnailCacheKey(); } void GoodThumbSource::setDelayedStorageLocation( const StorageImageLocation &location) { } void GoodThumbSource::performDelayedLoad(Data::FileOrigin origin) { } bool GoodThumbSource::isDelayedStorageImage() const { return false; } void GoodThumbSource::setImageBytes(const QByteArray &bytes) { if (!bytes.isEmpty()) { cancel(); _loaded = App::readImage(bytes); _width = _loaded.width(); _height = _loaded.height(); _bytesSize = bytes.size(); } } int GoodThumbSource::width() { return _width; } int GoodThumbSource::height() { return _height; } int GoodThumbSource::bytesSize() { return _bytesSize; } void GoodThumbSource::setInformation(int size, int width, int height) { _width = width; _height = height; _bytesSize = size; } QByteArray GoodThumbSource::bytesForCache() { return QByteArray(); } } // namespace Data