diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index fcf51bb0b..24582c52c 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2845,6 +2845,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_prizes_additional_with" = "with"; "lng_prizes_about#one" = "**{count}** Telegram Premium Subscription {duration}."; "lng_prizes_about#other" = "**{count}** Telegram Premium Subscriptions {duration}."; +"lng_prizes_credits_about_single" = "**{amount}** will be distributed to the **1** winner."; +"lng_prizes_credits_about#one" = "**{amount}** will be distributed among {count} winner."; +"lng_prizes_credits_about#other" = "**{amount}** will be distributed among {count} winners."; +"lng_prizes_credits_about_amount#one" = "{count} Star"; +"lng_prizes_credits_about_amount#other" = "{count} Stars"; "lng_prizes_participants" = "Participants"; "lng_prizes_participants_all#one" = "All subscribers of the channel:"; "lng_prizes_participants_all#other" = "All subscribers of the channels:"; @@ -2918,6 +2923,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_prizes_results_more#other" = "and {count} more!"; "lng_prizes_results_one" = "The winner received their gift link in a private message."; "lng_prizes_results_all" = "All winners received gift links in private messages."; +"lng_prizes_credits_results_one#one" = "The winner received {count} Star."; +"lng_prizes_credits_results_one#other" = "The winner received {count} Stars."; +"lng_prizes_credits_results_all#one" = "All winners received {count} Star in total."; +"lng_prizes_credits_results_all#other" = "All winners received {count} Stars in total."; "lng_prizes_results_some" = "Some winners couldn't be selected."; "lng_gift_link_title" = "Gift Link"; diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index 5534c6848..2298ddcfb 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -471,8 +471,8 @@ GiveawayStart ComputeGiveawayStartData( auto result = GiveawayStart{ .untilDate = data.vuntil_date().v, .quantity = data.vquantity().v, - .months = data.vmonths().value_or_empty(),AssertIsDebug() - //.stars = data.vstars().value_or_empty(), + .months = data.vmonths().value_or_empty(), + .credits = data.vstars().value_or_empty(), .all = !data.is_only_new_subscribers(), }; result.channels.reserve(data.vchannels().v.size()); @@ -503,8 +503,8 @@ GiveawayResults ComputeGiveawayResultsData( .additionalPeersCount = additional.value_or_empty(), .winnersCount = data.vwinners_count().v, .unclaimedCount = data.vunclaimed_count().v, - .months = data.vmonths().value_or_empty(), AssertIsDebug() - //.stars = data.vstars().value_or_empty(), + .months = data.vmonths().value_or_empty(), + .credits = data.vstars().value_or_empty(), .refunded = data.is_refunded(), .all = !data.is_only_new_subscribers(), }; diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index b8c943edc..9a9ba0df5 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -108,6 +108,7 @@ struct GiveawayStart { TimeId untilDate = 0; int quantity = 0; int months = 0; + uint64 credits = 0; bool all = false; }; @@ -121,6 +122,7 @@ struct GiveawayResults { int winnersCount = 0; int unclaimedCount = 0; int months = 0; + uint64 credits = 0; bool refunded = false; bool all = false; }; diff --git a/Telegram/SourceFiles/history/view/media/history_view_giveaway.cpp b/Telegram/SourceFiles/history/view/media/history_view_giveaway.cpp index f2f98d05e..4641caa07 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_giveaway.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_giveaway.cpp @@ -21,11 +21,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_helpers.h" #include "lang/lang_keys.h" #include "main/main_session.h" +#include "ui/effects/credits_graphics.h" #include "ui/text/text_utilities.h" #include "styles/style_chat.h" namespace HistoryView { +constexpr auto kOutlineRatio = 0.85; + auto GenerateGiveawayStart( not_null parent, not_null data) @@ -49,10 +52,20 @@ auto GenerateGiveawayStart( nullptr, sticker, st::chatGiveawayStickerPadding, - tr::lng_prizes_badge( - tr::now, - lt_amount, - QString::number(quantity)))); + data->credits + ? QString::number(data->credits) + : tr::lng_prizes_badge( + tr::now, + lt_amount, + QString::number(quantity)), + data->credits + ? Ui::CreditsWhiteDoubledIcon( + st::chatGiveawayCreditsIconHeight, + kOutlineRatio) + : QImage(), + data->credits + ? std::make_optional(st::creditsBg3->c) + : std::nullopt)); auto pushText = [&]( TextWithEntities text, @@ -83,8 +96,29 @@ auto GenerateGiveawayStart( st::chatGiveawayPrizesWithPadding)); } - pushText( - tr::lng_prizes_about( + pushText((data->credits && (quantity == 1)) + ? tr::lng_prizes_credits_about_single( + tr::now, + lt_amount, + tr::lng_prizes_credits_about_amount( + tr::now, + lt_count, + data->credits, + Ui::Text::RichLangValue), + Ui::Text::RichLangValue) + : (data->credits && (quantity > 1)) + ? tr::lng_prizes_credits_about( + tr::now, + lt_count, + quantity, + lt_amount, + tr::lng_prizes_credits_about_amount( + tr::now, + lt_count, + data->credits, + Ui::Text::RichLangValue), + Ui::Text::RichLangValue) + : tr::lng_prizes_about( tr::now, lt_count, quantity, @@ -186,10 +220,20 @@ auto GenerateGiveawayResults( nullptr, sticker, st::chatGiveawayStickerPadding, - tr::lng_prizes_badge( - tr::now, - lt_amount, - QString::number(quantity)))); + data->credits + ? QString::number(data->credits) + : tr::lng_prizes_badge( + tr::now, + lt_amount, + QString::number(quantity)), + data->credits + ? Ui::CreditsWhiteDoubledIcon( + st::chatGiveawayCreditsIconHeight, + kOutlineRatio) + : QImage(), + data->credits + ? std::make_optional(st::creditsBg3->c) + : std::nullopt)); auto pushText = [&]( TextWithEntities text, @@ -237,7 +281,17 @@ auto GenerateGiveawayResults( data->winnersCount - data->winners.size())), st::chatGiveawayNoCountriesTitleMargin); } - pushText({ data->unclaimedCount + pushText({ (data->credits && isSingleWinner) + ? tr::lng_prizes_credits_results_one( + tr::now, + lt_count, + data->credits) + : (data->credits && !isSingleWinner) + ? tr::lng_prizes_credits_results_all( + tr::now, + lt_count, + data->credits) + : data->unclaimedCount ? tr::lng_prizes_results_some(tr::now) : isSingleWinner ? tr::lng_prizes_results_one(tr::now) diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp b/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp index 97ab60180..dad3954f5 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_media_generic.cpp @@ -18,6 +18,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/dynamic_image.h" #include "ui/dynamic_thumbnails.h" #include "ui/painter.h" +#include "ui/rect.h" #include "ui/round_rect.h" #include "styles/style_chat.h" @@ -438,9 +439,13 @@ StickerWithBadgePart::StickerWithBadgePart( Element *replacing, Fn lookup, QMargins padding, - QString badge) -: _sticker(parent, replacing, std::move(lookup), padding) -, _badgeText(badge) { + QString badge, + QImage customLeftIcon, + std::optional colorOverride) +: _customLeftIcon(std::move(customLeftIcon)) +, _sticker(parent, replacing, std::move(lookup), padding) +, _badgeText(badge) +, _colorOverride(std::move(colorOverride)) { } void StickerWithBadgePart::draw( @@ -500,10 +505,13 @@ void StickerWithBadgePart::paintBadge( { auto hq = PainterHighQualityEnabler(p); p.setPen(Qt::NoPen); - p.setBrush(context.messageStyle()->msgFileBg); + if (_colorOverride) { + p.setBrush(*_colorOverride); + } else { + p.setBrush(context.messageStyle()->msgFileBg); + } const auto half = st::chatGiveawayBadgeStroke / 2.; - const auto inner = QRectF(rect).marginsRemoved( - { half, half, half, half }); + const auto inner = QRectF(rect) - Margins(half); const auto radius = inner.height() / 2.; p.drawRoundedRect(inner, radius, radius); } @@ -534,9 +542,12 @@ void StickerWithBadgePart::validateBadge( const auto &font = st::chatGiveawayBadgeFont; _badgeFg = badgeFg; _badgeBorder = badgeBorder; - const auto width = font->width(_badgeText); + const auto iconWidth = _customLeftIcon.isNull() + ? 0 + : (_customLeftIcon.width() / style::DevicePixelRatio()); + const auto width = font->width(_badgeText) + iconWidth; const auto inner = QRect(0, 0, width, font->height); - const auto rect = inner.marginsAdded(st::chatGiveawayBadgePadding); + const auto rect = inner + st::chatGiveawayBadgePadding; const auto size = rect.size(); const auto ratio = style::DevicePixelRatio(); _badge = QImage(size * ratio, QImage::Format_ARGB32_Premultiplied); @@ -548,17 +559,27 @@ void StickerWithBadgePart::validateBadge( p.setPen(QPen(_badgeBorder, st::chatGiveawayBadgeStroke * 1.)); p.setBrush(Qt::NoBrush); const auto half = st::chatGiveawayBadgeStroke / 2.; - const auto smaller = QRectF( - rect.translated(-rect.topLeft()) - ).marginsRemoved({ half, half, half, half }); + const auto left = _customLeftIcon.isNull() + ? st::chatGiveawayBadgePadding.left() + : (st::chatGiveawayBadgePadding.left() - half * 2); + const auto smaller = QRectF(rect.translated(-rect.topLeft())) + - Margins(half); const auto radius = smaller.height() / 2.; p.drawRoundedRect(smaller, radius, radius); p.setPen(_badgeFg); p.setFont(font); p.drawText( - st::chatGiveawayBadgePadding.left(), + left + iconWidth, st::chatGiveawayBadgePadding.top() + font->ascent, _badgeText); + if (!_customLeftIcon.isNull()) { + const auto iconHeight = _customLeftIcon.height() + / style::DevicePixelRatio(); + p.drawImage( + left, + half + (inner.height() - iconHeight) / 2, + _customLeftIcon); + } } PeerBubbleListPart::PeerBubbleListPart( diff --git a/Telegram/SourceFiles/history/view/media/history_view_media_generic.h b/Telegram/SourceFiles/history/view/media/history_view_media_generic.h index bdc9f328f..bc7f18737 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_media_generic.h +++ b/Telegram/SourceFiles/history/view/media/history_view_media_generic.h @@ -227,7 +227,9 @@ public: Element *replacing, Fn lookup, QMargins padding, - QString badge); + QString badge, + QImage customLeftIcon, + std::optional colorOverride); void draw( Painter &p, @@ -252,12 +254,14 @@ private: void validateBadge(const PaintContext &context) const; void paintBadge(Painter &p, const PaintContext &context) const; + const QImage _customLeftIcon; StickerInBubblePart _sticker; QString _badgeText; mutable QColor _badgeFg; mutable QColor _badgeBorder; mutable QImage _badge; mutable QImage _badgeCache; + std::optional _colorOverride; }; diff --git a/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway_type_row.cpp b/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway_type_row.cpp index 2c597c066..0bcf303ed 100644 --- a/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway_type_row.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway_type_row.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/channel_statistics/boosts/giveaway/giveaway_type_row.h" #include "lang/lang_keys.h" +#include "ui/effects/credits_graphics.h" #include "ui/effects/premium_graphics.h" #include "ui/painter.h" #include "ui/rect.h" @@ -18,67 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_giveaway.h" #include "styles/style_statistics.h" -#include - namespace Giveaway { -namespace { - -[[nodiscard]] QImage CreditsCustomUserpic(int photoSize) { - auto svg = QSvgRenderer(Ui::Premium::Svg()); - auto result = QImage( - Size(photoSize) * style::DevicePixelRatio(), - QImage::Format_ARGB32_Premultiplied); - result.fill(Qt::transparent); - result.setDevicePixelRatio(style::DevicePixelRatio()); - - constexpr auto kPoints = uint(16); - constexpr auto kAngleStep = 2. * M_PI / kPoints; - constexpr auto kOutlineWidth = 1.6; - constexpr auto kStarShift = 3.8; - const auto userpicRect = Rect(Size(photoSize)); - const auto starRect = userpicRect - Margins(userpicRect.width() / 4.); - const auto starSize = starRect.size(); - const auto drawSingle = [&](QPainter &q) { - const auto s = style::ConvertFloatScale(kOutlineWidth); - q.save(); - q.setCompositionMode(QPainter::CompositionMode_Clear); - for (auto i = 0; i < kPoints; ++i) { - const auto angle = i * kAngleStep; - const auto x = s * std::cos(angle); - const auto y = s * std::sin(angle); - svg.render(&q, QRectF(QPointF(x, y), starSize)); - } - q.setCompositionMode(QPainter::CompositionMode_SourceOver); - svg.render(&q, Rect(starSize)); - q.restore(); - }; - { - auto p = QPainter(&result); - p.setPen(Qt::NoPen); - p.setBrush(st::lightButtonFg); - p.translate(starRect.topLeft()); - p.translate(style::ConvertFloatScale(kStarShift) / 2., 0); - drawSingle(p); - { - // Remove the previous star at bottom. - p.setCompositionMode(QPainter::CompositionMode_Clear); - p.save(); - p.resetTransform(); - p.fillRect( - userpicRect.x(), - userpicRect.y(), - userpicRect.width() / 2., - userpicRect.height(), - Qt::transparent); - p.restore(); - } - p.translate(-style::ConvertFloatScale(kStarShift), 0); - drawSingle(p); - } - return result; -} - -} // namespace constexpr auto kColorIndexSpecific = int(4); constexpr auto kColorIndexRandom = int(2); @@ -129,7 +70,7 @@ GiveawayTypeRow::GiveawayTypeRow( QString()) , _badge(std::move(badge)) { if (_type == Type::Credits) { - _customUserpic = CreditsCustomUserpic(_st.photoSize); + _customUserpic = Ui::CreditsWhiteDoubledIcon(_st.photoSize, 1.); } std::move( subtitle diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 42e580fa6..724a4f789 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -1009,6 +1009,7 @@ chatGiveawayEndDateMargin: margins(11px, 0px, 11px, 16px); chatGiveawayPeerSize: 32px; chatGiveawayPeerPadding: margins(5px, 7px, 12px, 0px); chatGiveawayPeerSkip: 8px; +chatGiveawayCreditsIconHeight: 19px; chatSimilarRadius: 12px; chatSimilarArrowSize: 6px; diff --git a/Telegram/SourceFiles/ui/effects/credits_graphics.cpp b/Telegram/SourceFiles/ui/effects/credits_graphics.cpp index 16dc2ba77..58fe9ae41 100644 --- a/Telegram/SourceFiles/ui/effects/credits_graphics.cpp +++ b/Telegram/SourceFiles/ui/effects/credits_graphics.cpp @@ -472,4 +472,64 @@ TextWithEntities GenerateEntryName(const Data::CreditsHistoryEntry &entry) { TextWithEntities::Simple); } +QImage CreditsWhiteDoubledIcon(int size, float64 outlineRatio) { + auto svg = QSvgRenderer(Ui::Premium::Svg()); + auto result = QImage( + Size(size) * style::DevicePixelRatio(), + QImage::Format_ARGB32_Premultiplied); + result.fill(Qt::transparent); + result.setDevicePixelRatio(style::DevicePixelRatio()); + + // constexpr auto kIdealSize = 42; + constexpr auto kPoints = uint(16); + constexpr auto kAngleStep = 2. * M_PI / kPoints; + constexpr auto kOutlineWidth = 1.6; + constexpr auto kStarShift = 3.8; + const auto userpicRect = Rect(Size(size)); + const auto starRect = userpicRect - Margins(userpicRect.width() / 4.); + const auto starSize = starRect.size(); + const auto drawSingle = [&](QPainter &q) { + const auto s = style::ConvertFloatScale(kOutlineWidth * outlineRatio); + q.save(); + q.setCompositionMode(QPainter::CompositionMode_Clear); + for (auto i = 0; i < kPoints; ++i) { + const auto angle = i * kAngleStep; + const auto x = s * std::cos(angle); + const auto y = s * std::sin(angle); + svg.render(&q, QRectF(QPointF(x, y), starSize)); + } + q.setCompositionMode(QPainter::CompositionMode_SourceOver); + svg.render(&q, Rect(starSize)); + q.restore(); + }; + { + auto p = QPainter(&result); + p.setPen(Qt::NoPen); + p.setBrush(st::lightButtonFg); + p.translate(starRect.topLeft()); + p.translate( + style::ConvertFloatScale(kStarShift * outlineRatio) / 2., + 0); + drawSingle(p); + { + // Remove the previous star at bottom. + p.setCompositionMode(QPainter::CompositionMode_Clear); + p.save(); + p.resetTransform(); + p.fillRect( + userpicRect.x(), + userpicRect.y(), + userpicRect.width() / 2., + userpicRect.height(), + Qt::transparent); + p.restore(); + } + p.translate( + -style::ConvertFloatScale(kStarShift * outlineRatio), + 0); + drawSingle(p); + } + return result; +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/effects/credits_graphics.h b/Telegram/SourceFiles/ui/effects/credits_graphics.h index 70d983056..7880f2b7a 100644 --- a/Telegram/SourceFiles/ui/effects/credits_graphics.h +++ b/Telegram/SourceFiles/ui/effects/credits_graphics.h @@ -73,4 +73,6 @@ Fn)> PaintPreviewCallback( [[nodiscard]] TextWithEntities GenerateEntryName( const Data::CreditsHistoryEntry &entry); +[[nodiscard]] QImage CreditsWhiteDoubledIcon(int size, float64 outlineRatio); + } // namespace Ui