mirror of https://github.com/procxx/kepka.git
Allow photos not have some of the thumbnails.
This commit is contained in:
parent
e27d2bc2d5
commit
7ad660a0e7
|
@ -580,7 +580,10 @@ GifsListWidget::LayoutItem *GifsListWidget::layoutPrepareInlineResult(
|
|||
int32 position) {
|
||||
auto it = _inlineLayouts.find(result);
|
||||
if (it == _inlineLayouts.cend()) {
|
||||
if (auto layout = LayoutItem::createLayout(this, result, _inlineWithThumb)) {
|
||||
if (auto layout = LayoutItem::createLayout(
|
||||
this,
|
||||
result,
|
||||
_inlineWithThumb)) {
|
||||
it = _inlineLayouts.emplace(result, std::move(layout)).first;
|
||||
it->second->initDimensions();
|
||||
} else {
|
||||
|
|
|
@ -140,7 +140,6 @@ public:
|
|||
void setDelayedStorageLocation(
|
||||
const StorageImageLocation &location) override;
|
||||
void performDelayedLoad(Data::FileOrigin origin) override;
|
||||
bool isDelayedStorageImage() const override;
|
||||
void setImageBytes(const QByteArray &bytes) override;
|
||||
|
||||
int width() override;
|
||||
|
@ -254,10 +253,6 @@ void ImageSource::setDelayedStorageLocation(
|
|||
void ImageSource::performDelayedLoad(Data::FileOrigin origin) {
|
||||
}
|
||||
|
||||
bool ImageSource::isDelayedStorageImage() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageSource::setImageBytes(const QByteArray &bytes) {
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,9 @@ constexpr auto kFastRevokeRestriction = 24 * 60 * TimeId(60);
|
|||
result.title = TextUtilities::SingleLine(qs(data.vtitle()));
|
||||
result.receiptMsgId = data.vreceipt_msg_id().value_or_empty();
|
||||
if (const auto photo = data.vphoto()) {
|
||||
result.photo = item->history()->owner().photoFromWeb(*photo);
|
||||
result.photo = item->history()->owner().photoFromWeb(
|
||||
*photo,
|
||||
ImageLocation());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
namespace {
|
||||
|
||||
constexpr auto kPhotoSideLimit = 1280;
|
||||
|
||||
using Data::PhotoMedia;
|
||||
using Data::PhotoSize;
|
||||
using Data::PhotoSizeIndex;
|
||||
|
@ -68,20 +70,54 @@ bool PhotoData::loading() const {
|
|||
return loading(PhotoSize::Large);
|
||||
}
|
||||
|
||||
int PhotoData::validSizeIndex(PhotoSize size) const {
|
||||
const auto index = PhotoSizeIndex(size);
|
||||
for (auto i = index; i != kPhotoSizeCount; ++i) {
|
||||
if (_images[i].location.valid()) {
|
||||
if (i != index) {
|
||||
int a = 0; AssertIsDebug();
|
||||
}
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return PhotoSizeIndex(PhotoSize::Large);
|
||||
}
|
||||
|
||||
bool PhotoData::hasExact(PhotoSize size) const {
|
||||
return _images[PhotoSizeIndex(size)].location.valid();
|
||||
}
|
||||
|
||||
bool PhotoData::loading(PhotoSize size) const {
|
||||
return (_images[PhotoSizeIndex(size)].loader != nullptr);
|
||||
return (_images[validSizeIndex(size)].loader != nullptr);
|
||||
}
|
||||
|
||||
bool PhotoData::failed(PhotoSize size) const {
|
||||
return (_images[PhotoSizeIndex(size)].flags & ImageFlag::Failed);
|
||||
return (_images[validSizeIndex(size)].flags & ImageFlag::Failed);
|
||||
}
|
||||
|
||||
const ImageLocation &PhotoData::location(PhotoSize size) const {
|
||||
return _images[PhotoSizeIndex(size)].location;
|
||||
return _images[validSizeIndex(size)].location;
|
||||
}
|
||||
|
||||
int PhotoData::SideLimit() {
|
||||
return kPhotoSideLimit;
|
||||
}
|
||||
|
||||
std::optional<QSize> PhotoData::size(PhotoSize size) const {
|
||||
const auto &provided = location(size);
|
||||
const auto result = QSize{ provided.width(), provided.height() };
|
||||
const auto limit = SideLimit();
|
||||
if (result.isEmpty()) {
|
||||
return std::nullopt;
|
||||
} else if (result.width() <= limit && result.height() <= limit) {
|
||||
return result;
|
||||
}
|
||||
const auto scaled = result.scaled(limit, limit, Qt::KeepAspectRatio);
|
||||
return QSize(std::max(scaled.width(), 1), std::max(scaled.height(), 1));
|
||||
}
|
||||
|
||||
int PhotoData::imageByteSize(PhotoSize size) const {
|
||||
return _images[PhotoSizeIndex(size)].byteSize;
|
||||
return _images[validSizeIndex(size)].byteSize;
|
||||
}
|
||||
|
||||
bool PhotoData::displayLoading() const {
|
||||
|
@ -212,7 +248,7 @@ void PhotoData::load(
|
|||
Data::FileOrigin origin,
|
||||
LoadFromCloudSetting fromCloud,
|
||||
bool autoLoading) {
|
||||
const auto index = PhotoSizeIndex(size);
|
||||
const auto index = validSizeIndex(size);
|
||||
auto &image = _images[index];
|
||||
if (image.loader) {
|
||||
if (fromCloud == LoadFromCloudOrLocal) {
|
||||
|
@ -227,6 +263,9 @@ void PhotoData::load(
|
|||
return;
|
||||
}
|
||||
}
|
||||
// Could've changed, if the requested size didn't have a location.
|
||||
size = static_cast<PhotoSize>(index);
|
||||
|
||||
image.flags &= ~ImageFlag::Cancelled;
|
||||
image.loader = CreateFileLoader(
|
||||
image.location.file(),
|
||||
|
@ -320,38 +359,36 @@ void PhotoData::updateImages(
|
|||
}
|
||||
const auto update = [&](PhotoSize size, const ImageWithLocation &data) {
|
||||
auto &image = _images[PhotoSizeIndex(size)];
|
||||
if (data.location.valid()
|
||||
&& (!image.location.valid()
|
||||
|| image.location.width() != data.location.width()
|
||||
|| image.location.height() != data.location.height())) {
|
||||
image.location = data.location;
|
||||
if (!data.location.valid()) {
|
||||
return;
|
||||
}
|
||||
const auto changed = !image.location.valid()
|
||||
|| (image.location.width() != data.location.width())
|
||||
|| (image.location.height() != data.location.height());
|
||||
if (changed || (data.bytesCount && !image.byteSize)) {
|
||||
image.byteSize = data.bytesCount;
|
||||
if (!data.preloaded.isNull()) {
|
||||
image.loader = nullptr;
|
||||
if (const auto media = activeMediaView()) {
|
||||
media->set(size, data.preloaded);
|
||||
}
|
||||
} else if (image.loader) {
|
||||
const auto origin = base::take(image.loader)->fileOrigin();
|
||||
load(size, origin);
|
||||
}
|
||||
if (changed) {
|
||||
image.location = data.location;
|
||||
}
|
||||
if (!data.preloaded.isNull()) {
|
||||
image.loader = nullptr;
|
||||
if (const auto media = activeMediaView()) {
|
||||
media->set(size, data.preloaded);
|
||||
}
|
||||
if (!data.bytes.isEmpty()) {
|
||||
if (const auto cacheKey = image.location.file().cacheKey()) {
|
||||
owner().cache().putIfEmpty(
|
||||
cacheKey,
|
||||
Storage::Cache::Database::TaggedValue(
|
||||
base::duplicate(data.bytes),
|
||||
Data::kImageCacheTag));
|
||||
}
|
||||
} else if (changed && image.loader) {
|
||||
const auto origin = base::take(image.loader)->fileOrigin();
|
||||
load(size, origin);
|
||||
}
|
||||
if (!data.bytes.isEmpty()) {
|
||||
if (const auto cacheKey = image.location.file().cacheKey()) {
|
||||
owner().cache().putIfEmpty(
|
||||
cacheKey,
|
||||
Storage::Cache::Database::TaggedValue(
|
||||
base::duplicate(data.bytes),
|
||||
Data::kImageCacheTag));
|
||||
}
|
||||
}
|
||||
//if (was->isDelayedStorageImage()) { // #TODO optimize
|
||||
// if (const auto location = now->location(); location.valid()) {
|
||||
// was->setDelayedStorageLocation(
|
||||
// Data::FileOrigin(),
|
||||
// location);
|
||||
// }
|
||||
//}
|
||||
};
|
||||
update(PhotoSize::Small, small);
|
||||
update(PhotoSize::Thumbnail, thumbnail);
|
||||
|
|
|
@ -84,6 +84,7 @@ public:
|
|||
const ImageWithLocation &small,
|
||||
const ImageWithLocation &thumbnail,
|
||||
const ImageWithLocation &large);
|
||||
[[nodiscard]] int validSizeIndex(Data::PhotoSize size) const;
|
||||
|
||||
[[nodiscard]] QByteArray inlineThumbnailBytes() const {
|
||||
return _inlineThumbnailBytes;
|
||||
|
@ -94,6 +95,9 @@ public:
|
|||
LoadFromCloudSetting fromCloud = LoadFromCloudOrLocal,
|
||||
bool autoLoading = false);
|
||||
|
||||
[[nodiscard]] static int SideLimit();
|
||||
|
||||
[[nodiscard]] bool hasExact(Data::PhotoSize size) const;
|
||||
[[nodiscard]] bool loading(Data::PhotoSize size) const;
|
||||
[[nodiscard]] bool failed(Data::PhotoSize size) const;
|
||||
void load(
|
||||
|
@ -102,6 +106,7 @@ public:
|
|||
LoadFromCloudSetting fromCloud = LoadFromCloudOrLocal,
|
||||
bool autoLoading = false);
|
||||
[[nodiscard]] const ImageLocation &location(Data::PhotoSize size) const;
|
||||
[[nodiscard]] std::optional<QSize> size(Data::PhotoSize size) const;
|
||||
[[nodiscard]] int imageByteSize(Data::PhotoSize size) const;
|
||||
|
||||
// For now they return size of the 'large' image.
|
||||
|
|
|
@ -16,8 +16,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history.h"
|
||||
#include "storage/file_download.h"
|
||||
#include "ui/image/image.h"
|
||||
//#include "facades.h"
|
||||
//#include "app.h"
|
||||
|
||||
namespace Data {
|
||||
|
||||
|
@ -48,11 +46,14 @@ Image *PhotoMedia::thumbnailInline() const {
|
|||
}
|
||||
|
||||
Image *PhotoMedia::image(PhotoSize size) const {
|
||||
return _images[PhotoSizeIndex(size)].get();
|
||||
if (const auto image = _images[PhotoSizeIndex(size)].get()) {
|
||||
return image;
|
||||
}
|
||||
return _images[_owner->validSizeIndex(size)].get();
|
||||
}
|
||||
|
||||
void PhotoMedia::wanted(PhotoSize size, Data::FileOrigin origin) {
|
||||
const auto index = PhotoSizeIndex(size);
|
||||
const auto index = _owner->validSizeIndex(size);
|
||||
if (!_images[index]) {
|
||||
_owner->load(size, origin);
|
||||
}
|
||||
|
@ -68,7 +69,16 @@ QSize PhotoMedia::size(PhotoSize size) const {
|
|||
}
|
||||
|
||||
void PhotoMedia::set(PhotoSize size, QImage image) {
|
||||
_images[PhotoSizeIndex(size)] = std::make_unique<Image>(
|
||||
const auto index = PhotoSizeIndex(size);
|
||||
const auto limit = PhotoData::SideLimit();
|
||||
if (image.width() > limit || image.height() > limit) {
|
||||
image = image.scaled(
|
||||
limit,
|
||||
limit,
|
||||
Qt::KeepAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
}
|
||||
_images[index] = std::make_unique<Image>(
|
||||
std::make_unique<Images::ImageSource>(std::move(image), "PNG"));
|
||||
_owner->session().downloaderTaskFinished().notify();
|
||||
}
|
||||
|
|
|
@ -74,7 +74,7 @@ Image *ReplyPreview::image(Data::FileOrigin origin) {
|
|||
: Images::Option::None;
|
||||
if (thumbnail) {
|
||||
prepare(thumbnail, option);
|
||||
} else {
|
||||
} else if (!_image) {
|
||||
if (const auto image = _documentMedia->thumbnailInline()) {
|
||||
prepare(image, option | Images::Option::Blurred);
|
||||
}
|
||||
|
@ -96,23 +96,11 @@ Image *ReplyPreview::image(Data::FileOrigin origin) {
|
|||
} else if (const auto large = _photoMedia->image(
|
||||
PhotoSize::Large)) {
|
||||
prepare(large, Images::Option(0));
|
||||
} else if (const auto blurred = _photoMedia->thumbnailInline()) {
|
||||
prepare(blurred, Images::Option::Blurred);
|
||||
} else if (!_image) {
|
||||
if (const auto blurred = _photoMedia->thumbnailInline()) {
|
||||
prepare(blurred, Images::Option::Blurred);
|
||||
}
|
||||
}
|
||||
|
||||
//if (small->isDelayedStorageImage() // #TODO optimize
|
||||
// && !large->isNull()
|
||||
// && !large->isDelayedStorageImage()
|
||||
// && large->loaded()) {
|
||||
// prepare(large, Images::Option(0));
|
||||
//} else if (small->loaded()) {
|
||||
// prepare(small, Images::Option(0));
|
||||
//} else {
|
||||
// small->load(origin);
|
||||
// if (const auto blurred = _photo->thumbnailInline()) {
|
||||
// prepare(blurred, Images::Option::Blurred);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
}
|
||||
return _image.get();
|
||||
|
|
|
@ -76,9 +76,9 @@ using ViewElement = HistoryView::Element;
|
|||
// c: crop 640x640
|
||||
// d: crop 1280x1280
|
||||
const auto InlineLevels = "i"_q;
|
||||
const auto SmallLevels = "sambcxydwi"_q;
|
||||
const auto ThumbnailLevels = "mbcxasydwi"_q;
|
||||
const auto LargeLevels = "yxwmsdcbai"_q;
|
||||
const auto SmallLevels = "sa"_q;
|
||||
const auto ThumbnailLevels = "mbsa"_q;
|
||||
const auto LargeLevels = "ydxcwmbsa"_q;
|
||||
|
||||
void CheckForSwitchInlineButton(not_null<HistoryItem*> item) {
|
||||
if (item->out() || !item->hasSwitchInlineButton()) {
|
||||
|
@ -2277,31 +2277,11 @@ void Session::photoConvert(
|
|||
|
||||
PhotoData *Session::photoFromWeb(
|
||||
const MTPWebDocument &data,
|
||||
const ImageLocation &thumbnailLocation,
|
||||
bool willBecomeNormal) {
|
||||
const ImageLocation &thumbnailLocation) {
|
||||
const auto large = Images::FromWebDocument(data);
|
||||
const auto thumbnailInline = ImagePtr();
|
||||
if (!large.valid()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto small = large;
|
||||
auto thumbnail = thumbnailLocation;
|
||||
if (willBecomeNormal) {
|
||||
const auto width = large.width();
|
||||
const auto height = large.height();
|
||||
|
||||
// #TODO optimize
|
||||
//auto thumbsize = shrinkToKeepAspect(width, height, 100, 100);
|
||||
//small = Images::Create(thumbsize.width(), thumbsize.height());
|
||||
|
||||
//if (!thumbnail.valid()) {
|
||||
// auto mediumsize = shrinkToKeepAspect(width, height, 320, 320);
|
||||
// thumbnail = Images::Create(mediumsize.width(), mediumsize.height());
|
||||
//}
|
||||
} else if (!thumbnail.valid()) {
|
||||
thumbnail = large;
|
||||
}
|
||||
|
||||
return photo(
|
||||
rand_value<PhotoId>(),
|
||||
uint64(0),
|
||||
|
@ -2310,8 +2290,8 @@ PhotoData *Session::photoFromWeb(
|
|||
0,
|
||||
false,
|
||||
QByteArray(),
|
||||
ImageWithLocation{ .location = small },
|
||||
ImageWithLocation{ .location = thumbnail },
|
||||
ImageWithLocation{},
|
||||
ImageWithLocation{ .location = thumbnailLocation },
|
||||
ImageWithLocation{ .location = large });
|
||||
}
|
||||
|
||||
|
|
|
@ -487,8 +487,7 @@ public:
|
|||
const MTPPhoto &data);
|
||||
[[nodiscard]] PhotoData *photoFromWeb(
|
||||
const MTPWebDocument &data,
|
||||
const ImageLocation &thumbnailLocation = ImageLocation(),
|
||||
bool willBecomeNormal = false);
|
||||
const ImageLocation &thumbnailLocation);
|
||||
|
||||
[[nodiscard]] not_null<DocumentData*> document(DocumentId id);
|
||||
not_null<DocumentData*> processDocument(const MTPDocument &data);
|
||||
|
|
|
@ -61,7 +61,9 @@ void Photo::create(FullMsgId contextId, PeerData *chat) {
|
|||
std::make_shared<PhotoCancelClickHandler>(_data, contextId, chat));
|
||||
if ((_dataMedia = _data->activeMediaView())) {
|
||||
dataMediaCreated();
|
||||
} else if (_data->inlineThumbnailBytes().isEmpty()) {
|
||||
} else if (_data->inlineThumbnailBytes().isEmpty()
|
||||
&& (_data->hasExact(PhotoSize::Small)
|
||||
|| _data->hasExact(PhotoSize::Thumbnail))) {
|
||||
_data->load(PhotoSize::Small, contextId);
|
||||
}
|
||||
}
|
||||
|
@ -281,11 +283,7 @@ void Photo::draw(Painter &p, const QRect &r, TextSelection selection, crl::time
|
|||
p.setOpacity(radialOpacity);
|
||||
auto icon = [&]() -> const style::icon* {
|
||||
if (radial || _data->loading()) {
|
||||
if (_data->uploading()
|
||||
|| _data->location(PhotoSize::Large).valid()) {
|
||||
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
||||
}
|
||||
return nullptr;
|
||||
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
||||
}
|
||||
return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload);
|
||||
}();
|
||||
|
@ -351,9 +349,7 @@ TextState Photo::textState(QPoint point, StateRequest request) const {
|
|||
} else if (_dataMedia->loaded()) {
|
||||
result.link = _openl;
|
||||
} else if (_data->loading()) {
|
||||
if (_data->location(PhotoSize::Large).valid()) {
|
||||
result.link = _cancell;
|
||||
}
|
||||
result.link = _cancell;
|
||||
} else {
|
||||
result.link = _savel;
|
||||
}
|
||||
|
@ -456,11 +452,7 @@ void Photo::drawGrouped(
|
|||
if (_data->waitingForAlbum()) {
|
||||
return &(selected ? st::historyFileThumbWaitingSelected : st::historyFileThumbWaiting);
|
||||
} else if (radial || _data->loading()) {
|
||||
if (_data->uploading()
|
||||
|| _data->location(PhotoSize::Large).valid()) {
|
||||
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
||||
}
|
||||
return nullptr;
|
||||
return &(selected ? st::historyFileThumbCancelSelected : st::historyFileThumbCancel);
|
||||
}
|
||||
return &(selected ? st::historyFileThumbDownloadSelected : st::historyFileThumbDownload);
|
||||
}();
|
||||
|
@ -504,9 +496,7 @@ TextState Photo::getStateGrouped(
|
|||
: _dataMedia->loaded()
|
||||
? _openl
|
||||
: _data->loading()
|
||||
? (_data->location(PhotoSize::Large).valid()
|
||||
? _cancell
|
||||
: nullptr)
|
||||
? _cancell
|
||||
: _savel);
|
||||
}
|
||||
|
||||
|
|
|
@ -338,13 +338,12 @@ void Gif::validateThumbnail(
|
|||
}
|
||||
|
||||
void Gif::prepareThumbnail(QSize size, QSize frame) const {
|
||||
if (const auto document = getShownDocument()) {
|
||||
ensureDataMediaCreated(document);
|
||||
validateThumbnail(_dataMedia->thumbnail(), size, frame, true);
|
||||
validateThumbnail(_dataMedia->thumbnailInline(), size, frame, false);
|
||||
} else {
|
||||
validateThumbnail(getResultThumb(), size, frame, true);
|
||||
}
|
||||
const auto document = getShownDocument();
|
||||
Assert(document != nullptr);
|
||||
|
||||
ensureDataMediaCreated(document);
|
||||
validateThumbnail(_dataMedia->thumbnail(), size, frame, true);
|
||||
validateThumbnail(_dataMedia->thumbnailInline(), size, frame, false);
|
||||
}
|
||||
|
||||
void Gif::ensureDataMediaCreated(not_null<DocumentData*> document) const {
|
||||
|
@ -439,6 +438,7 @@ void Gif::clipCallback(Media::Clip::Notification notification) {
|
|||
|
||||
Sticker::Sticker(not_null<Context*> context, not_null<Result*> result)
|
||||
: FileBase(context, result) {
|
||||
Expects(getResultDocument() != nullptr);
|
||||
}
|
||||
|
||||
Sticker::~Sticker() = default;
|
||||
|
@ -449,12 +449,11 @@ void Sticker::initDimensions() {
|
|||
}
|
||||
|
||||
void Sticker::preload() const {
|
||||
if (const auto document = getShownDocument()) {
|
||||
ensureDataMediaCreated(document);
|
||||
_dataMedia->checkStickerSmall();
|
||||
} else if (const auto thumb = getResultThumb()) {
|
||||
thumb->load(fileOrigin());
|
||||
}
|
||||
const auto document = getShownDocument();
|
||||
Assert(document != nullptr);
|
||||
|
||||
ensureDataMediaCreated(document);
|
||||
_dataMedia->checkStickerSmall();
|
||||
}
|
||||
|
||||
void Sticker::ensureDataMediaCreated(not_null<DocumentData*> document) const {
|
||||
|
@ -549,40 +548,25 @@ void Sticker::setupLottie() const {
|
|||
}
|
||||
|
||||
void Sticker::prepareThumbnail() const {
|
||||
if (const auto document = getShownDocument()) {
|
||||
ensureDataMediaCreated(document);
|
||||
if (!_lottie
|
||||
&& document->sticker()
|
||||
&& document->sticker()->animated
|
||||
&& _dataMedia->loaded()) {
|
||||
setupLottie();
|
||||
}
|
||||
_dataMedia->checkStickerSmall();
|
||||
if (const auto sticker = _dataMedia->getStickerSmall()) {
|
||||
if (!_lottie && !_thumbLoaded && _dataMedia->loaded()) {
|
||||
const auto thumbSize = getThumbSize();
|
||||
_thumb = sticker->pix(
|
||||
document->stickerSetOrigin(),
|
||||
thumbSize.width(),
|
||||
thumbSize.height());
|
||||
_thumbLoaded = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const auto origin = fileOrigin();
|
||||
if (const auto thumb = getResultThumb()) {
|
||||
if (thumb->loaded()) {
|
||||
if (!_thumbLoaded) {
|
||||
const auto thumbSize = getThumbSize();
|
||||
_thumb = thumb->pix(
|
||||
origin,
|
||||
thumbSize.width(),
|
||||
thumbSize.height());
|
||||
_thumbLoaded = true;
|
||||
}
|
||||
} else {
|
||||
thumb->load(origin);
|
||||
}
|
||||
const auto document = getShownDocument();
|
||||
Assert(document != nullptr);
|
||||
|
||||
ensureDataMediaCreated(document);
|
||||
if (!_lottie
|
||||
&& document->sticker()
|
||||
&& document->sticker()->animated
|
||||
&& _dataMedia->loaded()) {
|
||||
setupLottie();
|
||||
}
|
||||
_dataMedia->checkStickerSmall();
|
||||
if (const auto sticker = _dataMedia->getStickerSmall()) {
|
||||
if (!_lottie && !_thumbLoaded && _dataMedia->loaded()) {
|
||||
const auto thumbSize = getThumbSize();
|
||||
_thumb = sticker->pix(
|
||||
document->stickerSetOrigin(),
|
||||
thumbSize.width(),
|
||||
thumbSize.height());
|
||||
_thumbLoaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -692,18 +676,18 @@ void Photo::validateThumbnail(
|
|||
}
|
||||
|
||||
void Photo::prepareThumbnail(QSize size, QSize frame) const {
|
||||
if (const auto photo = getShownPhoto()) {
|
||||
using PhotoSize = Data::PhotoSize;
|
||||
if (!_photoMedia) {
|
||||
_photoMedia = photo->createMediaView();
|
||||
_photoMedia->wanted(PhotoSize::Thumbnail, fileOrigin());
|
||||
}
|
||||
validateThumbnail(_photoMedia->image(PhotoSize::Thumbnail), size, frame, true);
|
||||
validateThumbnail(_photoMedia->image(PhotoSize::Small), size, frame, false);
|
||||
validateThumbnail(_photoMedia->thumbnailInline(), size, frame, false);
|
||||
} else if (const auto thumbnail = getResultThumb()) {
|
||||
validateThumbnail(thumbnail, size, frame, true);
|
||||
using PhotoSize = Data::PhotoSize;
|
||||
|
||||
const auto photo = getShownPhoto();
|
||||
Assert(photo != nullptr);
|
||||
|
||||
if (!_photoMedia) {
|
||||
_photoMedia = photo->createMediaView();
|
||||
_photoMedia->wanted(PhotoSize::Thumbnail, fileOrigin());
|
||||
}
|
||||
validateThumbnail(_photoMedia->image(PhotoSize::Thumbnail), size, frame, true);
|
||||
validateThumbnail(_photoMedia->image(PhotoSize::Small), size, frame, false);
|
||||
validateThumbnail(_photoMedia->thumbnailInline(), size, frame, false);
|
||||
}
|
||||
|
||||
Video::Video(not_null<Context*> context, not_null<Result*> result)
|
||||
|
@ -711,6 +695,8 @@ Video::Video(not_null<Context*> context, not_null<Result*> result)
|
|||
, _link(getResultPreviewHandler())
|
||||
, _title(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip)
|
||||
, _description(st::emojiPanWidth - st::emojiScroll.width - st::inlineResultsLeft - st::inlineThumbSize - st::inlineThumbSkip) {
|
||||
Assert(getResultDocument() != nullptr);
|
||||
|
||||
if (int duration = content_duration()) {
|
||||
_duration = formatDurationText(duration);
|
||||
_durationWidth = st::normalFont->width(_duration);
|
||||
|
@ -718,12 +704,10 @@ Video::Video(not_null<Context*> context, not_null<Result*> result)
|
|||
}
|
||||
|
||||
bool Video::withThumbnail() const {
|
||||
if (const auto document = getShownDocument()) {
|
||||
if (document->hasThumbnail()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return getResultThumb() != nullptr;
|
||||
const auto document = getShownDocument();
|
||||
Assert(document != nullptr);
|
||||
|
||||
return document->hasThumbnail();
|
||||
}
|
||||
|
||||
void Video::initDimensions() {
|
||||
|
@ -818,9 +802,7 @@ void Video::prepareThumbnail(QSize size) const {
|
|||
return;
|
||||
}
|
||||
}
|
||||
const auto thumb = document->hasThumbnail()
|
||||
? _documentMedia->thumbnail()
|
||||
: getResultThumb();
|
||||
const auto thumb = _documentMedia->thumbnail();
|
||||
if (!thumb) {
|
||||
return;
|
||||
}
|
||||
|
@ -864,6 +846,8 @@ File::File(not_null<Context*> context, not_null<Result*> result)
|
|||
, _open(std::make_shared<OpenFileClickHandler>(result))
|
||||
, _cancel(std::make_shared<CancelFileClickHandler>(result))
|
||||
, _document(getShownDocument()) {
|
||||
Expects(getResultDocument() != nullptr);
|
||||
|
||||
updateStatusText();
|
||||
|
||||
// We have to save document, not read it from Result every time.
|
||||
|
@ -1146,7 +1130,8 @@ TextState Contact::getState(
|
|||
}
|
||||
|
||||
void Contact::prepareThumbnail(int width, int height) const {
|
||||
const auto thumb = getResultThumb(); // #TODO optimize
|
||||
// #TODO optimize use photo / document thumbnail as well
|
||||
const auto thumb = getResultThumb();
|
||||
if (!thumb) {
|
||||
if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) {
|
||||
_thumb = getResultContactAvatar(width, height);
|
||||
|
@ -1235,7 +1220,8 @@ void Article::paint(Painter &p, const QRect &clip, const PaintContext *context)
|
|||
prepareThumbnail(st::inlineThumbSize, st::inlineThumbSize);
|
||||
QRect rthumb(style::rtlrect(0, st::inlineRowMargin, st::inlineThumbSize, st::inlineThumbSize, _width));
|
||||
if (_thumb.isNull()) {
|
||||
const auto thumb = getResultThumb(); // #TODO optimize
|
||||
// #TODO optimize use photo / document thumbnail as well
|
||||
const auto thumb = getResultThumb();
|
||||
if (!thumb && !_thumbLetter.isEmpty()) {
|
||||
int32 index = (_thumbLetter.at(0).unicode() % 4);
|
||||
style::color colors[] = {
|
||||
|
@ -1300,7 +1286,8 @@ TextState Article::getState(
|
|||
}
|
||||
|
||||
void Article::prepareThumbnail(int width, int height) const {
|
||||
const auto thumb = getResultThumb(); // #TODO optimize
|
||||
// #TODO optimize use photo / document thumbnail as well
|
||||
const auto thumb = getResultThumb();
|
||||
if (!thumb) {
|
||||
if (_thumb.width() != width * cIntRetinaFactor() || _thumb.height() != height * cIntRetinaFactor()) {
|
||||
_thumb = getResultContactAvatar(width, height);
|
||||
|
|
|
@ -69,16 +69,18 @@ PhotoData *ItemBase::getPreviewPhoto() const {
|
|||
void ItemBase::preload() const {
|
||||
const auto origin = fileOrigin();
|
||||
if (_result) {
|
||||
if (_result->_photo) {
|
||||
_result->_photo->load(Data::PhotoSize::Thumbnail, origin);
|
||||
} else if (_result->_document) {
|
||||
_result->_document->loadThumbnail(origin);
|
||||
} else if (!_result->_thumb->isNull()) {
|
||||
_result->_thumb->load(origin);
|
||||
if (const auto photo = _result->_photo) {
|
||||
if (photo->hasExact(Data::PhotoSize::Thumbnail)) {
|
||||
photo->load(Data::PhotoSize::Thumbnail, origin);
|
||||
}
|
||||
} else if (const auto document = _result->_document) {
|
||||
document->loadThumbnail(origin);
|
||||
} else if (const auto thumb = _result->_thumb; !thumb->isNull()) {
|
||||
thumb->load(origin);
|
||||
}
|
||||
} else if (_document) {
|
||||
_document->loadThumbnail(origin);
|
||||
} else if (_photo) {
|
||||
} else if (_photo && _photo->hasExact(Data::PhotoSize::Thumbnail)) {
|
||||
_photo->load(Data::PhotoSize::Thumbnail, origin);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,33 +47,29 @@ Result::Result(const Creator &creator) : _queryId(creator.queryId), _type(creato
|
|||
std::unique_ptr<Result> Result::create(
|
||||
uint64 queryId,
|
||||
const MTPBotInlineResult &mtpData) {
|
||||
using StringToTypeMap = QMap<QString, Result::Type>;
|
||||
static StaticNeverFreedPointer<StringToTypeMap> stringToTypeMap{ ([]() -> StringToTypeMap* {
|
||||
auto result = std::make_unique<StringToTypeMap>();
|
||||
result->insert(qsl("photo"), Result::Type::Photo);
|
||||
result->insert(qsl("video"), Result::Type::Video);
|
||||
result->insert(qsl("audio"), Result::Type::Audio);
|
||||
result->insert(qsl("voice"), Result::Type::Audio);
|
||||
result->insert(qsl("sticker"), Result::Type::Sticker);
|
||||
result->insert(qsl("file"), Result::Type::File);
|
||||
result->insert(qsl("gif"), Result::Type::Gif);
|
||||
result->insert(qsl("article"), Result::Type::Article);
|
||||
result->insert(qsl("contact"), Result::Type::Contact);
|
||||
result->insert(qsl("venue"), Result::Type::Venue);
|
||||
result->insert(qsl("geo"), Result::Type::Geo);
|
||||
result->insert(qsl("game"), Result::Type::Game);
|
||||
return result.release();
|
||||
})() };
|
||||
using Type = Result::Type;
|
||||
|
||||
auto getInlineResultType = [](const MTPBotInlineResult &inlineResult) -> Type {
|
||||
QString type;
|
||||
switch (inlineResult.type()) {
|
||||
case mtpc_botInlineResult: type = qs(inlineResult.c_botInlineResult().vtype()); break;
|
||||
case mtpc_botInlineMediaResult: type = qs(inlineResult.c_botInlineMediaResult().vtype()); break;
|
||||
}
|
||||
return stringToTypeMap->value(type, Type::Unknown);
|
||||
};
|
||||
Type type = getInlineResultType(mtpData);
|
||||
const auto type = [&] {
|
||||
static const auto kStringToTypeMap = base::flat_map<QString, Type>{
|
||||
{ u"photo"_q, Type::Photo },
|
||||
{ u"video"_q, Type::Video },
|
||||
{ u"audio"_q, Type::Audio },
|
||||
{ u"voice"_q, Type::Audio },
|
||||
{ u"sticker"_q, Type::Sticker },
|
||||
{ u"file"_q, Type::File },
|
||||
{ u"gif"_q, Type::Gif },
|
||||
{ u"article"_q, Type::Article },
|
||||
{ u"contact"_q, Type::Contact },
|
||||
{ u"venue"_q, Type::Venue },
|
||||
{ u"geo"_q, Type::Geo },
|
||||
{ u"game"_q, Type::Game },
|
||||
};
|
||||
const auto type = mtpData.match([](const auto &data) {
|
||||
return qs(data.vtype());
|
||||
});
|
||||
const auto i = kStringToTypeMap.find(type);
|
||||
return (i != kStringToTypeMap.end()) ? i->second : Type::Unknown;
|
||||
}();
|
||||
if (type == Type::Unknown) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -95,12 +91,17 @@ std::unique_ptr<Result> Result::create(
|
|||
}
|
||||
return QByteArray();
|
||||
}();
|
||||
const auto contentMime = [&] {
|
||||
if (const auto content = r.vcontent()) {
|
||||
return content->match([&](const auto &data) {
|
||||
return data.vmime_type().v;
|
||||
});
|
||||
}
|
||||
return QByteArray();
|
||||
}();
|
||||
const auto imageThumb = !thumbMime.isEmpty()
|
||||
&& (thumbMime != kVideoThumbMime);
|
||||
const auto videoThumb = !thumbMime.isEmpty() && !imageThumb;
|
||||
if (imageThumb) {
|
||||
result->_thumb = Images::Create(*r.vthumb(), result->thumbBox());
|
||||
}
|
||||
if (const auto content = r.vcontent()) {
|
||||
result->_content_url = GetContentUrl(*content);
|
||||
if (result->_type == Type::Photo) {
|
||||
|
@ -108,9 +109,8 @@ std::unique_ptr<Result> Result::create(
|
|||
*content,
|
||||
(imageThumb
|
||||
? Images::FromWebDocument(*r.vthumb())
|
||||
: ImageLocation()),
|
||||
true);
|
||||
} else {
|
||||
: ImageLocation()));
|
||||
} else if (contentMime != "text/html"_q) {
|
||||
result->_document = Auth().data().documentFromWeb(
|
||||
result->adjustAttributes(*content),
|
||||
(imageThumb
|
||||
|
@ -121,6 +121,9 @@ std::unique_ptr<Result> Result::create(
|
|||
: ImageLocation()));
|
||||
}
|
||||
}
|
||||
if (!result->_photo && !result->_document && imageThumb) {
|
||||
result->_thumb = Images::Create(*r.vthumb(), result->thumbBox());
|
||||
}
|
||||
message = &r.vsend_message();
|
||||
} break;
|
||||
case mtpc_botInlineMediaResult: {
|
||||
|
@ -342,13 +345,13 @@ void Result::cancelFile() {
|
|||
}
|
||||
|
||||
bool Result::hasThumbDisplay() const {
|
||||
if (!_thumb->isNull()) {
|
||||
if (!_thumb->isNull()
|
||||
|| _photo
|
||||
|| (_document && _document->hasThumbnail())) {
|
||||
return true;
|
||||
}
|
||||
if (_type == Type::Contact) {
|
||||
} else if (_type == Type::Contact) {
|
||||
return true;
|
||||
}
|
||||
if (sendData->hasLocationCoords()) {
|
||||
} else if (sendData->hasLocationCoords()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -298,7 +298,9 @@ Photo::Photo(
|
|||
: ItemBase(delegate, parent)
|
||||
, _data(photo)
|
||||
, _link(std::make_shared<PhotoOpenClickHandler>(photo, parent->fullId())) {
|
||||
if (_data->inlineThumbnailBytes().isEmpty()) {
|
||||
if (_data->inlineThumbnailBytes().isEmpty()
|
||||
&& (_data->hasExact(Data::PhotoSize::Small)
|
||||
|| _data->hasExact(Data::PhotoSize::Thumbnail))) {
|
||||
_data->load(Data::PhotoSize::Small, parent->fullId());
|
||||
}
|
||||
}
|
||||
|
@ -1476,9 +1478,14 @@ Link::Link(
|
|||
}
|
||||
int32 tw = 0, th = 0;
|
||||
if (_page && _page->photo) {
|
||||
_page->photo->load(Data::PhotoSize::Small, parent->fullId());
|
||||
tw = style::ConvertScale(_page->photo->width());
|
||||
th = style::ConvertScale(_page->photo->height());
|
||||
const auto photo = _page->photo;
|
||||
if (photo->inlineThumbnailBytes().isEmpty()
|
||||
&& (photo->hasExact(Data::PhotoSize::Small)
|
||||
|| photo->hasExact(Data::PhotoSize::Thumbnail))) {
|
||||
photo->load(Data::PhotoSize::Small, parent->fullId());
|
||||
}
|
||||
tw = style::ConvertScale(photo->width());
|
||||
th = style::ConvertScale(photo->height());
|
||||
} else if (_page && _page->document && _page->document->hasThumbnail()) {
|
||||
_page->document->loadThumbnail(parent->fullId());
|
||||
const auto &location = _page->document->thumbnailLocation();
|
||||
|
|
|
@ -210,12 +210,6 @@ ImagePtr Create(
|
|||
std::move(image))));
|
||||
}
|
||||
|
||||
ImagePtr Create(int width, int height) {
|
||||
return ImagePtr(new Image(std::make_unique<DelayedStorageSource>(
|
||||
width,
|
||||
height)));
|
||||
}
|
||||
|
||||
template <typename SourceType>
|
||||
ImagePtr Create(
|
||||
const StorageImageLocation &location,
|
||||
|
|
|
@ -31,7 +31,6 @@ ImagePtr Create(
|
|||
const QByteArray &filecontent,
|
||||
QByteArray format,
|
||||
QImage &&data);
|
||||
ImagePtr Create(int width, int height);
|
||||
ImagePtr Create(const StorageImageLocation &location, int size = 0);
|
||||
ImagePtr CreateStickerSetThumbnail(const StorageImageLocation &location);
|
||||
ImagePtr Create( // photoCachedSize
|
||||
|
@ -79,7 +78,6 @@ public:
|
|||
virtual void setDelayedStorageLocation(
|
||||
const StorageImageLocation &location) = 0;
|
||||
virtual void performDelayedLoad(Data::FileOrigin origin) = 0;
|
||||
virtual bool isDelayedStorageImage() const = 0;
|
||||
virtual void setImageBytes(const QByteArray &bytes) = 0;
|
||||
|
||||
virtual int width() = 0;
|
||||
|
@ -215,9 +213,6 @@ public:
|
|||
QByteArray bytesForCache() const {
|
||||
return _source->bytesForCache();
|
||||
}
|
||||
bool isDelayedStorageImage() const {
|
||||
return _source->isDelayedStorageImage();
|
||||
}
|
||||
|
||||
bool loaded() const;
|
||||
bool isNull() const;
|
||||
|
|
|
@ -94,10 +94,6 @@ void ImageSource::setDelayedStorageLocation(
|
|||
void ImageSource::performDelayedLoad(Data::FileOrigin origin) {
|
||||
}
|
||||
|
||||
bool ImageSource::isDelayedStorageImage() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void ImageSource::setImageBytes(const QByteArray &bytes) {
|
||||
}
|
||||
|
||||
|
@ -215,10 +211,6 @@ void LocalFileSource::setDelayedStorageLocation(
|
|||
void LocalFileSource::performDelayedLoad(Data::FileOrigin origin) {
|
||||
}
|
||||
|
||||
bool LocalFileSource::isDelayedStorageImage() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void LocalFileSource::setImageBytes(const QByteArray &bytes) {
|
||||
_bytes = bytes;
|
||||
load({});
|
||||
|
@ -388,10 +380,6 @@ void RemoteSource::setDelayedStorageLocation(
|
|||
void RemoteSource::performDelayedLoad(Data::FileOrigin origin) {
|
||||
}
|
||||
|
||||
bool RemoteSource::isDelayedStorageImage() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray RemoteSource::bytesForCache() {
|
||||
return QByteArray();
|
||||
}
|
||||
|
@ -572,89 +560,6 @@ std::unique_ptr<FileLoader> GeoPointSource::createLoader(
|
|||
Data::kImageCacheTag);
|
||||
}
|
||||
|
||||
DelayedStorageSource::DelayedStorageSource()
|
||||
: StorageSource(StorageImageLocation(), 0) {
|
||||
}
|
||||
|
||||
DelayedStorageSource::DelayedStorageSource(int w, int h)
|
||||
: StorageSource(StorageImageLocation(StorageFileLocation(), w, h), 0) {
|
||||
}
|
||||
|
||||
void DelayedStorageSource::setDelayedStorageLocation(
|
||||
const StorageImageLocation &location) {
|
||||
_location = location;
|
||||
}
|
||||
|
||||
void DelayedStorageSource::performDelayedLoad(Data::FileOrigin origin) {
|
||||
if (!_loadRequested) {
|
||||
return;
|
||||
}
|
||||
_loadRequested = false;
|
||||
if (_loadCancelled) {
|
||||
return;
|
||||
}
|
||||
if (base::take(_loadFromCloud)) {
|
||||
load(origin);
|
||||
} else {
|
||||
loadLocal();
|
||||
}
|
||||
}
|
||||
//
|
||||
//void DelayedStorageSource::automaticLoad(
|
||||
// Data::FileOrigin origin,
|
||||
// const HistoryItem *item) {
|
||||
// if (_location.valid()) {
|
||||
// StorageSource::automaticLoad(origin, item);
|
||||
// return;
|
||||
// } else if (_loadCancelled || !item) {
|
||||
// return;
|
||||
// }
|
||||
// const auto loadFromCloud = Data::AutoDownload::Should(
|
||||
// Auth().settings().autoDownload(),
|
||||
// item->history()->peer,
|
||||
// this);
|
||||
//
|
||||
// if (_loadRequested) {
|
||||
// if (loadFromCloud) _loadFromCloud = loadFromCloud;
|
||||
// } else {
|
||||
// _loadFromCloud = loadFromCloud;
|
||||
// _loadRequested = true;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//void DelayedStorageSource::automaticLoadSettingsChanged() {
|
||||
// if (_loadCancelled) _loadCancelled = false;
|
||||
// StorageSource::automaticLoadSettingsChanged();
|
||||
//}
|
||||
|
||||
void DelayedStorageSource::load(Data::FileOrigin origin) {
|
||||
if (_location.valid()) {
|
||||
StorageSource::load(origin);
|
||||
} else {
|
||||
_loadRequested = _loadFromCloud = true;
|
||||
}
|
||||
}
|
||||
|
||||
void DelayedStorageSource::loadEvenCancelled(Data::FileOrigin origin) {
|
||||
_loadCancelled = false;
|
||||
StorageSource::loadEvenCancelled(origin);
|
||||
}
|
||||
|
||||
bool DelayedStorageSource::displayLoading() {
|
||||
return _location.valid() ? StorageSource::displayLoading() : true;
|
||||
}
|
||||
|
||||
void DelayedStorageSource::cancel() {
|
||||
if (_loadRequested) {
|
||||
_loadRequested = false;
|
||||
}
|
||||
StorageSource::cancel();
|
||||
}
|
||||
|
||||
bool DelayedStorageSource::isDelayedStorageImage() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
WebUrlSource::WebUrlSource(const QString &url, QSize box)
|
||||
: _url(url)
|
||||
, _box(box) {
|
||||
|
|
|
@ -32,7 +32,6 @@ public:
|
|||
void setDelayedStorageLocation(
|
||||
const StorageImageLocation &location) override;
|
||||
void performDelayedLoad(Data::FileOrigin origin) override;
|
||||
bool isDelayedStorageImage() const override;
|
||||
void setImageBytes(const QByteArray &bytes) override;
|
||||
|
||||
int width() override;
|
||||
|
@ -76,7 +75,6 @@ public:
|
|||
void setDelayedStorageLocation(
|
||||
const StorageImageLocation &location) override;
|
||||
void performDelayedLoad(Data::FileOrigin origin) override;
|
||||
bool isDelayedStorageImage() const override;
|
||||
void setImageBytes(const QByteArray &bytes) override;
|
||||
|
||||
int width() override;
|
||||
|
@ -116,7 +114,6 @@ public:
|
|||
void setDelayedStorageLocation(
|
||||
const StorageImageLocation &location) override;
|
||||
void performDelayedLoad(Data::FileOrigin origin) override;
|
||||
bool isDelayedStorageImage() const override;
|
||||
void setImageBytes(const QByteArray &bytes) override;
|
||||
|
||||
QByteArray bytesForCache() override;
|
||||
|
@ -228,35 +225,6 @@ protected:
|
|||
|
||||
};
|
||||
|
||||
class DelayedStorageSource : public StorageSource {
|
||||
public:
|
||||
DelayedStorageSource();
|
||||
DelayedStorageSource(int width, int height);
|
||||
|
||||
void load(Data::FileOrigin origin) override;
|
||||
void loadEvenCancelled(Data::FileOrigin origin) override;
|
||||
|
||||
void setDelayedStorageLocation(
|
||||
const StorageImageLocation &location) override;
|
||||
bool isDelayedStorageImage() const override;
|
||||
void performDelayedLoad(Data::FileOrigin origin) override;
|
||||
|
||||
bool loading() override {
|
||||
return _location.valid()
|
||||
? StorageSource::loading()
|
||||
: _loadRequested;
|
||||
}
|
||||
bool displayLoading() override;
|
||||
void cancel() override;
|
||||
|
||||
|
||||
private:
|
||||
bool _loadRequested = false;
|
||||
bool _loadCancelled = false;
|
||||
bool _loadFromCloud = false;
|
||||
|
||||
};
|
||||
|
||||
class WebUrlSource : public RemoteSource {
|
||||
public:
|
||||
// If !box.isEmpty() then resize the image to fit in this box.
|
||||
|
|
Loading…
Reference in New Issue