mirror of https://github.com/procxx/kepka.git
Start using document bytes from DocumentMedia.
This commit is contained in:
parent
888e42df34
commit
33f4946242
|
@ -11,23 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/rect_part.h"
|
||||
|
||||
enum class ImageRoundRadius;
|
||||
class MainWindow;
|
||||
class MainWidget;
|
||||
class HistoryItem;
|
||||
class History;
|
||||
|
||||
namespace HistoryView {
|
||||
class Element;
|
||||
} // namespace HistoryView
|
||||
|
||||
namespace Media {
|
||||
namespace Clip {
|
||||
class Reader;
|
||||
} // namespace Clip
|
||||
} // namespace Media
|
||||
|
||||
using HistoryItemsMap = base::flat_set<not_null<HistoryItem*>>;
|
||||
using GifItems = QHash<Media::Clip::Reader*, HistoryItem*>;
|
||||
|
||||
enum RoundCorners : int {
|
||||
SmallMaskCorners = 0x00, // for images
|
||||
LargeMaskCorners,
|
||||
|
|
|
@ -315,9 +315,10 @@ void EditCaptionBox::prepareGifPreview(DocumentData* document) {
|
|||
const auto callback = [=](Media::Clip::Notification notification) {
|
||||
clipCallback(notification);
|
||||
};
|
||||
_gifMedia = document ? document->createMediaView() : nullptr;
|
||||
if (document && document->isAnimation() && document->loaded()) {
|
||||
_gifPreview = Media::Clip::MakeReader(
|
||||
document,
|
||||
_gifMedia.get(),
|
||||
_msgId,
|
||||
callback);
|
||||
} else if (!isListEmpty) {
|
||||
|
|
|
@ -23,6 +23,7 @@ class SessionController;
|
|||
|
||||
namespace Data {
|
||||
class Media;
|
||||
class DocumentMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Ui {
|
||||
|
@ -94,6 +95,7 @@ private:
|
|||
bool _doc = false;
|
||||
|
||||
QPixmap _thumb;
|
||||
std::shared_ptr<Data::DocumentMedia> _gifMedia;
|
||||
Media::Clip::ReaderPointer _gifPreview;
|
||||
|
||||
object_ptr<Ui::InputField> _field = { nullptr };
|
||||
|
|
|
@ -604,7 +604,7 @@ void StickerSetBox::Inner::setupLottie(int index) {
|
|||
|
||||
element.animated = Stickers::LottieAnimationFromDocument(
|
||||
getLottiePlayer(),
|
||||
document,
|
||||
element.documentMedia.get(),
|
||||
Stickers::LottieSize::StickerSet,
|
||||
boundingBoxSize() * cIntRetinaFactor());
|
||||
}
|
||||
|
|
|
@ -642,6 +642,7 @@ StickersBox::Inner::Row::Row(
|
|||
, accessHash(accessHash)
|
||||
, thumbnail(thumbnail)
|
||||
, sticker(sticker)
|
||||
, stickerMedia(sticker ? sticker->createMediaView() : nullptr)
|
||||
, count(count)
|
||||
, title(title)
|
||||
, titleWidth(titleWidth)
|
||||
|
@ -947,7 +948,7 @@ void StickersBox::Inner::validateLottieAnimation(not_null<Row*> set) {
|
|||
}
|
||||
auto player = Stickers::LottieThumbnail(
|
||||
set->thumbnail,
|
||||
set->sticker,
|
||||
set->stickerMedia.get(),
|
||||
Stickers::LottieSize::SetsListThumbnail,
|
||||
QSize(
|
||||
st::contactsPhotoSize,
|
||||
|
@ -1645,6 +1646,7 @@ void StickersBox::Inner::updateRows() {
|
|||
}
|
||||
row->thumbnail = thumbnail;
|
||||
row->sticker = sticker;
|
||||
row->stickerMedia = sticker->createMediaView();
|
||||
row->pixw = pixw;
|
||||
row->pixh = pixh;
|
||||
}
|
||||
|
|
|
@ -233,15 +233,17 @@ private:
|
|||
bool removed,
|
||||
int32 pixw,
|
||||
int32 pixh);
|
||||
~Row();
|
||||
|
||||
bool isRecentSet() const {
|
||||
return (id == Stickers::CloudRecentSetId);
|
||||
}
|
||||
~Row();
|
||||
|
||||
uint64 id = 0;
|
||||
uint64 accessHash = 0;
|
||||
ImagePtr thumbnail;
|
||||
DocumentData *sticker = nullptr;
|
||||
std::shared_ptr<Data::DocumentMedia> stickerMedia;
|
||||
int32 count = 0;
|
||||
QString title;
|
||||
int titleWidth = 0;
|
||||
|
|
|
@ -1008,7 +1008,7 @@ auto FieldAutocompleteInner::getLottieRenderer()
|
|||
void FieldAutocompleteInner::setupLottie(StickerSuggestion &suggestion) {
|
||||
const auto document = suggestion.document;
|
||||
suggestion.animated = Stickers::LottiePlayerFromDocument(
|
||||
document,
|
||||
suggestion.documentMedia.get(),
|
||||
Stickers::LottieSize::InlineResults,
|
||||
stickerBoundingBox() * cIntRetinaFactor(),
|
||||
Lottie::Quality::Default,
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "stickers.h"
|
||||
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "boxes/stickers_box.h"
|
||||
|
@ -1146,10 +1147,11 @@ auto LottieCachedFromContent(
|
|||
template <typename Method>
|
||||
auto LottieFromDocument(
|
||||
Method &&method,
|
||||
not_null<DocumentData*> document,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
uint8 keyShift,
|
||||
QSize box) {
|
||||
const auto data = document->data();
|
||||
const auto document = media->owner();
|
||||
const auto data = media->bytes();
|
||||
const auto filepath = document->filepath();
|
||||
if (box.width() * box.height() > kDontCacheLottieAfterArea) {
|
||||
// Don't use frame caching for large stickers.
|
||||
|
@ -1172,13 +1174,13 @@ auto LottieFromDocument(
|
|||
}
|
||||
|
||||
std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
|
||||
not_null<DocumentData*> document,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
LottieSize sizeTag,
|
||||
QSize box,
|
||||
Lottie::Quality quality,
|
||||
std::shared_ptr<Lottie::FrameRenderer> renderer) {
|
||||
return LottiePlayerFromDocument(
|
||||
document,
|
||||
media,
|
||||
nullptr,
|
||||
sizeTag,
|
||||
box,
|
||||
|
@ -1187,7 +1189,7 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
|
|||
}
|
||||
|
||||
std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
|
||||
not_null<DocumentData*> document,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
const Lottie::ColorReplacements *replacements,
|
||||
LottieSize sizeTag,
|
||||
QSize box,
|
||||
|
@ -1202,18 +1204,18 @@ std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
|
|||
};
|
||||
const auto tag = replacements ? replacements->tag : uint8(0);
|
||||
const auto keyShift = ((tag << 4) & 0xF0) | (uint8(sizeTag) & 0x0F);
|
||||
return LottieFromDocument(method, document, uint8(keyShift), box);
|
||||
return LottieFromDocument(method, media, uint8(keyShift), box);
|
||||
}
|
||||
|
||||
not_null<Lottie::Animation*> LottieAnimationFromDocument(
|
||||
not_null<Lottie::MultiPlayer*> player,
|
||||
not_null<DocumentData*> document,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
LottieSize sizeTag,
|
||||
QSize box) {
|
||||
const auto method = [&](auto &&...args) {
|
||||
return player->append(std::forward<decltype(args)>(args)...);
|
||||
};
|
||||
return LottieFromDocument(method, document, uint8(sizeTag), box);
|
||||
return LottieFromDocument(method, media, uint8(sizeTag), box);
|
||||
}
|
||||
|
||||
bool HasLottieThumbnail(
|
||||
|
@ -1243,19 +1245,20 @@ bool HasLottieThumbnail(
|
|||
|
||||
std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
|
||||
ImagePtr thumbnail,
|
||||
not_null<DocumentData*> sticker,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
LottieSize sizeTag,
|
||||
QSize box,
|
||||
std::shared_ptr<Lottie::FrameRenderer> renderer) {
|
||||
const auto document = media->owner();
|
||||
const auto baseKey = thumbnail
|
||||
? thumbnail->location().file().bigFileBaseCacheKey()
|
||||
: sticker->bigFileBaseCacheKey();
|
||||
: document->bigFileBaseCacheKey();
|
||||
if (!baseKey) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto content = (thumbnail
|
||||
? thumbnail->bytesForCache()
|
||||
: Lottie::ReadContent(sticker->data(), sticker->filepath()));
|
||||
: Lottie::ReadContent(media->bytes(), document->filepath()));
|
||||
if (content.isEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1267,7 +1270,7 @@ std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
|
|||
method,
|
||||
*baseKey,
|
||||
uint8(sizeTag),
|
||||
&sticker->session(),
|
||||
&document->session(),
|
||||
content,
|
||||
box);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class DocumentData;
|
||||
|
||||
namespace Data {
|
||||
class DocumentMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Main {
|
||||
class Session;
|
||||
} // namespace Main
|
||||
|
@ -136,13 +140,13 @@ enum class LottieSize : uchar {
|
|||
};
|
||||
|
||||
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
|
||||
not_null<DocumentData*> document,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
LottieSize sizeTag,
|
||||
QSize box,
|
||||
Lottie::Quality quality = Lottie::Quality(),
|
||||
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
|
||||
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
|
||||
not_null<DocumentData*> document,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
const Lottie::ColorReplacements *replacements,
|
||||
LottieSize sizeTag,
|
||||
QSize box,
|
||||
|
@ -150,7 +154,7 @@ enum class LottieSize : uchar {
|
|||
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
|
||||
[[nodiscard]] not_null<Lottie::Animation*> LottieAnimationFromDocument(
|
||||
not_null<Lottie::MultiPlayer*> player,
|
||||
not_null<DocumentData*> document,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
LottieSize sizeTag,
|
||||
QSize box);
|
||||
|
||||
|
@ -159,7 +163,7 @@ enum class LottieSize : uchar {
|
|||
not_null<DocumentData*> sticker);
|
||||
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
|
||||
ImagePtr thumbnail,
|
||||
not_null<DocumentData*> sticker,
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
LottieSize sizeTag,
|
||||
QSize box,
|
||||
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
|
||||
|
|
|
@ -67,6 +67,7 @@ struct StickerIcon {
|
|||
: setId(setId)
|
||||
, thumbnail(thumbnail)
|
||||
, sticker(sticker)
|
||||
, stickerMedia(sticker ? sticker->createMediaView() : nullptr)
|
||||
, pixw(pixw)
|
||||
, pixh(pixh) {
|
||||
}
|
||||
|
@ -74,6 +75,7 @@ struct StickerIcon {
|
|||
ImagePtr thumbnail;
|
||||
mutable Lottie::SinglePlayer *lottie = nullptr;
|
||||
DocumentData *sticker = nullptr;
|
||||
std::shared_ptr<Data::DocumentMedia> stickerMedia;
|
||||
ChannelData *megagroup = nullptr;
|
||||
int pixw = 0;
|
||||
int pixh = 0;
|
||||
|
@ -704,7 +706,7 @@ void StickersListWidget::Footer::validateIconLottieAnimation(
|
|||
}
|
||||
auto player = Stickers::LottieThumbnail(
|
||||
icon.thumbnail,
|
||||
icon.sticker,
|
||||
icon.stickerMedia.get(),
|
||||
Stickers::LottieSize::StickersFooter,
|
||||
QSize(
|
||||
st::stickerIconWidth - 2 * st::stickerIconPadding,
|
||||
|
@ -1692,7 +1694,7 @@ void StickersListWidget::setupLottie(Set &set, int section, int index) {
|
|||
ensureLottiePlayer(set);
|
||||
sticker.animated = Stickers::LottieAnimationFromDocument(
|
||||
set.lottiePlayer,
|
||||
document,
|
||||
sticker.documentMedia.get(),
|
||||
Stickers::LottieSize::StickersPanel,
|
||||
boundingBoxSize() * cIntRetinaFactor());
|
||||
_lottieData[set.id].items.emplace(
|
||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_session.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "main/main_session.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
#include "core/application.h" // Core::App().showTheme.
|
||||
|
@ -178,9 +179,11 @@ void CloudThemes::showPreview(const CloudTheme &cloud) {
|
|||
|
||||
void CloudThemes::applyFromDocument(const CloudTheme &cloud) {
|
||||
const auto document = _session->data().document(cloud.documentId);
|
||||
loadDocumentAndInvoke(_updatingFrom, cloud, document, [=] {
|
||||
loadDocumentAndInvoke(_updatingFrom, cloud, document, [=](
|
||||
std::shared_ptr<Data::DocumentMedia> media) {
|
||||
const auto document = media->owner();
|
||||
auto preview = Window::Theme::PreviewFromFile(
|
||||
document->data(),
|
||||
media->bytes(),
|
||||
document->location().name(),
|
||||
cloud);
|
||||
if (preview) {
|
||||
|
@ -192,7 +195,9 @@ void CloudThemes::applyFromDocument(const CloudTheme &cloud) {
|
|||
|
||||
void CloudThemes::previewFromDocument(const CloudTheme &cloud) {
|
||||
const auto document = _session->data().document(cloud.documentId);
|
||||
loadDocumentAndInvoke(_previewFrom, cloud, document, [=] {
|
||||
loadDocumentAndInvoke(_previewFrom, cloud, document, [=](
|
||||
std::shared_ptr<Data::DocumentMedia> media) {
|
||||
const auto document = media->owner();
|
||||
Core::App().showTheme(document, cloud);
|
||||
});
|
||||
}
|
||||
|
@ -201,12 +206,13 @@ void CloudThemes::loadDocumentAndInvoke(
|
|||
LoadingDocument &value,
|
||||
const CloudTheme &cloud,
|
||||
not_null<DocumentData*> document,
|
||||
Fn<void()> callback) {
|
||||
Fn<void(std::shared_ptr<Data::DocumentMedia>)> callback) {
|
||||
const auto alreadyWaiting = (value.document != nullptr);
|
||||
if (alreadyWaiting) {
|
||||
value.document->cancel();
|
||||
}
|
||||
value.document = document;
|
||||
value.documentMedia = document->createMediaView();
|
||||
value.document->save(
|
||||
Data::FileOriginTheme(cloud.id, cloud.accessHash),
|
||||
QString());
|
||||
|
@ -228,8 +234,9 @@ void CloudThemes::loadDocumentAndInvoke(
|
|||
|
||||
void CloudThemes::invokeForLoaded(LoadingDocument &value) {
|
||||
const auto onstack = std::move(value.callback);
|
||||
auto media = std::move(value.documentMedia);
|
||||
value = LoadingDocument();
|
||||
onstack();
|
||||
onstack(std::move(media));
|
||||
}
|
||||
|
||||
void CloudThemes::scheduleReload() {
|
||||
|
|
|
@ -17,6 +17,8 @@ class Session;
|
|||
|
||||
namespace Data {
|
||||
|
||||
class DocumentMedia;
|
||||
|
||||
struct CloudTheme {
|
||||
uint64 id = 0;
|
||||
uint64 accessHash = 0;
|
||||
|
@ -54,8 +56,9 @@ private:
|
|||
struct LoadingDocument {
|
||||
CloudTheme theme;
|
||||
DocumentData *document = nullptr;
|
||||
std::shared_ptr<Data::DocumentMedia> documentMedia;
|
||||
rpl::lifetime subscription;
|
||||
Fn<void()> callback;
|
||||
Fn<void(std::shared_ptr<Data::DocumentMedia>)> callback;
|
||||
};
|
||||
|
||||
void parseThemes(const QVector<MTPTheme> &list);
|
||||
|
@ -71,7 +74,7 @@ private:
|
|||
LoadingDocument &value,
|
||||
const CloudTheme &cloud,
|
||||
not_null<DocumentData*> document,
|
||||
Fn<void()> callback);
|
||||
Fn<void(std::shared_ptr<Data::DocumentMedia>)> callback);
|
||||
void invokeForLoaded(LoadingDocument &value);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
|
|
|
@ -587,7 +587,10 @@ void DocumentData::validateLottieSticker() {
|
|||
}
|
||||
|
||||
void DocumentData::setDataAndCache(const QByteArray &data) {
|
||||
setData(data);
|
||||
_data = data;
|
||||
if (const auto media = activeMediaView()) {
|
||||
media->setBytes(data);
|
||||
}
|
||||
if (saveToCache() && data.size() <= Storage::kMaxFileInMemory) {
|
||||
owner().cache().put(
|
||||
cacheKey(),
|
||||
|
@ -734,11 +737,12 @@ auto DocumentData::bigFileBaseCacheKey() const
|
|||
}
|
||||
|
||||
bool DocumentData::saveToCache() const {
|
||||
return (type == StickerDocument && size < Storage::kMaxStickerInMemory)
|
||||
|| (isAnimation() && size < Storage::kMaxAnimationInMemory)
|
||||
|| (isVoiceMessage() && size < Storage::kMaxVoiceInMemory)
|
||||
|| (type == WallPaperDocument)
|
||||
|| (isTheme() && size < Storage::kMaxFileInMemory);
|
||||
return (size < Storage::kMaxFileInMemory)
|
||||
&& ((type == StickerDocument)
|
||||
|| isAnimation()
|
||||
|| isVoiceMessage()
|
||||
|| (type == WallPaperDocument)
|
||||
|| isTheme());
|
||||
}
|
||||
|
||||
void DocumentData::unload() {
|
||||
|
@ -814,6 +818,7 @@ bool DocumentData::loaded(FilePathResolve resolve) const {
|
|||
that->setGoodThumbnailDataReady();
|
||||
|
||||
if (const auto media = activeMediaView()) {
|
||||
media->setBytes(_loader->bytes());
|
||||
media->checkStickerLarge(_loader.get());
|
||||
}
|
||||
destroyLoader();
|
||||
|
@ -824,7 +829,7 @@ bool DocumentData::loaded(FilePathResolve resolve) const {
|
|||
}
|
||||
_owner->notifyDocumentLayoutChanged(this);
|
||||
}
|
||||
return !data().isEmpty() || !filepath(resolve).isEmpty();
|
||||
return !rawBytes().isEmpty() || !filepath(resolve).isEmpty();
|
||||
}
|
||||
|
||||
void DocumentData::destroyLoader() const {
|
||||
|
@ -918,10 +923,10 @@ void DocumentData::save(
|
|||
if (loaded(FilePathResolve::Checked)) {
|
||||
auto &l = location(true);
|
||||
if (!toFile.isEmpty()) {
|
||||
if (!_data.isEmpty()) {
|
||||
if (!rawBytes().isEmpty()) {
|
||||
QFile f(toFile);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.write(_data);
|
||||
f.write(rawBytes());
|
||||
f.close();
|
||||
|
||||
setLocation(FileLocation(toFile));
|
||||
|
@ -1085,7 +1090,7 @@ QByteArray documentWaveformEncode5bit(const VoiceWaveform &waveform) {
|
|||
return result;
|
||||
}
|
||||
|
||||
QByteArray DocumentData::data() const {
|
||||
QByteArray DocumentData::rawBytes() const {
|
||||
if (!_data.isEmpty()) {
|
||||
ActiveCache().up(const_cast<DocumentData*>(this));
|
||||
}
|
||||
|
@ -1115,8 +1120,10 @@ void DocumentData::setLocation(const FileLocation &loc) {
|
|||
|
||||
QString DocumentData::filepath(FilePathResolve resolve) const {
|
||||
bool check = (resolve != FilePathResolve::Cached);
|
||||
QString result = (check && _location.name().isEmpty()) ? QString() : location(check).name();
|
||||
bool saveFromData = result.isEmpty() && !data().isEmpty();
|
||||
QString result = (check && _location.name().isEmpty())
|
||||
? QString()
|
||||
: location(check).name();
|
||||
bool saveFromData = result.isEmpty() && !rawBytes().isEmpty();
|
||||
if (saveFromData) {
|
||||
if (resolve != FilePathResolve::SaveFromData
|
||||
&& resolve != FilePathResolve::SaveFromDataSilent) {
|
||||
|
@ -1131,7 +1138,7 @@ QString DocumentData::filepath(FilePathResolve resolve) const {
|
|||
if (!filename.isEmpty()) {
|
||||
QFile f(filename);
|
||||
if (f.open(QIODevice::WriteOnly)) {
|
||||
if (f.write(data()) == data().size()) {
|
||||
if (f.write(rawBytes()) == rawBytes().size()) {
|
||||
f.close();
|
||||
const_cast<DocumentData*>(this)->_location = FileLocation(filename);
|
||||
Local::writeFileLocation(mediaKey(), _location);
|
||||
|
@ -1263,8 +1270,8 @@ auto DocumentData::createStreamingLoader(
|
|||
}
|
||||
if (!forceRemoteLoader) {
|
||||
const auto &location = this->location(true);
|
||||
if (!data().isEmpty()) {
|
||||
return Media::Streaming::MakeBytesLoader(data());
|
||||
if (!rawBytes().isEmpty()) {
|
||||
return Media::Streaming::MakeBytesLoader(rawBytes());
|
||||
} else if (!location.isEmpty() && location.accessEnable()) {
|
||||
auto result = Media::Streaming::MakeFileLoader(location.name());
|
||||
location.accessDisable();
|
||||
|
@ -1545,6 +1552,9 @@ void DocumentData::collectLocalData(not_null<DocumentData*> local) {
|
|||
if (!local->_data.isEmpty()) {
|
||||
ActiveCache().decrement(_data.size());
|
||||
_data = local->_data;
|
||||
if (const auto media = activeMediaView()) {
|
||||
media->setBytes(local->_data);
|
||||
}
|
||||
ActiveCache().increment(_data.size());
|
||||
if (!_data.isEmpty()) {
|
||||
ActiveCache().up(this);
|
||||
|
@ -1642,7 +1652,7 @@ base::binary_guard ReadImageAsync(
|
|||
FnMut<void(QImage&&)> done) {
|
||||
auto result = base::binary_guard();
|
||||
crl::async([
|
||||
bytes = document->data(),
|
||||
bytes = document->rawBytes(),
|
||||
path = document->filepath(),
|
||||
postprocess = std::move(postprocess),
|
||||
guard = result.make_guard(),
|
||||
|
@ -1672,30 +1682,4 @@ base::binary_guard ReadImageAsync(
|
|||
return result;
|
||||
}
|
||||
|
||||
//void HandleUnsupportedMedia(
|
||||
// not_null<DocumentData*> document,
|
||||
// FullMsgId contextId) {
|
||||
// using Error = ::Media::Streaming::Error;
|
||||
//
|
||||
// document->setInappPlaybackFailed();
|
||||
// const auto filepath = document->filepath(
|
||||
// DocumentData::FilePathResolve::SaveFromData);
|
||||
// if (filepath.isEmpty()) {
|
||||
// const auto save = [=] {
|
||||
// Ui::hideLayer();
|
||||
// DocumentSaveClickHandler::Save(
|
||||
// (contextId ? contextId : Data::FileOrigin()),
|
||||
// document,
|
||||
// document->owner().message(contextId));
|
||||
// };
|
||||
// Ui::show(Box<ConfirmBox>(
|
||||
// tr::lng_player_cant_stream(tr::now),
|
||||
// tr::lng_player_download(tr::now),
|
||||
// tr::lng_cancel(tr::now),
|
||||
// save));
|
||||
// } else if (IsValidMediaFile(filepath)) {
|
||||
// File::Launch(filepath);
|
||||
// }
|
||||
//}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -127,7 +127,7 @@ public:
|
|||
void setWaitingForAlbum();
|
||||
[[nodiscard]] bool waitingForAlbum() const;
|
||||
|
||||
[[nodiscard]] QByteArray data() const;
|
||||
[[nodiscard]] QByteArray rawBytes() const;
|
||||
[[nodiscard]] const FileLocation &location(bool check = false) const;
|
||||
void setLocation(const FileLocation &loc);
|
||||
|
||||
|
@ -163,9 +163,6 @@ public:
|
|||
void recountIsImage();
|
||||
[[nodiscard]] bool supportsStreaming() const;
|
||||
void setNotSupportsStreaming();
|
||||
void setData(const QByteArray &data) {
|
||||
_data = data;
|
||||
}
|
||||
void setDataAndCache(const QByteArray &data);
|
||||
bool checkWallPaperProperties();
|
||||
[[nodiscard]] bool isWallPaper() const;
|
||||
|
|
|
@ -82,11 +82,16 @@ enum class FileType {
|
|||
} // namespace
|
||||
|
||||
DocumentMedia::DocumentMedia(not_null<DocumentData*> owner)
|
||||
: _owner(owner) {
|
||||
: _owner(owner)
|
||||
, _bytes(owner->rawBytes()) {
|
||||
}
|
||||
|
||||
DocumentMedia::~DocumentMedia() = default;
|
||||
|
||||
not_null<DocumentData*> DocumentMedia::owner() const {
|
||||
return _owner;
|
||||
}
|
||||
|
||||
void DocumentMedia::goodThumbnailWanted() {
|
||||
_flags |= Flag::GoodThumbnailWanted;
|
||||
}
|
||||
|
@ -135,7 +140,7 @@ void DocumentMedia::checkStickerLarge() {
|
|||
if (data->animated || !_owner->loaded()) {
|
||||
return;
|
||||
}
|
||||
const auto bytes = _owner->data();
|
||||
const auto bytes = _owner->rawBytes();
|
||||
if (bytes.isEmpty()) {
|
||||
const auto &loc = _owner->location(true);
|
||||
if (loc.accessEnable()) {
|
||||
|
@ -155,6 +160,16 @@ void DocumentMedia::checkStickerLarge() {
|
|||
}
|
||||
}
|
||||
|
||||
void DocumentMedia::setBytes(const QByteArray &bytes) {
|
||||
if (!bytes.isEmpty()) {
|
||||
_bytes = bytes;
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray DocumentMedia::bytes() const {
|
||||
return _bytes;
|
||||
}
|
||||
|
||||
void DocumentMedia::checkStickerSmall() {
|
||||
const auto data = _owner->sticker();
|
||||
if ((data && data->animated) || _owner->thumbnailEnoughForSticker()) {
|
||||
|
@ -184,18 +199,18 @@ void DocumentMedia::checkStickerLarge(not_null<FileLoader*> loader) {
|
|||
if (_owner->sticker()
|
||||
&& !_sticker
|
||||
&& !loader->imageData().isNull()
|
||||
&& !_owner->data().isEmpty()) {
|
||||
&& !_owner->rawBytes().isEmpty()) {
|
||||
_sticker = std::make_unique<Image>(
|
||||
std::make_unique<Images::LocalFileSource>(
|
||||
QString(),
|
||||
_owner->data(),
|
||||
_owner->rawBytes(),
|
||||
loader->imageFormat(),
|
||||
loader->imageData()));
|
||||
}
|
||||
}
|
||||
|
||||
void DocumentMedia::GenerateGoodThumbnail(not_null<DocumentData*> document) {
|
||||
const auto data = document->data();
|
||||
const auto data = document->rawBytes();
|
||||
const auto type = document->isWallPaper()
|
||||
? FileType::WallPaper
|
||||
: document->isTheme()
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
explicit DocumentMedia(not_null<DocumentData*> owner);
|
||||
~DocumentMedia();
|
||||
|
||||
[[nodiscard]] not_null<DocumentData*> owner() const;
|
||||
|
||||
void goodThumbnailWanted();
|
||||
[[nodiscard]] Image *goodThumbnail() const;
|
||||
void setGoodThumbnail(QImage thumbnail);
|
||||
|
@ -30,6 +32,9 @@ public:
|
|||
[[nodiscard]] Image *getStickerLarge();
|
||||
void checkStickerLarge(not_null<FileLoader*> loader);
|
||||
|
||||
void setBytes(const QByteArray &bytes);
|
||||
[[nodiscard]] QByteArray bytes() const;
|
||||
|
||||
// For DocumentData.
|
||||
static void CheckGoodThumbnail(not_null<DocumentData*> document);
|
||||
|
||||
|
@ -47,6 +52,7 @@ private:
|
|||
std::unique_ptr<Image> _goodThumbnail;
|
||||
mutable std::unique_ptr<Image> _inlineThumbnail;
|
||||
std::unique_ptr<Image> _sticker;
|
||||
QByteArray _bytes;
|
||||
Flags _flags;
|
||||
|
||||
};
|
||||
|
|
|
@ -386,6 +386,8 @@ void Document::draw(Painter &p, const QRect &r, TextSelection selection, crl::ti
|
|||
|
||||
auto voiceStatusOverride = QString();
|
||||
if (const auto voice = Get<HistoryDocumentVoice>()) {
|
||||
ensureDataMediaCreated();
|
||||
|
||||
const VoiceWaveform *wf = nullptr;
|
||||
uchar norm_value = 0;
|
||||
if (const auto voiceData = _data->voice()) {
|
||||
|
@ -393,7 +395,7 @@ void Document::draw(Painter &p, const QRect &r, TextSelection selection, crl::ti
|
|||
if (wf->isEmpty()) {
|
||||
wf = nullptr;
|
||||
if (loaded) {
|
||||
Local::countVoiceWaveform(_data);
|
||||
Local::countVoiceWaveform(_dataMedia.get());
|
||||
}
|
||||
} else if (wf->at(0) < 0) {
|
||||
wf = nullptr;
|
||||
|
|
|
@ -271,8 +271,10 @@ void Sticker::setDiceIndex(const QString &emoji, int index) {
|
|||
}
|
||||
|
||||
void Sticker::setupLottie() {
|
||||
Expects(_dataMedia != nullptr);
|
||||
|
||||
_lottie = Stickers::LottiePlayerFromDocument(
|
||||
_data,
|
||||
_dataMedia.get(),
|
||||
_replacements,
|
||||
Stickers::LottieSize::MessageHistory,
|
||||
_size * cIntRetinaFactor(),
|
||||
|
|
|
@ -146,6 +146,9 @@ int Gif::resizeGetHeight(int width) {
|
|||
|
||||
void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
|
||||
const auto document = getShownDocument();
|
||||
if (document) {
|
||||
ensureDataMediaCreated(document);
|
||||
}
|
||||
document->automaticLoad(fileOrigin(), nullptr);
|
||||
|
||||
bool loaded = document->loaded(), loading = document->loading(), displayLoading = document->displayLoading();
|
||||
|
@ -154,7 +157,7 @@ void Gif::paint(Painter &p, const QRect &clip, const PaintContext *context) cons
|
|||
&& !_gif.isBad()
|
||||
&& CanPlayInline(document)) {
|
||||
auto that = const_cast<Gif*>(this);
|
||||
that->_gif = Media::Clip::MakeReader(document, FullMsgId(), [that](Media::Clip::Notification notification) {
|
||||
that->_gif = Media::Clip::MakeReader(_dataMedia.get(), FullMsgId(), [that](Media::Clip::Notification notification) {
|
||||
that->clipCallback(notification);
|
||||
});
|
||||
if (_gif) _gif->setAutoplay();
|
||||
|
@ -508,9 +511,11 @@ QSize Sticker::getThumbSize() const {
|
|||
return QSize(qMax(w, 1), qMax(h, 1));
|
||||
}
|
||||
|
||||
void Sticker::setupLottie(not_null<DocumentData*> document) const {
|
||||
void Sticker::setupLottie() const {
|
||||
Expects(_dataMedia != nullptr);
|
||||
|
||||
_lottie = Stickers::LottiePlayerFromDocument(
|
||||
document,
|
||||
_dataMedia.get(),
|
||||
Stickers::LottieSize::InlineResults,
|
||||
QSize(
|
||||
st::stickerPanSize.width() - st::buttonRadius * 2,
|
||||
|
@ -530,7 +535,7 @@ void Sticker::prepareThumbnail() const {
|
|||
&& document->sticker()
|
||||
&& document->sticker()->animated
|
||||
&& document->loaded()) {
|
||||
setupLottie(document);
|
||||
setupLottie();
|
||||
}
|
||||
_dataMedia->checkStickerSmall();
|
||||
if (const auto sticker = _dataMedia->getStickerSmall()) {
|
||||
|
@ -1318,7 +1323,10 @@ void Game::paint(Painter &p, const QRect &clip, const PaintContext *context) con
|
|||
|
||||
// Gif thumb
|
||||
auto thumbDisplayed = false, radial = false;
|
||||
auto document = getResultDocument();
|
||||
const auto document = getResultDocument();
|
||||
if (document) {
|
||||
ensureDataMediaCreated(document);
|
||||
}
|
||||
auto animatedThumb = document && document->isAnimation();
|
||||
if (animatedThumb) {
|
||||
document->automaticLoad(fileOrigin(), nullptr);
|
||||
|
@ -1326,7 +1334,7 @@ void Game::paint(Painter &p, const QRect &clip, const PaintContext *context) con
|
|||
bool loaded = document->loaded(), loading = document->loading(), displayLoading = document->displayLoading();
|
||||
if (loaded && !_gif && !_gif.isBad()) {
|
||||
auto that = const_cast<Game*>(this);
|
||||
that->_gif = Media::Clip::MakeReader(document, FullMsgId(), [that](Media::Clip::Notification notification) {
|
||||
that->_gif = Media::Clip::MakeReader(_dataMedia.get(), FullMsgId(), [that](Media::Clip::Notification notification) {
|
||||
that->clipCallback(notification);
|
||||
});
|
||||
if (_gif) _gif->setAutoplay();
|
||||
|
@ -1403,7 +1411,7 @@ void Game::prepareThumbnail(QSize size) const {
|
|||
validateThumbnail(photo->thumbnail(), size, true);
|
||||
validateThumbnail(photo->thumbnailInline(), size, false);
|
||||
} else if (const auto document = getResultDocument()) {
|
||||
ensureDataMediaCreated(document);
|
||||
Assert(_dataMedia != nullptr);
|
||||
validateThumbnail(document->thumbnail(), size, true);
|
||||
validateThumbnail(_dataMedia->thumbnailInline(), size, false);
|
||||
}
|
||||
|
|
|
@ -193,7 +193,7 @@ public:
|
|||
|
||||
private:
|
||||
void ensureDataMediaCreated(not_null<DocumentData*> document) const;
|
||||
void setupLottie(not_null<DocumentData*> document) const;
|
||||
void setupLottie() const;
|
||||
QSize getThumbSize() const;
|
||||
void prepareThumbnail() const;
|
||||
|
||||
|
|
|
@ -761,7 +761,6 @@ void Mixer::play(
|
|||
|
||||
auto type = audio.type();
|
||||
AudioMsgId stopped;
|
||||
auto notLoadedYet = false;
|
||||
{
|
||||
QMutexLocker lock(&AudioMutex);
|
||||
Audio::AttachToDevice();
|
||||
|
@ -799,42 +798,18 @@ void Mixer::play(
|
|||
current->state.id = audio;
|
||||
current->lastUpdateWhen = 0;
|
||||
current->lastUpdatePosition = 0;
|
||||
if (externalData) {
|
||||
current->setExternalData(std::move(externalData));
|
||||
} else {
|
||||
current->setExternalData(nullptr);
|
||||
current->file = audio.audio()->location(true);
|
||||
current->data = audio.audio()->data();
|
||||
notLoadedYet = (current->file.isEmpty() && current->data.isEmpty());
|
||||
}
|
||||
if (notLoadedYet) {
|
||||
auto newState = (type == AudioMsgId::Type::Song)
|
||||
? State::Stopped
|
||||
: State::StoppedAtError;
|
||||
setStoppedState(current, newState);
|
||||
} else {
|
||||
current->state.position = (positionMs * current->state.frequency)
|
||||
/ 1000LL;
|
||||
current->state.state = current->externalData
|
||||
? State::Paused
|
||||
: fadedStart
|
||||
? State::Starting
|
||||
: State::Playing;
|
||||
current->loading = true;
|
||||
emit loaderOnStart(current->state.id, positionMs);
|
||||
if (type == AudioMsgId::Type::Voice) {
|
||||
emit suppressSong();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (notLoadedYet) {
|
||||
if (type == AudioMsgId::Type::Song || type == AudioMsgId::Type::Video) {
|
||||
DocumentOpenClickHandler::Open(
|
||||
audio.contextId(),
|
||||
audio.audio(),
|
||||
Auth().data().message(audio.contextId()));
|
||||
} else {
|
||||
onError(audio);
|
||||
current->setExternalData(std::move(externalData));
|
||||
current->state.position = (positionMs * current->state.frequency)
|
||||
/ 1000LL;
|
||||
current->state.state = current->externalData
|
||||
? State::Paused
|
||||
: fadedStart
|
||||
? State::Starting
|
||||
: State::Playing;
|
||||
current->loading = true;
|
||||
emit loaderOnStart(current->state.id, positionMs);
|
||||
if (type == AudioMsgId::Type::Voice) {
|
||||
emit suppressSong();
|
||||
}
|
||||
}
|
||||
if (stopped) {
|
||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "media/clip/media_clip_reader.h"
|
||||
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "media/clip/media_clip_ffmpeg.h"
|
||||
#include "media/clip/media_clip_check_streaming.h"
|
||||
|
@ -91,15 +92,20 @@ Reader::Reader(const QString &filepath, Callback &&callback, Mode mode, crl::tim
|
|||
init(FileLocation(filepath), QByteArray());
|
||||
}
|
||||
|
||||
Reader::Reader(not_null<DocumentData*> document, FullMsgId msgId, Callback &&callback, Mode mode, crl::time seekMs)
|
||||
Reader::Reader(
|
||||
not_null<Data::DocumentMedia*> media,
|
||||
FullMsgId msgId,
|
||||
Callback &&callback,
|
||||
Mode mode,
|
||||
crl::time seekMs)
|
||||
: _callback(std::move(callback))
|
||||
, _mode(mode)
|
||||
, _audioMsgId(
|
||||
document,
|
||||
media->owner(),
|
||||
msgId,
|
||||
(mode == Mode::Video) ? AudioMsgId::CreateExternalPlayId() : 0)
|
||||
, _seekPositionMs(seekMs) {
|
||||
init(document->location(), document->data());
|
||||
init(media->owner()->location(), media->bytes());
|
||||
}
|
||||
|
||||
Reader::Reader(const QByteArray &data, Callback &&callback, Mode mode, crl::time seekMs)
|
||||
|
|
|
@ -14,6 +14,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
class FileLocation;
|
||||
|
||||
namespace Data {
|
||||
class DocumentMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Media {
|
||||
namespace Clip {
|
||||
|
||||
|
@ -56,8 +60,8 @@ public:
|
|||
Video,
|
||||
};
|
||||
|
||||
Reader(not_null<Data::DocumentMedia*> media, FullMsgId msgId, Callback &&callback, Mode mode = Mode::Gif, crl::time seekMs = 0);
|
||||
Reader(const QString &filepath, Callback &&callback, Mode mode = Mode::Gif, crl::time seekMs = 0);
|
||||
Reader(not_null<DocumentData*> document, FullMsgId msgId, Callback &&callback, Mode mode = Mode::Gif, crl::time seekMs = 0);
|
||||
Reader(const QByteArray &data, Callback &&callback, Mode mode = Mode::Gif, crl::time seekMs = 0);
|
||||
|
||||
// Reader can be already deleted.
|
||||
|
|
|
@ -1220,8 +1220,9 @@ void OverlayWidget::notifyFileDialogShown(bool shown) {
|
|||
void OverlayWidget::onSaveAs() {
|
||||
QString file;
|
||||
if (_doc) {
|
||||
const FileLocation &location(_doc->location(true));
|
||||
if (!_doc->data().isEmpty() || location.accessEnable()) {
|
||||
const auto &location = _doc->location(true);
|
||||
const auto bytes = _docMedia->bytes();
|
||||
if (!bytes.isEmpty() || location.accessEnable()) {
|
||||
QFileInfo alreadyInfo(location.name());
|
||||
QDir alreadyDir(alreadyInfo.dir());
|
||||
QString name = alreadyInfo.fileName(), filter;
|
||||
|
@ -1240,17 +1241,19 @@ void OverlayWidget::onSaveAs() {
|
|||
|
||||
file = FileNameForSave(tr::lng_save_file(tr::now), filter, qsl("doc"), name, true, alreadyDir);
|
||||
if (!file.isEmpty() && file != location.name()) {
|
||||
if (_doc->data().isEmpty()) {
|
||||
if (bytes.isEmpty()) {
|
||||
QFile(file).remove();
|
||||
QFile(location.name()).copy(file);
|
||||
} else {
|
||||
QFile f(file);
|
||||
f.open(QIODevice::WriteOnly);
|
||||
f.write(_doc->data());
|
||||
f.write(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
if (_doc->data().isEmpty()) location.accessDisable();
|
||||
if (bytes.isEmpty()) {
|
||||
location.accessDisable();
|
||||
}
|
||||
} else {
|
||||
DocumentSaveClickHandler::Save(
|
||||
fileOrigin(),
|
||||
|
@ -2330,7 +2333,7 @@ void OverlayWidget::initThemePreview() {
|
|||
|
||||
Assert(_doc && _doc->isTheme());
|
||||
|
||||
const auto bytes = _doc->data();
|
||||
const auto bytes = _docMedia->bytes();
|
||||
auto &location = _doc->location();
|
||||
if (bytes.isEmpty()
|
||||
&& (location.isEmpty() || !location.accessEnable())) {
|
||||
|
|
|
@ -30,11 +30,8 @@ struct Key;
|
|||
// This value is used in local cache database settings!
|
||||
constexpr auto kMaxFileInMemory = 10 * 1024 * 1024;
|
||||
|
||||
// 2 MB audio is hold in memory and auto loaded
|
||||
constexpr auto kMaxVoiceInMemory = 2 * 1024 * 1024;
|
||||
|
||||
// 2 MB stickers hold in memory, auto loaded and displayed inline
|
||||
constexpr auto kMaxStickerInMemory = 2 * 1024 * 1024;
|
||||
constexpr auto kMaxStickerBytesSize = 2 * 1024 * 1024;
|
||||
|
||||
// 10 MB GIF and mp4 animations held in memory while playing
|
||||
constexpr auto kMaxWallPaperInMemory = kMaxFileInMemory;
|
||||
|
|
|
@ -836,7 +836,7 @@ void FileLoadTask::process() {
|
|||
&& (h > 0)
|
||||
&& (w <= StickerMaxSize)
|
||||
&& (h <= StickerMaxSize)
|
||||
&& (filesize < Storage::kMaxStickerInMemory);
|
||||
&& (filesize < Storage::kMaxStickerBytesSize);
|
||||
if (isSticker) {
|
||||
attributes.push_back(MTP_documentAttributeSticker(
|
||||
MTP_flags(0),
|
||||
|
|
|
@ -14,6 +14,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "chat_helpers/stickers.h"
|
||||
#include "data/data_drafts.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "boxes/send_files_box.h"
|
||||
#include "base/flags.h"
|
||||
#include "base/platform/base_platform_file_utilities.h"
|
||||
|
@ -37,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "main/main_session.h"
|
||||
#include "window/themes/window_theme.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "data/data_session.h"
|
||||
#include "history/history.h"
|
||||
#include "facades.h"
|
||||
|
||||
|
@ -3358,11 +3359,11 @@ Storage::Cache::Database::Settings cacheBigFileSettings() {
|
|||
|
||||
class CountWaveformTask : public Task {
|
||||
public:
|
||||
CountWaveformTask(DocumentData *doc)
|
||||
: _doc(doc)
|
||||
, _loc(doc->location(true))
|
||||
, _data(doc->data())
|
||||
, _wavemax(0) {
|
||||
CountWaveformTask(not_null<Data::DocumentMedia*> media)
|
||||
: _doc(media->owner())
|
||||
, _loc(_doc->location(true))
|
||||
, _data(media->bytes())
|
||||
, _wavemax(0) {
|
||||
if (_data.isEmpty() && !_loc.accessEnable()) {
|
||||
_doc = nullptr;
|
||||
}
|
||||
|
@ -3399,7 +3400,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
DocumentData *_doc;
|
||||
DocumentData *_doc = nullptr;
|
||||
FileLocation _loc;
|
||||
QByteArray _data;
|
||||
VoiceWaveform _waveform;
|
||||
|
@ -3407,13 +3408,14 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
void countVoiceWaveform(DocumentData *document) {
|
||||
void countVoiceWaveform(not_null<Data::DocumentMedia*> media) {
|
||||
const auto document = media->owner();
|
||||
if (const auto voice = document->voice()) {
|
||||
if (_localLoader) {
|
||||
voice->waveform.resize(1 + sizeof(TaskId));
|
||||
voice->waveform[0] = -1; // counting
|
||||
TaskId taskId = _localLoader->addTask(
|
||||
std::make_unique<CountWaveformTask>(document));
|
||||
std::make_unique<CountWaveformTask>(media));
|
||||
memcpy(voice->waveform.data() + 1, &taskId, sizeof(taskId));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ class History;
|
|||
|
||||
namespace Data {
|
||||
class WallPaper;
|
||||
class DocumentMedia;
|
||||
} // namespace Data
|
||||
|
||||
namespace Lang {
|
||||
|
@ -129,7 +130,7 @@ Storage::EncryptionKey cacheBigFileKey();
|
|||
QString cacheBigFilePath();
|
||||
Storage::Cache::Database::Settings cacheBigFileSettings();
|
||||
|
||||
void countVoiceWaveform(DocumentData *document);
|
||||
void countVoiceWaveform(not_null<Data::DocumentMedia*> media);
|
||||
|
||||
void cancelTask(TaskId id);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_cloud_themes.h"
|
||||
#include "data/data_file_origin.h"
|
||||
#include "data/data_document.h"
|
||||
#include "data/data_document_media.h"
|
||||
#include "data/data_session.h"
|
||||
#include "ui/image/image_prepare.h"
|
||||
#include "ui/widgets/popup_menu.h"
|
||||
|
@ -560,6 +561,7 @@ void CloudList::refreshColors(Element &element) {
|
|||
&& (!document || !document->isTheme()))) {
|
||||
element.check->setColors(ColorsFromCurrentTheme());
|
||||
} else if (document) {
|
||||
element.media = document ? document->createMediaView() : nullptr;
|
||||
document->save(
|
||||
Data::FileOriginTheme(theme.id, theme.accessHash),
|
||||
QString());
|
||||
|
@ -639,7 +641,9 @@ void CloudList::refreshColorsFromDocument(
|
|||
not_null<DocumentData*> document) {
|
||||
const auto id = element.id();
|
||||
const auto path = document->filepath();
|
||||
const auto data = document->data();
|
||||
const auto data = element.media
|
||||
? base::take(element.media)->bytes()
|
||||
: QByteArray();
|
||||
crl::async([=, guard = element.generating.make_guard()]() mutable {
|
||||
crl::on_main(std::move(guard), [
|
||||
=,
|
||||
|
|
|
@ -88,6 +88,7 @@ private:
|
|||
Data::CloudTheme theme;
|
||||
not_null<CloudListCheck*> check;
|
||||
std::unique_ptr<Ui::Radiobutton> button;
|
||||
std::shared_ptr<Data::DocumentMedia> media;
|
||||
base::binary_guard generating;
|
||||
bool waiting = false;
|
||||
|
||||
|
|
|
@ -226,7 +226,7 @@ void MediaPreviewWidget::setupLottie() {
|
|||
Expects(_document != nullptr);
|
||||
|
||||
_lottie = std::make_unique<Lottie::SinglePlayer>(
|
||||
Lottie::ReadContent(_document->data(), _document->filepath()),
|
||||
Lottie::ReadContent(_documentMedia->bytes(), _document->filepath()),
|
||||
Lottie::FrameRequest{ currentDimensions() * cIntRetinaFactor() },
|
||||
Lottie::Quality::High);
|
||||
|
||||
|
@ -266,7 +266,7 @@ QPixmap MediaPreviewWidget::currentImage() const {
|
|||
if (_document->loaded()) {
|
||||
if (!_gif && !_gif.isBad()) {
|
||||
auto that = const_cast<MediaPreviewWidget*>(this);
|
||||
that->_gif = Media::Clip::MakeReader(_document, FullMsgId(), [=](Media::Clip::Notification notification) {
|
||||
that->_gif = Media::Clip::MakeReader(_documentMedia.get(), FullMsgId(), [=](Media::Clip::Notification notification) {
|
||||
that->clipCallback(notification);
|
||||
});
|
||||
if (_gif) _gif->setAutoplay();
|
||||
|
|
Loading…
Reference in New Issue