2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-22 10:17:10 +00:00

Allow switch resale display to TON.

This commit is contained in:
John Preston 2025-07-30 12:21:25 +04:00
parent 9bc26b0068
commit 170544f68d
11 changed files with 94 additions and 33 deletions

View File

@ -3759,6 +3759,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_resale_symbol" = "Symbol"; "lng_gift_resale_symbol" = "Symbol";
"lng_gift_resale_symbols#one" = "{count} Symbol"; "lng_gift_resale_symbols#one" = "{count} Symbol";
"lng_gift_resale_symbols#other" = "{count} Symbols"; "lng_gift_resale_symbols#other" = "{count} Symbols";
"lng_gift_resale_switch_to" = "Switch to {currency}";
"lng_gift_resale_early" = "You will be able to resell this gift in {duration}."; "lng_gift_resale_early" = "You will be able to resell this gift in {duration}.";
"lng_gift_transfer_early" = "You will be able to transfer this gift in {duration}."; "lng_gift_transfer_early" = "You will be able to transfer this gift in {duration}.";
"lng_gift_resale_transfer_early_title" = "Try Later"; "lng_gift_resale_transfer_early_title" = "Try Later";

View File

@ -2842,7 +2842,10 @@ void SendGiftBox(
Settings::GlobalStarGiftBox, Settings::GlobalStarGiftBox,
window->uiShow(), window->uiShow(),
star->info, star->info,
peer->id, Settings::StarGiftResaleInfo{
.recipientId = peer->id,
.forceTon = star->forceTon,
},
Settings::CreditsEntryBoxStyleOverrides())); Settings::CreditsEntryBoxStyleOverrides()));
} else if (star && star->resale) { } else if (star && star->resale) {
const auto id = star->info.id; const auto id = star->info.id;
@ -3232,7 +3235,6 @@ void GiftResaleBox(
not_null<PeerData*> peer, not_null<PeerData*> peer,
ResaleGiftsDescriptor descriptor) { ResaleGiftsDescriptor descriptor) {
box->setWidth(st::boxWideWidth); box->setWidth(st::boxWideWidth);
box->addButton(tr::lng_create_group_back(), [=] { box->closeBox(); });
// Create a proper vertical layout for the title // Create a proper vertical layout for the title
const auto titleWrap = box->setPinnedToTopContent( const auto titleWrap = box->setPinnedToTopContent(
@ -3273,12 +3275,29 @@ void GiftResaleBox(
rpl::event_stream<> updated; rpl::event_stream<> updated;
ResaleGiftsDescriptor data; ResaleGiftsDescriptor data;
rpl::variable<ResaleFilter> filter; rpl::variable<ResaleFilter> filter;
rpl::variable<bool> ton;
rpl::lifetime loading; rpl::lifetime loading;
int lastMinHeight = 0; int lastMinHeight = 0;
}; };
const auto state = content->lifetime().make_state<State>(); const auto state = content->lifetime().make_state<State>();
state->data = std::move(descriptor); state->data = std::move(descriptor);
box->addButton(tr::lng_create_group_back(), [=] { box->closeBox(); });
#ifndef OS_MAC_STORE
const auto currency = box->addLeftButton(rpl::single(QString()), [=] {
state->ton = !state->ton.current();
state->updated.fire({});
});
currency->setText(tr::lng_gift_resale_switch_to(
lt_currency,
rpl::conditional(
state->ton.value(),
rpl::single(Ui::Text::IconEmoji(&st::starIconEmoji)),
rpl::single(Ui::Text::IconEmoji(&st::tonIconEmoji))),
Ui::Text::WithEntities));
#endif
box->heightValue() | rpl::start_with_next([=](int height) { box->heightValue() | rpl::start_with_next([=](int height) {
if (height > state->lastMinHeight) { if (height > state->lastMinHeight) {
state->lastMinHeight = height; state->lastMinHeight = height;
@ -3340,9 +3359,11 @@ void GiftResaleBox(
) | rpl::map([=] { ) | rpl::map([=] {
auto result = GiftsDescriptor(); auto result = GiftsDescriptor();
const auto selfId = window->session().userPeerId(); const auto selfId = window->session().userPeerId();
const auto forceTon = state->ton.current();
for (const auto &gift : state->data.list) { for (const auto &gift : state->data.list) {
result.list.push_back(GiftTypeStars{ result.list.push_back(GiftTypeStars{
.info = gift, .info = gift,
.forceTon = forceTon,
.resale = true, .resale = true,
.mine = (gift.unique->ownerId == selfId), .mine = (gift.unique->ownerId == selfId),
}); });

View File

@ -676,6 +676,7 @@ void ShowTransferGiftBox(
void ShowBuyResaleGiftBox( void ShowBuyResaleGiftBox(
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,
std::shared_ptr<Data::UniqueGift> gift, std::shared_ptr<Data::UniqueGift> gift,
bool forceTon,
not_null<PeerData*> to, not_null<PeerData*> to,
Fn<void()> closeParentBox) { Fn<void()> closeParentBox) {
show->show(Box([=](not_null<Ui::GenericBox*> box) { show->show(Box([=](not_null<Ui::GenericBox*> box) {
@ -684,7 +685,7 @@ void ShowBuyResaleGiftBox(
bool sent = false; bool sent = false;
}; };
const auto state = std::make_shared<State>(); const auto state = std::make_shared<State>();
state->ton = gift->onlyAcceptTon; state->ton = gift->onlyAcceptTon || forceTon;
if (gift->onlyAcceptTon) { if (gift->onlyAcceptTon) {
box->addRow( box->addRow(
@ -699,7 +700,9 @@ void ShowBuyResaleGiftBox(
object_ptr<Ui::SubTabs>( object_ptr<Ui::SubTabs>(
box, box,
Ui::SubTabsOptions{ Ui::SubTabsOptions{
.selected = u"stars"_q, .selected = (state->ton.current()
? u"ton"_q
: u"stars"_q),
.centered = true, .centered = true,
}, },
std::vector<Ui::SubTabsTab>{ std::vector<Ui::SubTabsTab>{

View File

@ -35,6 +35,7 @@ void ShowTransferGiftBox(
void ShowBuyResaleGiftBox( void ShowBuyResaleGiftBox(
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,
std::shared_ptr<Data::UniqueGift> gift, std::shared_ptr<Data::UniqueGift> gift,
bool forceTon,
not_null<PeerData*> to, not_null<PeerData*> to,
Fn<void()> closeParentBox); Fn<void()> closeParentBox);

View File

@ -1945,7 +1945,12 @@ void ResolveAndShowUniqueGift(
session->data().processUsers(data.vusers()); session->data().processUsers(data.vusers());
if (const auto gift = Api::FromTL(session, data.vgift())) { if (const auto gift = Api::FromTL(session, data.vgift())) {
using namespace ::Settings; using namespace ::Settings;
show->show(Box(GlobalStarGiftBox, show, *gift, PeerId(), st)); show->show(Box(
GlobalStarGiftBox,
show,
*gift,
StarGiftResaleInfo(),
st));
} }
}).fail([=](const MTP::Error &error) { }).fail([=](const MTP::Error &error) {
clear(); clear();

View File

@ -102,6 +102,7 @@ struct CreditsHistoryEntry final {
bool giftRefunded : 1 = false; bool giftRefunded : 1 = false;
bool giftUpgraded : 1 = false; bool giftUpgraded : 1 = false;
bool giftResale : 1 = false; bool giftResale : 1 = false;
bool giftResaleForceTon : 1 = false;
bool giftPinned : 1 = false; bool giftPinned : 1 = false;
bool savedToProfile : 1 = false; bool savedToProfile : 1 = false;
bool fromGiftsList : 1 = false; bool fromGiftsList : 1 = false;

View File

@ -92,10 +92,9 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
if (_descriptor == descriptor && _resalePrice == resalePrice) { if (_descriptor == descriptor && _resalePrice == resalePrice) {
return; return;
} }
auto player = base::take(_player);
const auto starsType = Ui::Premium::MiniStarsType::SlowStars; const auto starsType = Ui::Premium::MiniStarsType::SlowStars;
_mediaLifetime.destroy();
unsubscribe(); unsubscribe();
update();
const auto format = [=](int64 number) { const auto format = [=](int64 number) {
const auto onlyK = (number < 100'000'000); const auto onlyK = (number < 100'000'000);
@ -161,13 +160,15 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
_price.setMarkedText( _price.setMarkedText(
st::semiboldTextStyle, st::semiboldTextStyle,
(data.resale (data.resale
? (unique ? ((unique && data.forceTon)
? Data::FormatGiftResaleTon(*unique)
: (unique
? _delegate->monostar() ? _delegate->monostar()
: _delegate->star()).append(' ').append( : _delegate->star()).append(' ').append(
format(unique format(unique
? unique->starsForResale ? unique->starsForResale
: data.info.starsResellMin) : data.info.starsResellMin)
).append(data.info.resellCount > 1 ? "+" : "") ).append(data.info.resellCount > 1 ? "+" : ""))
: (_small && unique && unique->starsForResale) : (_small && unique && unique->starsForResale)
? Data::FormatGiftResaleAsked(*unique) ? Data::FormatGiftResaleAsked(*unique)
: unique : unique
@ -196,11 +197,18 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
Ui::Premium::CreditsIconGradientStops()); Ui::Premium::CreditsIconGradientStops());
} }
}); });
_delegate->sticker(
_resolvedDocument = nullptr;
_documentLifetime = _delegate->sticker(
descriptor descriptor
) | rpl::start_with_next([=](not_null<DocumentData*> document) { ) | rpl::start_with_next([=](not_null<DocumentData*> document) {
_documentLifetime.destroy();
setDocument(document); setDocument(document);
}, lifetime()); });
if (_resolvedDocument) {
_documentLifetime.destroy();
}
_patterned = false; _patterned = false;
_uniqueBackgroundCache = QImage(); _uniqueBackgroundCache = QImage();
_uniquePatternEmoji = nullptr; _uniquePatternEmoji = nullptr;
@ -232,16 +240,19 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor, Mode mode) {
} }
} }
bool GiftButton::documentResolved() const {
return _player || _mediaLifetime;
}
void GiftButton::setDocument(not_null<DocumentData*> document) { void GiftButton::setDocument(not_null<DocumentData*> document) {
_resolvedDocument = document;
if (_playerDocument == document) {
return;
}
const auto media = document->createMediaView(); const auto media = document->createMediaView();
media->checkStickerLarge(); media->checkStickerLarge();
media->goodThumbnailWanted(); media->goodThumbnailWanted();
rpl::single() | rpl::then( const auto destroyed = base::take(_player);
_playerDocument = nullptr;
_mediaLifetime = rpl::single() | rpl::then(
document->owner().session().downloaderTaskFinished() document->owner().session().downloaderTaskFinished()
) | rpl::filter([=] { ) | rpl::filter([=] {
return media->loaded(); return media->loaded();
@ -269,9 +280,13 @@ void GiftButton::setDocument(not_null<DocumentData*> document) {
st::giftBoxStickerSize); st::giftBoxStickerSize);
} }
result->setRepaintCallback([=] { update(); }); result->setRepaintCallback([=] { update(); });
_playerDocument = media->owner();
_player = std::move(result); _player = std::move(result);
update(); update();
}, _mediaLifetime); });
if (_playerDocument) {
_mediaLifetime.destroy();
}
} }
void GiftButton::setGeometry(QRect inner, QMargins extend) { void GiftButton::setGeometry(QRect inner, QMargins extend) {
@ -627,10 +642,11 @@ void GiftButton::paintEvent(QPaintEvent *e) {
QSize(icon.width() + 2 * add, icon.height() + 2 * add)); QSize(icon.width() + 2 * add, icon.height() + 2 * add));
p.drawEllipse(rect); p.drawEllipse(rect);
icon.paintInCenter(p, rect); icon.paintInCenter(p, rect);
} else if (unique->nanoTonForResale && unique->onlyAcceptTon) { } else if (!data.forceTon
&& unique->nanoTonForResale
&& unique->onlyAcceptTon) {
if (_tonIcon.isNull()) { if (_tonIcon.isNull()) {
_tonIcon = Ui::Earn::IconCurrencyColored( _tonIcon = st::tonIconEmoji.icon.instance(
st::tonIconEmojiSize,
QColor(255, 255, 255)); QColor(255, 255, 255));
} }
const auto size = _tonIcon.size() / _tonIcon.devicePixelRatio(); const auto size = _tonIcon.size() / _tonIcon.devicePixelRatio();

View File

@ -65,6 +65,7 @@ struct GiftTypeStars {
PeerData *from = nullptr; PeerData *from = nullptr;
TimeId date = 0; TimeId date = 0;
bool pinnedSelection : 1 = false; bool pinnedSelection : 1 = false;
bool forceTon : 1 = false;
bool userpic : 1 = false; bool userpic : 1 = false;
bool pinned : 1 = false; bool pinned : 1 = false;
bool hidden : 1 = false; bool hidden : 1 = false;
@ -160,7 +161,6 @@ private:
int height); int height);
void setDocument(not_null<DocumentData*> document); void setDocument(not_null<DocumentData*> document);
[[nodiscard]] bool documentResolved() const;
[[nodiscard]] QMargins currentExtend() const; [[nodiscard]] QMargins currentExtend() const;
void unsubscribe(); void unsubscribe();
@ -188,8 +188,12 @@ private:
QRect _button; QRect _button;
QMargins _extend; QMargins _extend;
DocumentData *_resolvedDocument = nullptr;
std::unique_ptr<HistoryView::StickerPlayer> _player; std::unique_ptr<HistoryView::StickerPlayer> _player;
DocumentData *_playerDocument = nullptr;
rpl::lifetime _mediaLifetime; rpl::lifetime _mediaLifetime;
rpl::lifetime _documentLifetime;
}; };

View File

@ -1235,14 +1235,17 @@ void GenericCreditsEntryBox(
box->setNoContentMargin(true); box->setNoContentMargin(true);
const auto slug = uniqueGift->slug; const auto slug = uniqueGift->slug;
const auto forceTon = e.giftResaleForceTon;
auto price = rpl::single( auto price = rpl::single(
rpl::empty rpl::empty
) | rpl::then(session->data().giftUpdates( ) | rpl::then(session->data().giftUpdates(
) | rpl::filter([=](const Data::GiftUpdate &update) { ) | rpl::filter([=](const Data::GiftUpdate &update) {
return (update.action == Data::GiftUpdate::Action::ResaleChange) return (update.action == Data::GiftUpdate::Action::ResaleChange)
&& (update.slug == slug); && (update.slug == slug);
}) | rpl::to_empty) | rpl::map([unique = e.uniqueGift] { }) | rpl::to_empty) | rpl::map([forceTon, unique = e.uniqueGift] {
return Data::UniqueGiftResaleAsked(*unique); return forceTon
? Data::UniqueGiftResaleTon(*unique)
: Data::UniqueGiftResaleAsked(*unique);
}); });
auto change = [=] { auto change = [=] {
const auto style = st.giftWearBox const auto style = st.giftWearBox
@ -2091,6 +2094,7 @@ void GenericCreditsEntryBox(
ShowBuyResaleGiftBox( ShowBuyResaleGiftBox(
show, show,
e.uniqueGift, e.uniqueGift,
e.giftResaleForceTon,
to, to,
crl::guard(box, [=] { box->closeBox(); })); crl::guard(box, [=] { box->closeBox(); }));
} else if (canUpgradeFree) { } else if (canUpgradeFree) {
@ -2102,7 +2106,7 @@ void GenericCreditsEntryBox(
} }
}); });
if (canBuyResold) { if (canBuyResold) {
if (uniqueGift->onlyAcceptTon) { if (uniqueGift->onlyAcceptTon || e.giftResaleForceTon) {
button->setText(rpl::single(QString())); button->setText(rpl::single(QString()));
Ui::SetButtonTwoLabels( Ui::SetButtonTwoLabels(
button, button,
@ -2205,7 +2209,7 @@ void GlobalStarGiftBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,
const Data::StarGift &data, const Data::StarGift &data,
PeerId resaleRecipientId, StarGiftResaleInfo resale,
CreditsEntryBoxStyleOverrides st) { CreditsEntryBoxStyleOverrides st) {
const auto selfId = show->session().userPeerId(); const auto selfId = show->session().userPeerId();
const auto ownerId = data.unique ? data.unique->ownerId.value : 0; const auto ownerId = data.unique ? data.unique->ownerId.value : 0;
@ -2216,8 +2220,8 @@ void GlobalStarGiftBox(
.credits = CreditsAmount(data.stars), .credits = CreditsAmount(data.stars),
.bareGiftStickerId = data.document->id, .bareGiftStickerId = data.document->id,
.bareGiftOwnerId = ownerId, .bareGiftOwnerId = ownerId,
.bareGiftResaleRecipientId = ((resaleRecipientId != selfId) .bareGiftResaleRecipientId = ((resale.recipientId != selfId)
? resaleRecipientId.value ? resale.recipientId.value
: 0), : 0),
.stargiftId = data.id, .stargiftId = data.id,
.uniqueGift = data.unique, .uniqueGift = data.unique,
@ -2225,6 +2229,7 @@ void GlobalStarGiftBox(
.limitedCount = data.limitedCount, .limitedCount = data.limitedCount,
.limitedLeft = data.limitedLeft, .limitedLeft = data.limitedLeft,
.stargift = true, .stargift = true,
.giftResaleForceTon = resale.forceTon,
.fromGiftSlug = true, .fromGiftSlug = true,
.in = (ownerId == show->session().userPeerId().value), .in = (ownerId == show->session().userPeerId().value),
.gift = true, .gift = true,

View File

@ -155,11 +155,16 @@ void CreditsPrizeBox(
not_null<Window::SessionController*> controller, not_null<Window::SessionController*> controller,
const Data::GiftCode &data, const Data::GiftCode &data,
TimeId date); TimeId date);
struct StarGiftResaleInfo {
PeerId recipientId;
bool forceTon = false;
};
void GlobalStarGiftBox( void GlobalStarGiftBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
std::shared_ptr<ChatHelpers::Show> show, std::shared_ptr<ChatHelpers::Show> show,
const Data::StarGift &data, const Data::StarGift &data,
PeerId resaleRecipientId, StarGiftResaleInfo resale,
CreditsEntryBoxStyleOverrides st = {}); CreditsEntryBoxStyleOverrides st = {});
[[nodiscard]] Data::CreditsHistoryEntry SavedStarGiftEntry( [[nodiscard]] Data::CreditsHistoryEntry SavedStarGiftEntry(

View File

@ -85,7 +85,6 @@ tonIconEmoji: IconEmoji {
icon: icon{{ "payments/ton_emoji-18x18", currencyFg }}; icon: icon{{ "payments/ton_emoji-18x18", currencyFg }};
padding: margins(0px, 1px, 0px, 0px); padding: margins(0px, 1px, 0px, 0px);
} }
tonIconEmojiSize: 18px;
creditsHistoryEntryTypeAds: icon {{ "folders/folders_channels", premiumButtonFg }}; creditsHistoryEntryTypeAds: icon {{ "folders/folders_channels", premiumButtonFg }};