diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 0b9f4c334..6b11445f1 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2114,6 +2114,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_giveaway_maximum_countries_error#other" = "You can select maximum {count} countries."; "lng_giveaway_maximum_channels_error#one" = "You can select maximum {count} channel."; "lng_giveaway_maximum_channels_error#other" = "You can select maximum {count} channels."; +"lng_giveaway_maximum_users_error#one" = "You can select maximum {count} user."; +"lng_giveaway_maximum_users_error#other" = "You can select maximum {count} users."; "lng_giveaway_channels_confirm_title" = "Channel is Private"; "lng_giveaway_channels_confirm_about" = "Are you sure you want to add a private channel? Users won't be able to join it without an invite link."; diff --git a/Telegram/SourceFiles/api/api_premium.cpp b/Telegram/SourceFiles/api/api_premium.cpp index 185e2728c..629abc0d0 100644 --- a/Telegram/SourceFiles/api/api_premium.cpp +++ b/Telegram/SourceFiles/api/api_premium.cpp @@ -435,18 +435,38 @@ Data::SubscriptionOptions PremiumGiftCodeOptions::options(int amount) { } } -[[nodiscard]] int PremiumGiftCodeOptions::giveawayBoostsPerPremium() const { +int PremiumGiftCodeOptions::giveawayBoostsPerPremium() const { constexpr auto kFallbackCount = 4; return _peer->session().account().appConfig().get( u"giveaway_boosts_per_premium"_q, kFallbackCount); } -[[nodiscard]] int PremiumGiftCodeOptions::giveawayCountriesMax() const { +int PremiumGiftCodeOptions::giveawayCountriesMax() const { constexpr auto kFallbackCount = 10; return _peer->session().account().appConfig().get( u"giveaway_countries_max"_q, kFallbackCount); } +int PremiumGiftCodeOptions::giveawayAddPeersMax() const { + constexpr auto kFallbackCount = 10; + return _peer->session().account().appConfig().get( + u"giveaway_add_peers_max"_q, + kFallbackCount); +} + +int PremiumGiftCodeOptions::giveawayPeriodMax() const { + constexpr auto kFallbackCount = 3600 * 24 * 7; + return _peer->session().account().appConfig().get( + u"giveaway_period_max"_q, + kFallbackCount); +} + +bool PremiumGiftCodeOptions::giveawayGiftsPurchaseAvailable() const { + return _peer->session().account().appConfig().get( + u"giveaway_gifts_purchase_available"_q, + false); +} + } // namespace Api diff --git a/Telegram/SourceFiles/api/api_premium.h b/Telegram/SourceFiles/api/api_premium.h index cfc7c6ec1..deb66df80 100644 --- a/Telegram/SourceFiles/api/api_premium.h +++ b/Telegram/SourceFiles/api/api_premium.h @@ -158,6 +158,9 @@ public: [[nodiscard]] int giveawayBoostsPerPremium() const; [[nodiscard]] int giveawayCountriesMax() const; + [[nodiscard]] int giveawayAddPeersMax() const; + [[nodiscard]] int giveawayPeriodMax() const; + [[nodiscard]] bool giveawayGiftsPurchaseAvailable() const; private: struct Token final { diff --git a/Telegram/SourceFiles/info/boosts/create_giveaway_box.cpp b/Telegram/SourceFiles/info/boosts/create_giveaway_box.cpp index 27b9a49f7..a1f72950b 100644 --- a/Telegram/SourceFiles/info/boosts/create_giveaway_box.cpp +++ b/Telegram/SourceFiles/info/boosts/create_giveaway_box.cpp @@ -51,6 +51,18 @@ namespace { return dateNow; } +[[nodiscard]] Fn CreateErrorCallback( + int max, + tr::phrase phrase) { + return [=](int count) { + const auto error = (count >= max); + if (error) { + Ui::Toast::Show(phrase(tr::now, lt_count, max)); + } + return error; + }; +} + } // namespace void CreateGiveawayBox( @@ -188,11 +200,16 @@ void CreateGiveawayBox( }, peersBox->lifetime()); }; + using Controller = Giveaway::AwardMembersListController; + auto listController = std::make_unique( + controller, + peer); + listController->setCheckError(CreateErrorCallback( + state->apiOptions.giveawayAddPeersMax(), + tr::lng_giveaway_maximum_users_error)); box->uiShow()->showBox( Box( - std::make_unique( - controller, - peer), + std::move(listController), std::move(initBox)), Ui::LayerOption::KeepOther); }); @@ -349,13 +366,16 @@ void CreateGiveawayBox( }); }; + using Controller = Giveaway::MyChannelsListController; + auto controller = std::make_unique( + peer, + box->uiShow(), + state->selectedToSubscribe); + controller->setCheckError(CreateErrorCallback( + state->apiOptions.giveawayAddPeersMax(), + tr::lng_giveaway_maximum_channels_error)); box->uiShow()->showBox( - Box( - std::make_unique( - peer, - box->uiShow(), - state->selectedToSubscribe), - std::move(initBox)), + Box(std::move(controller), std::move(initBox)), Ui::LayerOption::KeepOther); }); @@ -394,18 +414,9 @@ void CreateGiveawayBox( auto done = [=](std::vector list) { state->countriesValue = std::move(list); }; - auto error = [=](int count) { - const auto max = state->apiOptions.giveawayCountriesMax(); - const auto error = (count >= max); - if (error) { - Ui::Toast::Show(tr::lng_giveaway_maximum_countries_error( - tr::now, - lt_count, - max)); - } - return error; - }; - + auto error = CreateErrorCallback( + state->apiOptions.giveawayCountriesMax(), + tr::lng_giveaway_maximum_countries_error); box->uiShow()->showBox(Box( Ui::SelectCountriesBox, state->countriesValue.current(), @@ -469,7 +480,6 @@ void CreateGiveawayBox( st::defaultSettingsButton); button->setClickedCallback([=] { - constexpr auto kSevenDays = 3600 * 24 * 7; box->uiShow()->showBox(Box([=](not_null b) { Ui::ChooseDateTimeBox(b, { .title = tr::lng_giveaway_date_select(), @@ -482,7 +492,7 @@ void CreateGiveawayBox( .time = state->dateValue.current(), .max = [=] { return QDateTime::currentSecsSinceEpoch() - + kSevenDays; + + state->apiOptions.giveawayPeriodMax();; }, }); })); diff --git a/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.cpp b/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.cpp index b6307e32a..dd6df700f 100644 --- a/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.cpp +++ b/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.cpp @@ -112,7 +112,13 @@ AwardMembersListController::AwardMembersListController( } void AwardMembersListController::rowClicked(not_null row) { - delegate()->peerListSetRowChecked(row, !row->checked()); + const auto checked = !row->checked(); + if (checked + && _checkErrorCallback + && _checkErrorCallback(delegate()->peerListSelectedRowsCount())) { + return; + } + delegate()->peerListSetRowChecked(row, checked); } std::unique_ptr AwardMembersListController::createRow( @@ -130,6 +136,10 @@ base::unique_qptr AwardMembersListController::rowContextMenu( return nullptr; } +void AwardMembersListController::setCheckError(Fn callback) { + _checkErrorCallback = std::move(callback); +} + MyChannelsListController::MyChannelsListController( not_null peer, std::shared_ptr show, @@ -160,6 +170,11 @@ std::unique_ptr MyChannelsListController::createRestoredRow( void MyChannelsListController::rowClicked(not_null row) { const auto channel = row->peer()->asChannel(); const auto checked = !row->checked(); + if (checked + && _checkErrorCallback + && _checkErrorCallback(delegate()->peerListSelectedRowsCount())) { + return; + } if (checked && channel && channel->username().isEmpty()) { _show->showBox(Box(Ui::ConfirmBox, Ui::ConfirmBoxArgs{ .text = tr::lng_giveaway_channels_confirm_about(), @@ -224,6 +239,10 @@ void MyChannelsListController::prepare() { }).send(); } +void MyChannelsListController::setCheckError(Fn callback) { + _checkErrorCallback = std::move(callback); +} + std::unique_ptr MyChannelsListController::createRow( not_null channel) const { if (channel->isMegagroup()) { diff --git a/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.h b/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.h index 2c1e589c2..8d08a8a15 100644 --- a/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.h +++ b/Telegram/SourceFiles/info/boosts/giveaway/giveaway_list_controllers.h @@ -29,6 +29,8 @@ public: not_null navigation, not_null peer); + void setCheckError(Fn callback); + void rowClicked(not_null row) override; std::unique_ptr createRow( not_null participant) const override; @@ -36,6 +38,9 @@ public: QWidget *parent, not_null row) override; +private: + Fn _checkErrorCallback; + }; class MyChannelsListController : public PeerListController { @@ -45,6 +50,8 @@ public: std::shared_ptr show, std::vector> selected); + void setCheckError(Fn callback); + Main::Session &session() const override; void prepare() override; void rowClicked(not_null row) override; @@ -61,6 +68,8 @@ private: const not_null _peer; const std::shared_ptr _show; + Fn _checkErrorCallback; + std::vector> _selected; rpl::lifetime _apiLifetime; diff --git a/Telegram/SourceFiles/info/boosts/info_boosts_inner_widget.cpp b/Telegram/SourceFiles/info/boosts/info_boosts_inner_widget.cpp index 73edbd68d..66445a109 100644 --- a/Telegram/SourceFiles/info/boosts/info_boosts_inner_widget.cpp +++ b/Telegram/SourceFiles/info/boosts/info_boosts_inner_widget.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "info/boosts/info_boosts_inner_widget.h" +#include "api/api_premium.h" #include "api/api_statistics.h" #include "boxes/peers/edit_peer_invite_link.h" #include "info/boosts/create_giveaway_box.h" @@ -182,6 +183,10 @@ void FillGetBoostsButton( not_null controller, std::shared_ptr show, not_null peer) { + if (!Api::PremiumGiftCodeOptions(peer).giveawayGiftsPurchaseAvailable()) { + return; + } + ::Settings::AddSkip(content); const auto &st = st::getBoostsButton; const auto &icon = st::getBoostsButtonIcon; const auto button = content->add( @@ -199,6 +204,8 @@ void FillGetBoostsButton( st::infoSharedMediaButtonIconPosition.x(), (st.height + rect::m::sum::v(st.padding) - icon.height()) / 2, })->show(); + ::Settings::AddSkip(content); + ::Settings::AddDividerText(content, tr::lng_boosts_get_boosts_subtext()); } } // namespace @@ -293,10 +300,7 @@ void InnerWidget::fill() { ::Settings::AddSkip(inner); ::Settings::AddDividerText(inner, tr::lng_boosts_link_subtext()); - ::Settings::AddSkip(inner); FillGetBoostsButton(inner, _controller, _show, _peer); - ::Settings::AddSkip(inner); - ::Settings::AddDividerText(inner, tr::lng_boosts_get_boosts_subtext()); resizeToWidth(width()); crl::on_main([=]{ fakeShowed->fire({}); });