From 7f4d13c54a58f0e36bda4c2f4df233a285bbadaf Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 20 Mar 2024 18:09:37 +0400 Subject: [PATCH] Fix chat intro sticker aspect ratio. --- .../chat_helpers/stickers_lottie.h | 1 + .../history/view/history_view_about_view.cpp | 3 +- .../view/media/history_view_giveaway.cpp | 34 ++++-- .../view/media/history_view_giveaway.h | 5 +- .../view/media/history_view_sticker.cpp | 6 +- .../settings/business/settings_chat_intro.cpp | 103 ++++++++++++++---- Telegram/SourceFiles/ui/chat/chat.style | 1 + 7 files changed, 120 insertions(+), 33 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/stickers_lottie.h b/Telegram/SourceFiles/chat_helpers/stickers_lottie.h index 17ae65c9d..7bd24ac8f 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_lottie.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_lottie.h @@ -67,6 +67,7 @@ enum class StickerLottieSize : uint8 { EmojiInteractionReserved6, EmojiInteractionReserved7, ChatIntroHelloSticker, + StickerEmojiSize, }; [[nodiscard]] uint8 LottieCacheKeyShift( uint8 replacementsTag, diff --git a/Telegram/SourceFiles/history/view/history_view_about_view.cpp b/Telegram/SourceFiles/history/view/history_view_about_view.cpp index 2fe291427..6fe6bba3d 100644 --- a/Telegram/SourceFiles/history/view/history_view_about_view.cpp +++ b/Telegram/SourceFiles/history/view/history_view_about_view.cpp @@ -146,7 +146,8 @@ auto GenerateChatIntro( push(std::make_unique( parent, replacing, - sticker)); + sticker, + st::chatIntroStickerPadding)); }; } diff --git a/Telegram/SourceFiles/history/view/media/history_view_giveaway.cpp b/Telegram/SourceFiles/history/view/media/history_view_giveaway.cpp index 544ff717f..38a04b6ee 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_giveaway.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_giveaway.cpp @@ -342,9 +342,11 @@ QSize TextDelimeterPart::countCurrentSize(int newWidth) { StickerInBubblePart::StickerInBubblePart( not_null parent, Element *replacing, - Fn lookup) + Fn lookup, + QMargins padding) : _parent(parent) -, _lookup(std::move(lookup)) { +, _lookup(std::move(lookup)) +, _padding(padding) { ensureCreated(replacing); } @@ -353,14 +355,14 @@ void StickerInBubblePart::draw( not_null owner, const PaintContext &context, int outerWidth) const { - const auto stickerSize = st::msgServiceGiftBoxStickerSize; - const auto sticker = QRect( - (outerWidth - stickerSize) / 2, - st::chatGiveawayStickerTop + _skipTop, - stickerSize, - stickerSize); ensureCreated(); if (_sticker) { + const auto stickerSize = _sticker->countOptimalSize(); + const auto sticker = QRect( + (outerWidth - stickerSize.width()) / 2, + _padding.top() + _skipTop, + stickerSize.width(), + stickerSize.height()); _sticker->draw(p, context, sticker); } } @@ -384,8 +386,15 @@ std::unique_ptr StickerInBubblePart::stickerTakePlayer( } QSize StickerInBubblePart::countOptimalSize() { - const auto size = st::msgServiceGiftBoxStickerSize; - return { size, st::chatGiveawayStickerTop + size }; + ensureCreated(); + const auto size = _sticker ? _sticker->countOptimalSize() : [&] { + const auto fallback = _lookup().size; + return QSize{ fallback, fallback }; + }(); + return { + _padding.left() + size.width() + _padding.right(), + _padding.top() + size.height() + _padding.bottom(), + }; } QSize StickerInBubblePart::countCurrentSize(int newWidth) { @@ -414,8 +423,9 @@ StickerWithBadgePart::StickerWithBadgePart( not_null parent, Element *replacing, Fn lookup, + QMargins padding, QString badge) -: _sticker(parent, replacing, std::move(lookup)) +: _sticker(parent, replacing, std::move(lookup), padding) , _badgeText(badge) { } @@ -751,6 +761,7 @@ auto GenerateGiveawayStart( parent, nullptr, sticker, + QMargins(0, st::chatGiveawayStickerTop, 0, 0), tr::lng_prizes_badge( tr::now, lt_amount, @@ -887,6 +898,7 @@ auto GenerateGiveawayResults( parent, nullptr, sticker, + QMargins(0, st::chatGiveawayStickerTop, 0, 0), tr::lng_prizes_badge( tr::now, lt_amount, diff --git a/Telegram/SourceFiles/history/view/media/history_view_giveaway.h b/Telegram/SourceFiles/history/view/media/history_view_giveaway.h index 33b84f23d..54db41cc8 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_giveaway.h +++ b/Telegram/SourceFiles/history/view/media/history_view_giveaway.h @@ -177,7 +177,8 @@ public: StickerInBubblePart( not_null parent, Element *replacing, - Fn lookup); + Fn lookup, + QMargins padding); [[nodiscard]] not_null parent() const { return _parent; @@ -207,6 +208,7 @@ private: const not_null _parent; Fn _lookup; mutable int _skipTop = 0; + mutable QMargins _padding; mutable std::optional _sticker; }; @@ -218,6 +220,7 @@ public: not_null parent, Element *replacing, Fn lookup, + QMargins padding, QString badge); void draw( diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp index 338c163fa..0fe8f1b26 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp @@ -139,7 +139,11 @@ bool Sticker::emojiSticker() const { void Sticker::initSize(int customSize) { if (customSize > 0) { - _size = { customSize, customSize }; + const auto original = Size(_data); + const auto proposed = QSize{ customSize, customSize }; + _size = original.isEmpty() + ? proposed + : DownscaledSize(original, proposed); } else if (emojiSticker() || _diceIndex >= 0) { _size = EmojiSize(); if (_diceIndex > 0) { diff --git a/Telegram/SourceFiles/settings/business/settings_chat_intro.cpp b/Telegram/SourceFiles/settings/business/settings_chat_intro.cpp index 6ce2ddfad..2e84f4d45 100644 --- a/Telegram/SourceFiles/settings/business/settings_chat_intro.cpp +++ b/Telegram/SourceFiles/settings/business/settings_chat_intro.cpp @@ -9,12 +9,16 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_premium.h" #include "boxes/peers/edit_peer_color_box.h" // ButtonStyleWithRightEmoji +#include "chat_helpers/stickers_lottie.h" #include "chat_helpers/tabbed_panel.h" #include "chat_helpers/tabbed_selector.h" #include "core/application.h" #include "data/business/data_business_info.h" #include "data/data_document.h" +#include "data/data_document_media.h" #include "data/data_session.h" +#include "history/view/media/history_view_media_common.h" +#include "history/view/media/history_view_sticker_player.h" #include "history/view/history_view_about_view.h" #include "history/view/history_view_context_menu.h" #include "history/view/history_view_element.h" @@ -97,7 +101,6 @@ public: struct Descriptor { not_null controller; not_null button; - DocumentId ensureAddedId = 0; }; void show(Descriptor &&descriptor); void repaint(); @@ -164,10 +167,49 @@ private: current), st::settingsChatIntroFieldMargins); field->setMaxLength(limit); - HistoryView::AddLengthLimitLabel(field, limit); + AddLengthLimitLabel(field, limit); return field; } + +rpl::producer> IconPlayerValue( + not_null sticker, + Fn update) { + const auto media = sticker->createMediaView(); + media->checkStickerLarge(); + media->goodThumbnailWanted(); + + return rpl::single() | rpl::then( + sticker->owner().session().downloaderTaskFinished() + ) | rpl::filter([=] { + return media->loaded(); + }) | rpl::take(1) | rpl::map([=] { + auto result = std::shared_ptr(); + const auto info = sticker->sticker(); + const auto box = QSize(st::emojiSize, st::emojiSize); + if (info->isLottie()) { + result = std::make_shared( + ChatHelpers::LottiePlayerFromDocument( + media.get(), + ChatHelpers::StickerLottieSize::StickerEmojiSize, + box, + Lottie::Quality::High)); + } else if (info->isWebm()) { + result = std::make_shared( + media->owner()->location(), + media->bytes(), + box); + } else { + result = std::make_shared( + media->owner()->location(), + media->bytes(), + box); + } + result->setRepaintCallback(update); + return result; + }); +} + [[nodiscard]] object_ptr CreateIntroStickerButton( not_null parent, std::shared_ptr show, @@ -188,7 +230,9 @@ private: struct State { StickerPanel panel; - DocumentId stickerId = 0; + DocumentData *sticker = nullptr; + std::shared_ptr player; + rpl::lifetime playerLifetime; }; const auto state = right->lifetime().make_state(); state->panel.someCustomChosen( @@ -200,11 +244,23 @@ private: std::move( stickerValue ) | rpl::start_with_next([=](DocumentData *sticker) { - state->stickerId = sticker ? sticker->id : 0; - right->resize( - (sticker ? button.emojiWidth : button.noneWidth) + button.added, - right->height()); - right->update(); + state->sticker = sticker; + if (sticker) { + right->resize(button.emojiWidth + button.added, right->height()); + IconPlayerValue( + sticker, + [=] { right->update(); } + ) | rpl::start_with_next([=]( + std::shared_ptr player) { + state->player = std::move(player); + right->update(); + }, state->playerLifetime); + } else { + state->playerLifetime.destroy(); + state->player = nullptr; + right->resize(button.noneWidth + button.added, right->height()); + right->update(); + } }, right->lifetime()); rpl::combine( @@ -220,8 +276,26 @@ private: ) | rpl::start_with_next([=] { auto p = QPainter(right); const auto height = right->height(); - if (false) { - // #TODO paint small sticker + if (state->player) { + if (state->player->ready()) { + const auto frame = state->player->frame( + QSize(st::emojiSize, st::emojiSize), + QColor(0, 0, 0, 0), + false, + crl::now(), + !right->window()->isActiveWindow()).image; + const auto target = DownscaledSize( + frame.size(), + QSize(st::emojiSize, st::emojiSize)); + p.drawImage( + QRect( + button.added + (st::emojiSize - target.width()) / 2, + (height - target.height()) / 2, + target.width(), + target.height()), + frame); + state->player->markFrameShown(); + } } else { const auto &font = st::normalFont; p.setFont(font); @@ -241,7 +315,6 @@ private: state->panel.show({ .controller = controller, .button = right, - .ensureAddedId = state->stickerId, }); } }); @@ -384,14 +457,6 @@ void StickerPanel::show(Descriptor &&descriptor) { } } _panelButton = button; - const auto feed = [=, now = descriptor.ensureAddedId]( - std::vector list) { - list.insert(begin(list), 0); - if (now && !ranges::contains(list, now)) { - list.push_back(now); - } - _panel->selector()->provideRecentEmoji(list); - }; const auto parent = _panel->parentWidget(); const auto global = button->mapToGlobal(QPoint()); const auto local = parent->mapFromGlobal(global); diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 16dcf7f14..dba8a16ea 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -1066,3 +1066,4 @@ chatIntroStickerSize: 96px; chatIntroWidth: 224px; chatIntroTitleMargin: margins(11px, 16px, 11px, 4px); chatIntroMargin: margins(11px, 0px, 11px, 0px); +chatIntroStickerPadding: margins(10px, 8px, 10px, 16px);