Improved received star gift box.

This commit is contained in:
John Preston 2024-10-11 15:05:41 +04:00
parent 21f909dd4b
commit 36de2b6ca6
5 changed files with 187 additions and 110 deletions

View file

@ -3061,6 +3061,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_sold_out_title" = "Sold Out!";
"lng_gift_sold_out_text#one" = "All {count} gift was already sold.";
"lng_gift_sold_out_text#other" = "All {count} gifts were already sold.";
"lng_gift_send_small" = "send a gift";
"lng_gift_sell_small#one" = "sell for {count} Star";
"lng_gift_sell_small#other" = "sell for {count} Stars";
"lng_accounts_limit_title" = "Limit Reached";
"lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected account.";

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/prepare_short_info_box.h"
#include "boxes/peers/replace_boost_box.h" // BoostsForGift.
#include "boxes/premium_preview_box.h" // ShowPremiumPreviewBox.
#include "boxes/star_gift_box.h" // ShowStarGiftBox.
#include "data/data_boosts.h"
#include "data/data_changes.h"
#include "data/data_channel.h"
@ -123,7 +124,8 @@ namespace {
[[nodiscard]] object_ptr<Ui::RpWidget> MakePeerTableValue(
not_null<QWidget*> parent,
not_null<Window::SessionNavigation*> controller,
PeerId id) {
PeerId id,
bool withSendGiftButton = false) {
auto result = object_ptr<Ui::AbstractButton>(parent);
const auto raw = result.data();
@ -134,15 +136,40 @@ namespace {
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(raw, peer, st);
const auto label = Ui::CreateChild<Ui::FlatLabel>(
raw,
peer->name(),
withSendGiftButton ? peer->shortName() : peer->name(),
st::giveawayGiftCodeValue);
raw->widthValue(
) | rpl::start_with_next([=](int width) {
const auto send = withSendGiftButton
? Ui::CreateChild<Ui::RoundButton>(
raw,
tr::lng_gift_send_small(),
st::starGiftSmallButton)
: nullptr;
if (send) {
send->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
send->setClickedCallback([=] {
Ui::ShowStarGiftBox(controller->parentController(), peer);
});
}
rpl::combine(
raw->widthValue(),
send ? send->widthValue() : rpl::single(0)
) | rpl::start_with_next([=](int width, int sendWidth) {
const auto position = st::giveawayGiftCodeNamePosition;
label->resizeToNaturalWidth(width - position.x());
const auto sendSkip = sendWidth
? (st::normalFont->spacew + sendWidth)
: 0;
label->resizeToNaturalWidth(width - position.x() - sendSkip);
label->moveToLeft(position.x(), position.y(), width);
const auto top = (raw->height() - userpic->height()) / 2;
userpic->moveToLeft(0, top, width);
if (send) {
send->moveToLeft(
position.x() + label->width() + st::normalFont->spacew,
(position.y()
+ st::giveawayGiftCodeValue.style.font->ascent
- st::starGiftSmallButton.style.font->ascent),
width);
}
}, label->lifetime());
userpic->setAttribute(Qt::WA_TransparentForMouseEvents);
@ -210,6 +237,71 @@ void AddTableRow(
valueMargins);
}
object_ptr<Ui::RpWidget> MakeStarGiftStarsValue(
not_null<QWidget*> parent,
not_null<Window::SessionNavigation*> controller,
const Data::CreditsHistoryEntry &entry,
Fn<void()> convertToStars) {
auto result = object_ptr<Ui::RpWidget>(parent);
const auto raw = result.data();
const auto session = &controller->session();
const auto makeContext = [session](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(update),
};
};
auto star = session->data().customEmojiManager().creditsEmoji();
const auto label = Ui::CreateChild<Ui::FlatLabel>(
raw,
rpl::single(
star.append(' ' + Lang::FormatCountDecimal(entry.credits))),
st::giveawayGiftCodeValue,
st::defaultPopupMenu,
std::move(makeContext));
const auto convert = convertToStars
? Ui::CreateChild<Ui::RoundButton>(
raw,
tr::lng_gift_sell_small(
lt_count_decimal,
rpl::single(entry.convertStars * 1.)),
st::starGiftSmallButton)
: nullptr;
if (convert) {
convert->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
convert->setClickedCallback(std::move(convertToStars));
}
rpl::combine(
raw->widthValue(),
convert ? convert->widthValue() : rpl::single(0)
) | rpl::start_with_next([=](int width, int convertWidth) {
const auto convertSkip = convertWidth
? (st::normalFont->spacew + convertWidth)
: 0;
label->resizeToNaturalWidth(width - convertSkip);
label->moveToLeft(0, 0, width);
if (convert) {
convert->moveToLeft(
label->width() + st::normalFont->spacew,
(st::giveawayGiftCodeValue.style.font->ascent
- st::starGiftSmallButton.style.font->ascent),
width);
}
}, label->lifetime());
label->heightValue() | rpl::start_with_next([=](int height) {
raw->resize(
raw->width(),
height + st::giveawayGiftCodeValueMargin.bottom());
}, raw->lifetime());
label->setAttribute(Qt::WA_TransparentForMouseEvents);
return result;
}
not_null<Ui::FlatLabel*> AddTableRow(
not_null<Ui::TableLayout*> table,
rpl::producer<QString> label,
@ -942,7 +1034,8 @@ void ResolveGiveawayInfo(
void AddStarGiftTable(
not_null<Window::SessionNavigation*> controller,
not_null<Ui::VerticalLayout*> container,
const Data::CreditsHistoryEntry &entry) {
const Data::CreditsHistoryEntry &entry,
Fn<void()> convertToStars) {
auto table = container->add(
object_ptr<Ui::TableLayout>(
container,
@ -950,18 +1043,13 @@ void AddStarGiftTable(
st::giveawayGiftCodeTableMargin);
const auto peerId = PeerId(entry.barePeerId);
const auto session = &controller->session();
const auto makeContext = [session](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(update),
};
};
if (peerId) {
const auto withSendButton = entry.in;
AddTableRow(
table,
tr::lng_credits_box_history_entry_peer_in(),
controller,
peerId);
MakePeerTableValue(table, controller, peerId, withSendButton),
st::giveawayGiftCodePeerMargin);
} else if (!entry.soldOutInfo) {
AddTableRow(
table,
@ -984,13 +1072,17 @@ void AddStarGiftTable(
langDateTime(entry.lastSaleDate))));
}
{
auto star = session->data().customEmojiManager().creditsEmoji();
const auto margin = st::giveawayGiftCodeValueMargin
- QMargins(0, 0, 0, st::giveawayGiftCodeValueMargin.bottom());
AddTableRow(
table,
tr::lng_gift_link_label_value(),
rpl::single(
star.append(' ' + Lang::FormatCountDecimal(entry.credits))),
makeContext);
MakeStarGiftStarsValue(
table,
controller,
entry,
std::move(convertToStars)),
margin);
}
if (!entry.date.isNull()) {
AddTableRow(
@ -1018,7 +1110,6 @@ void AddStarGiftTable(
Ui::Text::WithEntities)));
}
if (!entry.description.empty()) {
const auto session = &controller->session();
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,

View file

@ -57,7 +57,8 @@ void ResolveGiveawayInfo(
void AddStarGiftTable(
not_null<Window::SessionNavigation*> controller,
not_null<Ui::VerticalLayout*> container,
const Data::CreditsHistoryEntry &entry);
const Data::CreditsHistoryEntry &entry,
Fn<void()> convertToStars);
void AddCreditsHistoryEntryTable(
not_null<Window::SessionNavigation*> controller,
not_null<Ui::VerticalLayout*> container,

View file

@ -208,10 +208,24 @@ startGiveawayButtonLoading: InfiniteRadialAnimation(defaultInfiniteRadialAnimati
thickness: 2px;
}
starGiftBox: Box(giveawayGiftCodeBox) {
buttonPadding: margins(22px, 11px, 22px, 52px);
}
starConvertButtonLoading: InfiniteRadialAnimation(startGiveawayButtonLoading) {
color: windowActiveTextFg;
thickness: 2px;
}
starGiftSmallButton: RoundButton(defaultActiveButton) {
textFg: windowActiveTextFg;
textFgOver: windowActiveTextFg;
textBg: lightButtonBgOver;
textBgOver: lightButtonBgOver;
width: -12px;
height: 18px;
radius: 9px;
textTop: 0px;
style: TextStyle(defaultTextStyle) {
font: font(12px);
}
ripple: RippleAnimation(defaultRippleAnimation) {
color: lightButtonBgRipple;
}
}

View file

@ -743,7 +743,7 @@ void ReceiptCreditsBox(
: nullptr;
const auto canConvert = gotStarGift && !e.converted && starGiftSender;
box->setStyle(canConvert ? st::starGiftBox : st::giveawayGiftCodeBox);
box->setStyle(st::giveawayGiftCodeBox);
box->setNoContentMargin(true);
const auto content = box->verticalLayout();
@ -1091,8 +1091,61 @@ void ReceiptCreditsBox(
Ui::AddSkip(content);
Ui::AddSkip(content);
struct State final {
rpl::variable<bool> confirmButtonBusy;
rpl::variable<bool> convertButtonBusy;
};
const auto state = box->lifetime().make_state<State>();
const auto weakWindow = base::make_weak(controller);
if (isStarGift && e.id.isEmpty()) {
AddStarGiftTable(controller, content, e);
const auto convert = [=, weak = Ui::MakeWeak(box)] {
const auto stars = e.convertStars;
const auto name = starGiftSender->shortName();
ConfirmConvertStarGift(box->uiShow(), name, stars, [=] {
if (state->convertButtonBusy.current()
|| state->confirmButtonBusy.current()) {
return;
}
state->convertButtonBusy = true;
const auto window = weakWindow.get();
const auto itemId = MsgId(e.bareMsgId);
if (window && stars) {
const auto done = [=](bool ok) {
if (const auto window = weakWindow.get()) {
if (ok) {
using GiftAction = Data::GiftUpdate::Action;
window->session().data().notifyGiftUpdate({
.itemId = FullMsgId(
starGiftSender->id,
itemId),
.action = GiftAction::Convert,
});
}
}
if (const auto strong = weak.data()) {
if (ok) {
strong->closeBox();
} else {
state->convertButtonBusy = false;
}
}
};
ConvertStarGift(
window,
starGiftSender,
itemId,
stars,
done);
}
});
};
AddStarGiftTable(
controller,
content,
e,
canConvert ? convert : Fn<void()>());
} else {
AddCreditsHistoryEntryTable(controller, content, e);
AddSubscriptionEntryTable(controller, content, s);
@ -1175,11 +1228,6 @@ void ReceiptCreditsBox(
const auto toRenew = (s.cancelled || s.expired)
&& !s.inviteHash.isEmpty();
const auto toCancel = !toRenew && s;
struct State final {
rpl::variable<bool> confirmButtonBusy;
rpl::variable<bool> convertButtonBusy;
};
const auto state = box->lifetime().make_state<State>();
auto confirmText = rpl::conditional(
state->confirmButtonBusy.value(),
rpl::single(QString()),
@ -1192,7 +1240,6 @@ void ReceiptCreditsBox(
? tr::lng_gift_display_on_page_hide()
: tr::lng_gift_display_on_page())
: tr::lng_box_ok()));
const auto weakWindow = base::make_weak(controller);
const auto send = [=, weak = Ui::MakeWeak(box)] {
if (canConvert) {
const auto save = !e.savedToProfile;
@ -1290,85 +1337,6 @@ void ReceiptCreditsBox(
}) | rpl::start_with_next([=] {
button->resizeToWidth(buttonWidth);
}, button->lifetime());
if (canConvert) {
using namespace Ui;
auto convertText = rpl::conditional(
state->convertButtonBusy.value(),
rpl::single(QString()),
tr::lng_gift_convert_to_stars(
lt_count,
rpl::single(e.convertStars * 1.)));
const auto convert = CreateChild<RoundButton>(
button->parentWidget(),
std::move(convertText),
st::defaultLightButton);
convert->setTextTransform(RoundButton::TextTransform::NoTransform);
convert->widthValue() | rpl::filter([=] {
return convert->widthNoMargins() != buttonWidth;
}) | rpl::start_with_next([=] {
convert->resizeToWidth(buttonWidth);
}, convert->lifetime());
button->positionValue(
) | rpl::start_with_next([=](QPoint position) {
convert->move(
position.x(),
(position.y()
+ st::starGiftBox.buttonHeight
+ st::starGiftBox.buttonPadding.bottom()
- st::starGiftBox.buttonPadding.top()
- convert->height()));
}, convert->lifetime());
convert->setClickedCallback([=, weak = Ui::MakeWeak(box)] {
const auto stars = e.convertStars;
const auto name = starGiftSender->shortName();
ConfirmConvertStarGift(box->uiShow(), name, stars, [=] {
if (state->convertButtonBusy.current()
|| state->confirmButtonBusy.current()) {
return;
}
state->convertButtonBusy = true;
const auto window = weakWindow.get();
const auto itemId = MsgId(e.bareMsgId);
if (window && stars) {
const auto done = [=](bool ok) {
if (const auto window = weakWindow.get()) {
if (ok) {
using GiftAction = Data::GiftUpdate::Action;
window->session().data().notifyGiftUpdate({
.itemId = FullMsgId(
starGiftSender->id,
itemId),
.action = GiftAction::Convert,
});
}
}
if (const auto strong = weak.data()) {
if (ok) {
strong->closeBox();
} else {
state->convertButtonBusy = false;
}
}
};
ConvertStarGift(
window,
starGiftSender,
itemId,
stars,
done);
}
});
});
using namespace Info::Statistics;
const auto loadingAnimation = InfiniteRadialAnimationWidget(
convert,
convert->height() / 2,
&st::starConvertButtonLoading);
AddChildToWidgetCenter(convert, loadingAnimation);
loadingAnimation->showOn(state->convertButtonBusy.value());
}
}
void GiftedCreditsBox(