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