mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Allow to load video components of photos.
This commit is contained in:
parent
1a9c241b96
commit
0126578dbd
9 changed files with 151 additions and 13 deletions
|
@ -166,8 +166,8 @@ public:
|
||||||
[[nodiscard]] bool videoThumbnailLoading() const;
|
[[nodiscard]] bool videoThumbnailLoading() const;
|
||||||
[[nodiscard]] bool videoThumbnailFailed() const;
|
[[nodiscard]] bool videoThumbnailFailed() const;
|
||||||
void loadVideoThumbnail(Data::FileOrigin origin);
|
void loadVideoThumbnail(Data::FileOrigin origin);
|
||||||
const ImageLocation &videoThumbnailLocation() const;
|
[[nodiscard]] const ImageLocation &videoThumbnailLocation() const;
|
||||||
int videoThumbnailByteSize() const;
|
[[nodiscard]] int videoThumbnailByteSize() const;
|
||||||
|
|
||||||
void updateThumbnails(
|
void updateThumbnails(
|
||||||
const QByteArray &inlineThumbnailBytes,
|
const QByteArray &inlineThumbnailBytes,
|
||||||
|
|
|
@ -39,6 +39,7 @@ PhotoData::~PhotoData() {
|
||||||
for (auto &image : _images) {
|
for (auto &image : _images) {
|
||||||
base::take(image.loader).reset();
|
base::take(image.loader).reset();
|
||||||
}
|
}
|
||||||
|
base::take(_video.loader).reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
Data::Session &PhotoData::owner() const {
|
Data::Session &PhotoData::owner() const {
|
||||||
|
@ -294,7 +295,8 @@ void PhotoData::updateImages(
|
||||||
const QByteArray &inlineThumbnailBytes,
|
const QByteArray &inlineThumbnailBytes,
|
||||||
const ImageWithLocation &small,
|
const ImageWithLocation &small,
|
||||||
const ImageWithLocation &thumbnail,
|
const ImageWithLocation &thumbnail,
|
||||||
const ImageWithLocation &large) {
|
const ImageWithLocation &large,
|
||||||
|
const ImageWithLocation &video) {
|
||||||
if (!inlineThumbnailBytes.isEmpty()
|
if (!inlineThumbnailBytes.isEmpty()
|
||||||
&& _inlineThumbnailBytes.isEmpty()) {
|
&& _inlineThumbnailBytes.isEmpty()) {
|
||||||
_inlineThumbnailBytes = inlineThumbnailBytes;
|
_inlineThumbnailBytes = inlineThumbnailBytes;
|
||||||
|
@ -315,6 +317,13 @@ void PhotoData::updateImages(
|
||||||
update(PhotoSize::Small, small);
|
update(PhotoSize::Small, small);
|
||||||
update(PhotoSize::Thumbnail, thumbnail);
|
update(PhotoSize::Thumbnail, thumbnail);
|
||||||
update(PhotoSize::Large, large);
|
update(PhotoSize::Large, large);
|
||||||
|
|
||||||
|
Data::UpdateCloudFile(
|
||||||
|
_video,
|
||||||
|
video,
|
||||||
|
owner().cache(),
|
||||||
|
Data::kAnimationCacheTag,
|
||||||
|
[&](Data::FileOrigin origin) { loadVideo(origin); });
|
||||||
}
|
}
|
||||||
|
|
||||||
int PhotoData::width() const {
|
int PhotoData::width() const {
|
||||||
|
@ -325,6 +334,50 @@ int PhotoData::height() const {
|
||||||
return _images[PhotoSizeIndex(PhotoSize::Large)].location.height();
|
return _images[PhotoSizeIndex(PhotoSize::Large)].location.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PhotoData::hasVideo() const {
|
||||||
|
return _video.location.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhotoData::videoLoading() const {
|
||||||
|
return _video.loader != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PhotoData::videoFailed() const {
|
||||||
|
return (_video.flags & Data::CloudFile::Flag::Failed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoData::loadVideo(Data::FileOrigin origin) {
|
||||||
|
const auto autoLoading = false;
|
||||||
|
const auto finalCheck = [=] {
|
||||||
|
if (const auto active = activeMediaView()) {
|
||||||
|
return active->videoContent().isEmpty();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
const auto done = [=](QByteArray result) {
|
||||||
|
if (const auto active = activeMediaView()) {
|
||||||
|
active->setVideo(std::move(result));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Data::LoadCloudFile(
|
||||||
|
&session(),
|
||||||
|
_video,
|
||||||
|
origin,
|
||||||
|
LoadFromCloudOrLocal,
|
||||||
|
autoLoading,
|
||||||
|
Data::kAnimationCacheTag,
|
||||||
|
finalCheck,
|
||||||
|
done);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ImageLocation &PhotoData::videoLocation() const {
|
||||||
|
return _video.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PhotoData::videoByteSize() const {
|
||||||
|
return _video.byteSize;
|
||||||
|
}
|
||||||
|
|
||||||
PhotoClickHandler::PhotoClickHandler(
|
PhotoClickHandler::PhotoClickHandler(
|
||||||
not_null<PhotoData*> photo,
|
not_null<PhotoData*> photo,
|
||||||
FullMsgId context,
|
FullMsgId context,
|
||||||
|
|
|
@ -82,7 +82,8 @@ public:
|
||||||
const QByteArray &inlineThumbnailBytes,
|
const QByteArray &inlineThumbnailBytes,
|
||||||
const ImageWithLocation &small,
|
const ImageWithLocation &small,
|
||||||
const ImageWithLocation &thumbnail,
|
const ImageWithLocation &thumbnail,
|
||||||
const ImageWithLocation &large);
|
const ImageWithLocation &large,
|
||||||
|
const ImageWithLocation &video);
|
||||||
[[nodiscard]] int validSizeIndex(Data::PhotoSize size) const;
|
[[nodiscard]] int validSizeIndex(Data::PhotoSize size) const;
|
||||||
|
|
||||||
[[nodiscard]] QByteArray inlineThumbnailBytes() const {
|
[[nodiscard]] QByteArray inlineThumbnailBytes() const {
|
||||||
|
@ -111,6 +112,13 @@ public:
|
||||||
[[nodiscard]] std::optional<QSize> size(Data::PhotoSize size) const;
|
[[nodiscard]] std::optional<QSize> size(Data::PhotoSize size) const;
|
||||||
[[nodiscard]] int imageByteSize(Data::PhotoSize size) const;
|
[[nodiscard]] int imageByteSize(Data::PhotoSize size) const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool hasVideo() const;
|
||||||
|
[[nodiscard]] bool videoLoading() const;
|
||||||
|
[[nodiscard]] bool videoFailed() const;
|
||||||
|
void loadVideo(Data::FileOrigin origin);
|
||||||
|
[[nodiscard]] const ImageLocation &videoLocation() const;
|
||||||
|
[[nodiscard]] int videoByteSize() const;
|
||||||
|
|
||||||
// For now they return size of the 'large' image.
|
// For now they return size of the 'large' image.
|
||||||
int width() const;
|
int width() const;
|
||||||
int height() const;
|
int height() const;
|
||||||
|
@ -127,6 +135,7 @@ public:
|
||||||
private:
|
private:
|
||||||
QByteArray _inlineThumbnailBytes;
|
QByteArray _inlineThumbnailBytes;
|
||||||
std::array<Data::CloudFile, Data::kPhotoSizeCount> _images;
|
std::array<Data::CloudFile, Data::kPhotoSizeCount> _images;
|
||||||
|
Data::CloudFile _video;
|
||||||
|
|
||||||
int32 _dc = 0;
|
int32 _dc = 0;
|
||||||
uint64 _access = 0;
|
uint64 _access = 0;
|
||||||
|
|
|
@ -85,6 +85,25 @@ void PhotoMedia::set(PhotoSize size, QImage image) {
|
||||||
_owner->session().notifyDownloaderTaskFinished();
|
_owner->session().notifyDownloaderTaskFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray PhotoMedia::videoContent() const {
|
||||||
|
return _videoBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize PhotoMedia::videoSize() const {
|
||||||
|
const auto &location = _owner->videoLocation();
|
||||||
|
return { location.width(), location.height() };
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoMedia::videoWanted(Data::FileOrigin origin) {
|
||||||
|
if (_videoBytes.isEmpty()) {
|
||||||
|
_owner->loadVideo(origin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PhotoMedia::setVideo(QByteArray content) {
|
||||||
|
_videoBytes = std::move(content);
|
||||||
|
}
|
||||||
|
|
||||||
bool PhotoMedia::loaded() const {
|
bool PhotoMedia::loaded() const {
|
||||||
const auto index = PhotoSizeIndex(PhotoSize::Large);
|
const auto index = PhotoSizeIndex(PhotoSize::Large);
|
||||||
return (_images[index] != nullptr);
|
return (_images[index] != nullptr);
|
||||||
|
|
|
@ -28,6 +28,11 @@ public:
|
||||||
void wanted(PhotoSize size, Data::FileOrigin origin);
|
void wanted(PhotoSize size, Data::FileOrigin origin);
|
||||||
void set(PhotoSize size, QImage image);
|
void set(PhotoSize size, QImage image);
|
||||||
|
|
||||||
|
[[nodiscard]] QByteArray videoContent() const;
|
||||||
|
[[nodiscard]] QSize videoSize() const;
|
||||||
|
void videoWanted(Data::FileOrigin origin);
|
||||||
|
void setVideo(QByteArray content);
|
||||||
|
|
||||||
[[nodiscard]] bool loaded() const;
|
[[nodiscard]] bool loaded() const;
|
||||||
[[nodiscard]] float64 progress() const;
|
[[nodiscard]] float64 progress() const;
|
||||||
|
|
||||||
|
@ -42,6 +47,7 @@ private:
|
||||||
const not_null<PhotoData*> _owner;
|
const not_null<PhotoData*> _owner;
|
||||||
mutable std::unique_ptr<Image> _inlineThumbnail;
|
mutable std::unique_ptr<Image> _inlineThumbnail;
|
||||||
std::array<std::unique_ptr<Image>, kPhotoSizeCount> _images;
|
std::array<std::unique_ptr<Image>, kPhotoSizeCount> _images;
|
||||||
|
QByteArray _videoBytes;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2157,7 +2157,8 @@ not_null<PhotoData*> Session::processPhoto(
|
||||||
QByteArray(),
|
QByteArray(),
|
||||||
small,
|
small,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
large);
|
large,
|
||||||
|
ImageWithLocation{});
|
||||||
}, [&](const MTPDphotoEmpty &data) {
|
}, [&](const MTPDphotoEmpty &data) {
|
||||||
return photo(data.vid().v);
|
return photo(data.vid().v);
|
||||||
});
|
});
|
||||||
|
@ -2173,7 +2174,8 @@ not_null<PhotoData*> Session::photo(
|
||||||
const QByteArray &inlineThumbnailBytes,
|
const QByteArray &inlineThumbnailBytes,
|
||||||
const ImageWithLocation &small,
|
const ImageWithLocation &small,
|
||||||
const ImageWithLocation &thumbnail,
|
const ImageWithLocation &thumbnail,
|
||||||
const ImageWithLocation &large) {
|
const ImageWithLocation &large,
|
||||||
|
const ImageWithLocation &video) {
|
||||||
const auto result = photo(id);
|
const auto result = photo(id);
|
||||||
photoApplyFields(
|
photoApplyFields(
|
||||||
result,
|
result,
|
||||||
|
@ -2185,7 +2187,8 @@ not_null<PhotoData*> Session::photo(
|
||||||
inlineThumbnailBytes,
|
inlineThumbnailBytes,
|
||||||
small,
|
small,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
large);
|
large,
|
||||||
|
video);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2233,7 +2236,8 @@ PhotoData *Session::photoFromWeb(
|
||||||
QByteArray(),
|
QByteArray(),
|
||||||
ImageWithLocation{},
|
ImageWithLocation{},
|
||||||
ImageWithLocation{ .location = thumbnailLocation },
|
ImageWithLocation{ .location = thumbnailLocation },
|
||||||
ImageWithLocation{ .location = large });
|
ImageWithLocation{ .location = large },
|
||||||
|
ImageWithLocation{});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Session::photoApplyFields(
|
void Session::photoApplyFields(
|
||||||
|
@ -2271,6 +2275,22 @@ void Session::photoApplyFields(
|
||||||
? ImageWithLocation()
|
? ImageWithLocation()
|
||||||
: Images::FromPhotoSize(_session, data, *i);
|
: Images::FromPhotoSize(_session, data, *i);
|
||||||
};
|
};
|
||||||
|
const auto video = [&] {
|
||||||
|
const auto sizes = data.vvideo_sizes();
|
||||||
|
if (!sizes || sizes->v.isEmpty()) {
|
||||||
|
return ImageWithLocation();
|
||||||
|
}
|
||||||
|
const auto area = [](const MTPVideoSize &size) {
|
||||||
|
return size.match([](const MTPDvideoSize &data) {
|
||||||
|
return data.vw().v * data.vh().v;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const auto max = ranges::max_element(
|
||||||
|
sizes->v,
|
||||||
|
std::greater<>(),
|
||||||
|
area);
|
||||||
|
return Images::FromVideoSize(_session, data, *max);
|
||||||
|
};
|
||||||
const auto large = image(LargeLevels);
|
const auto large = image(LargeLevels);
|
||||||
if (large.location.valid()) {
|
if (large.location.valid()) {
|
||||||
photoApplyFields(
|
photoApplyFields(
|
||||||
|
@ -2283,7 +2303,8 @@ void Session::photoApplyFields(
|
||||||
FindPhotoInlineThumbnail(data),
|
FindPhotoInlineThumbnail(data),
|
||||||
image(SmallLevels),
|
image(SmallLevels),
|
||||||
image(ThumbnailLevels),
|
image(ThumbnailLevels),
|
||||||
large);
|
large,
|
||||||
|
video());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2297,7 +2318,8 @@ void Session::photoApplyFields(
|
||||||
const QByteArray &inlineThumbnailBytes,
|
const QByteArray &inlineThumbnailBytes,
|
||||||
const ImageWithLocation &small,
|
const ImageWithLocation &small,
|
||||||
const ImageWithLocation &thumbnail,
|
const ImageWithLocation &thumbnail,
|
||||||
const ImageWithLocation &large) {
|
const ImageWithLocation &large,
|
||||||
|
const ImageWithLocation &video) {
|
||||||
if (!date) {
|
if (!date) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2308,7 +2330,8 @@ void Session::photoApplyFields(
|
||||||
inlineThumbnailBytes,
|
inlineThumbnailBytes,
|
||||||
small,
|
small,
|
||||||
thumbnail,
|
thumbnail,
|
||||||
large);
|
large,
|
||||||
|
video);
|
||||||
}
|
}
|
||||||
|
|
||||||
not_null<DocumentData*> Session::document(DocumentId id) {
|
not_null<DocumentData*> Session::document(DocumentId id) {
|
||||||
|
|
|
@ -403,7 +403,8 @@ public:
|
||||||
const QByteArray &inlineThumbnailBytes,
|
const QByteArray &inlineThumbnailBytes,
|
||||||
const ImageWithLocation &small,
|
const ImageWithLocation &small,
|
||||||
const ImageWithLocation &thumbnail,
|
const ImageWithLocation &thumbnail,
|
||||||
const ImageWithLocation &large);
|
const ImageWithLocation &large,
|
||||||
|
const ImageWithLocation &video);
|
||||||
void photoConvert(
|
void photoConvert(
|
||||||
not_null<PhotoData*> original,
|
not_null<PhotoData*> original,
|
||||||
const MTPPhoto &data);
|
const MTPPhoto &data);
|
||||||
|
@ -671,7 +672,8 @@ private:
|
||||||
const QByteArray &inlineThumbnailBytes,
|
const QByteArray &inlineThumbnailBytes,
|
||||||
const ImageWithLocation &small,
|
const ImageWithLocation &small,
|
||||||
const ImageWithLocation &thumbnail,
|
const ImageWithLocation &thumbnail,
|
||||||
const ImageWithLocation &large);
|
const ImageWithLocation &large,
|
||||||
|
const ImageWithLocation &video);
|
||||||
|
|
||||||
void documentApplyFields(
|
void documentApplyFields(
|
||||||
not_null<DocumentData*> document,
|
not_null<DocumentData*> document,
|
||||||
|
|
|
@ -268,4 +268,26 @@ ImageWithLocation FromVideoSize(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageWithLocation FromVideoSize(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const MTPDphoto &photo,
|
||||||
|
const MTPVideoSize &size) {
|
||||||
|
return size.match([&](const MTPDvideoSize &data) {
|
||||||
|
return ImageWithLocation{
|
||||||
|
.location = ImageLocation(
|
||||||
|
DownloadLocation{ StorageFileLocation(
|
||||||
|
photo.vdc_id().v,
|
||||||
|
session->userId(),
|
||||||
|
MTP_inputPhotoFileLocation(
|
||||||
|
photo.vid(),
|
||||||
|
photo.vaccess_hash(),
|
||||||
|
photo.vfile_reference(),
|
||||||
|
data.vtype())) },
|
||||||
|
data.vw().v,
|
||||||
|
data.vh().v),
|
||||||
|
.bytesCount = data.vsize().v
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Images
|
} // namespace Images
|
||||||
|
|
|
@ -31,6 +31,10 @@ namespace Images {
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPDdocument &document,
|
const MTPDdocument &document,
|
||||||
const MTPVideoSize &size);
|
const MTPVideoSize &size);
|
||||||
|
[[nodiscard]] ImageWithLocation FromVideoSize(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const MTPDphoto &photo,
|
||||||
|
const MTPVideoSize &size);
|
||||||
[[nodiscard]] ImageWithLocation FromImageInMemory(
|
[[nodiscard]] ImageWithLocation FromImageInMemory(
|
||||||
const QImage &image,
|
const QImage &image,
|
||||||
const char *format);
|
const char *format);
|
||||||
|
|
Loading…
Add table
Reference in a new issue