diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp index 32f759d1c..3ca933fd7 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_reactions.cpp @@ -47,7 +47,7 @@ void AddReactionIcon( button->sizeValue( ) | rpl::start_with_next([=](QSize size) { icon->moveToLeft( - st::settingsSectionIconLeft, + st::editPeerReactionsIconLeft, (size.height() - icon->height()) / 2, size.width()); }, icon->lifetime()); @@ -153,7 +153,9 @@ void EditAllowedReactionsBox( container, rpl::single(entry.title), st::manageGroupButton.button); - AddReactionIcon(button, entry.centerIcon); + AddReactionIcon(button, entry.centerIcon + ? entry.centerIcon + : entry.appearAnimation.get()); state->toggles.emplace(entry.emoji, button); button->toggleOn(rpl::single( active(entry) diff --git a/Telegram/SourceFiles/data/data_message_reactions.cpp b/Telegram/SourceFiles/data/data_message_reactions.cpp index 715643db5..d1c96a295 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.cpp +++ b/Telegram/SourceFiles/data/data_message_reactions.cpp @@ -85,11 +85,13 @@ void Reactions::preloadImageFor(const QString &emoji) { } auto &set = _images.emplace(emoji).first->second; const auto i = ranges::find(_available, emoji, &Reaction::emoji); - const auto document = (i != end(_available)) - ? i->centerIcon.get() - : nullptr; + const auto document = (i == end(_available)) + ? nullptr + : i->centerIcon + ? i->centerIcon + : i->appearAnimation.get(); if (document) { - loadImage(set, document); + loadImage(set, document, !i->centerIcon); } else if (!_waitingForList) { _waitingForList = true; refresh(); @@ -106,16 +108,35 @@ QImage Reactions::resolveImageFor( auto &set = (i != end(_images)) ? i->second : _images[emoji]; const auto resolve = [&](QImage &image, int size) { const auto factor = style::DevicePixelRatio(); + const auto frameSize = set.fromAppearAnimation + ? (size / 2) + : size; image = set.icon->frame().scaled( - size * factor, - size * factor, + frameSize * factor, + frameSize * factor, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + if (set.fromAppearAnimation) { + auto result = QImage( + size * factor, + size * factor, + QImage::Format_ARGB32_Premultiplied); + result.fill(Qt::transparent); + + auto p = QPainter(&result); + p.drawImage( + (size - frameSize) * factor / 2, + (size - frameSize) * factor / 2, + image); + p.end(); + + std::swap(result, image); + } image.setDevicePixelRatio(factor); }; if (set.bottomInfo.isNull() && set.icon) { - resolve(set.bottomInfo, st::reactionInfoSize); - resolve(set.inlineList, st::reactionBottomSize); + resolve(set.bottomInfo, st::reactionInfoImage); + resolve(set.inlineList, st::reactionBottomImage); crl::async([icon = std::move(set.icon)]{}); } switch (size) { @@ -131,11 +152,13 @@ void Reactions::resolveImages() { continue; } const auto i = ranges::find(_available, emoji, &Reaction::emoji); - const auto document = (i != end(_available)) - ? i->centerIcon.get() - : nullptr; + const auto document = (i == end(_available)) + ? nullptr + : i->centerIcon + ? i->centerIcon + : i->appearAnimation.get(); if (document) { - loadImage(set, document); + loadImage(set, document, !i->centerIcon); } else { LOG(("API Error: Reaction for emoji '%1' not found!" ).arg(emoji)); @@ -145,10 +168,12 @@ void Reactions::resolveImages() { void Reactions::loadImage( ImageSet &set, - not_null document) { + not_null document, + bool fromAppearAnimation) { if (!set.bottomInfo.isNull() || set.icon) { return; } else if (!set.media) { + set.fromAppearAnimation = fromAppearAnimation; set.media = document->createMediaView(); set.media->checkStickerLarge(); } @@ -285,8 +310,8 @@ std::optional Reactions::parse(const MTPAvailableReaction &entry) { .activateEffects = _owner->processDocument( data.veffect_animation()), .centerIcon = (data.vcenter_icon() - ? _owner->processDocument(*data.vcenter_icon()) - : selectAnimation), + ? _owner->processDocument(*data.vcenter_icon()).get() + : nullptr), .aroundAnimation = (data.varound_animation() ? _owner->processDocument( *data.varound_animation()).get() diff --git a/Telegram/SourceFiles/data/data_message_reactions.h b/Telegram/SourceFiles/data/data_message_reactions.h index d52146441..7827f4b6e 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.h +++ b/Telegram/SourceFiles/data/data_message_reactions.h @@ -26,7 +26,7 @@ struct Reaction { not_null selectAnimation; not_null activateAnimation; not_null activateEffects; - not_null centerIcon; + DocumentData *centerIcon = nullptr; DocumentData *aroundAnimation = nullptr; bool active = false; }; @@ -78,6 +78,7 @@ private: QImage inlineList; std::shared_ptr media; std::unique_ptr icon; + bool fromAppearAnimation = false; }; void request(); @@ -85,7 +86,10 @@ private: [[nodiscard]] std::optional parse( const MTPAvailableReaction &entry); - void loadImage(ImageSet &set, not_null document); + void loadImage( + ImageSet &set, + not_null document, + bool fromAppearAnimation); void setLottie(ImageSet &set); void resolveImages(); void downloadTaskFinished(); diff --git a/Telegram/SourceFiles/history/view/history_view_bottom_info.cpp b/Telegram/SourceFiles/history/view/history_view_bottom_info.cpp index 1e5fc9c9a..94d3431cd 100644 --- a/Telegram/SourceFiles/history/view/history_view_bottom_info.cpp +++ b/Telegram/SourceFiles/history/view/history_view_bottom_info.cpp @@ -253,8 +253,8 @@ void BottomInfo::paintReactions( } if (!reaction.image.isNull()) { p.drawImage( - x, - y + (st::msgDateFont->height - st::reactionInfoSize) / 2, + x + (st::reactionInfoSize - st::reactionInfoImage) / 2, + y + (st::msgDateFont->height - st::reactionInfoImage) / 2, reaction.image); } if (reaction.countTextWidth > 0) { diff --git a/Telegram/SourceFiles/history/view/history_view_reactions.cpp b/Telegram/SourceFiles/history/view/history_view_reactions.cpp index 7723f36d4..311576f05 100644 --- a/Telegram/SourceFiles/history/view/history_view_reactions.cpp +++ b/Telegram/SourceFiles/history/view/history_view_reactions.cpp @@ -185,6 +185,7 @@ void InlineList::paint( const auto stm = context.messageStyle(); const auto padding = st::reactionBottomPadding; const auto size = st::reactionBottomSize; + const auto skip = (size - st::reactionBottomImage) / 2; const auto inbubble = (_data.flags & InlineListData::Flag::InBubble); p.setFont(st::semiboldFont); for (const auto &button : _buttons) { @@ -216,7 +217,7 @@ void InlineList::paint( ::Data::Reactions::ImageSize::InlineList); } if (!button.image.isNull()) { - p.drawImage(inner.topLeft(), button.image); + p.drawImage(inner.topLeft() + QPoint(skip, skip), button.image); } p.setPen(!inbubble ? (chosen diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 6cae52612..7d5bb99f4 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -711,7 +711,8 @@ editPeerInviteLinkBoxBottomSkip: 15px; editPeerReactionsButton: SettingsButton(infoProfileButton) { padding: margins(59px, 13px, 8px, 11px); } -editPeerReactionsPreview: 28px; +editPeerReactionsPreview: 48px; +editPeerReactionsIconLeft: 12px; historyTopBarBack: IconButton(infoTopBarBack) { width: 52px; diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index e59fe7e94..7a1af4f12 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -965,11 +965,13 @@ sendAsButton: SendAsButton { reactionBottomPadding: margins(5px, 2px, 7px, 2px); reactionBottomSize: 16px; +reactionBottomImage: 28px; reactionBottomSkip: 3px; reactionBottomBetween: 4px; reactionBottomInBubbleLeft: -3px; reactionInfoSize: 15px; +reactionInfoImage: 30px; reactionInfoSkip: 3px; reactionInfoDigitSkip: 6px; reactionInfoBetween: 3px;