Added support of display media from poll answers as grouped media.

This commit is contained in:
23rd
2026-03-17 11:24:06 +03:00
parent dc3d27993b
commit 8c131cc616
2 changed files with 165 additions and 7 deletions
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "media/view/media_view_group_thumbs.h"
#include "base/variant.h"
#include "data/data_shared_media.h"
#include "data/data_user_photos.h"
#include "data/data_photo.h"
@@ -14,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_media_types.h"
#include "data/data_poll.h"
#include "data/data_session.h"
#include "data/data_web_page.h"
#include "data/data_file_origin.h"
@@ -155,6 +157,50 @@ Key ComputeKey(const GroupThumbs::CollageSlice &slice, int index) {
return GroupThumbs::CollageKey{ index };
}
std::optional<WebPageCollage::Item> PollAnswerMediaItemByIndex(
not_null<PollData*> poll,
int index) {
using MaybeItem = std::optional<WebPageCollage::Item>;
auto current = 0;
for (const auto &answer : poll->answers) {
if (const auto media = answer.media) {
const auto item = media->match(
[&](const MTPDinputMediaPhoto &media) -> MaybeItem {
return media.vid().match(
[&](const MTPDinputPhoto &p) -> MaybeItem {
return poll->owner().photo(p.vid().v).get();
},
[](const auto &) -> MaybeItem {
return std::nullopt;
});
},
[&](const MTPDinputMediaDocument &media) -> MaybeItem {
return media.vid().match(
[&](const MTPDinputDocument &d) -> MaybeItem {
const auto parsed
= poll->owner().document(d.vid().v);
if (parsed->sticker()) {
return std::nullopt;
}
return parsed.get();
},
[](const auto &) -> MaybeItem {
return std::nullopt;
});
},
[](const auto &) -> MaybeItem {
return std::nullopt;
});
if (item) {
if (current++ == index) {
return item;
}
}
}
}
return std::nullopt;
}
int ComputeThumbsLimit(int availableWidth) {
const auto singleWidth = st::mediaviewGroupWidth
+ 2 * st::mediaviewGroupSkip;
@@ -674,6 +720,16 @@ auto GroupThumbs::createThumb(Key key)
key,
*invoice,
collageKey->index);
} else if (const auto poll = media->poll()) {
if (const auto item = PollAnswerMediaItemByIndex(
poll,
collageKey->index)) {
return v::match(*item, [&](PhotoData *photo) {
return createThumb(key, photo);
}, [&](DocumentData *document) {
return createThumb(key, document);
});
}
}
}
}
@@ -691,13 +747,11 @@ auto GroupThumbs::createThumb(
if (index < 0 || index >= collage.items.size()) {
return createThumb(key, nullptr);
}
const auto &item = collage.items[index];
if (const auto photo = std::get_if<PhotoData*>(&item)) {
return createThumb(key, (*photo));
} else if (const auto document = std::get_if<DocumentData*>(&item)) {
return createThumb(key, (*document));
}
return createThumb(key, nullptr);
return v::match(collage.items[index], [&](PhotoData *photo) {
return createThumb(key, photo);
}, [&](DocumentData *document) {
return createThumb(key, document);
});
}
auto GroupThumbs::createThumb(
@@ -76,6 +76,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_resolver.h"
#include "data/data_file_click_handler.h"
#include "data/data_download_manager.h"
#include "data/data_poll.h"
#include "window/themes/window_theme_preview.h"
#include "window/window_peer_menu.h"
#include "window/window_controller.h"
@@ -251,6 +252,63 @@ QWidget *PipDelegate::pipParentWidget() {
return false;
}
[[nodiscard]] std::optional<WebPageCollage::Item> PollInputMediaItem(
not_null<PollData*> poll,
const std::optional<MTPInputMedia> &media) {
if (!media) {
return std::nullopt;
}
return media->match([&](const MTPDinputMediaPhoto &media)
-> std::optional<WebPageCollage::Item> {
return media.vid().match([&](const MTPDinputPhoto &photo) {
return std::make_optional<WebPageCollage::Item>(
poll->owner().photo(photo.vid().v).get());
}, [](const auto &) -> std::optional<WebPageCollage::Item> {
return std::nullopt;
});
}, [&](const MTPDinputMediaDocument &media)
-> std::optional<WebPageCollage::Item> {
return media.vid().match([&](const MTPDinputDocument &document) {
const auto parsed = poll->owner().document(document.vid().v);
return parsed->sticker()
? std::optional<WebPageCollage::Item>()
: std::make_optional<WebPageCollage::Item>(parsed.get());
}, [](const auto &) -> std::optional<WebPageCollage::Item> {
return std::nullopt;
});
}, [](const auto &) -> std::optional<WebPageCollage::Item> {
return std::nullopt;
});
}
[[nodiscard]] std::optional<WebPageCollage::Item> PollAnswerMediaItem(
not_null<PollData*> poll,
const PollAnswer &answer) {
return PollInputMediaItem(poll, answer.media);
}
[[nodiscard]] bool IsPollAnswerMediaItem(
not_null<PollData*> poll,
const WebPageCollage::Item &item) {
return ranges::any_of(poll->answers, [&](const PollAnswer &answer) {
const auto candidate = PollAnswerMediaItem(poll, answer);
return candidate && (*candidate == item);
});
}
[[nodiscard]] std::optional<WebPageCollage> PollAnswersCollage(
not_null<PollData*> poll) {
auto result = WebPageCollage();
for (const auto &answer : poll->answers) {
if (const auto item = PollAnswerMediaItem(poll, answer)) {
result.items.push_back(*item);
}
}
return result.items.empty()
? std::nullopt
: std::make_optional(std::move(result));
}
} // namespace
class OverlayWidget::SponsoredButton : public Ui::RippleButton {
@@ -3164,6 +3222,19 @@ auto OverlayWidget::sharedMediaType() const
if (const auto media = _message->media()) {
if (media->webpage() || media->invoice()) {
return std::nullopt;
} else if (const auto poll = media->poll()) {
const auto isPollMedia = [&](const auto &item) {
return IsPollAnswerMediaItem(poll, item)
|| (PollInputMediaItem(poll, poll->solutionMedia)
== item);
};
if ((_photo
&& isPollMedia(WebPageCollage::Item(_photo)))
|| (_document
&& isPollMedia(
WebPageCollage::Item(_document)))) {
return std::nullopt;
}
}
}
if (_photo) {
@@ -3400,6 +3471,18 @@ std::optional<OverlayWidget::CollageKey> OverlayWidget::collageKey() const {
return _document;
}
}
} else if (const auto poll = media->poll()) {
if (_photo
&& IsPollAnswerMediaItem(
poll,
WebPageCollage::Item(_photo))) {
return _photo;
} else if (_document
&& IsPollAnswerMediaItem(
poll,
WebPageCollage::Item(_document))) {
return _document;
}
}
}
}
@@ -3443,6 +3526,8 @@ void OverlayWidget::validateCollage() {
data.items.push_back(document);
}
}
} else if (const auto poll = media->poll()) {
_collageData = PollAnswersCollage(poll);
}
}
}
@@ -3499,6 +3584,25 @@ void OverlayWidget::refreshCaption() {
.append(media->webpage()->description);
}
return TextWithEntities();
} else if (const auto poll = media->poll()) {
const auto current = _photo
? WebPageCollage::Item(_photo)
: WebPageCollage::Item(_document);
for (const auto &answer : poll->answers) {
const auto candidate = PollAnswerMediaItem(
poll,
answer);
if (candidate && (*candidate == current)) {
return answer.text;
}
}
const auto solution = PollInputMediaItem(
poll,
poll->solutionMedia);
if (solution && (*solution == current)) {
return poll->solution;
}
return TextWithEntities();
}
}
return _message->translatedText();