Added ability to award specific users in giveaway box.

This commit is contained in:
23rd 2023-10-30 16:43:05 +03:00 committed by John Preston
parent 5a55e850d9
commit 2dcd8a9640
4 changed files with 110 additions and 6 deletions

View file

@ -10,11 +10,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_premium_option.h"
#include "api/api_text_entities.h"
#include "apiwrap.h"
#include "base/random.h"
#include "data/data_document.h"
#include "data/data_peer.h"
#include "data/data_peer_values.h"
#include "data/data_session.h"
#include "main/main_session.h"
#include "payments/payments_form.h"
#include "ui/text/format_values.h"
namespace Api {
@ -353,9 +355,16 @@ rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::request() {
for (const auto &tlOption : result.v) {
const auto &data = tlOption.data();
tlMapOptions[data.vusers().v].push_back(tlOption);
const auto token = Token{ data.vusers().v, data.vmonths().v };
_stores[token] = Store{
.amount = data.vamount().v,
.product = qs(data.vstore_product().value_or_empty()),
.quantity = data.vstore_quantity().value_or_empty(),
};
}
for (const auto &[amount, tlOptions] : tlMapOptions) {
if (amount == 1) {
if (amount == 1 && _optionsForOnePerson.currency.isEmpty()) {
_optionsForOnePerson.currency = qs(
tlOptions.front().data().vcurrency());
for (const auto &option : tlOptions) {
@ -376,6 +385,26 @@ rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::request() {
};
}
Payments::InvoicePremiumGiftCode PremiumGiftCodeOptions::invoice(
int users,
int monthsIndex) {
const auto randomId = base::RandomValue<uint64>();
const auto token = Token{
users,
_optionsForOnePerson.months[monthsIndex],
};
const auto &store = _stores[token];
return Payments::InvoicePremiumGiftCode{
.randomId = randomId,
.currency = _optionsForOnePerson.currency,
.amount = store.amount,
.storeProduct = store.product,
.storeQuantity = store.quantity,
.users = token.users,
.months = token.months,
};
}
Data::SubscriptionOptions PremiumGiftCodeOptions::options(int amount) {
const auto it = _subscriptionOptions.find(amount);
if (it != end(_subscriptionOptions)) {

View file

@ -16,6 +16,10 @@ namespace Main {
class Session;
} // namespace Main
namespace Payments {
struct InvoicePremiumGiftCode;
} // namespace Payments
namespace Api {
struct GiftCode {
@ -147,10 +151,25 @@ public:
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
[[nodiscard]] Data::SubscriptionOptions options(int amount);
[[nodiscard]] Payments::InvoicePremiumGiftCode invoice(
int users,
int monthsIndex);
private:
const not_null<PeerData*> _peer;
struct Token final {
int users = 0;
int months = 0;
friend inline constexpr auto operator<=>(Token, Token) = default;
};
struct Store final {
uint64 amount = 0;
QString product;
int quantity = 0;
};
using Amount = int;
const not_null<PeerData*> _peer;
base::flat_map<Amount, Data::SubscriptionOptions> _subscriptionOptions;
struct {
std::vector<int> months;
@ -158,6 +177,8 @@ private:
QString currency;
} _optionsForOnePerson;
base::flat_map<Token, Store> _stores;
MTP::Sender _api;
};

View file

@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/boosts/giveaway/giveaway_type_row.h"
#include "info/info_controller.h"
#include "lang/lang_keys.h"
#include "payments/payments_checkout_process.h" // Payments::CheckoutProcess
#include "payments/payments_form.h" // Payments::InvoicePremiumGiftCode
#include "settings/settings_common.h"
#include "settings/settings_premium.h" // Settings::ShowPremium
#include "ui/effects/premium_graphics.h"
@ -79,6 +81,8 @@ void CreateGiveawayBox(
rpl::event_stream<> toAwardAmountChanged;
rpl::variable<GiveawayType> typeValue;
bool confirmButtonBusy = false;
};
const auto state = box->lifetime().make_state<State>(peer);
const auto typeGroup = std::make_shared<GiveawayGroup>();
@ -213,9 +217,54 @@ void CreateGiveawayBox(
rebuildListOptions(1);
});
}
{
// TODO mini-icon.
const auto &stButton = st::premiumGiftBox;
box->setStyle(stButton);
auto button = object_ptr<Ui::RoundButton>(
box,
state->toAwardAmountChanged.events_starting_with(
rpl::empty_value()
) | rpl::map([=] {
return (typeGroup->value() == GiveawayType::SpecificUsers)
? tr::lng_giveaway_award()
: tr::lng_giveaway_start();
}) | rpl::flatten_latest(),
st::giveawayGiftCodeStartButton);
button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
button->resizeToWidth(box->width()
- stButton.buttonPadding.left()
- stButton.buttonPadding.right());
button->setClickedCallback([=] {
if (state->confirmButtonBusy) {
return;
}
if (typeGroup->value() == GiveawayType::SpecificUsers) {
if (state->selectedToAward.empty()) {
return;
}
auto invoice = state->apiOptions.invoice(
state->selectedToAward.size(),
durationGroup->value());
invoice.purpose = Payments::InvoicePremiumGiftCodeUsers{
ranges::views::all(
state->selectedToAward
) | ranges::views::transform([](
const not_null<PeerData*> p) {
return not_null{ p->asUser() };
}) | ranges::to_vector,
peer->asChannel(),
};
state->confirmButtonBusy = true;
Payments::CheckoutProcess::Start(
std::move(invoice),
crl::guard(box, [=](auto) {
state->confirmButtonBusy = false;
box->window()->setFocus();
}));
}
});
box->addButton(std::move(button));
}
state->typeValue.force_assign(GiveawayType::Random);
box->addButton(tr::lng_box_ok(), [=] {
box->closeBox();
});
}

View file

@ -291,6 +291,11 @@ giveawayGiftCodeLinkMargin: margins(24px, 8px, 24px, 12px);
giveawayGiftCodeGiftOption: PremiumOption(premiumGiftOption) {
badgeShift: point(5px, 0px);
}
giveawayGiftCodeStartButton: RoundButton(defaultActiveButton) {
height: 42px;
textTop: 12px;
radius: 6px;
}
boostLinkStatsButton: IconButton(defaultIconButton) {
width: giveawayGiftCodeLinkCopyWidth;