mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-25 01:36:48 +00:00
Added slider for prize quantity to giveaway box.
This commit is contained in:
parent
2dcd8a9640
commit
986d347ea4
@ -2078,9 +2078,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
"lng_giveaway_award_subtitle" = "Select recipients >";
|
||||
"lng_giveaway_award_chosen#one" = "{count} recipient >";
|
||||
"lng_giveaway_award_chosen#other" = "{count} recipients >";
|
||||
"lng_giveaway_quantity_title" = "Quantity of prizes / boosts";
|
||||
"lng_giveaway_quantity#one" = "{count} Subscription / Boost";
|
||||
"lng_giveaway_quantity#other" = "{count} Subscriptions / Boosts";
|
||||
"lng_giveaway_quantity_title" = "Quantity of prizes";
|
||||
"lng_giveaway_quantity#one" = "{count} boost";
|
||||
"lng_giveaway_quantity#other" = "{count} boosts";
|
||||
"lng_giveaway_quantity_about" = "Choose how many Premium subscriptions to give away and boosts to receive.";
|
||||
"lng_giveaway_channels_title" = "Channels included in the giveaway";
|
||||
"lng_giveaway_channels_this#one" = "this channel will receive {count} boost";
|
||||
|
@ -15,6 +15,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "data/data_peer.h"
|
||||
#include "data/data_peer_values.h"
|
||||
#include "data/data_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "main/main_app_config.h"
|
||||
#include "main/main_session.h"
|
||||
#include "payments/payments_form.h"
|
||||
#include "ui/text/format_values.h"
|
||||
@ -362,6 +364,9 @@ rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::request() {
|
||||
.product = qs(data.vstore_product().value_or_empty()),
|
||||
.quantity = data.vstore_quantity().value_or_empty(),
|
||||
};
|
||||
if (!ranges::contains(_availablePresets, data.vusers().v)) {
|
||||
_availablePresets.push_back(data.vusers().v);
|
||||
}
|
||||
}
|
||||
for (const auto &[amount, tlOptions] : tlMapOptions) {
|
||||
if (amount == 1 && _optionsForOnePerson.currency.isEmpty()) {
|
||||
@ -385,6 +390,10 @@ rpl::producer<rpl::no_value, QString> PremiumGiftCodeOptions::request() {
|
||||
};
|
||||
}
|
||||
|
||||
const std::vector<int> &PremiumGiftCodeOptions::availablePresets() const {
|
||||
return _availablePresets;
|
||||
}
|
||||
|
||||
Payments::InvoicePremiumGiftCode PremiumGiftCodeOptions::invoice(
|
||||
int users,
|
||||
int monthsIndex) {
|
||||
@ -426,4 +435,11 @@ Data::SubscriptionOptions PremiumGiftCodeOptions::options(int amount) {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] int PremiumGiftCodeOptions::giveawayBoostsPerPremium() const {
|
||||
constexpr auto kFallbackCount = 4;
|
||||
return _peer->session().account().appConfig().get<int>(
|
||||
u"giveaway_boosts_per_premium"_q,
|
||||
kFallbackCount);
|
||||
}
|
||||
|
||||
} // namespace Api
|
||||
|
@ -151,10 +151,13 @@ public:
|
||||
|
||||
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
|
||||
[[nodiscard]] Data::SubscriptionOptions options(int amount);
|
||||
[[nodiscard]] const std::vector<int> &availablePresets() const;
|
||||
[[nodiscard]] Payments::InvoicePremiumGiftCode invoice(
|
||||
int users,
|
||||
int monthsIndex);
|
||||
|
||||
[[nodiscard]] int giveawayBoostsPerPremium() const;
|
||||
|
||||
private:
|
||||
struct Token final {
|
||||
int users = 0;
|
||||
@ -177,6 +180,8 @@ private:
|
||||
QString currency;
|
||||
} _optionsForOnePerson;
|
||||
|
||||
std::vector<int> _availablePresets;
|
||||
|
||||
base::flat_map<Token, Store> _stores;
|
||||
|
||||
MTP::Sender _api;
|
||||
|
@ -23,7 +23,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/continuous_sliders.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "styles/style_layers.h"
|
||||
#include "styles/style_premium.h"
|
||||
#include "styles/style_settings.h"
|
||||
@ -81,6 +83,7 @@ void CreateGiveawayBox(
|
||||
rpl::event_stream<> toAwardAmountChanged;
|
||||
|
||||
rpl::variable<GiveawayType> typeValue;
|
||||
rpl::variable<int> sliderValue;
|
||||
|
||||
bool confirmButtonBusy = false;
|
||||
};
|
||||
@ -153,11 +156,104 @@ void CreateGiveawayBox(
|
||||
Settings::AddDivider(box->verticalLayout());
|
||||
Settings::AddSkip(box->verticalLayout());
|
||||
|
||||
const auto randomWrap = box->verticalLayout()->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
box,
|
||||
object_ptr<Ui::VerticalLayout>(box)));
|
||||
state->typeValue.value(
|
||||
) | rpl::start_with_next([=](GiveawayType type) {
|
||||
randomWrap->toggle(type == GiveawayType::Random, anim::type::instant);
|
||||
}, randomWrap->lifetime());
|
||||
|
||||
const auto sliderContainer = randomWrap->entity()->add(
|
||||
object_ptr<Ui::VerticalLayout>(randomWrap));
|
||||
const auto fillSliderContainer = [=] {
|
||||
if (sliderContainer->count()) {
|
||||
return;
|
||||
}
|
||||
const auto availablePresets = state->apiOptions.availablePresets();
|
||||
if (availablePresets.empty()) {
|
||||
return;
|
||||
}
|
||||
state->sliderValue = availablePresets.front();
|
||||
const auto title = Settings::AddSubsectionTitle(
|
||||
sliderContainer,
|
||||
tr::lng_giveaway_quantity_title());
|
||||
const auto rightLabel = Ui::CreateChild<Ui::FlatLabel>(
|
||||
sliderContainer,
|
||||
st::giveawayGiftCodeQuantitySubtitle);
|
||||
rightLabel->show();
|
||||
|
||||
const auto floatLabel = Ui::CreateChild<Ui::FlatLabel>(
|
||||
sliderContainer,
|
||||
st::giveawayGiftCodeQuantityFloat);
|
||||
floatLabel->show();
|
||||
|
||||
rpl::combine(
|
||||
tr::lng_giveaway_quantity(
|
||||
lt_count,
|
||||
state->sliderValue.value(
|
||||
) | rpl::map([=](int v) -> float64 {
|
||||
return state->apiOptions.giveawayBoostsPerPremium() * v;
|
||||
})),
|
||||
title->positionValue(),
|
||||
sliderContainer->geometryValue()
|
||||
) | rpl::start_with_next([=](QString s, const QPoint &p, QRect) {
|
||||
rightLabel->setText(std::move(s));
|
||||
rightLabel->moveToRight(st::boxRowPadding.right(), p.y());
|
||||
}, rightLabel->lifetime());
|
||||
|
||||
Settings::AddSkip(sliderContainer);
|
||||
Settings::AddSkip(sliderContainer);
|
||||
const auto slider = sliderContainer->add(
|
||||
object_ptr<Ui::MediaSlider>(sliderContainer, st::settingsScale),
|
||||
st::boxRowPadding);
|
||||
Settings::AddSkip(sliderContainer);
|
||||
slider->resize(slider->width(), st::settingsScale.seekSize.height());
|
||||
slider->setPseudoDiscrete(
|
||||
availablePresets.size(),
|
||||
[=](int index) { return availablePresets[index]; },
|
||||
availablePresets.front(),
|
||||
[=](int boosts) { state->sliderValue = boosts; },
|
||||
[](int) {});
|
||||
|
||||
state->sliderValue.value(
|
||||
) | rpl::start_with_next([=](int boosts) {
|
||||
floatLabel->setText(QString::number(boosts));
|
||||
|
||||
const auto count = availablePresets.size();
|
||||
const auto sliderWidth = slider->width()
|
||||
- st::settingsScale.seekSize.width();
|
||||
for (auto i = 0; i < count; i++) {
|
||||
if ((i + 1 == count || availablePresets[i + 1] > boosts)
|
||||
&& availablePresets[i] <= boosts) {
|
||||
const auto x = (sliderWidth * i) / (count - 1);
|
||||
floatLabel->moveToLeft(
|
||||
slider->x()
|
||||
+ x
|
||||
+ st::settingsScale.seekSize.width() / 2
|
||||
- floatLabel->width() / 2,
|
||||
slider->y() - floatLabel->height());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}, floatLabel->lifetime());
|
||||
|
||||
Settings::AddSkip(sliderContainer);
|
||||
Settings::AddDividerText(
|
||||
sliderContainer,
|
||||
tr::lng_giveaway_quantity_about());
|
||||
Settings::AddSkip(sliderContainer);
|
||||
|
||||
sliderContainer->resizeToWidth(box->width());
|
||||
};
|
||||
|
||||
const auto durationGroup = std::make_shared<Ui::RadiobuttonGroup>(0);
|
||||
{
|
||||
const auto listOptions = box->verticalLayout()->add(
|
||||
object_ptr<Ui::VerticalLayout>(box));
|
||||
const auto rebuildListOptions = [=](int amountUsers) {
|
||||
fillSliderContainer();
|
||||
while (listOptions->count()) {
|
||||
delete listOptions->widgetAt(0);
|
||||
}
|
||||
@ -192,16 +288,18 @@ void CreateGiveawayBox(
|
||||
std::move(terms),
|
||||
st::settingsDividerLabelPadding));
|
||||
|
||||
listOptions->resizeToWidth(box->width());
|
||||
box->verticalLayout()->resizeToWidth(box->width());
|
||||
};
|
||||
|
||||
state->typeValue.value(
|
||||
) | rpl::start_with_next([=](GiveawayType type) {
|
||||
rpl::combine(
|
||||
state->sliderValue.value(),
|
||||
state->typeValue.value()
|
||||
) | rpl::start_with_next([=](int users, GiveawayType type) {
|
||||
typeGroup->setValue(type);
|
||||
const auto rebuild = [=] {
|
||||
rebuildListOptions((type == GiveawayType::SpecificUsers)
|
||||
? state->selectedToAward.size()
|
||||
: 1);
|
||||
: users);
|
||||
};
|
||||
if (!listOptions->count()) {
|
||||
state->lifetimeApi = state->apiOptions.request(
|
||||
|
@ -296,6 +296,22 @@ giveawayGiftCodeStartButton: RoundButton(defaultActiveButton) {
|
||||
textTop: 12px;
|
||||
radius: 6px;
|
||||
}
|
||||
giveawayGiftCodeQuantitySubtitle: FlatLabel(defaultFlatLabel) {
|
||||
style: TextStyle(semiboldTextStyle) {
|
||||
font: font(boxFontSize semibold);
|
||||
}
|
||||
textFg: windowActiveTextFg;
|
||||
minWidth: 240px;
|
||||
align: align(right);
|
||||
}
|
||||
giveawayGiftCodeQuantityFloat: FlatLabel(defaultFlatLabel) {
|
||||
style: TextStyle(semiboldTextStyle) {
|
||||
font: font(13px);
|
||||
}
|
||||
textFg: windowActiveTextFg;
|
||||
minWidth: 50px;
|
||||
align: align(center);
|
||||
}
|
||||
|
||||
boostLinkStatsButton: IconButton(defaultIconButton) {
|
||||
width: giveawayGiftCodeLinkCopyWidth;
|
||||
|
Loading…
Reference in New Issue
Block a user