From 7ad660a0e7733e61a34bf4618e43fad99095b86d Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 26 May 2020 14:13:32 +0400 Subject: [PATCH] Allow photos not have some of the thumbnails. --- .../chat_helpers/gifs_list_widget.cpp | 5 +- .../chat_helpers/stickers_emoji_pack.cpp | 5 - .../SourceFiles/data/data_media_types.cpp | 4 +- Telegram/SourceFiles/data/data_photo.cpp | 103 +++++++++----- Telegram/SourceFiles/data/data_photo.h | 5 + .../SourceFiles/data/data_photo_media.cpp | 20 ++- .../SourceFiles/data/data_reply_preview.cpp | 22 +-- Telegram/SourceFiles/data/data_session.cpp | 32 +---- Telegram/SourceFiles/data/data_session.h | 3 +- .../history/view/media/history_view_photo.cpp | 24 +--- .../inline_bot_layout_internal.cpp | 127 ++++++++---------- .../inline_bots/inline_bot_layout_item.cpp | 16 ++- .../inline_bots/inline_bot_result.cpp | 77 ++++++----- .../SourceFiles/overview/overview_layout.cpp | 15 ++- Telegram/SourceFiles/ui/image/image.cpp | 6 - Telegram/SourceFiles/ui/image/image.h | 5 - .../SourceFiles/ui/image/image_source.cpp | 95 ------------- Telegram/SourceFiles/ui/image/image_source.h | 32 ----- 18 files changed, 233 insertions(+), 363 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 5398d74c4..aa719e28b 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -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 { diff --git a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp index 51b0bb31d..2c99cd707 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_emoji_pack.cpp @@ -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) { } diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index c10b98b82..09c99f508 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -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; } diff --git a/Telegram/SourceFiles/data/data_photo.cpp b/Telegram/SourceFiles/data/data_photo.cpp index 7c0c872a5..80e3386a5 100644 --- a/Telegram/SourceFiles/data/data_photo.cpp +++ b/Telegram/SourceFiles/data/data_photo.cpp @@ -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 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(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); diff --git a/Telegram/SourceFiles/data/data_photo.h b/Telegram/SourceFiles/data/data_photo.h index f08c8fe57..f0f67d727 100644 --- a/Telegram/SourceFiles/data/data_photo.h +++ b/Telegram/SourceFiles/data/data_photo.h @@ -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 size(Data::PhotoSize size) const; [[nodiscard]] int imageByteSize(Data::PhotoSize size) const; // For now they return size of the 'large' image. diff --git a/Telegram/SourceFiles/data/data_photo_media.cpp b/Telegram/SourceFiles/data/data_photo_media.cpp index 7f82a124b..46047046f 100644 --- a/Telegram/SourceFiles/data/data_photo_media.cpp +++ b/Telegram/SourceFiles/data/data_photo_media.cpp @@ -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( + 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( std::make_unique(std::move(image), "PNG")); _owner->session().downloaderTaskFinished().notify(); } diff --git a/Telegram/SourceFiles/data/data_reply_preview.cpp b/Telegram/SourceFiles/data/data_reply_preview.cpp index ba2d84d0b..989048ead 100644 --- a/Telegram/SourceFiles/data/data_reply_preview.cpp +++ b/Telegram/SourceFiles/data/data_reply_preview.cpp @@ -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(); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 5fbb81a1f..593820825 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -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 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(), 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 }); } diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 8ebbbe2c6..3039aa17c 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -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 document(DocumentId id); not_null processDocument(const MTPDocument &data); diff --git a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp index ad63d357d..50f493a26 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_photo.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_photo.cpp @@ -61,7 +61,9 @@ void Photo::create(FullMsgId contextId, PeerData *chat) { std::make_shared(_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); } diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index 050876814..858bb9877 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -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 document) const { @@ -439,6 +438,7 @@ void Gif::clipCallback(Media::Clip::Notification notification) { Sticker::Sticker(not_null context, not_null 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 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, not_null result) @@ -711,6 +695,8 @@ Video::Video(not_null context, not_null 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, not_null 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, not_null result) , _open(std::make_shared(result)) , _cancel(std::make_shared(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); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp index 0173e3b38..fdf6b2b0c 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_item.cpp @@ -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); } } diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp index 781e2caff..3039322e0 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.cpp @@ -47,33 +47,29 @@ Result::Result(const Creator &creator) : _queryId(creator.queryId), _type(creato std::unique_ptr Result::create( uint64 queryId, const MTPBotInlineResult &mtpData) { - using StringToTypeMap = QMap; - static StaticNeverFreedPointer stringToTypeMap{ ([]() -> StringToTypeMap* { - auto result = std::make_unique(); - 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{ + { 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::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::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::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; diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp index 439aea9a3..1001ade11 100644 --- a/Telegram/SourceFiles/overview/overview_layout.cpp +++ b/Telegram/SourceFiles/overview/overview_layout.cpp @@ -298,7 +298,9 @@ Photo::Photo( : ItemBase(delegate, parent) , _data(photo) , _link(std::make_shared(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(); diff --git a/Telegram/SourceFiles/ui/image/image.cpp b/Telegram/SourceFiles/ui/image/image.cpp index 81c73ffeb..94e6869ee 100644 --- a/Telegram/SourceFiles/ui/image/image.cpp +++ b/Telegram/SourceFiles/ui/image/image.cpp @@ -210,12 +210,6 @@ ImagePtr Create( std::move(image)))); } -ImagePtr Create(int width, int height) { - return ImagePtr(new Image(std::make_unique( - width, - height))); -} - template ImagePtr Create( const StorageImageLocation &location, diff --git a/Telegram/SourceFiles/ui/image/image.h b/Telegram/SourceFiles/ui/image/image.h index a72a6cced..1a4630683 100644 --- a/Telegram/SourceFiles/ui/image/image.h +++ b/Telegram/SourceFiles/ui/image/image.h @@ -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; diff --git a/Telegram/SourceFiles/ui/image/image_source.cpp b/Telegram/SourceFiles/ui/image/image_source.cpp index bb73d1aa2..61304fd5e 100644 --- a/Telegram/SourceFiles/ui/image/image_source.cpp +++ b/Telegram/SourceFiles/ui/image/image_source.cpp @@ -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 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) { diff --git a/Telegram/SourceFiles/ui/image/image_source.h b/Telegram/SourceFiles/ui/image/image_source.h index 5de31969e..913da40fc 100644 --- a/Telegram/SourceFiles/ui/image/image_source.h +++ b/Telegram/SourceFiles/ui/image/image_source.h @@ -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.