Fix spoiler hiding of ellipse image preview.

This commit is contained in:
John Preston 2025-03-20 16:55:12 +04:00
parent 7123a6d647
commit bb8ecf2f84
4 changed files with 72 additions and 25 deletions

View file

@ -171,8 +171,19 @@ struct AlbumCounts {
}
template <typename MediaType>
[[nodiscard]] uint64 CountCacheKey(not_null<MediaType*> data, bool spoiler) {
return (reinterpret_cast<uint64>(data.get()) & ~1) | (spoiler ? 1 : 0);
[[nodiscard]] uint64 CountCacheKey(
not_null<MediaType*> data,
ImageRoundRadius radius,
bool spoiler) {
return (reinterpret_cast<uint64>(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 <typename MediaType>
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 <typename MediaType>
}
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 <typename MediaType>
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 <typename MediaType>
};
}
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 <typename MediaType>
[[nodiscard]] ItemPreviewImage FindCachedPreview(
const std::vector<ItemPreviewImage> *existing,
not_null<MediaType*> 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<ItemPreviewImage>();
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<ItemPreviewImage>();
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) {

View file

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

View file

@ -95,6 +95,7 @@ private:
mutable std::unique_ptr<SpoilerAnimation> _spoiler;
mutable std::unique_ptr<LoadingContext> _loadingContext;
mutable const style::DialogsMiniIcon *_leftIcon = nullptr;
mutable QImage _cornersCache;
mutable bool _hasPlainLinkAtBegin = false;
};

View file

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