mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Implement progressive jpeg loading and sending.
This commit is contained in:
parent
0888901d79
commit
437c9320cd
22 changed files with 201 additions and 96 deletions
|
@ -214,14 +214,14 @@ void LoadCloudFile(
|
||||||
Fn<void()> progress,
|
Fn<void()> progress,
|
||||||
int downloadFrontPartSize = 0) {
|
int downloadFrontPartSize = 0) {
|
||||||
const auto loadSize = downloadFrontPartSize
|
const auto loadSize = downloadFrontPartSize
|
||||||
? downloadFrontPartSize
|
? std::min(downloadFrontPartSize, file.byteSize)
|
||||||
: file.byteSize;
|
: file.byteSize;
|
||||||
if (file.loader) {
|
if (file.loader) {
|
||||||
if (fromCloud == LoadFromCloudOrLocal) {
|
if (fromCloud == LoadFromCloudOrLocal) {
|
||||||
file.loader->permitLoadFromCloud();
|
file.loader->permitLoadFromCloud();
|
||||||
}
|
}
|
||||||
if (file.loader->fullSize() < loadSize) {
|
if (file.loader->loadSize() < loadSize) {
|
||||||
file.loader->increaseLoadSize(loadSize);
|
file.loader->increaseLoadSize(loadSize, autoLoading);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
} else if ((file.flags & CloudFile::Flag::Failed)
|
} else if ((file.flags & CloudFile::Flag::Failed)
|
||||||
|
@ -236,6 +236,7 @@ void LoadCloudFile(
|
||||||
origin,
|
origin,
|
||||||
QString(),
|
QString(),
|
||||||
loadSize,
|
loadSize,
|
||||||
|
file.byteSize,
|
||||||
UnknownFileLocation,
|
UnknownFileLocation,
|
||||||
LoadToCacheAsWell,
|
LoadToCacheAsWell,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
|
|
|
@ -1013,6 +1013,7 @@ void DocumentData::save(
|
||||||
&session(),
|
&session(),
|
||||||
_urlLocation,
|
_urlLocation,
|
||||||
size,
|
size,
|
||||||
|
size,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
autoLoading,
|
autoLoading,
|
||||||
cacheTag());
|
cacheTag());
|
||||||
|
@ -1039,6 +1040,7 @@ void DocumentData::save(
|
||||||
locationType(),
|
locationType(),
|
||||||
toFile,
|
toFile,
|
||||||
size,
|
size,
|
||||||
|
size,
|
||||||
(saveToCache() ? LoadToCacheAsWell : LoadToFileOnly),
|
(saveToCache() ? LoadToCacheAsWell : LoadToFileOnly),
|
||||||
fromCloud,
|
fromCloud,
|
||||||
autoLoading,
|
autoLoading,
|
||||||
|
|
|
@ -104,7 +104,7 @@ bool PhotoData::loading(PhotoSize size) const {
|
||||||
} else if (valid == existing) {
|
} else if (valid == existing) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return (_images[valid].loader->fullSize()
|
return (_images[valid].loader->loadSize()
|
||||||
>= _images[existing].progressivePartSize);
|
>= _images[existing].progressivePartSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +113,10 @@ bool PhotoData::failed(PhotoSize size) const {
|
||||||
return (flags & Data::CloudFile::Flag::Failed);
|
return (flags & Data::CloudFile::Flag::Failed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhotoData::clearFailed(PhotoSize size) {
|
||||||
|
_images[validSizeIndex(size)].flags &= ~Data::CloudFile::Flag::Failed;
|
||||||
|
}
|
||||||
|
|
||||||
const ImageLocation &PhotoData::location(PhotoSize size) const {
|
const ImageLocation &PhotoData::location(PhotoSize size) const {
|
||||||
return _images[validSizeIndex(size)].location;
|
return _images[validSizeIndex(size)].location;
|
||||||
}
|
}
|
||||||
|
@ -144,10 +148,11 @@ int PhotoData::imageByteSize(PhotoSize size) const {
|
||||||
|
|
||||||
bool PhotoData::displayLoading() const {
|
bool PhotoData::displayLoading() const {
|
||||||
const auto index = PhotoSizeIndex(PhotoSize::Large);
|
const auto index = PhotoSizeIndex(PhotoSize::Large);
|
||||||
return _images[index].loader
|
if (const auto loader = _images[index].loader.get()) {
|
||||||
? (!_images[index].loader->loadingLocal()
|
return !loader->finished()
|
||||||
|| !_images[index].loader->autoLoading())
|
&& (!loader->loadingLocal() || !loader->autoLoading());
|
||||||
: (uploading() && !waitingForAlbum());
|
}
|
||||||
|
return (uploading() && !waitingForAlbum());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhotoData::cancel() {
|
void PhotoData::cancel() {
|
||||||
|
@ -262,7 +267,6 @@ void PhotoData::load(
|
||||||
|
|
||||||
// Could've changed, if the requested size didn't have a location.
|
// Could've changed, if the requested size didn't have a location.
|
||||||
const auto validSize = static_cast<PhotoSize>(valid);
|
const auto validSize = static_cast<PhotoSize>(valid);
|
||||||
const auto existingSize = static_cast<PhotoSize>(existing);
|
|
||||||
const auto finalCheck = [=] {
|
const auto finalCheck = [=] {
|
||||||
if (const auto active = activeMediaView()) {
|
if (const auto active = activeMediaView()) {
|
||||||
return !active->image(size);
|
return !active->image(size);
|
||||||
|
@ -270,10 +274,25 @@ void PhotoData::load(
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
const auto done = [=](QImage result) {
|
const auto done = [=](QImage result) {
|
||||||
if (const auto active = activeMediaView()) {
|
Expects(_images[valid].loader != nullptr);
|
||||||
active->set(validSize, existingSize, std::move(result));
|
|
||||||
|
// Find out what progressive photo size have we loaded exactly.
|
||||||
|
auto goodFor = validSize;
|
||||||
|
const auto loadSize = _images[valid].loader->loadSize();
|
||||||
|
if (valid > 0 && _images[valid].byteSize > loadSize) {
|
||||||
|
for (auto i = valid; i != 0;) {
|
||||||
|
--i;
|
||||||
|
const auto required = _images[i].progressivePartSize;
|
||||||
|
if (required > 0 && required <= loadSize) {
|
||||||
|
goodFor = static_cast<PhotoSize>(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (validSize == PhotoSize::Large) {
|
if (const auto active = activeMediaView()) {
|
||||||
|
active->set(validSize, goodFor, std::move(result));
|
||||||
|
}
|
||||||
|
if (validSize == PhotoSize::Large && goodFor == validSize) {
|
||||||
_owner->photoLoadDone(this);
|
_owner->photoLoadDone(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -453,6 +472,7 @@ void PhotoSaveClickHandler::onClickImpl() const {
|
||||||
if (!data->date) {
|
if (!data->date) {
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
data->clearFailed(PhotoSize::Large);
|
||||||
data->load(context());
|
data->load(context());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,6 +111,7 @@ public:
|
||||||
[[nodiscard]] bool hasExact(Data::PhotoSize size) const;
|
[[nodiscard]] bool hasExact(Data::PhotoSize size) const;
|
||||||
[[nodiscard]] bool loading(Data::PhotoSize size) const;
|
[[nodiscard]] bool loading(Data::PhotoSize size) const;
|
||||||
[[nodiscard]] bool failed(Data::PhotoSize size) const;
|
[[nodiscard]] bool failed(Data::PhotoSize size) const;
|
||||||
|
void clearFailed(Data::PhotoSize size);
|
||||||
void load(
|
void load(
|
||||||
Data::PhotoSize size,
|
Data::PhotoSize size,
|
||||||
Data::FileOrigin origin,
|
Data::FileOrigin origin,
|
||||||
|
|
|
@ -51,11 +51,15 @@ Image *PhotoMedia::thumbnailInline() const {
|
||||||
Image *PhotoMedia::image(PhotoSize size) const {
|
Image *PhotoMedia::image(PhotoSize size) const {
|
||||||
const auto &original = _images[PhotoSizeIndex(size)];
|
const auto &original = _images[PhotoSizeIndex(size)];
|
||||||
if (const auto image = original.data.get()) {
|
if (const auto image = original.data.get()) {
|
||||||
return (original.goodFor >= size) ? image : nullptr;
|
if (original.goodFor >= size) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const auto &valid = _images[_owner->validSizeIndex(size)];
|
const auto &valid = _images[_owner->validSizeIndex(size)];
|
||||||
if (const auto image = valid.data.get()) {
|
if (const auto image = valid.data.get()) {
|
||||||
return (valid.goodFor >= size) ? image : nullptr;
|
if (valid.goodFor >= size) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2147,7 +2147,10 @@ not_null<PhotoData*> Session::processPhoto(
|
||||||
const auto i = find(levels);
|
const auto i = find(levels);
|
||||||
return (i == thumbs.end())
|
return (i == thumbs.end())
|
||||||
? ImageWithLocation()
|
? ImageWithLocation()
|
||||||
: Images::FromImageInMemory(i->second, "JPG");
|
: Images::FromImageInMemory(
|
||||||
|
i->second.image,
|
||||||
|
"JPG",
|
||||||
|
i->second.bytes);
|
||||||
};
|
};
|
||||||
const auto small = image(SmallLevels);
|
const auto small = image(SmallLevels);
|
||||||
const auto thumbnail = image(ThumbnailLevels);
|
const auto thumbnail = image(ThumbnailLevels);
|
||||||
|
@ -2271,7 +2274,7 @@ void Session::photoApplyFields(
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const auto found = ranges::max_element(sizes, std::greater<>(), area);
|
const auto found = ranges::max_element(sizes, std::less<>(), area);
|
||||||
return (found == sizes.end()
|
return (found == sizes.end()
|
||||||
|| found->type() != mtpc_photoSizeProgressive)
|
|| found->type() != mtpc_photoSizeProgressive)
|
||||||
? sizes.end()
|
? sizes.end()
|
||||||
|
|
|
@ -287,7 +287,11 @@ using PollId = uint64;
|
||||||
using WallPaperId = uint64;
|
using WallPaperId = uint64;
|
||||||
constexpr auto CancelledWebPageId = WebPageId(0xFFFFFFFFFFFFFFFFULL);
|
constexpr auto CancelledWebPageId = WebPageId(0xFFFFFFFFFFFFFFFFULL);
|
||||||
|
|
||||||
using PreparedPhotoThumbs = base::flat_map<char, QImage>;
|
struct PreparedPhotoThumb {
|
||||||
|
QImage image;
|
||||||
|
QByteArray bytes;
|
||||||
|
};
|
||||||
|
using PreparedPhotoThumbs = base::flat_map<char, PreparedPhotoThumb>;
|
||||||
|
|
||||||
// [0] == -1 -- counting, [0] == -2 -- could not count
|
// [0] == -1 -- counting, [0] == -2 -- could not count
|
||||||
using VoiceWaveform = QVector<signed char>;
|
using VoiceWaveform = QVector<signed char>;
|
||||||
|
|
|
@ -2137,7 +2137,7 @@ void OverlayWidget::displayDocument(
|
||||||
_themeCloudData = cloud;
|
_themeCloudData = cloud;
|
||||||
_radial.stop();
|
_radial.stop();
|
||||||
|
|
||||||
_touchbarDisplay.fire(TouchBarItemType::None);
|
_touchbarDisplay.fire(TouchBarItemType::None);
|
||||||
|
|
||||||
refreshMediaViewer();
|
refreshMediaViewer();
|
||||||
if (_document) {
|
if (_document) {
|
||||||
|
@ -4161,6 +4161,9 @@ void OverlayWidget::setVisibleHook(bool visible) {
|
||||||
_userPhotosData = std::nullopt;
|
_userPhotosData = std::nullopt;
|
||||||
_collage = nullptr;
|
_collage = nullptr;
|
||||||
_collageData = std::nullopt;
|
_collageData = std::nullopt;
|
||||||
|
assignMediaPointer(nullptr);
|
||||||
|
_preloadPhotos.clear();
|
||||||
|
_preloadDocuments.clear();
|
||||||
if (_menu) _menu->hideMenu(true);
|
if (_menu) _menu->hideMenu(true);
|
||||||
_controlsHideTimer.stop();
|
_controlsHideTimer.stop();
|
||||||
_controlsState = ControlsShown;
|
_controlsState = ControlsShown;
|
||||||
|
|
|
@ -1751,6 +1751,7 @@ void FormController::loadFile(File &file) {
|
||||||
SecureFileLocation,
|
SecureFileLocation,
|
||||||
QString(),
|
QString(),
|
||||||
file.size,
|
file.size,
|
||||||
|
file.size,
|
||||||
LoadToCacheAsWell,
|
LoadToCacheAsWell,
|
||||||
LoadFromCloudOrLocal,
|
LoadFromCloudOrLocal,
|
||||||
false,
|
false,
|
||||||
|
|
|
@ -32,7 +32,8 @@ public:
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QByteArray &data,
|
const QByteArray &data,
|
||||||
const QString &toFile,
|
const QString &toFile,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LocationType locationType,
|
LocationType locationType,
|
||||||
LoadToCacheSetting toCache,
|
LoadToCacheSetting toCache,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
|
@ -53,7 +54,8 @@ FromMemoryLoader::FromMemoryLoader(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QByteArray &data,
|
const QByteArray &data,
|
||||||
const QString &toFile,
|
const QString &toFile,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LocationType locationType,
|
LocationType locationType,
|
||||||
LoadToCacheSetting toCache,
|
LoadToCacheSetting toCache,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
|
@ -62,7 +64,8 @@ FromMemoryLoader::FromMemoryLoader(
|
||||||
) : FileLoader(
|
) : FileLoader(
|
||||||
session,
|
session,
|
||||||
toFile,
|
toFile,
|
||||||
size,
|
loadSize,
|
||||||
|
fullSize,
|
||||||
locationType,
|
locationType,
|
||||||
toCache,
|
toCache,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
|
@ -91,7 +94,8 @@ void FromMemoryLoader::startLoading() {
|
||||||
FileLoader::FileLoader(
|
FileLoader::FileLoader(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QString &toFile,
|
const QString &toFile,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LocationType locationType,
|
LocationType locationType,
|
||||||
LoadToCacheSetting toCache,
|
LoadToCacheSetting toCache,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
|
@ -104,9 +108,11 @@ FileLoader::FileLoader(
|
||||||
, _file(_filename)
|
, _file(_filename)
|
||||||
, _toCache(toCache)
|
, _toCache(toCache)
|
||||||
, _fromCloud(fromCloud)
|
, _fromCloud(fromCloud)
|
||||||
, _size(size)
|
, _loadSize(loadSize)
|
||||||
|
, _fullSize(fullSize)
|
||||||
, _locationType(locationType) {
|
, _locationType(locationType) {
|
||||||
Expects(!_filename.isEmpty() || (_size <= Storage::kMaxFileInMemory));
|
Expects(_loadSize <= _fullSize);
|
||||||
|
Expects(!_filename.isEmpty() || (_fullSize <= Storage::kMaxFileInMemory));
|
||||||
}
|
}
|
||||||
|
|
||||||
FileLoader::~FileLoader() {
|
FileLoader::~FileLoader() {
|
||||||
|
@ -169,13 +175,11 @@ Data::FileOrigin FileLoader::fileOrigin() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
float64 FileLoader::currentProgress() const {
|
float64 FileLoader::currentProgress() const {
|
||||||
if (_finished) return 1.;
|
return _finished
|
||||||
if (!fullSize()) return 0.;
|
? 1.
|
||||||
return snap(float64(currentOffset()) / fullSize(), 0., 1.);
|
: !_loadSize
|
||||||
}
|
? 0.
|
||||||
|
: std::clamp(float64(currentOffset()) / _loadSize, 0., 1.);
|
||||||
int FileLoader::fullSize() const {
|
|
||||||
return _size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileLoader::setFileName(const QString &fileName) {
|
bool FileLoader::setFileName(const QString &fileName) {
|
||||||
|
@ -191,10 +195,12 @@ void FileLoader::permitLoadFromCloud() {
|
||||||
_fromCloud = LoadFromCloudOrLocal;
|
_fromCloud = LoadFromCloudOrLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLoader::increaseLoadSize(int size) {
|
void FileLoader::increaseLoadSize(int size, bool autoLoading) {
|
||||||
Expects(size > _size);
|
Expects(size > _loadSize);
|
||||||
|
Expects(size <= _fullSize);
|
||||||
|
|
||||||
_size = size;
|
_loadSize = size;
|
||||||
|
_autoLoading = autoLoading;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLoader::notifyAboutProgress() {
|
void FileLoader::notifyAboutProgress() {
|
||||||
|
@ -211,10 +217,12 @@ void FileLoader::localLoaded(
|
||||||
start();
|
start();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result.data.size() < _size) {
|
const auto partial = result.data.startsWith("partial:");
|
||||||
|
constexpr auto kPrefix = 8;
|
||||||
|
if (partial && result.data.size() < _loadSize + kPrefix) {
|
||||||
_localStatus = LocalStatus::NotFound;
|
_localStatus = LocalStatus::NotFound;
|
||||||
if (checkForOpen()) {
|
if (checkForOpen()) {
|
||||||
startLoadingWithData(result.data);
|
startLoadingWithPartial(result.data);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -222,7 +230,11 @@ void FileLoader::localLoaded(
|
||||||
_imageFormat = imageFormat;
|
_imageFormat = imageFormat;
|
||||||
_imageData = imageData;
|
_imageData = imageData;
|
||||||
}
|
}
|
||||||
finishWithBytes(result.data);
|
finishWithBytes(partial
|
||||||
|
? QByteArray::fromRawData(
|
||||||
|
result.data.data() + kPrefix,
|
||||||
|
result.data.size() - kPrefix)
|
||||||
|
: result.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileLoader::start() {
|
void FileLoader::start() {
|
||||||
|
@ -272,7 +284,7 @@ void FileLoader::loadLocal(const Storage::Cache::Key &key) {
|
||||||
};
|
};
|
||||||
_session->data().cache().get(key, [=, callback = std::move(done)](
|
_session->data().cache().get(key, [=, callback = std::move(done)](
|
||||||
QByteArray &&value) mutable {
|
QByteArray &&value) mutable {
|
||||||
if (readImage) {
|
if (readImage && !value.startsWith("partial:")) {
|
||||||
crl::async([
|
crl::async([
|
||||||
value = std::move(value),
|
value = std::move(value),
|
||||||
done = std::move(callback)
|
done = std::move(callback)
|
||||||
|
@ -452,7 +464,9 @@ bool FileLoader::finalizeResult() {
|
||||||
_session->data().cache().put(
|
_session->data().cache().put(
|
||||||
cacheKey(),
|
cacheKey(),
|
||||||
Storage::Cache::Database::TaggedValue(
|
Storage::Cache::Database::TaggedValue(
|
||||||
base::duplicate(_data),
|
base::duplicate((!_fullSize || _data.size() == _fullSize)
|
||||||
|
? _data
|
||||||
|
: ("partial:" + _data)),
|
||||||
_cacheTag));
|
_cacheTag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -466,7 +480,8 @@ std::unique_ptr<FileLoader> CreateFileLoader(
|
||||||
const DownloadLocation &location,
|
const DownloadLocation &location,
|
||||||
Data::FileOrigin origin,
|
Data::FileOrigin origin,
|
||||||
const QString &toFile,
|
const QString &toFile,
|
||||||
int size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LocationType locationType,
|
LocationType locationType,
|
||||||
LoadToCacheSetting toCache,
|
LoadToCacheSetting toCache,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
|
@ -480,7 +495,8 @@ std::unique_ptr<FileLoader> CreateFileLoader(
|
||||||
origin,
|
origin,
|
||||||
locationType,
|
locationType,
|
||||||
toFile,
|
toFile,
|
||||||
size,
|
loadSize,
|
||||||
|
fullSize,
|
||||||
toCache,
|
toCache,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
autoLoading,
|
autoLoading,
|
||||||
|
@ -489,7 +505,8 @@ std::unique_ptr<FileLoader> CreateFileLoader(
|
||||||
result = std::make_unique<mtpFileLoader>(
|
result = std::make_unique<mtpFileLoader>(
|
||||||
session,
|
session,
|
||||||
data,
|
data,
|
||||||
size,
|
loadSize,
|
||||||
|
fullSize,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
autoLoading,
|
autoLoading,
|
||||||
cacheTag);
|
cacheTag);
|
||||||
|
@ -497,7 +514,8 @@ std::unique_ptr<FileLoader> CreateFileLoader(
|
||||||
result = std::make_unique<mtpFileLoader>(
|
result = std::make_unique<mtpFileLoader>(
|
||||||
session,
|
session,
|
||||||
data,
|
data,
|
||||||
size,
|
loadSize,
|
||||||
|
fullSize,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
autoLoading,
|
autoLoading,
|
||||||
cacheTag);
|
cacheTag);
|
||||||
|
@ -514,7 +532,8 @@ std::unique_ptr<FileLoader> CreateFileLoader(
|
||||||
session,
|
session,
|
||||||
data.bytes,
|
data.bytes,
|
||||||
toFile,
|
toFile,
|
||||||
size,
|
loadSize,
|
||||||
|
fullSize,
|
||||||
locationType,
|
locationType,
|
||||||
toCache,
|
toCache,
|
||||||
LoadFromCloudOrLocal,
|
LoadFromCloudOrLocal,
|
||||||
|
|
|
@ -57,7 +57,8 @@ public:
|
||||||
FileLoader(
|
FileLoader(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const QString &toFile,
|
const QString &toFile,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LocationType locationType,
|
LocationType locationType,
|
||||||
LoadToCacheSetting toCache,
|
LoadToCacheSetting toCache,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
|
@ -88,11 +89,16 @@ public:
|
||||||
[[nodiscard]] virtual Data::FileOrigin fileOrigin() const;
|
[[nodiscard]] virtual Data::FileOrigin fileOrigin() const;
|
||||||
[[nodiscard]] float64 currentProgress() const;
|
[[nodiscard]] float64 currentProgress() const;
|
||||||
[[nodiscard]] virtual int currentOffset() const;
|
[[nodiscard]] virtual int currentOffset() const;
|
||||||
[[nodiscard]] int fullSize() const;
|
[[nodiscard]] int fullSize() const {
|
||||||
|
return _fullSize;
|
||||||
|
}
|
||||||
|
[[nodiscard]] int loadSize() const {
|
||||||
|
return _loadSize;
|
||||||
|
}
|
||||||
|
|
||||||
bool setFileName(const QString &filename); // set filename for loaders to cache
|
bool setFileName(const QString &filename); // set filename for loaders to cache
|
||||||
void permitLoadFromCloud();
|
void permitLoadFromCloud();
|
||||||
void increaseLoadSize(int size);
|
void increaseLoadSize(int size, bool autoLoading);
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void cancel();
|
void cancel();
|
||||||
|
@ -134,7 +140,7 @@ protected:
|
||||||
virtual std::optional<MediaKey> fileLocationKey() const = 0;
|
virtual std::optional<MediaKey> fileLocationKey() const = 0;
|
||||||
virtual void cancelHook() = 0;
|
virtual void cancelHook() = 0;
|
||||||
virtual void startLoading() = 0;
|
virtual void startLoading() = 0;
|
||||||
virtual void startLoadingWithData(const QByteArray &data) {
|
virtual void startLoadingWithPartial(const QByteArray &data) {
|
||||||
startLoading();
|
startLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +169,8 @@ protected:
|
||||||
|
|
||||||
QByteArray _data;
|
QByteArray _data;
|
||||||
|
|
||||||
int _size = 0;
|
int _loadSize = 0;
|
||||||
|
int _fullSize = 0;
|
||||||
int _skippedBytes = 0;
|
int _skippedBytes = 0;
|
||||||
LocationType _locationType = LocationType();
|
LocationType _locationType = LocationType();
|
||||||
|
|
||||||
|
@ -181,7 +188,8 @@ protected:
|
||||||
const DownloadLocation &location,
|
const DownloadLocation &location,
|
||||||
Data::FileOrigin origin,
|
Data::FileOrigin origin,
|
||||||
const QString &toFile,
|
const QString &toFile,
|
||||||
int size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LocationType locationType,
|
LocationType locationType,
|
||||||
LoadToCacheSetting toCache,
|
LoadToCacheSetting toCache,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
|
|
|
@ -23,7 +23,8 @@ mtpFileLoader::mtpFileLoader(
|
||||||
Data::FileOrigin origin,
|
Data::FileOrigin origin,
|
||||||
LocationType type,
|
LocationType type,
|
||||||
const QString &to,
|
const QString &to,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LoadToCacheSetting toCache,
|
LoadToCacheSetting toCache,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
bool autoLoading,
|
bool autoLoading,
|
||||||
|
@ -31,7 +32,8 @@ mtpFileLoader::mtpFileLoader(
|
||||||
: FileLoader(
|
: FileLoader(
|
||||||
session,
|
session,
|
||||||
to,
|
to,
|
||||||
size,
|
loadSize,
|
||||||
|
fullSize,
|
||||||
type,
|
type,
|
||||||
toCache,
|
toCache,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
|
@ -43,14 +45,16 @@ mtpFileLoader::mtpFileLoader(
|
||||||
mtpFileLoader::mtpFileLoader(
|
mtpFileLoader::mtpFileLoader(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const WebFileLocation &location,
|
const WebFileLocation &location,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
bool autoLoading,
|
bool autoLoading,
|
||||||
uint8 cacheTag)
|
uint8 cacheTag)
|
||||||
: FileLoader(
|
: FileLoader(
|
||||||
session,
|
session,
|
||||||
QString(),
|
QString(),
|
||||||
size,
|
loadSize,
|
||||||
|
fullSize,
|
||||||
UnknownFileLocation,
|
UnknownFileLocation,
|
||||||
LoadToCacheAsWell,
|
LoadToCacheAsWell,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
|
@ -65,14 +69,16 @@ mtpFileLoader::mtpFileLoader(
|
||||||
mtpFileLoader::mtpFileLoader(
|
mtpFileLoader::mtpFileLoader(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const GeoPointLocation &location,
|
const GeoPointLocation &location,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
bool autoLoading,
|
bool autoLoading,
|
||||||
uint8 cacheTag)
|
uint8 cacheTag)
|
||||||
: FileLoader(
|
: FileLoader(
|
||||||
session,
|
session,
|
||||||
QString(),
|
QString(),
|
||||||
size,
|
loadSize,
|
||||||
|
fullSize,
|
||||||
UnknownFileLocation,
|
UnknownFileLocation,
|
||||||
LoadToCacheAsWell,
|
LoadToCacheAsWell,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
|
@ -101,8 +107,8 @@ uint64 mtpFileLoader::objId() const {
|
||||||
bool mtpFileLoader::readyToRequest() const {
|
bool mtpFileLoader::readyToRequest() const {
|
||||||
return !_finished
|
return !_finished
|
||||||
&& !_lastComplete
|
&& !_lastComplete
|
||||||
&& (_size != 0 || !haveSentRequests())
|
&& (_fullSize != 0 || !haveSentRequests())
|
||||||
&& (!_size || _nextRequestOffset < _size);
|
&& (!_fullSize || _nextRequestOffset < _loadSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mtpFileLoader::takeNextRequestOffset() {
|
int mtpFileLoader::takeNextRequestOffset() {
|
||||||
|
@ -114,9 +120,7 @@ int mtpFileLoader::takeNextRequestOffset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mtpFileLoader::feedPart(int offset, const QByteArray &bytes) {
|
bool mtpFileLoader::feedPart(int offset, const QByteArray &bytes) {
|
||||||
const auto buffer = (_size > 0 && offset + bytes.size() > _size)
|
const auto buffer = bytes::make_span(bytes);
|
||||||
? bytes::make_span(bytes).subspan(0, _size - offset)
|
|
||||||
: bytes::make_span(bytes);
|
|
||||||
if (!writeResultPart(offset, buffer)) {
|
if (!writeResultPart(offset, buffer)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -124,7 +128,7 @@ bool mtpFileLoader::feedPart(int offset, const QByteArray &bytes) {
|
||||||
_lastComplete = true;
|
_lastComplete = true;
|
||||||
}
|
}
|
||||||
const auto finished = !haveSentRequests()
|
const auto finished = !haveSentRequests()
|
||||||
&& (_lastComplete || (_size && _nextRequestOffset >= _size));
|
&& (_lastComplete || (_fullSize && _nextRequestOffset >= _loadSize));
|
||||||
if (finished) {
|
if (finished) {
|
||||||
removeFromQueue();
|
removeFromQueue();
|
||||||
if (!finalizeResult()) {
|
if (!finalizeResult()) {
|
||||||
|
@ -141,13 +145,13 @@ void mtpFileLoader::cancelOnFail() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mtpFileLoader::setWebFileSizeHook(int size) {
|
bool mtpFileLoader::setWebFileSizeHook(int size) {
|
||||||
if (!_size || _size == size) {
|
if (!_fullSize || _fullSize == size) {
|
||||||
_size = size;
|
_fullSize = _loadSize = size;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
LOG(("MTP Error: "
|
LOG(("MTP Error: "
|
||||||
"Bad size provided by bot for webDocument: %1, real: %2"
|
"Bad size provided by bot for webDocument: %1, real: %2"
|
||||||
).arg(_size
|
).arg(_fullSize
|
||||||
).arg(size));
|
).arg(size));
|
||||||
cancel(true);
|
cancel(true);
|
||||||
return false;
|
return false;
|
||||||
|
@ -157,12 +161,15 @@ void mtpFileLoader::startLoading() {
|
||||||
addToQueue();
|
addToQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mtpFileLoader::startLoadingWithData(const QByteArray &data) {
|
void mtpFileLoader::startLoadingWithPartial(const QByteArray &data) {
|
||||||
const auto parts = data.size() / Storage::kDownloadPartSize;
|
Expects(data.startsWith("partial:"));
|
||||||
|
|
||||||
|
constexpr auto kPrefix = 8;
|
||||||
|
const auto parts = (data.size() - kPrefix) / Storage::kDownloadPartSize;
|
||||||
const auto use = parts * Storage::kDownloadPartSize;
|
const auto use = parts * Storage::kDownloadPartSize;
|
||||||
if (use > 0) {
|
if (use > 0) {
|
||||||
_nextRequestOffset = use;
|
_nextRequestOffset = use;
|
||||||
feedPart(0, QByteArray::fromRawData(data.data(), use));
|
feedPart(0, QByteArray::fromRawData(data.data() + kPrefix, use));
|
||||||
}
|
}
|
||||||
startLoading();
|
startLoading();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,8 @@ public:
|
||||||
Data::FileOrigin origin,
|
Data::FileOrigin origin,
|
||||||
LocationType type,
|
LocationType type,
|
||||||
const QString &toFile,
|
const QString &toFile,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LoadToCacheSetting toCache,
|
LoadToCacheSetting toCache,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
bool autoLoading,
|
bool autoLoading,
|
||||||
|
@ -28,14 +29,16 @@ public:
|
||||||
mtpFileLoader(
|
mtpFileLoader(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const WebFileLocation &location,
|
const WebFileLocation &location,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
bool autoLoading,
|
bool autoLoading,
|
||||||
uint8 cacheTag);
|
uint8 cacheTag);
|
||||||
mtpFileLoader(
|
mtpFileLoader(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const GeoPointLocation &location,
|
const GeoPointLocation &location,
|
||||||
int32 size,
|
int loadSize,
|
||||||
|
int fullSize,
|
||||||
LoadFromCloudSetting fromCloud,
|
LoadFromCloudSetting fromCloud,
|
||||||
bool autoLoading,
|
bool autoLoading,
|
||||||
uint8 cacheTag);
|
uint8 cacheTag);
|
||||||
|
@ -48,7 +51,7 @@ private:
|
||||||
Storage::Cache::Key cacheKey() const override;
|
Storage::Cache::Key cacheKey() const override;
|
||||||
std::optional<MediaKey> fileLocationKey() const override;
|
std::optional<MediaKey> fileLocationKey() const override;
|
||||||
void startLoading() override;
|
void startLoading() override;
|
||||||
void startLoadingWithData(const QByteArray &data) override;
|
void startLoadingWithPartial(const QByteArray &data) override;
|
||||||
void cancelHook() override;
|
void cancelHook() override;
|
||||||
|
|
||||||
bool readyToRequest() const override;
|
bool readyToRequest() const override;
|
||||||
|
|
|
@ -446,6 +446,7 @@ webFileLoader::webFileLoader(
|
||||||
session,
|
session,
|
||||||
QString(),
|
QString(),
|
||||||
0,
|
0,
|
||||||
|
0,
|
||||||
UnknownFileLocation,
|
UnknownFileLocation,
|
||||||
LoadToCacheAsWell,
|
LoadToCacheAsWell,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
|
@ -489,7 +490,7 @@ int webFileLoader::currentOffset() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void webFileLoader::loadProgress(qint64 ready, qint64 total) {
|
void webFileLoader::loadProgress(qint64 ready, qint64 total) {
|
||||||
_size = total;
|
_fullSize = _loadSize = total;
|
||||||
_ready = ready;
|
_ready = ready;
|
||||||
notifyAboutProgress();
|
notifyAboutProgress();
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,8 +311,9 @@ void Uploader::uploadMedia(
|
||||||
: session().data().processDocument(
|
: session().data().processDocument(
|
||||||
media.document,
|
media.document,
|
||||||
Images::FromImageInMemory(
|
Images::FromImageInMemory(
|
||||||
media.photoThumbs.front().second,
|
media.photoThumbs.front().second.image,
|
||||||
"JPG"));
|
"JPG",
|
||||||
|
media.photoThumbs.front().second.bytes));
|
||||||
if (!media.data.isEmpty()) {
|
if (!media.data.isEmpty()) {
|
||||||
document->setDataAndCache(media.data);
|
document->setDataAndCache(media.data);
|
||||||
if (media.type == SendMediaType::ThemeFile) {
|
if (media.type == SendMediaType::ThemeFile) {
|
||||||
|
@ -345,7 +346,8 @@ void Uploader::upload(
|
||||||
file->document,
|
file->document,
|
||||||
Images::FromImageInMemory(
|
Images::FromImageInMemory(
|
||||||
file->thumb,
|
file->thumb,
|
||||||
ThumbnailFormat(file->filemime)));
|
ThumbnailFormat(file->filemime),
|
||||||
|
file->thumbbytes));
|
||||||
document->uploadingData = std::make_unique<Data::UploadState>(
|
document->uploadingData = std::make_unique<Data::UploadState>(
|
||||||
document->size);
|
document->size);
|
||||||
if (const auto active = document->activeMediaView()) {
|
if (const auto active = document->activeMediaView()) {
|
||||||
|
|
|
@ -32,6 +32,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
|
||||||
#include <QtCore/QBuffer>
|
#include <QtCore/QBuffer>
|
||||||
|
#include <QtGui/QImageWriter>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -202,17 +203,23 @@ SendMediaReady PreparePeerPhoto(MTP::DcId dcId, PeerId peerId, QImage &&image) {
|
||||||
Qt::KeepAspectRatio,
|
Qt::KeepAspectRatio,
|
||||||
Qt::SmoothTransformation);
|
Qt::SmoothTransformation);
|
||||||
};
|
};
|
||||||
const auto push = [&](const char *type, QImage &&image) {
|
const auto push = [&](
|
||||||
|
const char *type,
|
||||||
|
QImage &&image,
|
||||||
|
QByteArray bytes = QByteArray()) {
|
||||||
photoSizes.push_back(MTP_photoSize(
|
photoSizes.push_back(MTP_photoSize(
|
||||||
MTP_string(type),
|
MTP_string(type),
|
||||||
MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)),
|
MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)),
|
||||||
MTP_int(image.width()),
|
MTP_int(image.width()),
|
||||||
MTP_int(image.height()), MTP_int(0)));
|
MTP_int(image.height()), MTP_int(0)));
|
||||||
photoThumbs.emplace(type[0], std::move(image));
|
photoThumbs.emplace(type[0], PreparedPhotoThumb{
|
||||||
|
.image = std::move(image),
|
||||||
|
.bytes = std::move(bytes)
|
||||||
|
});
|
||||||
};
|
};
|
||||||
push("a", scaled(160));
|
push("a", scaled(160));
|
||||||
push("b", scaled(320));
|
push("b", scaled(320));
|
||||||
push("c", std::move(image));
|
push("c", std::move(image), jpeg);
|
||||||
|
|
||||||
const auto id = rand_value<PhotoId>();
|
const auto id = rand_value<PhotoId>();
|
||||||
const auto photo = MTP_photo(
|
const auto photo = MTP_photo(
|
||||||
|
@ -467,6 +474,7 @@ void FileLoadResult::setFileData(const QByteArray &filedata) {
|
||||||
|
|
||||||
void FileLoadResult::setThumbData(const QByteArray &thumbdata) {
|
void FileLoadResult::setThumbData(const QByteArray &thumbdata) {
|
||||||
if (!thumbdata.isEmpty()) {
|
if (!thumbdata.isEmpty()) {
|
||||||
|
thumbbytes = thumbdata;
|
||||||
int32 size = thumbdata.size();
|
int32 size = thumbdata.size();
|
||||||
for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) {
|
for (int32 i = 0, part = 0; i < size; i += kPhotoUploadPartSize, ++part) {
|
||||||
thumbparts.insert(part, thumbdata.mid(i, kPhotoUploadPartSize));
|
thumbparts.insert(part, thumbdata.mid(i, kPhotoUploadPartSize));
|
||||||
|
@ -864,17 +872,22 @@ void FileLoadTask::process() {
|
||||||
attributes.push_back(MTP_documentAttributeAnimated());
|
attributes.push_back(MTP_documentAttributeAnimated());
|
||||||
} else if (_type != SendMediaType::File) {
|
} else if (_type != SendMediaType::File) {
|
||||||
auto medium = (w > 320 || h > 320) ? fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
|
auto medium = (w > 320 || h > 320) ? fullimage.scaled(320, 320, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
|
||||||
photoThumbs.emplace('m', medium);
|
|
||||||
photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
|
|
||||||
|
|
||||||
auto full = (w > 1280 || h > 1280) ? fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
|
auto full = (w > 1280 || h > 1280) ? fullimage.scaled(1280, 1280, Qt::KeepAspectRatio, Qt::SmoothTransformation) : fullimage;
|
||||||
photoThumbs.emplace('y', full);
|
|
||||||
photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
QBuffer buffer(&filedata);
|
QBuffer buffer(&filedata);
|
||||||
full.save(&buffer, "JPG", 87);
|
QImageWriter writer(&buffer, "JPEG");
|
||||||
|
writer.setQuality(87);
|
||||||
|
writer.setProgressiveScanWrite(true);
|
||||||
|
writer.write(full);
|
||||||
}
|
}
|
||||||
|
photoThumbs.emplace('m', PreparedPhotoThumb{ .image = medium });
|
||||||
|
photoSizes.push_back(MTP_photoSize(MTP_string("m"), MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)), MTP_int(medium.width()), MTP_int(medium.height()), MTP_int(0)));
|
||||||
|
|
||||||
|
photoThumbs.emplace('y', PreparedPhotoThumb{
|
||||||
|
.image = full,
|
||||||
|
.bytes = filedata
|
||||||
|
});
|
||||||
|
photoSizes.push_back(MTP_photoSize(MTP_string("y"), MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)), MTP_int(full.width()), MTP_int(full.height()), MTP_int(0)));
|
||||||
|
|
||||||
photo = MTP_photo(
|
photo = MTP_photo(
|
||||||
MTP_flags(0),
|
MTP_flags(0),
|
||||||
|
|
|
@ -219,6 +219,7 @@ struct FileLoadResult {
|
||||||
uint64 thumbId = 0; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos)
|
uint64 thumbId = 0; // id is always file-id of media, thumbId is file-id of thumb ( == id for photos)
|
||||||
QString thumbname;
|
QString thumbname;
|
||||||
UploadFileParts thumbparts;
|
UploadFileParts thumbparts;
|
||||||
|
QByteArray thumbbytes;
|
||||||
QByteArray thumbmd5;
|
QByteArray thumbmd5;
|
||||||
QImage thumb;
|
QImage thumb;
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ StreamedFileDownloader::StreamedFileDownloader(
|
||||||
session,
|
session,
|
||||||
toFile,
|
toFile,
|
||||||
size,
|
size,
|
||||||
|
size,
|
||||||
locationType,
|
locationType,
|
||||||
toCache,
|
toCache,
|
||||||
fromCloud,
|
fromCloud,
|
||||||
|
@ -107,7 +108,7 @@ void StreamedFileDownloader::requestPart() {
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray StreamedFileDownloader::readLoadedPart(int offset) {
|
QByteArray StreamedFileDownloader::readLoadedPart(int offset) {
|
||||||
Expects(offset >= 0 && offset < _size);
|
Expects(offset >= 0 && offset < _fullSize);
|
||||||
Expects(!(offset % kPartSize));
|
Expects(!(offset % kPartSize));
|
||||||
|
|
||||||
const auto index = (offset / kPartSize);
|
const auto index = (offset / kPartSize);
|
||||||
|
|
|
@ -270,13 +270,15 @@ ImageWithLocation FromPhotoSize(
|
||||||
|
|
||||||
ImageWithLocation FromImageInMemory(
|
ImageWithLocation FromImageInMemory(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
const char *format) {
|
const char *format,
|
||||||
|
QByteArray bytes) {
|
||||||
if (image.isNull()) {
|
if (image.isNull()) {
|
||||||
return ImageWithLocation();
|
return ImageWithLocation();
|
||||||
}
|
}
|
||||||
auto bytes = QByteArray();
|
if (bytes.isEmpty()) {
|
||||||
auto buffer = QBuffer(&bytes);
|
auto buffer = QBuffer(&bytes);
|
||||||
image.save(&buffer, format);
|
image.save(&buffer, format);
|
||||||
|
}
|
||||||
return ImageWithLocation{
|
return ImageWithLocation{
|
||||||
.location = ImageLocation(
|
.location = ImageLocation(
|
||||||
DownloadLocation{ InMemoryLocation{ bytes } },
|
DownloadLocation{ InMemoryLocation{ bytes } },
|
||||||
|
|
|
@ -41,7 +41,8 @@ namespace Images {
|
||||||
const MTPVideoSize &size);
|
const MTPVideoSize &size);
|
||||||
[[nodiscard]] ImageWithLocation FromImageInMemory(
|
[[nodiscard]] ImageWithLocation FromImageInMemory(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
const char *format);
|
const char *format,
|
||||||
|
QByteArray bytes = QByteArray());
|
||||||
[[nodiscard]] ImageLocation FromWebDocument(const MTPWebDocument &document);
|
[[nodiscard]] ImageLocation FromWebDocument(const MTPWebDocument &document);
|
||||||
|
|
||||||
} // namespace Images
|
} // namespace Images
|
||||||
|
|
|
@ -462,7 +462,9 @@ SendMediaReady PrepareWallPaper(MTP::DcId dcId, const QImage &image) {
|
||||||
MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)),
|
MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)),
|
||||||
MTP_int(image.width()),
|
MTP_int(image.width()),
|
||||||
MTP_int(image.height()), MTP_int(0)));
|
MTP_int(image.height()), MTP_int(0)));
|
||||||
thumbnails.emplace(type[0], std::move(image));
|
thumbnails.emplace(
|
||||||
|
type[0],
|
||||||
|
PreparedPhotoThumb{ .image = std::move(image) });
|
||||||
};
|
};
|
||||||
push("s", scaled(320));
|
push("s", scaled(320));
|
||||||
|
|
||||||
|
|
|
@ -426,15 +426,21 @@ SendMediaReady PrepareThemeMedia(
|
||||||
thumbnail.save(&buffer, "JPG", 87);
|
thumbnail.save(&buffer, "JPG", 87);
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto push = [&](const char *type, QImage &&image) {
|
const auto push = [&](
|
||||||
|
const char *type,
|
||||||
|
QImage &&image,
|
||||||
|
QByteArray bytes = QByteArray()) {
|
||||||
sizes.push_back(MTP_photoSize(
|
sizes.push_back(MTP_photoSize(
|
||||||
MTP_string(type),
|
MTP_string(type),
|
||||||
MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)),
|
MTP_fileLocationToBeDeprecated(MTP_long(0), MTP_int(0)),
|
||||||
MTP_int(image.width()),
|
MTP_int(image.width()),
|
||||||
MTP_int(image.height()), MTP_int(0)));
|
MTP_int(image.height()), MTP_int(0)));
|
||||||
thumbnails.emplace(type[0], std::move(image));
|
thumbnails.emplace(type[0], PreparedPhotoThumb{
|
||||||
|
.image = std::move(image),
|
||||||
|
.bytes = std::move(bytes)
|
||||||
|
});
|
||||||
};
|
};
|
||||||
push("s", std::move(thumbnail));
|
push("s", std::move(thumbnail), thumbnailBytes);
|
||||||
|
|
||||||
const auto filename = base::FileNameFromUserString(name)
|
const auto filename = base::FileNameFromUserString(name)
|
||||||
+ qsl(".tdesktop-theme");
|
+ qsl(".tdesktop-theme");
|
||||||
|
|
Loading…
Add table
Reference in a new issue