diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 94ad89f2c..840a05eb1 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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_start" = "Start Giveaway"; "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_date_title" = "Date when giveaway ends"; "lng_giveaway_date" = "Date and Time"; diff --git a/Telegram/SourceFiles/info/channel_statistics/boosts/create_giveaway_box.cpp b/Telegram/SourceFiles/info/channel_statistics/boosts/create_giveaway_box.cpp index ac2d48783..8ce7ff6f1 100644 --- a/Telegram/SourceFiles/info/channel_statistics/boosts/create_giveaway_box.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/boosts/create_giveaway_box.cpp @@ -299,13 +299,25 @@ void CreateGiveawayBox( const auto typeGroup = std::make_shared(); const auto creditsGroup = std::make_shared(); + 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); AddPremiumTopBarWithDefaultTitleBar( box, rpl::duplicate(showFinished), rpl::conditional( - state->typeValue.value( - ) | rpl::map(rpl::mappers::_1 == GiveawayType::Random), + hideSpecificUsersOn(), tr::lng_giveaway_start(), tr::lng_giveaway_award()), peer->isMegagroup()); @@ -361,11 +373,65 @@ void CreateGiveawayBox( object_ptr( box, 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)); row->addRadio(typeGroup); row->setClickedCallback([=] { - state->typeValue.force_assign(GiveawayType::Random); + auto initBox = [=](not_null peersBox) { + peersBox->setTitle(tr::lng_giveaway_award_option()); + + auto aboveOwned = object_ptr(peersBox); + const auto above = aboveOwned.data(); + peersBox->peerListSetAboveWidget(std::move(aboveOwned)); + Ui::AddSkip(above); + const auto buttonRandom = above->add( + object_ptr( + 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( + navigation, + peer, + state->selectedToAward); + listController->setCheckError(CreateErrorCallback( + state->apiOptions.giveawayAddPeersMax(), + tr::lng_giveaway_maximum_users_error)); + box->uiShow()->showBox( + Box( + std::move(listController), + std::move(initBox)), + Ui::LayerOption::KeepOther); }); } const auto creditsOption = [=](int index) { @@ -430,60 +496,6 @@ void CreateGiveawayBox( state->typeValue.force_assign(GiveawayType::Credits); }); }; - if (!prepaid) { - const auto row = contentWrap->entity()->add( - object_ptr( - 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 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( - navigation, - peer, - state->selectedToAward); - listController->setCheckError(CreateErrorCallback( - state->apiOptions.giveawayAddPeersMax(), - tr::lng_giveaway_maximum_users_error)); - box->uiShow()->showBox( - Box( - std::move(listController), - std::move(initBox)), - Ui::LayerOption::KeepOther); - }); - } { const auto &padding = st::giveawayGiftCodeTypeDividerPadding; @@ -498,14 +510,10 @@ void CreateGiveawayBox( object_ptr(box))); state->typeValue.value( ) | rpl::start_with_next([=](GiveawayType type) { - randomWrap->toggle(type == GiveawayType::Random, anim::type::instant); + randomWrap->toggle(!isSpecificUsers(), anim::type::instant); }, randomWrap->lifetime()); - randomWrap->toggleOn( - state->typeValue.value( - ) | rpl::map((rpl::mappers::_1 == GiveawayType::Random) - || (rpl::mappers::_1 == GiveawayType::Credits)), - anim::type::instant); + randomWrap->toggleOn(hideSpecificUsersOn(), anim::type::instant); const auto randomCreditsWrap = randomWrap->entity()->add( object_ptr>( @@ -1049,7 +1057,7 @@ void CreateGiveawayBox( while (listOptionsSpecific->count()) { delete listOptionsSpecific->widgetAt(0); } - const auto listOptions = (type == GiveawayType::SpecificUsers) + const auto listOptions = isSpecificUsers() ? listOptionsSpecific : listOptionsRandom; if (type != GiveawayType::Credits) { @@ -1086,9 +1094,9 @@ void CreateGiveawayBox( state->typeValue.value() ) | rpl::start_with_next([=](int users, GiveawayType type) { typeGroup->setValue(type); - rebuildListOptions(type, (type == GiveawayType::SpecificUsers) - ? state->selectedToAward.size() - : users); + rebuildListOptions( + type, + isSpecificUsers() ? state->selectedToAward.size() : users); }, box->lifetime()); } else { typeGroup->setValue(GiveawayType::Random); @@ -1144,7 +1152,7 @@ void CreateGiveawayBox( ? (rpl::single(prepaid->months) | rpl::type_erased()) : state->chosenMonths.value(); const auto usersCountByType = [=](GiveawayType type) { - if (type != GiveawayType::SpecificUsers) { + if (!isSpecificUsers()) { return state->sliderValue.value() | rpl::type_erased(); } return state->toAwardAmountChanged.events_starting_with_copy( @@ -1347,18 +1355,23 @@ void CreateGiveawayBox( AddLabelWithBadgeToButton( button, rpl::conditional( - state->typeValue.value( - ) | rpl::map(rpl::mappers::_1 != GiveawayType::Random), - tr::lng_giveaway_award(), - tr::lng_giveaway_start()), + hideSpecificUsersOn(), + tr::lng_giveaway_start(), + tr::lng_giveaway_award()), rpl::conditional( state->typeValue.value( ) | rpl::map(rpl::mappers::_1 == GiveawayType::Credits), creditsGroup->value() | rpl::map([=](int v) { return creditsOption(v).yearlyBoosts; }), - state->sliderValue.value() | rpl::map([=](int v) -> int { - return state->apiOptions.giveawayBoostsPerPremium() * v; + rpl::combine( + 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)); @@ -1382,7 +1395,7 @@ void CreateGiveawayBox( return; } const auto type = typeGroup->current(); - const auto isSpecific = (type == GiveawayType::SpecificUsers); + const auto isSpecific = isSpecificUsers(); const auto isRandom = (type == GiveawayType::Random); const auto isCredits = (type == GiveawayType::Credits); if (!isSpecific && !isRandom && !isCredits) { diff --git a/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway_type_row.cpp b/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway_type_row.cpp index 56fa79c3d..2c597c066 100644 --- a/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway_type_row.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway_type_row.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_options.h" #include "ui/widgets/checkbox.h" #include "styles/style_boxes.h" +#include "styles/style_chat.h" #include "styles/style_giveaway.h" #include "styles/style_statistics.h" @@ -94,7 +95,8 @@ GiveawayTypeRow::GiveawayTypeRow( (type == Type::SpecificUsers) ? tr::lng_giveaway_award_option() : (type == Type::Random) - ? tr::lng_giveaway_create_option() + ? tr::lng_premium_summary_title() + // ? tr::lng_giveaway_create_option() : (type == Type::AllMembers) ? (group ? tr::lng_giveaway_users_all_group() @@ -131,8 +133,11 @@ GiveawayTypeRow::GiveawayTypeRow( } std::move( subtitle - ) | rpl::start_with_next([=] (const QString &s) { - _status.setText(st::defaultTextStyle, s, Ui::NameTextOptions()); + ) | rpl::start_with_next([=] (QString s) { + _status.setText( + st::defaultTextStyle, + s.replace(QChar('>'), QString()), + Ui::NameTextOptions()); }, lifetime()); std::move( title @@ -151,9 +156,10 @@ void GiveawayTypeRow::paintEvent(QPaintEvent *e) { const auto paintOver = (isOver() || isDown()) && !isDisabled(); const auto skipRight = _st.photoPosition.x(); const auto outerWidth = width(); + const auto isRandom = (_type == Type::Random); const auto isSpecific = (_type == Type::SpecificUsers); const auto isPrepaid = (_type == Type::Prepaid); - const auto hasUserpic = (_type == Type::Random) + const auto hasUserpic = isRandom || isSpecific || isPrepaid || (!_customUserpic.isNull()); @@ -204,12 +210,29 @@ void GiveawayTypeRow::paintEvent(QPaintEvent *e) { _badge); } + const auto statusIcon = isRandom ? &st::topicButtonArrow : nullptr; const auto statusx = _st.statusPosition.x(); 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.setPen((isSpecific || !hasUserpic) ? st::lightButtonFg : _st.statusFg); + p.setPen((isRandom || !hasUserpic) ? st::lightButtonFg : _st.statusFg); _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(