diff --git a/Telegram/SourceFiles/boxes/gift_credits_box.cpp b/Telegram/SourceFiles/boxes/gift_credits_box.cpp index 08d3806e5..48d68f324 100644 --- a/Telegram/SourceFiles/boxes/gift_credits_box.cpp +++ b/Telegram/SourceFiles/boxes/gift_credits_box.cpp @@ -383,6 +383,143 @@ struct GiftPriceTabs { }; } +class GiftButtonDelegate { +public: + [[nodiscard]] virtual TextWithEntities star() = 0; + [[nodiscard]] virtual std::any textContext() = 0; + [[nodiscard]] virtual QSize buttonSize() = 0; + [[nodiscard]] virtual QImage background() = 0; +}; + +class GiftButton final : public AbstractButton { +public: + GiftButton(QWidget *parent, not_null delegate); + using AbstractButton::AbstractButton; + + void setDescriptor(const GiftDescriptor &descriptor); + void setGeometry(QRect inner, QMargins extend); + +private: + void paintEvent(QPaintEvent *e) override; + + const not_null _delegate; + GiftDescriptor _descriptor; + Text::String _text; + Text::String _price; + QRect _button; + QMargins _extend; + std::unique_ptr _player; + +}; + +GiftButton::GiftButton( + QWidget *parent, + not_null delegate) +: AbstractButton(parent) +, _delegate(delegate) { +} + +void GiftButton::setDescriptor(const GiftDescriptor &descriptor) { + if (_descriptor == descriptor) { + return; + } + _descriptor = descriptor; + v::match(descriptor, [&](const GiftTypePremium &data) { + const auto months = data.months; + const auto years = (months % 12) ? 0 : months / 12; + _text = Text::String(st::giftBoxGiftHeight / 4); + _text.setMarkedText( + st::defaultTextStyle, + Text::Bold(years + ? tr::lng_years(tr::now, lt_count, years) + : tr::lng_months(tr::now, lt_count, months) + ).append('\n').append( + tr::lng_gift_premium_label(tr::now) + )); + _price.setText( + st::semiboldTextStyle, + FillAmountAndCurrency( + data.cost, + data.currency, + true)); + }, [&](const GiftTypeStars &data) { + _price.setMarkedText( + st::semiboldTextStyle, + _delegate->star().append(QString::number(data.stars)), + kMarkupTextOptions, + _delegate->textContext()); + }); + const auto buttonw = _price.maxWidth(); + const auto buttonh = st::semiboldFont->height; + const auto inner = QRect( + QPoint(), + QSize(buttonw, buttonh) + ).marginsAdded(st::giftBoxButtonPadding); + const auto single = _delegate->buttonSize(); + const auto skipx = (single.width() - inner.width()) / 2; + const auto skipy = single.height() + - st::giftBoxButtonBottom + - inner.height(); + const auto outer = (single.width() - 2 * skipx); + _button = QRect(skipx, skipy, outer, inner.height()); +} + +void GiftButton::setGeometry(QRect inner, QMargins extend) { + _extend = extend; + AbstractButton::setGeometry(inner.marginsAdded(extend)); +} + +void GiftButton::paintEvent(QPaintEvent *e) { + auto p = QPainter(this); + const auto position = QPoint(_extend.left(), _extend.top()); + p.drawImage(0, 0, _delegate->background()); + + auto hq = PainterHighQualityEnabler(p); + const auto premium = v::is(_descriptor); + const auto singlew = _delegate->buttonSize().width(); + p.setFont(st::normalFont); + v::match(_descriptor, [&](const GiftTypePremium &data) { + if (data.discountPercent > 0) { + p.setPen(st::attentionBoxButton.textFg); + p.drawText(QRect(position, QSize(singlew, st::normalFont->height * 2)), '-' + QString::number(data.discountPercent) + '%', style::al_center); + } + }, [&](const GiftTypeStars &data) { + if (data.limited) { + p.setPen(st::windowActiveTextFg); + p.drawText(QRect(position, QSize(singlew, st::normalFont->height * 2)), u"limited"_q, style::al_center); + } + }); + p.setBrush(premium ? st::lightButtonBgOver : st::creditsBg3); + p.setPen(Qt::NoPen); + if (!premium) { + p.setOpacity(0.12); + } + const auto geometry = _button.translated(position); + const auto radius = geometry.height() / 2.; + p.drawRoundedRect(geometry, radius, radius); + if (!premium) { + p.setOpacity(1.); + } + + if (!_text.isEmpty()) { + p.setPen(st::windowFg); + _text.draw(p, { + .position = (position + + QPoint(0, st::giftBoxPremiumTextTop)), + .availableWidth = singlew, + .align = style::al_top, + }); + } + + const auto padding = st::giftBoxButtonPadding; + p.setPen(premium ? st::windowActiveTextFg : st::creditsFg); + _price.draw(p, { + .position = (geometry.topLeft() + + QPoint(padding.left(), padding.top())), + .availableWidth = _price.maxWidth(), + }); +} + [[nodiscard]] object_ptr MakeGiftsList( not_null window, not_null peer, @@ -390,109 +527,128 @@ struct GiftPriceTabs { auto result = object_ptr((QWidget*)nullptr); const auto raw = result.data(); - struct Button { - GiftDescriptor descriptor; - Text::String text; - Text::String price; - QRect geometry; - QRect button; - std::unique_ptr player; - }; - struct State { - std::vector