Allow photos not have some of the thumbnails.

This commit is contained in:
John Preston 2020-05-26 14:13:32 +04:00
parent e27d2bc2d5
commit 7ad660a0e7
18 changed files with 233 additions and 363 deletions

View File

@ -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 {

View File

@ -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) {
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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();
}

View File

@ -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();

View File

@ -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 });
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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();

View File

@ -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,

View File

@ -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;

View File

@ -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) {

View File

@ -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.