2018-10-25 08:12:56 +00:00
|
|
|
/*
|
|
|
|
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 "media/media_clip_reader.h"
|
|
|
|
#include "auth_session.h"
|
|
|
|
|
|
|
|
namespace Data {
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
constexpr auto kGoodThumbQuality = 87;
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
GoodThumbSource::GoodThumbSource(not_null<DocumentData*> 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<FileLocation>(_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();
|
|
|
|
}
|
2018-10-25 09:24:45 +00:00
|
|
|
const auto bytesSize = bytes.size();
|
2018-10-25 08:12:56 +00:00
|
|
|
ready(
|
|
|
|
std::move(guard),
|
|
|
|
std::move(result.thumbnail),
|
2018-10-25 09:24:45 +00:00
|
|
|
bytesSize,
|
2018-10-25 08:12:56 +00:00
|
|
|
std::move(bytes));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// NB: This method is called from crl::async(), 'this' is unreliable.
|
|
|
|
void GoodThumbSource::ready(
|
|
|
|
base::binary_guard &&guard,
|
|
|
|
QImage &&image,
|
2018-10-25 09:24:45 +00:00
|
|
|
int bytesSize,
|
|
|
|
QByteArray &&bytesForCache) {
|
2018-10-25 08:12:56 +00:00
|
|
|
crl::on_main([
|
|
|
|
=,
|
|
|
|
guard = std::move(guard),
|
|
|
|
image = std::move(image),
|
2018-10-25 09:24:45 +00:00
|
|
|
bytes = std::move(bytesForCache)
|
2018-10-25 08:12:56 +00:00
|
|
|
]() mutable {
|
|
|
|
if (!guard.alive()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (image.isNull()) {
|
|
|
|
_empty = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
_loaded = std::move(image);
|
|
|
|
_width = _loaded.width();
|
|
|
|
_height = _loaded.height();
|
2018-10-25 09:24:45 +00:00
|
|
|
_bytesSize = bytesSize;
|
2018-10-25 08:12:56 +00:00
|
|
|
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 {
|
2018-10-25 09:24:45 +00:00
|
|
|
ready(std::move(guard), App::readImage(value), value.size());
|
2018-10-25 08:12:56 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
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<Storage::Cache::Key> 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);
|
2018-10-25 09:24:45 +00:00
|
|
|
_width = _loaded.width();
|
|
|
|
_height = _loaded.height();
|
|
|
|
_bytesSize = bytes.size();
|
2018-10-25 08:12:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int GoodThumbSource::width() {
|
|
|
|
return _width;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GoodThumbSource::height() {
|
|
|
|
return _height;
|
|
|
|
}
|
|
|
|
|
2018-10-25 09:24:45 +00:00
|
|
|
int GoodThumbSource::bytesSize() {
|
|
|
|
return _bytesSize;
|
|
|
|
}
|
|
|
|
|
2018-10-25 08:12:56 +00:00
|
|
|
void GoodThumbSource::setInformation(int size, int width, int height) {
|
|
|
|
_width = width;
|
|
|
|
_height = height;
|
2018-10-25 09:24:45 +00:00
|
|
|
_bytesSize = size;
|
2018-10-25 08:12:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray GoodThumbSource::bytesForCache() {
|
|
|
|
return QByteArray();
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace Data
|