United buttons for premium giveaway and premium gifts to single button.

This commit is contained in:
23rd 2024-08-28 16:34:31 +03:00 committed by John Preston
parent 19492f7e7b
commit aea87bb5cb
3 changed files with 119 additions and 82 deletions

View file

@ -2772,6 +2772,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_giveaway_users_about_group" = "Choose if you want to limit the giveaway only to those who joined the group after the giveaway started or to members from specific countries."; "lng_giveaway_users_about_group" = "Choose if you want to limit the giveaway only to those who joined the group after the giveaway started or to members from specific countries.";
"lng_giveaway_start" = "Start Giveaway"; "lng_giveaway_start" = "Start Giveaway";
"lng_giveaway_award" = "Gift Premium"; "lng_giveaway_award" = "Gift Premium";
"lng_giveaway_random_button" = "Choose randomly";
"lng_giveaway_start_sure" = "Are you sure you want to start this prepaid giveaway now? This action cannot be undone."; "lng_giveaway_start_sure" = "Are you sure you want to start this prepaid giveaway now? This action cannot be undone.";
"lng_giveaway_date_title" = "Date when giveaway ends"; "lng_giveaway_date_title" = "Date when giveaway ends";
"lng_giveaway_date" = "Date and Time"; "lng_giveaway_date" = "Date and Time";

View file

@ -299,13 +299,25 @@ 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 isSpecificUsers = [=] {
return !state->selectedToAward.empty();
};
const auto hideSpecificUsersOn = [=] {
return rpl::combine(
state->typeValue.value(),
state->toAwardAmountChanged.events_starting_with(
rpl::empty_value()) | rpl::type_erased()
) | rpl::map([=](GiveawayType type, auto) {
return (type == GiveawayType::Credits) || !isSpecificUsers();
});
};
auto showFinished = Ui::BoxShowFinishes(box); auto showFinished = Ui::BoxShowFinishes(box);
AddPremiumTopBarWithDefaultTitleBar( AddPremiumTopBarWithDefaultTitleBar(
box, box,
rpl::duplicate(showFinished), rpl::duplicate(showFinished),
rpl::conditional( rpl::conditional(
state->typeValue.value( hideSpecificUsersOn(),
) | rpl::map(rpl::mappers::_1 == GiveawayType::Random),
tr::lng_giveaway_start(), tr::lng_giveaway_start(),
tr::lng_giveaway_award()), tr::lng_giveaway_award()),
peer->isMegagroup()); peer->isMegagroup());
@ -361,11 +373,65 @@ void CreateGiveawayBox(
object_ptr<Giveaway::GiveawayTypeRow>( object_ptr<Giveaway::GiveawayTypeRow>(
box, box,
GiveawayType::Random, GiveawayType::Random,
tr::lng_giveaway_create_subtitle(), state->toAwardAmountChanged.events_starting_with(
rpl::empty_value()
) | rpl::map([=] {
const auto &selected = state->selectedToAward;
return selected.empty()
? tr::lng_giveaway_create_subtitle()
: (selected.size() == 1)
? rpl::single(selected.front()->name())
: tr::lng_giveaway_award_chosen(
lt_count,
rpl::single(selected.size()) | tr::to_count());
}) | rpl::flatten_latest(),
group)); group));
row->addRadio(typeGroup); row->addRadio(typeGroup);
row->setClickedCallback([=] { row->setClickedCallback([=] {
state->typeValue.force_assign(GiveawayType::Random); auto initBox = [=](not_null<PeerListBox*> peersBox) {
peersBox->setTitle(tr::lng_giveaway_award_option());
auto aboveOwned = object_ptr<Ui::VerticalLayout>(peersBox);
const auto above = aboveOwned.data();
peersBox->peerListSetAboveWidget(std::move(aboveOwned));
Ui::AddSkip(above);
const auto buttonRandom = above->add(
object_ptr<Ui::SettingsButton>(
peersBox,
tr::lng_giveaway_random_button(),
st::settingsButtonLightNoIcon));
buttonRandom->setClickedCallback([=] {
state->selectedToAward.clear();
state->toAwardAmountChanged.fire({});
state->typeValue.force_assign(GiveawayType::Random);
peersBox->closeBox();
});
Ui::AddSkip(above);
peersBox->addButton(tr::lng_settings_save(), [=] {
state->selectedToAward = peersBox->collectSelectedRows();
state->toAwardAmountChanged.fire({});
state->typeValue.force_assign(GiveawayType::Random);
peersBox->closeBox();
});
peersBox->addButton(tr::lng_cancel(), [=] {
peersBox->closeBox();
});
};
using Controller = Giveaway::AwardMembersListController;
auto listController = std::make_unique<Controller>(
navigation,
peer,
state->selectedToAward);
listController->setCheckError(CreateErrorCallback(
state->apiOptions.giveawayAddPeersMax(),
tr::lng_giveaway_maximum_users_error));
box->uiShow()->showBox(
Box<PeerListBox>(
std::move(listController),
std::move(initBox)),
Ui::LayerOption::KeepOther);
}); });
} }
const auto creditsOption = [=](int index) { const auto creditsOption = [=](int index) {
@ -430,60 +496,6 @@ void CreateGiveawayBox(
state->typeValue.force_assign(GiveawayType::Credits); state->typeValue.force_assign(GiveawayType::Credits);
}); });
}; };
if (!prepaid) {
const auto row = contentWrap->entity()->add(
object_ptr<Giveaway::GiveawayTypeRow>(
box,
GiveawayType::SpecificUsers,
state->toAwardAmountChanged.events_starting_with(
rpl::empty_value()
) | rpl::map([=] {
const auto &selected = state->selectedToAward;
return selected.empty()
? tr::lng_giveaway_award_subtitle()
: (selected.size() == 1)
? rpl::single(selected.front()->name())
: tr::lng_giveaway_award_chosen(
lt_count,
rpl::single(selected.size()) | tr::to_count());
}) | rpl::flatten_latest(),
group));
row->addRadio(typeGroup);
row->setClickedCallback([=] {
auto initBox = [=](not_null<PeerListBox*> peersBox) {
peersBox->setTitle(tr::lng_giveaway_award_option());
peersBox->addButton(tr::lng_settings_save(), [=] {
state->selectedToAward = peersBox->collectSelectedRows();
state->toAwardAmountChanged.fire({});
peersBox->closeBox();
});
peersBox->addButton(tr::lng_cancel(), [=] {
peersBox->closeBox();
});
peersBox->boxClosing(
) | rpl::start_with_next([=] {
state->typeValue.force_assign(
state->selectedToAward.empty()
? GiveawayType::Random
: GiveawayType::SpecificUsers);
}, peersBox->lifetime());
};
using Controller = Giveaway::AwardMembersListController;
auto listController = std::make_unique<Controller>(
navigation,
peer,
state->selectedToAward);
listController->setCheckError(CreateErrorCallback(
state->apiOptions.giveawayAddPeersMax(),
tr::lng_giveaway_maximum_users_error));
box->uiShow()->showBox(
Box<PeerListBox>(
std::move(listController),
std::move(initBox)),
Ui::LayerOption::KeepOther);
});
}
{ {
const auto &padding = st::giveawayGiftCodeTypeDividerPadding; const auto &padding = st::giveawayGiftCodeTypeDividerPadding;
@ -498,14 +510,10 @@ void CreateGiveawayBox(
object_ptr<Ui::VerticalLayout>(box))); object_ptr<Ui::VerticalLayout>(box)));
state->typeValue.value( state->typeValue.value(
) | rpl::start_with_next([=](GiveawayType type) { ) | rpl::start_with_next([=](GiveawayType type) {
randomWrap->toggle(type == GiveawayType::Random, anim::type::instant); randomWrap->toggle(!isSpecificUsers(), anim::type::instant);
}, randomWrap->lifetime()); }, randomWrap->lifetime());
randomWrap->toggleOn( randomWrap->toggleOn(hideSpecificUsersOn(), anim::type::instant);
state->typeValue.value(
) | rpl::map((rpl::mappers::_1 == GiveawayType::Random)
|| (rpl::mappers::_1 == GiveawayType::Credits)),
anim::type::instant);
const auto randomCreditsWrap = randomWrap->entity()->add( const auto randomCreditsWrap = randomWrap->entity()->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>( object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
@ -1049,7 +1057,7 @@ void CreateGiveawayBox(
while (listOptionsSpecific->count()) { while (listOptionsSpecific->count()) {
delete listOptionsSpecific->widgetAt(0); delete listOptionsSpecific->widgetAt(0);
} }
const auto listOptions = (type == GiveawayType::SpecificUsers) const auto listOptions = isSpecificUsers()
? listOptionsSpecific ? listOptionsSpecific
: listOptionsRandom; : listOptionsRandom;
if (type != GiveawayType::Credits) { if (type != GiveawayType::Credits) {
@ -1086,9 +1094,9 @@ void CreateGiveawayBox(
state->typeValue.value() state->typeValue.value()
) | rpl::start_with_next([=](int users, GiveawayType type) { ) | rpl::start_with_next([=](int users, GiveawayType type) {
typeGroup->setValue(type); typeGroup->setValue(type);
rebuildListOptions(type, (type == GiveawayType::SpecificUsers) rebuildListOptions(
? state->selectedToAward.size() type,
: users); isSpecificUsers() ? state->selectedToAward.size() : users);
}, box->lifetime()); }, box->lifetime());
} else { } else {
typeGroup->setValue(GiveawayType::Random); typeGroup->setValue(GiveawayType::Random);
@ -1144,7 +1152,7 @@ void CreateGiveawayBox(
? (rpl::single(prepaid->months) | rpl::type_erased()) ? (rpl::single(prepaid->months) | rpl::type_erased())
: state->chosenMonths.value(); : state->chosenMonths.value();
const auto usersCountByType = [=](GiveawayType type) { const auto usersCountByType = [=](GiveawayType type) {
if (type != GiveawayType::SpecificUsers) { if (!isSpecificUsers()) {
return state->sliderValue.value() | rpl::type_erased(); return state->sliderValue.value() | rpl::type_erased();
} }
return state->toAwardAmountChanged.events_starting_with_copy( return state->toAwardAmountChanged.events_starting_with_copy(
@ -1347,18 +1355,23 @@ void CreateGiveawayBox(
AddLabelWithBadgeToButton( AddLabelWithBadgeToButton(
button, button,
rpl::conditional( rpl::conditional(
state->typeValue.value( hideSpecificUsersOn(),
) | rpl::map(rpl::mappers::_1 != GiveawayType::Random), tr::lng_giveaway_start(),
tr::lng_giveaway_award(), tr::lng_giveaway_award()),
tr::lng_giveaway_start()),
rpl::conditional( rpl::conditional(
state->typeValue.value( state->typeValue.value(
) | rpl::map(rpl::mappers::_1 == GiveawayType::Credits), ) | rpl::map(rpl::mappers::_1 == GiveawayType::Credits),
creditsGroup->value() | rpl::map([=](int v) { creditsGroup->value() | rpl::map([=](int v) {
return creditsOption(v).yearlyBoosts; return creditsOption(v).yearlyBoosts;
}), }),
state->sliderValue.value() | rpl::map([=](int v) -> int { rpl::combine(
return state->apiOptions.giveawayBoostsPerPremium() * v; state->sliderValue.value(),
hideSpecificUsersOn()
) | rpl::map([=](int v, bool random) -> int {
const auto c = random
? v
: int(state->selectedToAward.size());
return state->apiOptions.giveawayBoostsPerPremium() * c;
})), })),
state->confirmButtonBusy.value() | rpl::map(!rpl::mappers::_1)); state->confirmButtonBusy.value() | rpl::map(!rpl::mappers::_1));
@ -1382,7 +1395,7 @@ void CreateGiveawayBox(
return; return;
} }
const auto type = typeGroup->current(); const auto type = typeGroup->current();
const auto isSpecific = (type == GiveawayType::SpecificUsers); const auto isSpecific = isSpecificUsers();
const auto isRandom = (type == GiveawayType::Random); const auto isRandom = (type == GiveawayType::Random);
const auto isCredits = (type == GiveawayType::Credits); const auto isCredits = (type == GiveawayType::Credits);
if (!isSpecific && !isRandom && !isCredits) { if (!isSpecific && !isRandom && !isCredits) {

View file

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/text/text_options.h" #include "ui/text/text_options.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
#include "styles/style_chat.h"
#include "styles/style_giveaway.h" #include "styles/style_giveaway.h"
#include "styles/style_statistics.h" #include "styles/style_statistics.h"
@ -94,7 +95,8 @@ GiveawayTypeRow::GiveawayTypeRow(
(type == Type::SpecificUsers) (type == Type::SpecificUsers)
? tr::lng_giveaway_award_option() ? tr::lng_giveaway_award_option()
: (type == Type::Random) : (type == Type::Random)
? tr::lng_giveaway_create_option() ? tr::lng_premium_summary_title()
// ? tr::lng_giveaway_create_option()
: (type == Type::AllMembers) : (type == Type::AllMembers)
? (group ? (group
? tr::lng_giveaway_users_all_group() ? tr::lng_giveaway_users_all_group()
@ -131,8 +133,11 @@ GiveawayTypeRow::GiveawayTypeRow(
} }
std::move( std::move(
subtitle subtitle
) | rpl::start_with_next([=] (const QString &s) { ) | rpl::start_with_next([=] (QString s) {
_status.setText(st::defaultTextStyle, s, Ui::NameTextOptions()); _status.setText(
st::defaultTextStyle,
s.replace(QChar('>'), QString()),
Ui::NameTextOptions());
}, lifetime()); }, lifetime());
std::move( std::move(
title title
@ -151,9 +156,10 @@ void GiveawayTypeRow::paintEvent(QPaintEvent *e) {
const auto paintOver = (isOver() || isDown()) && !isDisabled(); const auto paintOver = (isOver() || isDown()) && !isDisabled();
const auto skipRight = _st.photoPosition.x(); const auto skipRight = _st.photoPosition.x();
const auto outerWidth = width(); const auto outerWidth = width();
const auto isRandom = (_type == Type::Random);
const auto isSpecific = (_type == Type::SpecificUsers); const auto isSpecific = (_type == Type::SpecificUsers);
const auto isPrepaid = (_type == Type::Prepaid); const auto isPrepaid = (_type == Type::Prepaid);
const auto hasUserpic = (_type == Type::Random) const auto hasUserpic = isRandom
|| isSpecific || isSpecific
|| isPrepaid || isPrepaid
|| (!_customUserpic.isNull()); || (!_customUserpic.isNull());
@ -204,12 +210,29 @@ void GiveawayTypeRow::paintEvent(QPaintEvent *e) {
_badge); _badge);
} }
const auto statusIcon = isRandom ? &st::topicButtonArrow : nullptr;
const auto statusx = _st.statusPosition.x(); const auto statusx = _st.statusPosition.x();
const auto statusy = _st.statusPosition.y(); const auto statusy = _st.statusPosition.y();
const auto statusw = outerWidth - statusx - skipRight; const auto statusw = outerWidth
- statusx
- skipRight
- (statusIcon
? (statusIcon->width() + st::boostsListMiniIconSkip)
: 0);
p.setFont(st::contactsStatusFont); p.setFont(st::contactsStatusFont);
p.setPen((isSpecific || !hasUserpic) ? st::lightButtonFg : _st.statusFg); p.setPen((isRandom || !hasUserpic) ? st::lightButtonFg : _st.statusFg);
_status.drawLeftElided(p, statusx, statusy, statusw, outerWidth); _status.drawLeftElided(p, statusx, statusy, statusw, outerWidth);
if (statusIcon) {
statusIcon->paint(
p,
QPoint(
statusx
+ std::min(_status.maxWidth(), statusw)
+ st::boostsListMiniIconSkip,
statusy + st::contactsStatusFont->descent),
outerWidth,
st::lightButtonFg->c);
}
} }
void GiveawayTypeRow::addRadio( void GiveawayTypeRow::addRadio(