diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index 7223c6dbcc..97ef0e6d65 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -171,8 +171,19 @@ struct AlbumCounts { } template -[[nodiscard]] uint64 CountCacheKey(not_null data, bool spoiler) { - return (reinterpret_cast(data.get()) & ~1) | (spoiler ? 1 : 0); +[[nodiscard]] uint64 CountCacheKey( + not_null data, + ImageRoundRadius radius, + bool spoiler) { + return (reinterpret_cast(data.get()) & ~3) + | ((radius == ImageRoundRadius::Ellipse) ? 2 : 0) + | (spoiler ? 1 : 0); +} + +[[nodiscard]] uint64 SimpleCacheKey(ImageRoundRadius radius, bool spoiler) { + return uint64() + | ((radius == ImageRoundRadius::Ellipse) ? 2 : 0) + | (spoiler ? 1 : 0); } [[nodiscard]] ItemPreviewImage PreparePhotoPreviewImage( @@ -181,7 +192,7 @@ template ImageRoundRadius radius, bool spoiler) { const auto photo = media->owner(); - const auto counted = CountCacheKey(photo, spoiler); + const auto counted = CountCacheKey(photo, radius, spoiler); if (const auto small = media->image(PhotoSize::Small)) { return { PreparePreviewImage(small, radius, spoiler), counted }; } else if (const auto thumbnail = media->image(PhotoSize::Thumbnail)) { @@ -191,15 +202,15 @@ template } const auto allowedToDownload = media->autoLoadThumbnailAllowed( item->history()->peer); - const auto spoilered = uint64(spoiler ? 1 : 0); - const auto cacheKey = allowedToDownload ? spoilered : counted; + const auto simple = SimpleCacheKey(radius, spoiler); + const auto cacheKey = allowedToDownload ? simple : counted; if (allowedToDownload) { media->owner()->load(PhotoSize::Small, item->fullId()); } if (const auto blurred = media->thumbnailInline()) { return { PreparePreviewImage(blurred, radius, spoiler), cacheKey }; } - return { QImage(), allowedToDownload ? spoilered : cacheKey }; + return { QImage(), allowedToDownload ? simple : cacheKey }; } [[nodiscard]] ItemPreviewImage PrepareFilePreviewImage( @@ -210,7 +221,7 @@ template Expects(media->owner()->hasThumbnail()); const auto document = media->owner(); - const auto readyCacheKey = CountCacheKey(document, spoiler); + const auto readyCacheKey = CountCacheKey(document, radius, spoiler); if (const auto thumbnail = media->thumbnail()) { return { PreparePreviewImage(thumbnail, radius, spoiler), @@ -218,11 +229,11 @@ template }; } document->loadThumbnail(item->fullId()); - const auto spoilered = uint64(spoiler ? 1 : 0); + const auto simple = SimpleCacheKey(radius, spoiler); if (const auto blurred = media->thumbnailInline()) { - return { PreparePreviewImage(blurred, radius, spoiler), spoilered }; + return { PreparePreviewImage(blurred, radius, spoiler), simple }; } - return { QImage(), spoilered }; + return { QImage(), simple }; } [[nodiscard]] QImage PutPlayIcon(QImage preview) { @@ -274,13 +285,14 @@ template [[nodiscard]] ItemPreviewImage FindCachedPreview( const std::vector *existing, not_null data, + ImageRoundRadius radius, bool spoiler) { if (!existing) { return {}; } const auto i = ranges::find( *existing, - CountCacheKey(data, spoiler), + CountCacheKey(data, radius, spoiler), &ItemPreviewImage::cacheKey); return (i != end(*existing)) ? *i : ItemPreviewImage(); } @@ -856,13 +868,17 @@ ItemPreview MediaPhoto::toPreview(ToPreviewOptions options) const { } auto images = std::vector(); auto context = std::any(); - if (auto found = FindCachedPreview(options.existing, _photo, _spoiler)) { + const auto radius = _chat + ? ImageRoundRadius::Ellipse + : ImageRoundRadius::Small; + if (auto found = FindCachedPreview( + options.existing, + _photo, + radius, + _spoiler)) { images.push_back(std::move(found)); } else { const auto media = _photo->createMediaView(); - const auto radius = _chat - ? ImageRoundRadius::Ellipse - : ImageRoundRadius::Small; if (auto prepared = PreparePhotoPreview( parent(), media, @@ -1103,13 +1119,17 @@ ItemPreview MediaFile::toPreview(ToPreviewOptions options) const { const auto existing = options.existing; const auto spoilered = _spoiler || (_document->isVideoMessage() && ttlSeconds()); - if (auto found = FindCachedPreview(existing, _document, spoilered)) { + const auto radius = _document->isVideoMessage() + ? ImageRoundRadius::Ellipse + : ImageRoundRadius::Small; + if (auto found = FindCachedPreview( + existing, + _document, + radius, + spoilered)) { images.push_back(std::move(found)); } else if (TryFilePreview(_document)) { const auto media = _document->createMediaView(); - const auto radius = _document->isVideoMessage() - ? ImageRoundRadius::Ellipse - : ImageRoundRadius::Small; if (auto prepared = PrepareFilePreview( parent(), media, @@ -1811,13 +1831,17 @@ ItemPreview MediaWebPage::toPreview(ToPreviewOptions options) const { || _page->type == WebPageType::Video || _page->type == WebPageType::Document; if (pageTypeWithPreview || !_page->collage.items.empty()) { - if (auto found = FindCachedPreview(options.existing, _page, false)) { + const auto radius = ImageRoundRadius::Small; + if (auto found = FindCachedPreview( + options.existing, + _page, + radius, + false)) { return { .text = caption, .images = { std::move(found) } }; } auto context = std::any(); auto images = std::vector(); auto prepared = ItemPreviewImage(); - const auto radius = ImageRoundRadius::Small; if (const auto photo = MediaWebPage::photo()) { const auto media = photo->createMediaView(); prepared = PreparePhotoPreview(parent(), media, radius, false); @@ -2065,10 +2089,18 @@ ItemPreview MediaInvoice::toPreview(ToPreviewOptions options) const { if (!photo && !document) { continue; } else if (images.size() < kMaxPreviewImages) { - auto found = photo - ? FindCachedPreview(existing, not_null(photo), spoiler) - : FindCachedPreview(existing, not_null(document), spoiler); const auto radius = ImageRoundRadius::Small; + auto found = photo + ? FindCachedPreview( + existing, + not_null(photo), + radius, + spoiler) + : FindCachedPreview( + existing, + not_null(document), + radius, + spoiler); if (found) { images.push_back(std::move(found)); } else if (photo) { diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp index 51fb657cdb..cbbe38518e 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.cpp @@ -370,7 +370,18 @@ void MessageView::paint( if (image.hasSpoiler()) { const auto frame = DefaultImageSpoiler().frame( _spoiler->index(context.now, pausedSpoiler)); - FillSpoilerRect(p, mini, frame); + if (image.isEllipse()) { + const auto radius = st::dialogsMiniPreview / 2; + static auto mask = Images::CornersMask(radius); + FillSpoilerRect( + p, + mini, + Images::CornersMaskRef(mask), + frame, + _cornersCache); + } else { + FillSpoilerRect(p, mini, frame); + } } } rect.setLeft(rect.x() + w); diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h index 56aa8c2a9d..9fa6571c90 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_message_view.h @@ -95,6 +95,7 @@ private: mutable std::unique_ptr _spoiler; mutable std::unique_ptr _loadingContext; mutable const style::DialogsMiniIcon *_leftIcon = nullptr; + mutable QImage _cornersCache; mutable bool _hasPlainLinkAtBegin = false; }; diff --git a/Telegram/SourceFiles/history/view/history_view_item_preview.h b/Telegram/SourceFiles/history/view/history_view_item_preview.h index b29da9442d..9656d701ff 100644 --- a/Telegram/SourceFiles/history/view/history_view_item_preview.h +++ b/Telegram/SourceFiles/history/view/history_view_item_preview.h @@ -16,6 +16,9 @@ struct ItemPreviewImage { [[nodiscard]] bool hasSpoiler() const { return (cacheKey & 1); } + [[nodiscard]] bool isEllipse() const { + return (cacheKey & 2); + } explicit operator bool() const { return !data.isNull();