From 9b599644d95db958c508e843748b2eb155a14b75 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 13 Nov 2025 14:48:23 +0400 Subject: [PATCH] Improve bidding logic. --- Telegram/Resources/langs/lang.strings | 1 + .../boxes/star_gift_auction_box.cpp | 30 ++++++++-- .../payments/ui/payments_reaction_box.cpp | 60 +++++++++---------- .../payments/ui/payments_reaction_box.h | 1 + Telegram/SourceFiles/ui/effects/premium.style | 1 - 5 files changed, 53 insertions(+), 40 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index aa3c2a9cdd..2d8e25311b 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -4038,6 +4038,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_auction_bid_your_winning" = "You're winning"; "lng_auction_bid_winners_title" = "Top 3 Winners"; "lng_auction_bid_place" = "Place a {stars} Bid"; +"lng_auction_bid_increase" = "Add {stars} to Your Bid"; "lng_auction_bid_placed_title" = "Your bid has been placed"; "lng_auction_bid_increased_title" = "Your bid has been increased"; "lng_auction_bid_done_text#one" = "If you fall below the **top {count}**, your bid will roll over to the next round."; diff --git a/Telegram/SourceFiles/boxes/star_gift_auction_box.cpp b/Telegram/SourceFiles/boxes/star_gift_auction_box.cpp index 53cb3eb447..23a70db3d8 100644 --- a/Telegram/SourceFiles/boxes/star_gift_auction_box.cpp +++ b/Telegram/SourceFiles/boxes/star_gift_auction_box.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/star_gift_auction_box.h" #include "base/unixtime.h" +#include "boxes/send_credits_box.h" // CreditsEmojiSmall #include "boxes/star_gift_box.h" #include "calls/group/calls_group_common.h" #include "core/credits_amount.h" @@ -47,6 +48,7 @@ namespace { constexpr auto kAuctionAboutShownPref = "gift_auction_about_shown"_cs; constexpr auto kBidPlacedToastDuration = 5 * crl::time(1000); +constexpr auto kMaxShownBid = 30'000; [[nodiscard]] rpl::producer MinutesLeftTillValue(TimeId endDate) { return [=](auto consumer) { @@ -128,9 +130,24 @@ void AuctionBidBox(not_null box, AuctionBidBoxArgs &&args) { rpl::variable >(std::move(args.state)); auto submit = [=](rpl::producer amount) { - return std::move(amount) | rpl::map([=](int count) { - return TextWithEntities{ "Place a " + QString::number(count) + " Bid" }; - }); + return rpl::combine( + state->value(), + std::move(amount) + ) | rpl::map([=](const Data::GiftAuctionState &state, int count) { + return !state.my.bid + ? tr::lng_auction_bid_place( + lt_stars, + rpl::single(Ui::CreditsEmojiSmall().append( + Lang::FormatCountDecimal(count))), + tr::marked) + : (count <= state.my.bid) + ? tr::lng_box_ok(tr::marked) + : tr::lng_auction_bid_increase( + lt_stars, + rpl::single(Ui::CreditsEmojiSmall().append( + Lang::FormatCountDecimal(count - state.my.bid))), + tr::marked); + }) | rpl::flatten_latest(); }; const auto show = args.show; const auto session = &show->session(); @@ -165,15 +182,16 @@ void AuctionBidBox(not_null box, AuctionBidBoxArgs &&args) { }; PlaceAuctionBid(show, peer, amount, now, done); }; + const auto mine = state->current().my.bid; PaidReactionsBox(box, { - .min = int(state->current().my.bid + .min = int(mine ? state->current().my.minBidAmount : state->current().minBidAmount), + .explicitlyAllowed = int(mine), .chosen = int(state->current().my.bid), - .max = 10'000, + .max = kMaxShownBid, .top = std::move(top), .session = session, - .name = u"hello"_q, .submit = submit, .colorings = session->appConfig().groupCallColorings(), .balanceValue = session->credits().balanceValue(), diff --git a/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp b/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp index 1192ecc8a0..aef5d4dcb8 100644 --- a/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp @@ -92,11 +92,16 @@ struct Discreter { thresholds.emplace(1. / 8, 10); thresholds.emplace(1. / 3, 100); thresholds.emplace(1., max); - } else { + } else if (max <= 10000) { thresholds.emplace(1. / 8, 10); thresholds.emplace(1. / 3, 100); thresholds.emplace(2. / 3, 1000); thresholds.emplace(1., max); + } else { + thresholds.emplace(1. / 10, 10); + thresholds.emplace(1. / 6, 100); + thresholds.emplace(1. / 3, 1000); + thresholds.emplace(1., max); } const auto ratioToValue = [=](float64 ratio) { @@ -131,12 +136,17 @@ void PaidReactionSlider( not_null container, const style::MediaSlider &st, int min, + int explicitlyAllowed, int current, int max, Fn changed, Fn activeFgOverride = nullptr) { Expects(current >= 1 && current <= max); + Expects(explicitlyAllowed <= max); + if (!explicitlyAllowed) { + explicitlyAllowed = min; + } const auto slider = container->add( object_ptr(container, st), st::boxRowPadding + QMargins(0, st::paidReactSliderTop, 0, 0)); @@ -161,7 +171,9 @@ void PaidReactionSlider( slider->setValue(discreter.valueToRatio(current)); const auto ratioToValue = [=](float64 ratio) { const auto value = discreter.ratioToValue(ratio); - return std::max(value, min); + return (value <= explicitlyAllowed && explicitlyAllowed < min) + ? explicitlyAllowed + : std::max(value, min); }; slider->setAdjustCallback([=](float64 ratio) { return discreter.valueToRatio(ratioToValue(ratio)); @@ -569,8 +581,17 @@ void PaidReactionsBox( const auto dark = args.dark; args.min = std::max(args.min, 1); - args.max = std::max(args.max, args.min + 1); - args.chosen = std::clamp(args.chosen, args.min, args.max); + args.max = std::max({ + args.min + 1, + args.max, + args.explicitlyAllowed, + args.chosen, + }); + + const auto allowed = args.explicitlyAllowed; + args.chosen = (allowed && args.chosen == allowed) + ? allowed + : std::clamp(args.chosen, args.min, args.max); box->setWidth(st::boxWideWidth); box->setStyle(dark ? st::darkEditStarsBox : st::paidReactBox); @@ -651,6 +672,7 @@ void PaidReactionsBox( content, (dark ? st::darkEditStarsSlider : st::paidReactSlider), args.min, + args.explicitlyAllowed, args.chosen, args.max, changed, @@ -778,35 +800,7 @@ void PaidReactionsBox( args.send(0, state->shownPeer.current()); }, box->lifetime()); - { - const auto buttonLabel = CreateChild( - button, - rpl::single(QString()), - st::creditsBoxButtonLabel); - args.submit( - state->chosen.value() - ) | rpl::start_with_next([=](const TextWithEntities &text) { - buttonLabel->setMarkedText(text); - }, buttonLabel->lifetime()); - buttonLabel->setTextColorOverride( - box->getDelegate()->style().button.textFg->c); - button->sizeValue( - ) | rpl::start_with_next([=](const QSize &size) { - buttonLabel->moveToLeft( - (size.width() - buttonLabel->width()) / 2, - (size.height() - buttonLabel->height()) / 2); - }, buttonLabel->lifetime()); - buttonLabel->setAttribute(Qt::WA_TransparentForMouseEvents); - } - - box->widthValue( - ) | rpl::start_with_next([=](int width) { - const auto &padding = st::paidReactBox.buttonPadding; - button->resizeToWidth(width - - padding.left() - - padding.right()); - button->moveToLeft(padding.left(), button->y()); - }, button->lifetime()); + button->setText(args.submit(state->chosen.value())); { const auto balance = Settings::AddBalanceWidget( diff --git a/Telegram/SourceFiles/payments/ui/payments_reaction_box.h b/Telegram/SourceFiles/payments/ui/payments_reaction_box.h index af63a8c219..83b6dbe9c8 100644 --- a/Telegram/SourceFiles/payments/ui/payments_reaction_box.h +++ b/Telegram/SourceFiles/payments/ui/payments_reaction_box.h @@ -35,6 +35,7 @@ struct PaidReactionTop { struct PaidReactionBoxArgs { int min = 0; + int explicitlyAllowed = 0; int chosen = 0; int max = 0; diff --git a/Telegram/SourceFiles/ui/effects/premium.style b/Telegram/SourceFiles/ui/effects/premium.style index 641914865c..e58cfbfb79 100644 --- a/Telegram/SourceFiles/ui/effects/premium.style +++ b/Telegram/SourceFiles/ui/effects/premium.style @@ -404,7 +404,6 @@ boostFeatureProfileIcon: icon{{ "settings/premium/features/feature_profile_cover paidReactBox: Box(boostBox) { buttonPadding: margins(22px, 22px, 22px, 22px); - buttonHeight: 42px; button: RoundButton(defaultActiveButton) { height: 42px; textTop: 12px;