mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-06 15:13:57 +02:00
Added slider for prize quantity to giveaway box.
This commit is contained in:
parent
2dcd8a9640
commit
986d347ea4
5 changed files with 142 additions and 7 deletions
|
@ -2078,9 +2078,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_giveaway_award_subtitle" = "Select recipients >";
|
"lng_giveaway_award_subtitle" = "Select recipients >";
|
||||||
"lng_giveaway_award_chosen#one" = "{count} recipient >";
|
"lng_giveaway_award_chosen#one" = "{count} recipient >";
|
||||||
"lng_giveaway_award_chosen#other" = "{count} recipients >";
|
"lng_giveaway_award_chosen#other" = "{count} recipients >";
|
||||||
"lng_giveaway_quantity_title" = "Quantity of prizes / boosts";
|
"lng_giveaway_quantity_title" = "Quantity of prizes";
|
||||||
"lng_giveaway_quantity#one" = "{count} Subscription / Boost";
|
"lng_giveaway_quantity#one" = "{count} boost";
|
||||||
"lng_giveaway_quantity#other" = "{count} Subscriptions / Boosts";
|
"lng_giveaway_quantity#other" = "{count} boosts";
|
||||||
"lng_giveaway_quantity_about" = "Choose how many Premium subscriptions to give away and boosts to receive.";
|
"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_title" = "Channels included in the giveaway";
|
||||||
"lng_giveaway_channels_this#one" = "this channel will receive {count} boost";
|
"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.h"
|
||||||
#include "data/data_peer_values.h"
|
#include "data/data_peer_values.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "main/main_account.h"
|
||||||
|
#include "main/main_app_config.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "payments/payments_form.h"
|
#include "payments/payments_form.h"
|
||||||
#include "ui/text/format_values.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()),
|
.product = qs(data.vstore_product().value_or_empty()),
|
||||||
.quantity = data.vstore_quantity().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) {
|
for (const auto &[amount, tlOptions] : tlMapOptions) {
|
||||||
if (amount == 1 && _optionsForOnePerson.currency.isEmpty()) {
|
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(
|
Payments::InvoicePremiumGiftCode PremiumGiftCodeOptions::invoice(
|
||||||
int users,
|
int users,
|
||||||
int monthsIndex) {
|
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
|
} // namespace Api
|
||||||
|
|
|
@ -151,10 +151,13 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
|
[[nodiscard]] rpl::producer<rpl::no_value, QString> request();
|
||||||
[[nodiscard]] Data::SubscriptionOptions options(int amount);
|
[[nodiscard]] Data::SubscriptionOptions options(int amount);
|
||||||
|
[[nodiscard]] const std::vector<int> &availablePresets() const;
|
||||||
[[nodiscard]] Payments::InvoicePremiumGiftCode invoice(
|
[[nodiscard]] Payments::InvoicePremiumGiftCode invoice(
|
||||||
int users,
|
int users,
|
||||||
int monthsIndex);
|
int monthsIndex);
|
||||||
|
|
||||||
|
[[nodiscard]] int giveawayBoostsPerPremium() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Token final {
|
struct Token final {
|
||||||
int users = 0;
|
int users = 0;
|
||||||
|
@ -177,6 +180,8 @@ private:
|
||||||
QString currency;
|
QString currency;
|
||||||
} _optionsForOnePerson;
|
} _optionsForOnePerson;
|
||||||
|
|
||||||
|
std::vector<int> _availablePresets;
|
||||||
|
|
||||||
base::flat_map<Token, Store> _stores;
|
base::flat_map<Token, Store> _stores;
|
||||||
|
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
|
|
|
@ -23,7 +23,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "ui/layers/generic_box.h"
|
#include "ui/layers/generic_box.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
|
#include "ui/widgets/continuous_sliders.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
|
#include "ui/wrap/slide_wrap.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_premium.h"
|
#include "styles/style_premium.h"
|
||||||
#include "styles/style_settings.h"
|
#include "styles/style_settings.h"
|
||||||
|
@ -81,6 +83,7 @@ void CreateGiveawayBox(
|
||||||
rpl::event_stream<> toAwardAmountChanged;
|
rpl::event_stream<> toAwardAmountChanged;
|
||||||
|
|
||||||
rpl::variable<GiveawayType> typeValue;
|
rpl::variable<GiveawayType> typeValue;
|
||||||
|
rpl::variable<int> sliderValue;
|
||||||
|
|
||||||
bool confirmButtonBusy = false;
|
bool confirmButtonBusy = false;
|
||||||
};
|
};
|
||||||
|
@ -153,11 +156,104 @@ void CreateGiveawayBox(
|
||||||
Settings::AddDivider(box->verticalLayout());
|
Settings::AddDivider(box->verticalLayout());
|
||||||
Settings::AddSkip(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 durationGroup = std::make_shared<Ui::RadiobuttonGroup>(0);
|
||||||
{
|
{
|
||||||
const auto listOptions = box->verticalLayout()->add(
|
const auto listOptions = box->verticalLayout()->add(
|
||||||
object_ptr<Ui::VerticalLayout>(box));
|
object_ptr<Ui::VerticalLayout>(box));
|
||||||
const auto rebuildListOptions = [=](int amountUsers) {
|
const auto rebuildListOptions = [=](int amountUsers) {
|
||||||
|
fillSliderContainer();
|
||||||
while (listOptions->count()) {
|
while (listOptions->count()) {
|
||||||
delete listOptions->widgetAt(0);
|
delete listOptions->widgetAt(0);
|
||||||
}
|
}
|
||||||
|
@ -192,16 +288,18 @@ void CreateGiveawayBox(
|
||||||
std::move(terms),
|
std::move(terms),
|
||||||
st::settingsDividerLabelPadding));
|
st::settingsDividerLabelPadding));
|
||||||
|
|
||||||
listOptions->resizeToWidth(box->width());
|
box->verticalLayout()->resizeToWidth(box->width());
|
||||||
};
|
};
|
||||||
|
|
||||||
state->typeValue.value(
|
rpl::combine(
|
||||||
) | rpl::start_with_next([=](GiveawayType type) {
|
state->sliderValue.value(),
|
||||||
|
state->typeValue.value()
|
||||||
|
) | rpl::start_with_next([=](int users, GiveawayType type) {
|
||||||
typeGroup->setValue(type);
|
typeGroup->setValue(type);
|
||||||
const auto rebuild = [=] {
|
const auto rebuild = [=] {
|
||||||
rebuildListOptions((type == GiveawayType::SpecificUsers)
|
rebuildListOptions((type == GiveawayType::SpecificUsers)
|
||||||
? state->selectedToAward.size()
|
? state->selectedToAward.size()
|
||||||
: 1);
|
: users);
|
||||||
};
|
};
|
||||||
if (!listOptions->count()) {
|
if (!listOptions->count()) {
|
||||||
state->lifetimeApi = state->apiOptions.request(
|
state->lifetimeApi = state->apiOptions.request(
|
||||||
|
|
|
@ -296,6 +296,22 @@ giveawayGiftCodeStartButton: RoundButton(defaultActiveButton) {
|
||||||
textTop: 12px;
|
textTop: 12px;
|
||||||
radius: 6px;
|
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) {
|
boostLinkStatsButton: IconButton(defaultIconButton) {
|
||||||
width: giveawayGiftCodeLinkCopyWidth;
|
width: giveawayGiftCodeLinkCopyWidth;
|
||||||
|
|
Loading…
Add table
Reference in a new issue