Added support of credits subscriptions to send credits box.

This commit is contained in:
23rd 2024-11-11 02:23:19 +03:00 committed by John Preston
parent 03d9fb4115
commit 09643aef82
4 changed files with 148 additions and 10 deletions

View file

@ -2445,6 +2445,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_credits_box_out_media#other" = "Do you want to unlock {media} in {chat} for **{count} Stars**?";
"lng_credits_box_out_media_user#one" = "Do you want to unlock {media} from {user} for **{count} Star**?";
"lng_credits_box_out_media_user#other" = "Do you want to unlock {media} from {user} for **{count} Stars**?";
"lng_credits_box_out_subscription#one" = "Do you want to subscribe to **{title}** in **{bot}** for **{count}** star per month?";
"lng_credits_box_out_subscription#other" = "Do you want to subscribe to **{title}** in **{bot}** for **{count}** stars per month?";
"lng_credits_box_out_subscription_confirm#one" = "Subscribe for {emoji} {count} / month";
"lng_credits_box_out_subscription_confirm#other" = "Subscribe for {emoji} {count} / month";
"lng_credits_box_out_photo" = "a photo";
"lng_credits_box_out_photos#one" = "{count} photo";
"lng_credits_box_out_photos#other" = "{count} photos";

View file

@ -26,17 +26,22 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "settings/settings_credits_graphics.h"
#include "ui/boxes/confirm_box.h"
#include "ui/controls/userpic_button.h"
#include "ui/effects/credits_graphics.h"
#include "ui/effects/premium_graphics.h"
#include "ui/effects/premium_top_bar.h" // Ui::Premium::ColorizedSvg.
#include "ui/image/image_prepare.h"
#include "ui/layers/generic_box.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/text_utilities.h"
#include "ui/vertical_list.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/peer_bubble.h"
#include "styles/style_boxes.h"
#include "styles/style_chat.h"
#include "styles/style_credits.h"
#include "styles/style_giveaway.h"
#include "styles/style_info.h" // inviteLinkSubscribeBoxTerms
#include "styles/style_layers.h"
#include "styles/style_premium.h"
#include "styles/style_settings.h"
@ -92,6 +97,44 @@ struct PaidMediaData {
};
}
void AddTerms(
not_null<Ui::BoxContent*> box,
not_null<Ui::RpWidget*> button,
const style::Box &stBox) {
const auto terms = Ui::CreateChild<Ui::FlatLabel>(
button->parentWidget(),
tr::lng_channel_invite_subscription_terms(
lt_link,
rpl::combine(
tr::lng_paid_react_agree_link(),
tr::lng_group_invite_subscription_about_url()
) | rpl::map([](const QString &text, const QString &url) {
return Ui::Text::Link(text, url);
}),
Ui::Text::RichLangValue),
st::inviteLinkSubscribeBoxTerms);
const auto &buttonPadding = stBox.buttonPadding;
const auto style = box->lifetime().make_state<style::Box>(style::Box{
.buttonPadding = buttonPadding + QMargins(0, 0, 0, terms->height()),
.buttonHeight = stBox.buttonHeight,
.button = stBox.button,
.margin = stBox.margin,
.title = stBox.title,
.bg = stBox.bg,
.titleAdditionalFg = stBox.titleAdditionalFg,
.shadowIgnoreTopSkip = stBox.shadowIgnoreTopSkip,
.shadowIgnoreBottomSkip = stBox.shadowIgnoreBottomSkip,
});
button->geometryValue() | rpl::start_with_next([=](const QRect &rect) {
terms->resizeToWidth(box->width()
- rect::m::sum::h(st::boxRowPadding));
terms->moveToLeft(
rect.x() + (rect.width() - terms->width()) / 2,
rect::bottom(rect) + buttonPadding.bottom() / 2);
}, terms->lifetime());
box->setStyle(*style);
}
[[nodiscard]] rpl::producer<TextWithEntities> SendCreditsConfirmText(
not_null<Main::Session*> session,
not_null<Payments::CreditsFormData*> form) {
@ -150,6 +193,16 @@ struct PaidMediaData {
}
const auto bot = session->data().user(form->botId);
if (form->invoice.subscriptionPeriod) {
return tr::lng_credits_box_out_subscription(
lt_count,
rpl::single(form->invoice.amount) | tr::to_count(),
lt_title,
rpl::single(TextWithEntities{ form->title }),
lt_bot,
rpl::single(TextWithEntities{ bot->name() }),
Ui::Text::RichLangValue);
}
return tr::lng_credits_box_out_sure(
lt_count,
rpl::single(form->invoice.amount) | tr::to_count(),
@ -190,6 +243,57 @@ struct PaidMediaData {
st::defaultUserpicButton);
}
[[nodiscard]] not_null<Ui::RpWidget*> SendCreditsBadge(
not_null<Ui::RpWidget*> parent,
int credits) {
const auto widget = Ui::CreateChild<Ui::RpWidget>(parent);
const auto &font = st::chatGiveawayBadgeFont;
const auto text = QString::number(credits);
const auto iconHeight = font->ascent - font->descent;
const auto iconWidth = iconHeight + st::lineWidth;
const auto width = font->width(text) + iconWidth + st::lineWidth;
const auto inner = QRect(0, 0, width, font->height);
const auto rect = inner + st::subscriptionCreditsBadgePadding;
const auto size = rect.size();
const auto svg = widget->lifetime().make_state<QSvgRenderer>(
Ui::Premium::Svg());
const auto half = st::chatGiveawayBadgeStroke / 2.;
const auto left = st::subscriptionCreditsBadgePadding.left();
const auto smaller = QRectF(rect.translated(-rect.topLeft()))
- Margins(half);
const auto radius = smaller.height() / 2.;
widget->resize(size);
widget->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(widget);
auto hq = PainterHighQualityEnabler(p);
p.setPen(QPen(st::premiumButtonFg, st::chatGiveawayBadgeStroke * 1.));
p.setBrush(st::creditsBg3);
p.drawRoundedRect(smaller, radius, radius);
p.translate(0, font->descent / 2);
p.setPen(st::premiumButtonFg);
p.setBrush(st::premiumButtonFg);
svg->render(
&p,
QRect(
left,
half + (inner.height() - iconHeight) / 2,
iconHeight,
iconHeight));
p.setFont(font);
p.drawText(
left + iconWidth,
st::subscriptionCreditsBadgePadding.top() + font->ascent,
text);
}, widget->lifetime());
return widget;
}
} // namespace
void SendCreditsBox(
@ -203,7 +307,8 @@ void SendCreditsBox(
rpl::variable<bool> confirmButtonBusy = false;
};
const auto state = box->lifetime().make_state<State>();
box->setStyle(st::giveawayGiftCodeBox);
const auto &stBox = st::giveawayGiftCodeBox;
box->setStyle(stBox);
box->setNoContentMargin(true);
const auto session = form->invoice.session;
@ -245,14 +350,36 @@ void SendCreditsBox(
content,
SendCreditsThumbnail(content, session, form.get(), photoSize)));
thumb->setAttribute(Qt::WA_TransparentForMouseEvents);
if (form->invoice.subscriptionPeriod) {
const auto badge = SendCreditsBadge(content, form->invoice.amount);
thumb->geometryValue() | rpl::start_with_next([=](const QRect &r) {
badge->moveToLeft(
r.x() + (r.width() - badge->width()) / 2,
rect::bottom(r) - badge->height() / 2);
}, badge->lifetime());
Ui::AddSkip(content);
Ui::AddSkip(content);
}
Ui::AddSkip(content);
box->addRow(object_ptr<Ui::CenterWrap<>>(
box,
object_ptr<Ui::FlatLabel>(
box,
tr::lng_credits_box_out_title(),
form->invoice.subscriptionPeriod
? rpl::single(form->title)
: tr::lng_credits_box_out_title(),
st::settingsPremiumUserTitle)));
if (form->invoice.subscriptionPeriod && form->botId && form->photo) {
Ui::AddSkip(content);
Ui::AddSkip(content);
const auto bot = session->data().user(form->botId);
box->addRow(
object_ptr<Ui::CenterWrap<>>(
box,
Ui::CreatePeerBubble(box, bot)));
Ui::AddSkip(content);
}
Ui::AddSkip(content);
box->addRow(object_ptr<Ui::CenterWrap<>>(
box,
@ -306,6 +433,9 @@ void SendCreditsBox(
}
}).send();
});
if (form->invoice.subscriptionPeriod) {
AddTerms(box, button, stBox);
}
{
using namespace Info::Statistics;
const auto loadingAnimation = InfiniteRadialAnimationWidget(
@ -317,12 +447,14 @@ void SendCreditsBox(
SetButtonMarkedLabel(
button,
rpl::combine(
tr::lng_credits_box_out_confirm(
lt_count,
rpl::single(form->invoice.amount) | tr::to_count(),
lt_emoji,
rpl::single(CreditsEmojiSmall(session)),
Ui::Text::RichLangValue),
(form->invoice.subscriptionPeriod
? tr::lng_credits_box_out_subscription_confirm
: tr::lng_credits_box_out_confirm)(
lt_count,
rpl::single(form->invoice.amount) | tr::to_count(),
lt_emoji,
rpl::single(CreditsEmojiSmall(session)),
Ui::Text::RichLangValue),
state->confirmButtonBusy.value()
) | rpl::map([](TextWithEntities &&text, bool busy) {
return busy ? TextWithEntities() : std::move(text);
@ -332,7 +464,7 @@ void SendCreditsBox(
box->getDelegate()->style().button.textFg->c);
const auto buttonWidth = st::boxWidth
- rect::m::sum::h(st::giveawayGiftCodeBox.buttonPadding);
- rect::m::sum::h(stBox.buttonPadding);
button->widthValue() | rpl::filter([=] {
return (button->widthNoMargins() != buttonWidth);
}) | rpl::start_with_next([=] {

View file

@ -295,7 +295,7 @@ auto Entry::unreadStateChangeNotifier(bool required) {
_flags |= Flag::InUnreadChangeBlock;
const auto notify = required && inChatList();
const auto wasState = notify ? chatListUnreadState() : UnreadState();
return gsl::finally([=] {
return gsl::finally([=, this] {
_flags &= ~Flag::InUnreadChangeBlock;
if (notify) {
Assert(inChatList());

View file

@ -156,3 +156,5 @@ giftListAbout: FlatLabel(defaultFlatLabel) {
giftListAboutMargin: margins(12px, 24px, 12px, 24px);
giftBoxEmojiToggleTop: 7px;
giftBoxLimitTop: 28px;
subscriptionCreditsBadgePadding: margins(10px, 1px, 8px, 3px);