Nice gifts promo box.

This commit is contained in:
John Preston
2025-12-05 12:39:03 +04:00
parent f01c93ed58
commit 627152e2a9
4 changed files with 89 additions and 122 deletions
+2
View File
@@ -3908,6 +3908,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_upgrade_tradable_about" = "Sell or auction your gift on third-party NFT marketplaces.";
"lng_gift_upgrade_tradable_about_user" = "{name} will be able to sell the gift on Telegram and NFT marketplaces.";
"lng_gift_upgrade_tradable_about_channel" = "Admins of {name} will be able to sell the gift on Telegram and NFT marketplaces.";
"lng_gift_upgrade_wearable_title" = "Wearable";
"lng_gift_upgrade_wearable_about" = "Display gifts on your page and set them as profile covers or statuses.";
"lng_gift_upgrade_button" = "Upgrade for {price}";
"lng_gift_upgrade_decreases" = "Price decreases in {time}";
"lng_gift_upgrade_see_table" = "See how this price will decrease {arrow}";
@@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_streaming.h"
#include "data/data_peer_values.h"
#include "data/data_premium_limits.h"
#include "info/profile/info_profile_icon.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "main/main_domain.h" // kMaxAccounts
@@ -43,7 +44,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h"
#include "api/api_premium.h"
#include "apiwrap.h"
#include "styles/style_credits.h" // upgradeGiftSubtext
#include "styles/style_info.h" // infoStarsUnderstood
#include "styles/style_layers.h"
#include "styles/style_menu_icons.h"
#include "styles/style_premium.h"
#include "styles/style_settings.h"
@@ -899,6 +903,45 @@ struct VideoPreviewDocument {
return result;
}
void AddGiftsInfoRows(not_null<Ui::VerticalLayout*> container) {
const auto infoRow = [&](
rpl::producer<QString> title,
rpl::producer<QString> text,
not_null<const style::icon*> icon) {
auto raw = container->add(
object_ptr<Ui::VerticalLayout>(container));
raw->add(
object_ptr<Ui::FlatLabel>(
raw,
std::move(title) | Ui::Text::ToBold(),
st::defaultFlatLabel),
st::settingsPremiumRowTitlePadding);
raw->add(
object_ptr<Ui::FlatLabel>(
raw,
std::move(text),
st::upgradeGiftSubtext),
st::settingsPremiumRowAboutPadding);
object_ptr<Info::Profile::FloatingIcon>(
raw,
*icon,
st::starrefInfoIconPosition);
};
infoRow(
tr::lng_gift_upgrade_unique_title(),
tr::lng_gift_upgrade_unique_about(),
&st::menuIconUnique);
infoRow(
tr::lng_gift_upgrade_tradable_title(),
tr::lng_gift_upgrade_tradable_about(),
&st::menuIconTradable);
infoRow(
tr::lng_gift_upgrade_wearable_title(),
tr::lng_gift_upgrade_wearable_about(),
&st::menuIconNftWear);
}
void PreviewBox(
not_null<Ui::GenericBox*> box,
std::shared_ptr<ChatHelpers::Show> show,
@@ -1104,16 +1147,31 @@ void PreviewBox(
st::premiumPreviewAboutPadding,
style::al_top
)->setTryMakeSimilarLines(true);
box->addRow(
CreateSwitch(box->verticalLayout(), &state->selected, state->order),
st::premiumDotsMargin);
const auto gifts = (state->selected.current() == PremiumFeature::Gifts);
if (gifts) {
box->setStyle(st::giftBox);
AddGiftsInfoRows(box->verticalLayout());
} else {
box->addRow(
CreateSwitch(box->verticalLayout(), &state->selected, state->order),
st::premiumDotsMargin);
}
const auto showFinished = [=] {
state->showFinished = true;
if (base::take(state->preloadScheduled)) {
state->preload();
}
};
if ((descriptor.fromSettings && show->session().premium())
if (gifts) {
box->setShowFinishedCallback(showFinished);
box->addButton(
rpl::single(QString()),
[=] { box->closeBox(); }
)->setText(rpl::single(Ui::Text::IconEmoji(
&st::infoStarsUnderstood
).append(' ').append(tr::lng_auction_about_understood(tr::now))));
} else if ((descriptor.fromSettings && show->session().premium())
|| descriptor.hideSubscriptionButton) {
box->setShowFinishedCallback(showFinished);
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
@@ -1320,126 +1320,31 @@ void AuctionInfoBox(
state->minutesTillEnd = MinutesLeftTillValue(now.endDate);
state->secondsTillStart = SecondsLeftTillValue(now.startDate);
const auto started = !state->secondsTillStart.current();
const auto perRound = now.gift->auctionGiftsPerRound;
box->setStyle(st::giftBox);
box->setNoContentMargin(true);
if (!started) {
const auto container = box->verticalLayout();
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));
} else {
const auto name = now.gift->resellTitle;
const auto extend = st::defaultDropdownMenu.wrap.shadow.extend;
const auto side = st::giftBoxGiftSmall;
const auto size = QSize(side, side).grownBy(extend);
const auto preview = box->addRow(
object_ptr<FixedHeightWidget>(box, size.height()),
st::auctionInfoPreviewMargin);
const auto gift = CreateChild<GiftButton>(preview, &state->delegate);
gift->setAttribute(Qt::WA_TransparentForMouseEvents);
gift->setDescriptor(GiftTypeStars{
.info = *now.gift,
}, GiftButtonMode::Minimal);
const auto container = box->verticalLayout();
auto gift = MakePreviewAuctionStream(
*now.gift,
state->attributes.value());
AddUniqueGiftCover(container, std::move(gift), {
.pretitle = started ? nullptr : 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::Gifts);
},
.subtitleLinkColored = true,
});
AddSkip(container, st::defaultVerticalListSkip * 2);
preview->widthValue() | rpl::start_with_next([=](int width) {
const auto left = (width - size.width()) / 2;
gift->setGeometry(
QRect(QPoint(left, 0), size).marginsRemoved(extend),
extend);
}, gift->lifetime());
const auto rounds = state->value.current().totalRounds;
auto aboutText = state->value.value(
) | rpl::map([=](const Data::GiftAuctionState &state) {
if (state.finished()) {
return tr::lng_auction_text_ended(tr::now, tr::marked);
}
return tr::lng_auction_text(
tr::now,
lt_count,
perRound,
lt_name,
tr::bold(name),
lt_link,
tr::lng_auction_text_link(
tr::now,
lt_arrow,
Text::IconEmoji(&st::textMoreIconEmoji),
tr::link),
tr::rich);
});
box->addRow(
object_ptr<FlatLabel>(
box,
name,
st::uniqueGiftTitle),
style::al_top);
const auto about = box->addRow(
object_ptr<FlatLabel>(
box,
std::move(aboutText),
st::uniqueGiftSubtitle),
(st::boxRowPadding
+ QMargins(0, st::auctionInfoSubtitleSkip, 0, 0)),
style::al_top);
about->setTryMakeSimilarLines(true);
about->setClickHandlerFilter([=](const auto &...) {
show->show(Box(AuctionAboutBox, rounds, perRound, nullptr));
return false;
});
const auto close = CreateChild<IconButton>(
box->verticalLayout(),
st::boxTitleClose);
close->setClickedCallback([=] { box->closeBox(); });
const auto menu = CreateChild<IconButton>(
box->verticalLayout(),
st::boxTitleMenu);
menu->setClickedCallback(MakeAuctionMenuCallback(menu, show, now));
const auto weakMenu = base::make_weak(menu);
box->verticalLayout()->widthValue() | rpl::start_with_next([=](int) {
close->moveToRight(0, 0);
if (const auto strong = weakMenu.get()) {
strong->moveToRight(close->width(), 0);
}
}, close->lifetime());
rpl::combine(
state->value.value(),
state->minutesTillEnd.value()
) | rpl::start_with_next([=](
const Data::GiftAuctionState &state,
int minutes) {
const auto finished = state.finished() || (minutes <= 0);
about->setTextColorOverride(finished
? st::attentionButtonFg->c
: std::optional<QColor>());
if (const auto strong = finished ? weakMenu.get() : nullptr) {
delete strong;
}
}, box->lifetime());
}
AddUniqueCloseButton(
box,
{},
now.finished() ? nullptr : MakeAuctionFillMenuCallback(show, now));
box->addRow(
AuctionInfoTable(box, box->verticalLayout(), state->value.value()),
@@ -1736,10 +1641,10 @@ 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_button(tr::marked)
: preview
? tr::lng_auction_join_early_bid(tr::marked)
: (type != AuctionButtonCountdownType::Place)
? tr::lng_auction_join_button(tr::marked)
: tr::lng_auction_join_bid(tr::marked);
}) | rpl::flatten_latest();
+3 -1
View File
@@ -3166,7 +3166,7 @@ void AddUniqueGiftCover(
}
subtitle->moveToLeft(skip, top);
top += subtitle->height() + skip;
top += subtitle->height() + (skip / 2);
if (attrs) {
attrs->resizeToWidth(width
@@ -3174,6 +3174,8 @@ void AddUniqueGiftCover(
- st::giftBoxPadding.right());
attrs->moveToLeft(st::giftBoxPadding.left(), top);
top += attrs->height() + (skip / 2);
} else {
top += (skip / 2);
}
cover->resize(width, top);