Implement upcoming auction preview box.
This commit is contained in:
@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "base/timer_rpl.h"
|
||||
#include "base/unixtime.h"
|
||||
#include "boxes/peers/replace_boost_box.h"
|
||||
#include "boxes/premium_preview_box.h"
|
||||
#include "boxes/send_credits_box.h" // CreditsEmojiSmall
|
||||
#include "boxes/share_box.h"
|
||||
#include "boxes/star_gift_box.h"
|
||||
@@ -991,33 +992,55 @@ void AuctionBidBox(not_null<GenericBox*> box, AuctionBidBoxArgs &&args) {
|
||||
tr::lng_auction_rounds_label(),
|
||||
rpl::single(tr::marked(
|
||||
Lang::FormatCountDecimal(now.totalRounds))));
|
||||
AddTableRow(
|
||||
raw,
|
||||
tr::lng_auction_rounds_first(),
|
||||
((now.roundDurationFirst % 3600)
|
||||
? tr::lng_minutes(
|
||||
const auto formatDuration = [&](TimeId value, bool exact) {
|
||||
return (!(value % 3600))
|
||||
? (exact ? tr::lng_hours : tr::lng_auction_rounds_hours)(
|
||||
tr::now,
|
||||
lt_count,
|
||||
rpl::single(now.roundDurationFirst / 60.),
|
||||
tr::marked)
|
||||
: tr::lng_hours(
|
||||
value / 3600)
|
||||
: (!(value % 60))
|
||||
? (exact ? tr::lng_minutes : tr::lng_auction_rounds_minutes)(
|
||||
tr::now,
|
||||
lt_count,
|
||||
rpl::single(now.roundDurationFirst / 3600.),
|
||||
tr::marked)));
|
||||
if (now.totalRounds > 1) {
|
||||
value / 60)
|
||||
: (exact ? tr::lng_seconds : tr::lng_auction_rounds_seconds)(
|
||||
tr::now,
|
||||
lt_count,
|
||||
value);
|
||||
};
|
||||
for (auto i = 0, n = int(now.roundParameters.size()); i != n; ++i) {
|
||||
const auto &that = now.roundParameters[i];
|
||||
const auto next = (i + 1 < n)
|
||||
? now.roundParameters[i + 1]
|
||||
: Data::GiftAuctionRound{ now.totalRounds + 1 };
|
||||
const auto exact = (next.number == that.number + 1);
|
||||
const auto extended = that.extendTop && that.extendDuration;
|
||||
const auto duration = formatDuration(that.duration, exact);
|
||||
const auto value = extended
|
||||
? tr::lng_auction_rounds_extended(
|
||||
tr::now,
|
||||
lt_duration,
|
||||
duration,
|
||||
lt_increase,
|
||||
formatDuration(that.extendDuration, true),
|
||||
lt_n,
|
||||
QString::number(that.extendTop))
|
||||
: duration;
|
||||
AddTableRow(
|
||||
raw,
|
||||
tr::lng_auction_rounds_rest(
|
||||
lt_last,
|
||||
rpl::single(QString::number(now.totalRounds))),
|
||||
((now.roundDurationRest % 3600)
|
||||
? tr::lng_auction_rounds_rest_minutes(
|
||||
lt_count,
|
||||
rpl::single(now.roundDurationRest / 60.),
|
||||
tr::marked)
|
||||
: tr::lng_auction_rounds_rest_hours(
|
||||
lt_count,
|
||||
rpl::single(now.roundDurationRest / 3600.),
|
||||
tr::marked)));
|
||||
(exact
|
||||
? tr::lng_auction_rounds_exact(
|
||||
lt_n,
|
||||
rpl::single(QString::number(that.number)))
|
||||
: tr::lng_auction_rounds_range(
|
||||
lt_n,
|
||||
rpl::single(QString::number(that.number)),
|
||||
lt_last,
|
||||
rpl::single(QString::number(next.number - 1)))),
|
||||
object_ptr<FlatLabel>(
|
||||
raw,
|
||||
value,
|
||||
st::auctionInfoValueMultiline));
|
||||
}
|
||||
} else {
|
||||
auto roundText = state->value.value(
|
||||
@@ -1180,12 +1203,9 @@ void AuctionGotGiftsBox(
|
||||
.pattern = Data::UniqueGiftPattern{
|
||||
.document = info.document,
|
||||
},
|
||||
.backdrop = Data::UniqueGiftBackdrop{
|
||||
.centerColor = QColor(0x3a, 0x76, 0xb4),
|
||||
.edgeColor = QColor(0x10, 0x2d, 0x4d),
|
||||
.patternColor = QColor(0, 0, 0, 0),
|
||||
.textColor = QColor(0xff, 0xff, 0xff),
|
||||
},
|
||||
.backdrop = (info.background
|
||||
? info.background->backdrop()
|
||||
: Data::UniqueGiftBackdrop()),
|
||||
};
|
||||
return rpl::single(initial) | rpl::then(std::move(
|
||||
attributes
|
||||
@@ -1302,11 +1322,22 @@ void AuctionInfoBox(
|
||||
box->setNoContentMargin(true);
|
||||
if (!started) {
|
||||
const auto container = box->verticalLayout();
|
||||
AddUniqueGiftCover(
|
||||
container,
|
||||
MakePreviewAuctionStream(*now.gift, state->attributes.value()),
|
||||
tr::lng_gift_upgrade_about());
|
||||
|
||||
auto gift = MakePreviewAuctionStream(
|
||||
*now.gift,
|
||||
state->attributes.value());
|
||||
AddUniqueGiftCover(container, std::move(gift), {
|
||||
.pretitle = tr::lng_auction_preview_name(),
|
||||
.subtitle = tr::lng_auction_preview_learn_gifts(
|
||||
lt_arrow,
|
||||
rpl::single(Text::IconEmoji(&st::textMoreIconEmoji)),
|
||||
tr::link),
|
||||
.subtitleClick = [=] {
|
||||
ShowPremiumPreviewBox(
|
||||
window,
|
||||
PremiumFeature::AnimatedEmoji); AssertIsDebug();
|
||||
},
|
||||
.subtitleLinkColored = true,
|
||||
});
|
||||
AddSkip(container, st::defaultVerticalListSkip * 2);
|
||||
|
||||
AddUniqueCloseButton(box, {}, MakeAuctionFillMenuCallback(show, now));
|
||||
@@ -1712,9 +1743,11 @@ void SetAuctionButtonCountdownText(
|
||||
) | rpl::map([=](const Data::GiftAuctionState &state, int leftTill) {
|
||||
return (state.finished() || (!preview && leftTill <= 0))
|
||||
? tr::lng_box_ok(tr::marked)
|
||||
: (type == AuctionButtonCountdownType::Place)
|
||||
? tr::lng_auction_join_bid(tr::marked)
|
||||
: tr::lng_auction_join_button(tr::marked);
|
||||
: (type != AuctionButtonCountdownType::Place)
|
||||
? tr::lng_auction_join_button(tr::marked)
|
||||
: preview
|
||||
? tr::lng_auction_join_early_bid(tr::marked)
|
||||
: tr::lng_auction_join_bid(tr::marked);
|
||||
}) | rpl::flatten_latest();
|
||||
|
||||
auto buttonSubtitle = rpl::combine(
|
||||
|
||||
@@ -137,6 +137,7 @@ constexpr auto kCrossfadeDuration = crl::time(400);
|
||||
constexpr auto kUpgradeDoneToastDuration = 4 * crl::time(1000);
|
||||
constexpr auto kGiftsPreloadTimeout = 3 * crl::time(1000);
|
||||
constexpr auto kResellPriceCacheLifetime = 60 * crl::time(1000);
|
||||
constexpr auto kGradientButtonBgOpacity = 0.6;
|
||||
|
||||
using namespace HistoryView;
|
||||
using namespace Info::PeerGifts;
|
||||
@@ -2798,38 +2799,73 @@ void SetupResalePriceButton(
|
||||
void AddUniqueGiftCover(
|
||||
not_null<VerticalLayout*> container,
|
||||
rpl::producer<Data::UniqueGift> data,
|
||||
rpl::producer<QString> subtitleOverride,
|
||||
rpl::producer<CreditsAmount> resalePrice,
|
||||
Fn<void()> resaleClick) {
|
||||
UniqueGiftCoverArgs &&args) {
|
||||
const auto cover = container->add(object_ptr<RpWidget>(container));
|
||||
|
||||
struct Released {
|
||||
Released() : white(QColor(255, 255, 255)) {
|
||||
Released() : link(QColor(255, 255, 255)) {
|
||||
}
|
||||
|
||||
rpl::variable<TextWithEntities> subtitleText;
|
||||
style::owned_color white;
|
||||
std::optional<Ui::Premium::ColoredMiniStars> stars;
|
||||
style::owned_color link;
|
||||
style::FlatLabel st;
|
||||
PeerData *by = nullptr;
|
||||
QColor bg;
|
||||
};
|
||||
const auto released = cover->lifetime().make_state<Released>();
|
||||
released->st = st::uniqueGiftReleasedBy;
|
||||
released->st.palette.linkFg = released->white.color();
|
||||
released->st.palette.linkFg = released->link.color();
|
||||
|
||||
if (resalePrice) {
|
||||
if (args.resalePrice) {
|
||||
auto background = rpl::duplicate(
|
||||
data
|
||||
) | rpl::map([=](const Data::UniqueGift &unique) {
|
||||
return unique.backdrop.patternColor;
|
||||
auto result = unique.backdrop.patternColor;
|
||||
result.setAlphaF(kGradientButtonBgOpacity * result.alphaF());
|
||||
return result;
|
||||
});
|
||||
SetupResalePriceButton(
|
||||
cover,
|
||||
std::move(background),
|
||||
std::move(resalePrice),
|
||||
std::move(resaleClick));
|
||||
std::move(args.resalePrice),
|
||||
std::move(args.resaleClick));
|
||||
}
|
||||
|
||||
const auto pretitle = args.pretitle
|
||||
? CreateChild<FlatLabel>(
|
||||
cover,
|
||||
std::move(args.pretitle),
|
||||
st::uniqueGiftPretitle)
|
||||
: nullptr;
|
||||
if (pretitle) {
|
||||
released->stars.emplace(
|
||||
cover,
|
||||
true,
|
||||
Ui::Premium::MiniStarsType::SlowStars);
|
||||
const auto white = QColor(255, 255, 255);
|
||||
released->stars->setColorOverride(QGradientStops{
|
||||
{ 0., anim::with_alpha(white, .3) },
|
||||
{ 1., white },
|
||||
});
|
||||
pretitle->geometryValue() | rpl::start_with_next([=](QRect rect) {
|
||||
const auto half = rect.height() / 2;
|
||||
released->stars->setCenter(rect - QMargins(half, 0, half, 0));
|
||||
}, pretitle->lifetime());
|
||||
pretitle->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
pretitle->setTextColorOverride(QColor(255, 255, 255));
|
||||
pretitle->paintOn([=](QPainter &p) {
|
||||
auto hq = PainterHighQualityEnabler(p);
|
||||
const auto radius = pretitle->height() / 2.;
|
||||
p.setPen(Qt::NoPen);
|
||||
auto bg = released->bg;
|
||||
bg.setAlphaF(kGradientButtonBgOpacity * bg.alphaF());
|
||||
p.setBrush(bg);
|
||||
p.drawRoundedRect(pretitle->rect(), radius, radius);
|
||||
p.translate(-pretitle->pos());
|
||||
released->stars->paint(p);
|
||||
});
|
||||
}
|
||||
const auto title = CreateChild<FlatLabel>(
|
||||
cover,
|
||||
rpl::duplicate(
|
||||
@@ -2837,13 +2873,10 @@ void AddUniqueGiftCover(
|
||||
) | rpl::map([](const Data::UniqueGift &now) { return now.title; }),
|
||||
st::uniqueGiftTitle);
|
||||
title->setTextColorOverride(QColor(255, 255, 255));
|
||||
released->subtitleText = subtitleOverride
|
||||
? std::move(
|
||||
subtitleOverride
|
||||
) | Ui::Text::ToWithEntities() | rpl::type_erased()
|
||||
released->subtitleText = args.subtitle
|
||||
? std::move(args.subtitle)
|
||||
: rpl::duplicate(data) | rpl::map([=](const Data::UniqueGift &gift) {
|
||||
released->by = gift.releasedBy;
|
||||
released->bg = gift.backdrop.patternColor;
|
||||
return gift.releasedBy
|
||||
? tr::lng_gift_unique_number_by(
|
||||
tr::now,
|
||||
@@ -2860,13 +2893,18 @@ void AddUniqueGiftCover(
|
||||
});
|
||||
if (!released->by) {
|
||||
released->st = st::uniqueGiftSubtitle;
|
||||
released->st.palette.linkFg = released->white.color();
|
||||
released->st.palette.linkFg = released->link.color();
|
||||
}
|
||||
const auto subtitle = CreateChild<FlatLabel>(
|
||||
cover,
|
||||
released->subtitleText.value(),
|
||||
released->st);
|
||||
if (released->by) {
|
||||
if (const auto handler = args.subtitleClick) {
|
||||
subtitle->setClickHandlerFilter([=](const auto &...) {
|
||||
handler();
|
||||
return false;
|
||||
});
|
||||
} else if (released->by) {
|
||||
const auto button = CreateChild<AbstractButton>(cover);
|
||||
subtitle->raise();
|
||||
subtitle->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
@@ -2912,15 +2950,28 @@ void AddUniqueGiftCover(
|
||||
};
|
||||
const auto state = cover->lifetime().make_state<State>();
|
||||
const auto lottieSize = st::creditsHistoryEntryStarGiftSize;
|
||||
const auto updateLinkFg = args.subtitleLinkColored;
|
||||
const auto updateColors = [=](float64 progress) {
|
||||
subtitle->setTextColorOverride((progress == 0.)
|
||||
const auto color = (progress == 0.)
|
||||
? state->now.gift->backdrop.textColor
|
||||
: (progress == 1.)
|
||||
? state->next.gift->backdrop.textColor
|
||||
: anim::color(
|
||||
state->now.gift->backdrop.textColor,
|
||||
state->next.gift->backdrop.textColor,
|
||||
progress));
|
||||
progress);
|
||||
if (updateLinkFg) {
|
||||
released->link.update(color);
|
||||
}
|
||||
subtitle->setTextColorOverride(color);
|
||||
released->bg = (progress == 0.)
|
||||
? state->now.gift->backdrop.patternColor
|
||||
: (progress == 1.)
|
||||
? state->next.gift->backdrop.patternColor
|
||||
: anim::color(
|
||||
state->now.gift->backdrop.patternColor,
|
||||
state->next.gift->backdrop.patternColor,
|
||||
progress);
|
||||
};
|
||||
std::move(
|
||||
data
|
||||
@@ -2974,10 +3025,24 @@ void AddUniqueGiftCover(
|
||||
}
|
||||
const auto available = width - 2 * skip;
|
||||
title->resizeToWidth(available);
|
||||
title->moveToLeft(skip, st::uniqueGiftTitleTop);
|
||||
|
||||
subtitle->resizeToWidth(available);
|
||||
subtitle->moveToLeft(skip, st::uniqueGiftSubtitleTop);
|
||||
|
||||
auto top = st::uniqueGiftTitleTop;
|
||||
if (pretitle) {
|
||||
pretitle->move((width - pretitle->width()) / 2, top);
|
||||
top += pretitle->height()
|
||||
+ (st::uniqueGiftSubtitleTop - st::uniqueGiftTitleTop)
|
||||
- title->height();
|
||||
}
|
||||
|
||||
title->moveToLeft(skip, top);
|
||||
if (pretitle) {
|
||||
top += title->height() + st::defaultVerticalListSkip;
|
||||
} else {
|
||||
top += st::uniqueGiftSubtitleTop - st::uniqueGiftTitleTop;
|
||||
}
|
||||
|
||||
subtitle->moveToLeft(skip, top);
|
||||
|
||||
cover->resize(width, subtitle->y() + subtitle->height() + skip);
|
||||
}, cover->lifetime());
|
||||
@@ -3007,7 +3072,7 @@ void AddUniqueGiftCover(
|
||||
}
|
||||
p.drawImage(0, 0, gift.gradient);
|
||||
|
||||
if (gift.gift->backdrop.patternColor.alpha() > 0) {
|
||||
if (gift.gift->pattern.document != gift.gift->model.document) {
|
||||
Ui::PaintBgPoints(
|
||||
p,
|
||||
Ui::PatternBgPoints(),
|
||||
@@ -3803,16 +3868,16 @@ struct UpgradeArgs : StarGiftUpgradeArgs {
|
||||
void AddUpgradeGiftCover(
|
||||
not_null<VerticalLayout*> container,
|
||||
const UpgradeArgs &args) {
|
||||
AddUniqueGiftCover(
|
||||
container,
|
||||
MakeUpgradeGiftStream(args),
|
||||
(args.savedId
|
||||
? tr::lng_gift_upgrade_about()
|
||||
AddUniqueGiftCover(container, MakeUpgradeGiftStream(args), {
|
||||
.subtitle = (args.savedId
|
||||
? tr::lng_gift_upgrade_about(tr::marked)
|
||||
: (args.peer->isBroadcast()
|
||||
? tr::lng_gift_upgrade_preview_about_channel
|
||||
: tr::lng_gift_upgrade_preview_about)(
|
||||
lt_name,
|
||||
rpl::single(args.peer->shortName()))));
|
||||
rpl::single(tr::marked(args.peer->shortName())),
|
||||
tr::marked)),
|
||||
});
|
||||
}
|
||||
|
||||
class UpgradePriceValue final {
|
||||
|
||||
@@ -65,12 +65,19 @@ void ShowStarGiftBox(
|
||||
not_null<Window::SessionController*> controller,
|
||||
not_null<PeerData*> peer);
|
||||
|
||||
struct UniqueGiftCoverArgs {
|
||||
rpl::producer<QString> pretitle;
|
||||
rpl::producer<TextWithEntities> subtitle;
|
||||
Fn<void()> subtitleClick;
|
||||
bool subtitleLinkColored = false;
|
||||
rpl::producer<CreditsAmount> resalePrice;
|
||||
Fn<void()> resaleClick;
|
||||
};
|
||||
|
||||
void AddUniqueGiftCover(
|
||||
not_null<VerticalLayout*> container,
|
||||
rpl::producer<Data::UniqueGift> data,
|
||||
rpl::producer<QString> subtitleOverride = nullptr,
|
||||
rpl::producer<CreditsAmount> resalePrice = nullptr,
|
||||
Fn<void()> resaleClick = nullptr);
|
||||
UniqueGiftCoverArgs &&args);
|
||||
void AddWearGiftCover(
|
||||
not_null<VerticalLayout*> container,
|
||||
const Data::UniqueGift &data,
|
||||
|
||||
Reference in New Issue
Block a user