From 1ac33d30bdad181dfb18bef172ba0220fab7e375 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 8 Jan 2025 17:36:25 +0400 Subject: [PATCH] Version 5.10.2: Improve gifts layout. --- Telegram/SourceFiles/boxes/star_gift_box.cpp | 120 +++++++++++------- Telegram/SourceFiles/boxes/star_gift_box.h | 9 ++ .../view/media/history_view_premium_gift.cpp | 5 +- .../view/media/history_view_unique_gift.cpp | 11 +- .../peer_gifts/info_peer_gifts_common.cpp | 51 ++++++-- .../info/peer_gifts/info_peer_gifts_common.h | 5 +- .../settings/settings_credits_graphics.cpp | 1 + Telegram/SourceFiles/ui/effects/credits.style | 6 +- 8 files changed, 144 insertions(+), 64 deletions(-) diff --git a/Telegram/SourceFiles/boxes/star_gift_box.cpp b/Telegram/SourceFiles/boxes/star_gift_box.cpp index 74cbfd4db..2ba9fddc2 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_box.cpp @@ -298,48 +298,6 @@ auto GenerateGiftMedia( }; } -struct PatternPoint { - QPointF position; - float64 scale = 1.; - float64 opacity = 1.; -}; -[[nodiscard]] const std::vector &PatternPoints() { - static const auto kSmall = 0.7; - static const auto kFaded = 0.3; - static const auto kLarge = 0.85; - static const auto kOpaque = 0.5; - static const auto result = std::vector{ - { { 0.5, 0.066 }, kSmall, kFaded }, - - { { 0.177, 0.168 }, kSmall, kFaded }, - { { 0.822, 0.168 }, kSmall, kFaded }, - - { { 0.37, 0.168 }, kLarge, kOpaque }, - { { 0.63, 0.168 }, kLarge, kOpaque }, - - { { 0.277, 0.308 }, kSmall, kOpaque }, - { { 0.723, 0.308 }, kSmall, kOpaque }, - - { { 0.13, 0.42 }, kSmall, kFaded }, - { { 0.87, 0.42 }, kSmall, kFaded }, - - { { 0.27, 0.533 }, kLarge, kOpaque }, - { { 0.73, 0.533 }, kLarge, kOpaque }, - - { { 0.2, 0.73 }, kSmall, kFaded }, - { { 0.8, 0.73 }, kSmall, kFaded }, - - { { 0.302, 0.825 }, kLarge, kOpaque }, - { { 0.698, 0.825 }, kLarge, kOpaque }, - - { { 0.5, 0.876 }, kLarge, kFaded }, - - { { 0.144, 0.936 }, kSmall, kFaded }, - { { 0.856, 0.936 }, kSmall, kFaded }, - }; - return result; -} - [[nodiscard]] QImage CreateGradient( QSize size, const Data::UniqueGift &gift) { @@ -2108,6 +2066,7 @@ void AddUniqueGiftCover( PaintPoints( p, + PatternPoints(), gift.emojis, gift.emoji.get(), *gift.gift, @@ -2383,8 +2342,83 @@ void UpgradeBox( AddUniqueCloseButton(box); } +const std::vector &PatternPoints() { + static const auto kSmall = 0.7; + static const auto kFaded = 0.2; + static const auto kLarge = 0.85; + static const auto kOpaque = 0.3; + static const auto result = std::vector{ + { { 0.5, 0.066 }, kSmall, kFaded }, + + { { 0.177, 0.168 }, kSmall, kFaded }, + { { 0.822, 0.168 }, kSmall, kFaded }, + + { { 0.37, 0.168 }, kLarge, kOpaque }, + { { 0.63, 0.168 }, kLarge, kOpaque }, + + { { 0.277, 0.308 }, kSmall, kOpaque }, + { { 0.723, 0.308 }, kSmall, kOpaque }, + + { { 0.13, 0.42 }, kSmall, kFaded }, + { { 0.87, 0.42 }, kSmall, kFaded }, + + { { 0.27, 0.533 }, kLarge, kOpaque }, + { { 0.73, 0.533 }, kLarge, kOpaque }, + + { { 0.2, 0.73 }, kSmall, kFaded }, + { { 0.8, 0.73 }, kSmall, kFaded }, + + { { 0.302, 0.825 }, kLarge, kOpaque }, + { { 0.698, 0.825 }, kLarge, kOpaque }, + + { { 0.5, 0.876 }, kLarge, kFaded }, + + { { 0.144, 0.936 }, kSmall, kFaded }, + { { 0.856, 0.936 }, kSmall, kFaded }, + }; + return result; +} + +const std::vector &PatternPointsSmall() { + static const auto kSmall = 0.45; + static const auto kFaded = 0.2; + static const auto kLarge = 0.55; + static const auto kOpaque = 0.3; + static const auto result = std::vector{ + { { 0.5, 0.066 }, kSmall, kFaded }, + + { { 0.177, 0.168 }, kSmall, kFaded }, + { { 0.822, 0.168 }, kSmall, kFaded }, + + { { 0.37, 0.168 }, kLarge, kOpaque }, + { { 0.63, 0.168 }, kLarge, kOpaque }, + + { { 0.277, 0.308 }, kSmall, kOpaque }, + { { 0.723, 0.308 }, kSmall, kOpaque }, + + { { 0.13, 0.42 }, kSmall, kFaded }, + { { 0.87, 0.42 }, kSmall, kFaded }, + + { { 0.27, 0.533 }, kLarge, kOpaque }, + { { 0.73, 0.533 }, kLarge, kOpaque }, + + { { 0.2, 0.73 }, kSmall, kFaded }, + { { 0.8, 0.73 }, kSmall, kFaded }, + + { { 0.302, 0.825 }, kLarge, kOpaque }, + { { 0.698, 0.825 }, kLarge, kOpaque }, + + { { 0.5, 0.876 }, kLarge, kFaded }, + + { { 0.144, 0.936 }, kSmall, kFaded }, + { { 0.856, 0.936 }, kSmall, kFaded }, + }; + return result; +} + void PaintPoints( QPainter &p, + const std::vector &points, base::flat_map &cache, not_null emoji, const Data::UniqueGift &gift, @@ -2417,7 +2451,7 @@ void PaintPoints( } } }; - for (const auto point : PatternPoints()) { + for (const auto &point : points) { paintPoint(point); } } diff --git a/Telegram/SourceFiles/boxes/star_gift_box.h b/Telegram/SourceFiles/boxes/star_gift_box.h index dc85a0019..bacb3997d 100644 --- a/Telegram/SourceFiles/boxes/star_gift_box.h +++ b/Telegram/SourceFiles/boxes/star_gift_box.h @@ -42,8 +42,17 @@ void AddUniqueGiftCover( rpl::producer data, rpl::producer subtitleOverride = nullptr); +struct PatternPoint { + QPointF position; + float64 scale = 1.; + float64 opacity = 1.; +}; +[[nodiscard]] const std::vector &PatternPoints(); +[[nodiscard]] const std::vector &PatternPointsSmall(); + void PaintPoints( QPainter &p, + const std::vector &points, base::flat_map &cache, not_null emoji, const Data::UniqueGift &gift, diff --git a/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp b/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp index 0a17cca84..f7d94fe67 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp @@ -312,7 +312,8 @@ QImage PremiumGift::cornerTag(const PaintContext &context) { if (_data.unique) { badge = { .text = tr::lng_gift_collectible_tag(tr::now), - .bg = _data.unique->backdrop.patternColor, + .bg1 = _data.unique->backdrop.edgeColor, + .bg2 = _data.unique->backdrop.patternColor, .fg = QColor(255, 255, 255), }; } else if (const auto count = _data.limitedCount) { @@ -325,7 +326,7 @@ QImage PremiumGift::cornerTag(const PaintContext &context) { (((count % 1000) && (count < 10'000)) ? Lang::FormatCountDecimal(count) : Lang::FormatCountToShort(count).string))), - .bg = context.st->msgServiceBg()->c, + .bg1 = context.st->msgServiceBg()->c, .fg = context.st->msgServiceFg()->c, }; } else { diff --git a/Telegram/SourceFiles/history/view/media/history_view_unique_gift.cpp b/Telegram/SourceFiles/history/view/media/history_view_unique_gift.cpp index a41e867d0..c2db18f8d 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_unique_gift.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_unique_gift.cpp @@ -525,7 +525,13 @@ Fn UniqueGiftBg( const auto doubled = width + 2 * shift; const auto outer = QRect(-shift, -shift, doubled, doubled); p.setClipRect(inner); - Ui::PaintPoints(p, state->cache, state->pattern.get(), *gift, outer); + Ui::PaintPoints( + p, + Ui::PatternPoints(), + state->cache, + state->pattern.get(), + *gift, + outer); p.setClipping(false); const auto add = style::ConvertScale(2); @@ -536,7 +542,8 @@ Fn UniqueGiftBg( inner.height() + 2 * add); auto badge = Info::PeerGifts::GiftBadge{ .text = tr::lng_gift_collectible_tag(tr::now), - .bg = gift->backdrop.patternColor, + .bg1 = gift->backdrop.edgeColor, + .bg2 = gift->backdrop.patternColor, .fg = gift->backdrop.textColor, }; if (state->badgeCache.isNull() || state->badgeKey != badge) { diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp index eded88409..54c7cc007 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.cpp @@ -42,10 +42,14 @@ std::strong_ordering operator<=>(const GiftBadge &a, const GiftBadge &b) { if (result1 != std::strong_ordering::equal) { return result1; } - const auto result2 = (a.bg.rgb() <=> b.bg.rgb()); + const auto result2 = (a.bg1.rgb() <=> b.bg1.rgb()); if (result2 != std::strong_ordering::equal) { return result2; } + const auto result3 = (a.bg2.rgb() <=> b.bg2.rgb()); + if (result3 != std::strong_ordering::equal) { + return result3; + } return a.fg.rgb() <=> b.fg.rgb(); } @@ -148,6 +152,7 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) { if (mode != Mode::Full) { _button = QRect(); + _small = true; return; } const auto buttonw = _price.maxWidth(); @@ -263,11 +268,11 @@ void GiftButton::cacheUniqueBackground( if (!_patterned && _uniquePatternEmoji->ready()) { _patterned = true; auto p = QPainter(&_uniqueBackgroundCache); - p.setOpacity(0.5); p.setClipRect(inner); const auto skip = inner.width() / 3; Ui::PaintPoints( p, + Ui::PatternPointsSmall(), _uniquePatternCache, _uniquePatternEmoji.get(), *unique, @@ -338,7 +343,9 @@ void GiftButton::paintEvent(QPaintEvent *e) { p.drawImage( QRect( (width - size.width()) / 2, - (_text.isEmpty() + (_small + ? st::giftBoxSmallStickerTop + : _text.isEmpty() ? st::giftBoxStickerStarTop : st::giftBoxStickerTop), size.width(), @@ -348,7 +355,9 @@ void GiftButton::paintEvent(QPaintEvent *e) { if (hidden) { const auto topleft = QPoint( (width - st::giftBoxStickerSize.width()) / 2, - (_text.isEmpty() + (_small + ? st::giftBoxSmallStickerTop + : _text.isEmpty() ? st::giftBoxStickerStarTop : st::giftBoxStickerTop)); _delegate->hiddenMark()->paint( @@ -372,8 +381,9 @@ void GiftButton::paintEvent(QPaintEvent *e) { const auto kMinus = QChar(0x2212); return GiftBadge{ .text = kMinus + QString::number(data.discountPercent) + '%', - .bg = st::attentionButtonFg->c, + .bg1 = st::attentionButtonFg->c, .fg = st::windowBg->c, + .small = true, }; } return GiftBadge(); @@ -383,7 +393,7 @@ void GiftButton::paintEvent(QPaintEvent *e) { return GiftBadge{ .text = (soldOut ? tr::lng_gift_stars_sold_out(tr::now) - : !data.userpic + : (!data.userpic && !data.info.unique) ? tr::lng_gift_stars_limited(tr::now) : (count == 1) ? tr::lng_gift_limited_of_one(tr::now) @@ -393,19 +403,23 @@ void GiftButton::paintEvent(QPaintEvent *e) { (((count % 1000) && (count < 10'000)) ? Lang::FormatCountDecimal(count) : Lang::FormatCountToShort(count).string))), - .bg = (unique - ? unique->backdrop.patternColor + .bg1 = (unique + ? unique->backdrop.edgeColor : soldOut ? st::attentionButtonFg->c : st::windowActiveTextFg->c), + .bg2 = (unique + ? unique->backdrop.patternColor + : QColor(0, 0, 0, 0)), .fg = unique ? QColor(255, 255, 255) : st::windowBg->c, + .small = true, }; } return GiftBadge(); }); if (badge) { - const auto rubberOut = _extend.top(); + const auto rubberOut = st::lineWidth; const auto inner = rect().marginsRemoved(_extend); p.setClipRect(inner.marginsAdded( { rubberOut, rubberOut, rubberOut, rubberOut })); @@ -413,8 +427,8 @@ void GiftButton::paintEvent(QPaintEvent *e) { const auto cached = _delegate->cachedBadge(badge); const auto width = cached.width() / cached.devicePixelRatio(); p.drawImage( - position.x() + singlew + _extend.top() - width, - position.y() - _extend.top(), + position.x() + singlew + rubberOut - width, + position.y() - rubberOut, cached); } if (!_button.isEmpty()) { @@ -633,7 +647,9 @@ rpl::producer> GiftStickerValue( } QImage ValidateRotatedBadge(const GiftBadge &badge, int added) { - const auto &font = st::semiboldFont; + const auto &font = badge.small + ? st::giftBoxGiftBadgeFont + : st::semiboldFont; const auto twidth = font->width(badge.text) + 2 * added; const auto skip = int(std::ceil(twidth / M_SQRT2)); const auto ratio = style::DevicePixelRatio(); @@ -670,12 +686,19 @@ QImage ValidateRotatedBadge(const GiftBadge &badge, int added) { auto p = QPainter(&result); auto hq = PainterHighQualityEnabler(p); p.setPen(Qt::NoPen); - p.setBrush(badge.bg); + p.setBrush(badge.bg1); p.save(); p.translate(textpos); p.rotate(45.); - p.drawRect(-5 * twidth, 0, twidth * 12, font->height); + const auto rect = QRect(-5 * twidth, 0, twidth * 12, font->height); + p.drawRect(rect); + if (badge.bg2.alpha() > 0) { + p.setOpacity(0.5); + p.setBrush(badge.bg2); + p.drawRect(rect); + p.setOpacity(1.); + } p.restore(); p.drawImage(0, 0, scaled); diff --git a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h index bf02e9e26..faab730ef 100644 --- a/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h +++ b/Telegram/SourceFiles/info/peer_gifts/info_peer_gifts_common.h @@ -74,8 +74,10 @@ struct GiftDescriptor : std::variant { struct GiftBadge { QString text; - QColor bg; + QColor bg1; + QColor bg2 = QColor(0, 0, 0, 0); QColor fg; + bool small = false; explicit operator bool() const { return !text.isEmpty(); @@ -148,6 +150,7 @@ private: std::optional _stars; bool _subscribed = false; bool _patterned = false; + bool _small = false; QRect _button; QMargins _extend; diff --git a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp index fdd757525..98ada1547 100644 --- a/Telegram/SourceFiles/settings/settings_credits_graphics.cpp +++ b/Telegram/SourceFiles/settings/settings_credits_graphics.cpp @@ -1348,6 +1348,7 @@ void ReceiptCreditsBox( }; const auto canUpgrade = e.stargiftId && e.canUpgradeGift + && (e.in || giftToSelf) && !e.uniqueGift; const auto canUpgradeFree = canUpgrade && (e.starsUpgradedBySender > 0); diff --git a/Telegram/SourceFiles/ui/effects/credits.style b/Telegram/SourceFiles/ui/effects/credits.style index 15e27eec7..d8390fe12 100644 --- a/Telegram/SourceFiles/ui/effects/credits.style +++ b/Telegram/SourceFiles/ui/effects/credits.style @@ -109,11 +109,12 @@ giftBoxTabStyle: semiboldTextStyle; giftBoxTabFg: windowSubTextFg; giftBoxTabFgActive: windowBoldFg; giftBoxTabBgActive: windowBgRipple; -giftBoxPadding: margins(20px, 4px, 20px, 24px); +giftBoxPadding: margins(11px, 4px, 11px, 24px); giftBoxGiftSkip: point(10px, 8px); giftBoxGiftHeight: 164px; -giftBoxGiftSmall: 124px; +giftBoxGiftSmall: 108px; giftBoxGiftRadius: 12px; +giftBoxGiftBadgeFont: font(10px semibold); giftBoxPremiumIconSize: 64px; giftBoxPremiumIconTop: 10px; giftBoxPremiumTextTop: 84px; @@ -125,6 +126,7 @@ giftBoxPreviewTextPadding: margins(12px, 4px, 12px, 4px); giftBoxButtonMargin: margins(12px, 8px, 12px, 12px); giftBoxStickerTop: 0px; giftBoxStickerStarTop: 24px; +giftBoxSmallStickerTop: 16px; giftBoxStickerSize: size(80px, 80px); giftBoxUserpicSize: 24px; giftBoxUserpicSkip: 2px;