diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 4aa6eae95..f8d2b1175 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -4729,6 +4729,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_view_button_boost" = "Boost"; "lng_view_button_giftcode" = "Open"; "lng_view_button_iv" = "Instant View"; +"lng_view_button_stickerset" = "View stickers"; +"lng_view_button_emojipack" = "View emoji"; "lng_sponsored_hide_ads" = "Hide"; "lng_sponsored_title" = "What are sponsored messages?"; diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp index 0fe8f1b26..c8527d999 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp @@ -137,6 +137,10 @@ bool Sticker::emojiSticker() const { return _emojiSticker; } +bool Sticker::webpagePart() const { + return _webpagePart; +} + void Sticker::initSize(int customSize) { if (customSize > 0) { const auto original = Size(_data); @@ -355,6 +359,8 @@ void Sticker::paintPath( helper.emplace(Ui::CustomEmoji::PreviewColorFromTextColor( ComputeEmojiTextColor(context))); pathGradient->overrideColors(helper->color(), helper->color()); + } else if (webpagePart()) { + pathGradient->overrideColors(st::shadowFg, st::shadowFg); } else if (context.selected()) { pathGradient->overrideColors( context.st->msgServiceBgSelected(), @@ -513,6 +519,10 @@ void Sticker::setEmojiSticker() { _emojiSticker = true; } +void Sticker::setWebpagePart() { + _webpagePart = true; +} + void Sticker::setupPlayer() { Expects(_dataMedia != nullptr); diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.h b/Telegram/SourceFiles/history/view/media/history_view_sticker.h index 1cbd7ea82..c6bbbd0da 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_sticker.h +++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.h @@ -69,6 +69,7 @@ public: void setCustomCachingTag(ChatHelpers::StickerLottieSize tag); void setCustomEmojiPart(); void setEmojiSticker(); + void setWebpagePart(); [[nodiscard]] bool atTheEnd() const { return (_frameIndex >= 0) && (_frameIndex + 1 == _framesCount); } @@ -98,6 +99,7 @@ private: [[nodiscard]] bool hasPremiumEffect() const; [[nodiscard]] bool customEmojiPart() const; [[nodiscard]] bool emojiSticker() const; + [[nodiscard]] bool webpagePart() const; void paintAnimationFrame( Painter &p, const PaintContext &context, @@ -137,6 +139,7 @@ private: bool _skipPremiumEffect : 1 = false; bool _customEmojiPart : 1 = false; bool _emojiSticker : 1 = false; + bool _webpagePart : 1 = false; }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp index 0f9c850c0..478835fc0 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.cpp @@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_reply.h" #include "history/view/history_view_sponsored_click_handler.h" #include "history/view/media/history_view_media_common.h" +#include "history/view/media/history_view_sticker.h" #include "lang/lang_keys.h" #include "main/main_session.h" #include "menu/menu_sponsored.h" @@ -179,6 +180,10 @@ constexpr auto kMaxOriginalEntryLines = 8192; ? tr::lng_view_button_user(tr::now) : (type == WebPageType::BotApp) ? tr::lng_view_button_bot_app(tr::now) + : (page->stickerSet && page->stickerSet->isEmoji) + ? tr::lng_view_button_emojipack(tr::now) + : (type == WebPageType::StickerSet) + ? tr::lng_view_button_stickerset(tr::now) : QString()); if (page->iv) { const auto manager = &page->owner().customEmojiManager(); @@ -211,7 +216,8 @@ constexpr auto kMaxOriginalEntryLines = 8192; && (webpage->photo || webpage->document)) || ((type == WebPageType::WallPaper) && webpage->document - && webpage->document->isWallPaper()); + && webpage->document->isWallPaper()) + || (type == WebPageType::StickerSet); } } // namespace @@ -285,6 +291,24 @@ QSize WebPage::countOptimalSize() { } const auto lineHeight = UnitedLineHeight(); + if (_data->stickerSet && !_stickerSet) { + _stickerSet = std::make_unique(); + for (const auto &sticker : _data->stickerSet->items) { + if (!sticker->sticker()) { + continue; + } + _stickerSet->views.push_back( + std::make_unique(_parent, sticker, true)); + } + const auto side = std::ceil(_stickerSet->views.size() / 2.); + const auto box = lineHeight * 2; + const auto single = box / side; + for (const auto &view : _stickerSet->views) { + view->setWebpagePart(); + view->initSize(single); + } + } + if (!_openl && (!_data->url.isEmpty() || _sponsoredData)) { const auto original = _parent->data()->originalText(); const auto previewOfHiddenUrl = [&] { @@ -510,21 +534,22 @@ QSize WebPage::countCurrentSize(int newWidth) { const auto innerWidth = newWidth - rect::m::sum::h(padding); auto newHeight = 0; + const auto specialRightPix = (_sponsoredData || _stickerSet); const auto lineHeight = UnitedLineHeight(); - const auto linesMax = (_sponsoredData || isLogEntryOriginal()) + const auto linesMax = (specialRightPix || isLogEntryOriginal()) ? kMaxOriginalEntryLines : 5; const auto siteNameHeight = _siteNameLines ? lineHeight : 0; const auto twoTitleLines = 2 * st::webPageTitleFont->height; const auto descriptionLineHeight = st::webPageDescriptionFont->height; - const auto asSponsored = (!!_sponsoredData); - if (asArticle() || asSponsored) { - const auto sponsoredUserpic = (asSponsored && _sponsoredData->peer); + if (asArticle() || specialRightPix) { + const auto sponsoredUserpic = (_sponsoredData + && _sponsoredData->peer); constexpr auto kSponsoredUserpicLines = 2; _pixh = lineHeight - * (asSponsored ? kSponsoredUserpicLines : linesMax); + * (specialRightPix ? kSponsoredUserpicLines : linesMax); do { - _pixw = asSponsored + _pixw = specialRightPix ? _pixh : ArticleThumbWidth(_data->photo, _pixh); const auto wleft = innerWidth @@ -644,6 +669,7 @@ void WebPage::ensurePhotoMediaCreated() const { bool WebPage::hasHeavyPart() const { return _photoMedia || (_sponsoredData && !_sponsoredData->userpicView.null()) + || (_stickerSet) || (_attach ? _attach->hasHeavyPart() : false); } @@ -727,6 +753,30 @@ void WebPage::draw(Painter &p, const PaintContext &context) const { } auto lineHeight = UnitedLineHeight(); + if (_stickerSet) { + const auto viewsCount = _stickerSet->views.size(); + const auto topLeft = QPoint(inner.left() + paintw - _pixh, tshift); + const auto side = std::ceil(viewsCount / 2.); + const auto box = lineHeight * 2; + const auto single = box / side; + for (auto i = 0; i < side; i++) { + for (auto j = 0; j < side; j++) { + const auto index = i * side + j; + if (viewsCount <= index) { + break; + } + const auto &view = _stickerSet->views[index]; + const auto size = view->countOptimalSize(); + const auto offsetX = (single - size.width()) / 2.; + const auto offsetY = (single - size.height()) / 2.; + const auto x = j * size.width() + offsetX; + const auto y = i * size.height() + offsetY; + const auto w = size.width(); + const auto h = size.height(); + view->draw(p, context, QRect(QPoint(x, y) + topLeft, size)); + } + } + } if (asArticle()) { ensurePhotoMediaCreated(); diff --git a/Telegram/SourceFiles/history/view/media/history_view_web_page.h b/Telegram/SourceFiles/history/view/media/history_view_web_page.h index 1f06f929c..37471f869 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_web_page.h +++ b/Telegram/SourceFiles/history/view/media/history_view_web_page.h @@ -21,6 +21,8 @@ class RippleAnimation; namespace HistoryView { +class Sticker; + class WebPage : public Media { public: WebPage( @@ -130,6 +132,12 @@ private: mutable std::shared_ptr _photoMedia; mutable std::unique_ptr _ripple; + struct StickerSet final { + std::vector> views; + }; + + std::unique_ptr _stickerSet; + struct SponsoredData final { PeerData *peer = nullptr; Ui::PeerUserpicView userpicView;