Added support of prepaid giveaway with credits.

This commit is contained in:
23rd 2024-08-31 09:29:35 +03:00 committed by John Preston
parent 3ae9f86097
commit 0982aa166a
9 changed files with 102 additions and 49 deletions

View file

@ -5370,6 +5370,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_boosts_prepaid_giveaway_moths#other" = "{count}-month subscriptions"; "lng_boosts_prepaid_giveaway_moths#other" = "{count}-month subscriptions";
"lng_boosts_prepaid_giveaway_status#one" = "{count} subscription {duration}"; "lng_boosts_prepaid_giveaway_status#one" = "{count} subscription {duration}";
"lng_boosts_prepaid_giveaway_status#other" = "{count} subscriptions {duration}"; "lng_boosts_prepaid_giveaway_status#other" = "{count} subscriptions {duration}";
"lng_boosts_prepaid_giveaway_credits_status#one" = "{amount} among {count} winner.";
"lng_boosts_prepaid_giveaway_credits_status#other" = "{amount} among {count} winners.";
"lng_channel_earn_title" = "Monetization"; "lng_channel_earn_title" = "Monetization";
"lng_channel_earn_about" = "Telegram shares 50% of the revenue from ads displayed in your channel. {link}"; "lng_channel_earn_about" = "Telegram shares 50% of the revenue from ads displayed in your channel. {link}";

View file

@ -508,7 +508,9 @@ rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::applyPrepaid(
_api.request(MTPpayments_LaunchPrepaidGiveaway( _api.request(MTPpayments_LaunchPrepaidGiveaway(
_peer->input, _peer->input,
MTP_long(prepaidId), MTP_long(prepaidId),
Payments::InvoicePremiumGiftCodeGiveawayToTL(invoice) invoice.creditsAmount
? Payments::InvoiceCreditsGiveawayToTL(invoice)
: Payments::InvoicePremiumGiftCodeGiveawayToTL(invoice)
)).done([=](const MTPUpdates &result) { )).done([=](const MTPUpdates &result) {
_peer->session().api().applyUpdates(result); _peer->session().api().applyUpdates(result);
consumer.put_done(); consumer.put_done();

View file

@ -573,13 +573,19 @@ rpl::producer<rpl::no_value, QString> Boosts::request() {
) | ranges::views::transform([](const MTPPrepaidGiveaway &r) { ) | ranges::views::transform([](const MTPPrepaidGiveaway &r) {
return r.match([&](const MTPDprepaidGiveaway &data) { return r.match([&](const MTPDprepaidGiveaway &data) {
return Data::BoostPrepaidGiveaway{ return Data::BoostPrepaidGiveaway{
.months = data.vmonths().v,
.id = data.vid().v,
.quantity = data.vquantity().v,
.date = base::unixtime::parse(data.vdate().v), .date = base::unixtime::parse(data.vdate().v),
.id = data.vid().v,
.months = data.vmonths().v,
.quantity = data.vquantity().v,
}; };
}, [&](const MTPDprepaidStarsGiveaway &data) { }, [&](const MTPDprepaidStarsGiveaway &data) {
return Data::BoostPrepaidGiveaway(AssertIsDebug()); return Data::BoostPrepaidGiveaway{
.date = base::unixtime::parse(data.vdate().v),
.id = data.vid().v,
.credits = data.vstars().v,
.quantity = data.vquantity().v,
.boosts = data.vboosts().v,
};
}); });
}) | ranges::to_vector; }) | ranges::to_vector;
} }

View file

@ -54,10 +54,12 @@ struct BoostsListSlice final {
}; };
struct BoostPrepaidGiveaway final { struct BoostPrepaidGiveaway final {
int months = 0;
uint64 id = 0;
int quantity = 0;
QDateTime date; QDateTime date;
uint64 id = 0;
uint64 credits = 0;
int months = 0;
int quantity = 0;
int boosts = 0;
}; };
struct BoostStatus final { struct BoostStatus final {

View file

@ -59,6 +59,7 @@ namespace {
constexpr auto kDoneTooltipDuration = 5 * crl::time(1000); constexpr auto kDoneTooltipDuration = 5 * crl::time(1000);
constexpr auto kAdditionalPrizeLengthMax = 128; constexpr auto kAdditionalPrizeLengthMax = 128;
constexpr auto kColorIndexCredits = int(1);
[[nodiscard]] QDateTime ThreeDaysAfterToday() { [[nodiscard]] QDateTime ThreeDaysAfterToday() {
auto dateNow = QDateTime::currentDateTime(); auto dateNow = QDateTime::currentDateTime();
@ -299,6 +300,8 @@ void CreateGiveawayBox(
const auto typeGroup = std::make_shared<GiveawayGroup>(); const auto typeGroup = std::make_shared<GiveawayGroup>();
const auto creditsGroup = std::make_shared<CreditsGroup>(); const auto creditsGroup = std::make_shared<CreditsGroup>();
const auto isPrepaidCredits = (prepaid && prepaid->credits);
const auto isSpecificUsers = [=] { const auto isSpecificUsers = [=] {
return !state->selectedToAward.empty(); return !state->selectedToAward.empty();
}; };
@ -355,16 +358,26 @@ void CreateGiveawayBox(
contentWrap->entity()->add( contentWrap->entity()->add(
object_ptr<Giveaway::GiveawayTypeRow>( object_ptr<Giveaway::GiveawayTypeRow>(
box, box,
GiveawayType::Prepaid, prepaid->credits
prepaid->id, ? GiveawayType::PrepaidCredits
: GiveawayType::Prepaid,
prepaid->credits ? kColorIndexCredits : prepaid->id,
tr::lng_boosts_prepaid_giveaway_single(), tr::lng_boosts_prepaid_giveaway_single(),
tr::lng_boosts_prepaid_giveaway_status( prepaid->credits
lt_count, ? tr::lng_boosts_prepaid_giveaway_credits_status(
rpl::single(prepaid->quantity) | tr::to_count(),
lt_duration,
tr::lng_premium_gift_duration_months(
lt_count, lt_count,
rpl::single(prepaid->months) | tr::to_count())), rpl::single(prepaid->quantity) | tr::to_count(),
lt_amount,
tr::lng_prize_credits_amount(
lt_count_decimal,
rpl::single(prepaid->credits) | tr::to_count()))
: tr::lng_boosts_prepaid_giveaway_status(
lt_count,
rpl::single(prepaid->quantity) | tr::to_count(),
lt_duration,
tr::lng_premium_gift_duration_months(
lt_count,
rpl::single(prepaid->months) | tr::to_count())),
QImage()) QImage())
)->setAttribute(Qt::WA_TransparentForMouseEvents); )->setAttribute(Qt::WA_TransparentForMouseEvents);
} }
@ -454,7 +467,6 @@ void CreateGiveawayBox(
if (state->apiCreditsOptions.options().empty()) { if (state->apiCreditsOptions.options().empty()) {
return; return;
} }
constexpr auto kColorIndexCredits = int(1);
static constexpr auto kOutdated = 1735689600; static constexpr auto kOutdated = 1735689600;
auto badge = [&] { auto badge = [&] {
@ -895,7 +907,9 @@ void CreateGiveawayBox(
lt_count, lt_count,
state->sliderValue.value( state->sliderValue.value(
) | rpl::map([=](int v) -> float64 { ) | rpl::map([=](int v) -> float64 {
return state->apiOptions.giveawayBoostsPerPremium() * v; return (prepaid && prepaid->boosts)
? prepaid->boosts
: (state->apiOptions.giveawayBoostsPerPremium() * v);
}))); })));
using IconType = Settings::IconType; using IconType = Settings::IconType;
@ -1355,21 +1369,23 @@ void CreateGiveawayBox(
hideSpecificUsersOn(), hideSpecificUsersOn(),
tr::lng_giveaway_start(), tr::lng_giveaway_start(),
tr::lng_giveaway_award()), tr::lng_giveaway_award()),
rpl::conditional( (prepaid && prepaid->boosts)
state->typeValue.value( ? rpl::single(prepaid->boosts)
) | rpl::map(rpl::mappers::_1 == GiveawayType::Credits), : rpl::conditional(
creditsGroup->value() | rpl::map([=](int v) { state->typeValue.value(
return creditsOption(v).yearlyBoosts; ) | rpl::map(rpl::mappers::_1 == GiveawayType::Credits),
}), creditsGroup->value() | rpl::map([=](int v) {
rpl::combine( return creditsOption(v).yearlyBoosts;
state->sliderValue.value(), }),
hideSpecificUsersOn() rpl::combine(
) | rpl::map([=](int v, bool random) -> int { state->sliderValue.value(),
const auto c = random hideSpecificUsersOn()
? v ) | rpl::map([=](int value, bool random) -> int {
: int(state->selectedToAward.size()); return state->apiOptions.giveawayBoostsPerPremium()
return state->apiOptions.giveawayBoostsPerPremium() * c; * (random
})), ? value
: int(state->selectedToAward.size()));
})),
state->confirmButtonBusy.value() | rpl::map(!rpl::mappers::_1)); state->confirmButtonBusy.value() | rpl::map(!rpl::mappers::_1));
{ {
@ -1399,7 +1415,13 @@ void CreateGiveawayBox(
return; return;
} }
auto invoice = [&] { auto invoice = [&] {
if (isCredits) { if (isPrepaidCredits) {
return Payments::InvoicePremiumGiftCode{
.creditsAmount = prepaid->credits,
.randomId = prepaid->id,
.users = prepaid->quantity,
};
} else if (isCredits) {
const auto option = creditsOption( const auto option = creditsOption(
creditsGroup->current()); creditsGroup->current());
return Payments::InvoicePremiumGiftCode{ return Payments::InvoicePremiumGiftCode{
@ -1433,7 +1455,7 @@ void CreateGiveawayBox(
}) | ranges::to_vector, }) | ranges::to_vector,
peer->asChannel(), peer->asChannel(),
}; };
} else if (isRandom || isCredits) { } else if (isRandom || isCredits || isPrepaidCredits) {
invoice.purpose = Payments::InvoicePremiumGiftCodeGiveaway{ invoice.purpose = Payments::InvoicePremiumGiftCodeGiveaway{
.boostPeer = peer->asChannel(), .boostPeer = peer->asChannel(),
.additionalChannels = ranges::views::all( .additionalChannels = ranges::views::all(

View file

@ -62,14 +62,14 @@ GiveawayTypeRow::GiveawayTypeRow(
|| _type == Type::Random || _type == Type::Random
|| _type == Type::Credits) || _type == Type::Credits)
? st::giveawayTypeListItem ? st::giveawayTypeListItem
: (_type == Type::Prepaid) : ((_type == Type::Prepaid) || (_type == Type::PrepaidCredits))
? st::boostsListBox.item ? st::boostsListBox.item
: st::giveawayGiftCodeMembersPeerList.item) : st::giveawayGiftCodeMembersPeerList.item)
, _userpic( , _userpic(
Ui::EmptyUserpic::UserpicColor(Ui::EmptyUserpic::ColorIndex(colorIndex)), Ui::EmptyUserpic::UserpicColor(Ui::EmptyUserpic::ColorIndex(colorIndex)),
QString()) QString())
, _badge(std::move(badge)) { , _badge(std::move(badge)) {
if (_type == Type::Credits) { if (_type == Type::Credits || _type == Type::PrepaidCredits) {
_customUserpic = Ui::CreditsWhiteDoubledIcon(_st.photoSize, 1.); _customUserpic = Ui::CreditsWhiteDoubledIcon(_st.photoSize, 1.);
} }
std::move( std::move(

View file

@ -27,6 +27,7 @@ public:
OnlyNewMembers, OnlyNewMembers,
Prepaid, Prepaid,
PrepaidCredits,
Credits, Credits,
}; };

View file

@ -253,9 +253,11 @@ void FillGetBoostsButton(
(st.height + rect::m::sum::v(st.padding) - icon.height()) / 2, (st.height + rect::m::sum::v(st.padding) - icon.height()) / 2,
})->show(); })->show();
Ui::AddSkip(content); Ui::AddSkip(content);
Ui::AddDividerText(content, peer->isMegagroup() Ui::AddDividerText(
? tr::lng_boosts_get_boosts_subtext_group() content,
: tr::lng_boosts_get_boosts_subtext()); peer->isMegagroup()
? tr::lng_boosts_get_boosts_subtext_group()
: tr::lng_boosts_get_boosts_subtext());
} }
} // namespace } // namespace
@ -334,6 +336,7 @@ void InnerWidget::fill() {
Ui::AddSkip(inner); Ui::AddSkip(inner);
if (!status.prepaidGiveaway.empty()) { if (!status.prepaidGiveaway.empty()) {
constexpr auto kColorIndexCredits = int(1);
const auto multiplier = Api::PremiumGiftCodeOptions(_peer) const auto multiplier = Api::PremiumGiftCodeOptions(_peer)
.giveawayBoostsPerPremium(); .giveawayBoostsPerPremium();
Ui::AddSkip(inner); Ui::AddSkip(inner);
@ -343,17 +346,30 @@ void InnerWidget::fill() {
using namespace Giveaway; using namespace Giveaway;
const auto button = inner->add(object_ptr<GiveawayTypeRow>( const auto button = inner->add(object_ptr<GiveawayTypeRow>(
inner, inner,
GiveawayTypeRow::Type::Prepaid, g.credits
g.id, ? GiveawayTypeRow::Type::PrepaidCredits
tr::lng_boosts_prepaid_giveaway_quantity( : GiveawayTypeRow::Type::Prepaid,
lt_count, g.credits ? kColorIndexCredits : g.id,
rpl::single(g.quantity) | tr::to_count()), g.credits
tr::lng_boosts_prepaid_giveaway_moths( ? tr::lng_boosts_prepaid_giveaway_single()
lt_count, : tr::lng_boosts_prepaid_giveaway_quantity(
rpl::single(g.months) | tr::to_count()), lt_count,
rpl::single(g.quantity) | tr::to_count()),
g.credits
? tr::lng_boosts_prepaid_giveaway_credits_status(
lt_count,
rpl::single(g.quantity) | tr::to_count(),
lt_amount,
tr::lng_prize_credits_amount(
lt_count_decimal,
rpl::single(g.credits) | tr::to_count()))
: tr::lng_boosts_prepaid_giveaway_moths(
lt_count,
rpl::single(g.months) | tr::to_count()),
Info::Statistics::CreateBadge( Info::Statistics::CreateBadge(
st::statisticsDetailsBottomCaptionStyle, st::statisticsDetailsBottomCaptionStyle,
QString::number(g.quantity * multiplier), QString::number(
g.boosts ? g.boosts : (g.quantity * multiplier)),
st::boostsListBadgeHeight, st::boostsListBadgeHeight,
st::boostsListBadgeTextPadding, st::boostsListBadgeTextPadding,
st::premiumButtonBg2, st::premiumButtonBg2,

View file

@ -269,6 +269,8 @@ struct FormUpdate : std::variant<
[[nodiscard]] MTPinputStorePaymentPurpose InvoicePremiumGiftCodeGiveawayToTL( [[nodiscard]] MTPinputStorePaymentPurpose InvoicePremiumGiftCodeGiveawayToTL(
const InvoicePremiumGiftCode &invoice); const InvoicePremiumGiftCode &invoice);
[[nodiscard]] MTPinputStorePaymentPurpose InvoiceCreditsGiveawayToTL(
const InvoicePremiumGiftCode &invoice);
class Form final : public base::has_weak_ptr { class Form final : public base::has_weak_ptr {
public: public: