diff --git a/Telegram/SourceFiles/media/view/media_view_group_thumbs.cpp b/Telegram/SourceFiles/media/view/media_view_group_thumbs.cpp index c03c20c8e7..6dea6c5327 100644 --- a/Telegram/SourceFiles/media/view/media_view_group_thumbs.cpp +++ b/Telegram/SourceFiles/media/view/media_view_group_thumbs.cpp @@ -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 PollAnswerMediaItemByIndex( + not_null poll, + int index) { + using MaybeItem = std::optional; + 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(&item)) { - return createThumb(key, (*photo)); - } else if (const auto document = std::get_if(&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( diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index 1f8c0e3a63..c74bc8829c 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -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 PollInputMediaItem( + not_null poll, + const std::optional &media) { + if (!media) { + return std::nullopt; + } + return media->match([&](const MTPDinputMediaPhoto &media) + -> std::optional { + return media.vid().match([&](const MTPDinputPhoto &photo) { + return std::make_optional( + poll->owner().photo(photo.vid().v).get()); + }, [](const auto &) -> std::optional { + return std::nullopt; + }); + }, [&](const MTPDinputMediaDocument &media) + -> std::optional { + return media.vid().match([&](const MTPDinputDocument &document) { + const auto parsed = poll->owner().document(document.vid().v); + return parsed->sticker() + ? std::optional() + : std::make_optional(parsed.get()); + }, [](const auto &) -> std::optional { + return std::nullopt; + }); + }, [](const auto &) -> std::optional { + return std::nullopt; + }); +} + +[[nodiscard]] std::optional PollAnswerMediaItem( + not_null poll, + const PollAnswer &answer) { + return PollInputMediaItem(poll, answer.media); +} + +[[nodiscard]] bool IsPollAnswerMediaItem( + not_null 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 PollAnswersCollage( + not_null 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() 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();