Implement upgraded unique gifts.

This commit is contained in:
John Preston 2024-12-26 10:10:44 +04:00
parent a87d19998e
commit 13d2f70c3a
22 changed files with 1077 additions and 157 deletions

View file

@ -2023,6 +2023,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_gift_unique_received" = "{user} sent you a unique collectible item";
"lng_action_gift_sent" = "You sent a gift for {cost}";
"lng_action_gift_unique_sent" = "You sent a unique collectible item";
"lng_action_gift_upgraded" = "{user} turned the gift from you to a unique collectible";
"lng_action_gift_upgraded_mine" = "You turned the gift from {user} to a unique collectible";
"lng_action_gift_received_anonymous" = "Unknown user sent you a gift for {cost}";
"lng_action_gift_for_stars#one" = "{count} Star";
"lng_action_gift_for_stars#other" = "{count} Stars";
@ -2440,6 +2442,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_premium_summary_button" = "Subscribe for {cost} per month";
"lng_premium_summary_new_badge" = "NEW";
"lng_soon_badge" = "Soon";
"lng_premium_success" = "You've successfully subscribed to Telegram Premium!";
"lng_premium_unavailable" = "This feature requires subscription to **Telegram Premium**.\n\nUnfortunately, **Telegram Premium** is not available in your region.";
@ -3279,7 +3282,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_sell_small#one" = "sell for {count} Star";
"lng_gift_sell_small#other" = "sell for {count} Stars";
"lng_gift_upgrade_title" = "Upgrade Gift";
"lng_gift_upgrade_about" = "Turn your gift into a unique collectible that you can transfer or auction.";
"lng_gift_upgrade_about" = "Turn your gift into a unique collectible\nthat you can transfer or auction.";
"lng_gift_upgrade_unique_title" = "Unique";
"lng_gift_upgrade_unique_about" = "Get a unique number, model, backdrop and symbol for your gift.";
"lng_gift_upgrade_transferable_title" = "Transferable";

View file

@ -94,7 +94,7 @@ constexpr auto kTransactionsLimit = 100;
const auto parsedGift = stargift
? FromTL(&peer->session(), *stargift)
: std::optional<Data::StarGift>();
const auto giftStickerId = parsedGift ? parsedGift->stickerId : 0;
const auto giftStickerId = parsedGift ? parsedGift->document->id : 0;
return Data::CreditsHistoryEntry{
.id = qs(tl.data().vid()),
.title = qs(tl.data().vtitle().value_or_empty()),

View file

@ -774,58 +774,58 @@ std::optional<Data::StarGift> FromTL(
.id = uint64(data.vid().v),
.stars = int64(data.vstars().v),
.starsConverted = int64(data.vconvert_stars().v),
.stickerId = document->id,
.starsUpgraded = int64(data.vupgrade_stars().value_or_empty()),
.document = document,
.limitedLeft = remaining.value_or_empty(),
.limitedCount = total.value_or_empty(),
.firstSaleDate = data.vfirst_sale_date().value_or_empty(),
.lastSaleDate = data.vlast_sale_date().value_or_empty(),
.upgradable = data.vupgrade_stars().has_value(),
.birthday = data.is_birthday(),
});
}, [&](const MTPDstarGiftUnique &data) {
const auto total = data.vavailability_total().v;
auto model = std::optional<Data::UniqueGiftModel>();
auto pattern = std::optional<Data::UniqueGiftPattern>();
for (const auto &attribute : data.vattributes().v) {
attribute.match([&](const MTPDstarGiftAttributeModel &data) {
model = FromTL(session, data);
}, [&](const MTPDstarGiftAttributePattern &data) {
pattern = FromTL(session, data);
}, [&](const MTPDstarGiftAttributeBackdrop &data) {
}, [&](const MTPDstarGiftAttributeOriginalDetails &data) {
});
}
if (!model
|| !model->document->sticker()
|| !pattern
|| !pattern->document->sticker()) {
return std::optional<Data::StarGift>();
}
auto result = Data::StarGift{
.id = uint64(data.vid().v),
.unique = std::make_shared<Data::UniqueGift>(Data::UniqueGift{
.title = qs(data.vtitle()),
.number = data.vnum().v,
.ownerId = peerFromUser(UserId(data.vowner_id().v)),
.model = *model,
.pattern = *pattern,
}),
.document = model->document,
.limitedLeft = (total - data.vavailability_issued().v),
.limitedCount = total,
};
const auto unique = result.unique.get();
for (const auto &attribute : data.vattributes().v) {
attribute.match([&](const MTPDstarGiftAttributeModel &data) {
unique->model.name = qs(data.vname());
unique->model.rarityPermille = data.vrarity_permille().v;
result.stickerId = data.vdocument_id().v;
}, [&](const MTPDstarGiftAttributePattern &data) {
unique->pattern.name = qs(data.vname());
unique->pattern.rarityPermille = data.vrarity_permille().v;
unique->pattern.documentId = data.vdocument_id().v;
}, [&](const MTPDstarGiftAttributeBackdrop &data) {
unique->backdrop.name = qs(data.vname());
unique->backdrop.rarityPermille = data.vrarity_permille().v;
unique->backdrop.centerColor = Ui::ColorFromSerialized(
data.vcenter_color());
unique->backdrop.edgeColor = Ui::ColorFromSerialized(
data.vedge_color());
unique->backdrop.patternColor = Ui::ColorFromSerialized(
data.vpattern_color());
unique->backdrop.textColor = Ui::ColorFromSerialized(
data.vtext_color());
unique->backdrop = FromTL(data);
}, [&](const MTPDstarGiftAttributeOriginalDetails &data) {
unique->originalDetails.date = data.vdate().v;
unique->originalDetails.senderId = peerFromUser(
UserId(data.vsender_id().value_or_empty()));
unique->originalDetails.recipientId = peerFromUser(
UserId(data.vrecipient_id().v));
unique->originalDetails.message = data.vmessage()
? Api::ParseTextWithEntities(session, *data.vmessage())
: TextWithEntities();
unique->originalDetails = FromTL(session, data);
});
}
return result.stickerId ? result : std::optional<Data::StarGift>();
return std::make_optional(result);
});
}
@ -849,15 +849,70 @@ std::optional<Data::UserStarGift> FromTL(
}
: TextWithEntities()),
.starsConverted = int64(data.vconvert_stars().value_or_empty()),
.starsUpgraded = int64(data.vupgrade_stars().value_or_empty()),
.fromId = (data.vfrom_id()
? peerFromUser(data.vfrom_id()->v)
: PeerId()),
.messageId = data.vmsg_id().value_or_empty(),
.date = data.vdate().v,
.upgradable = data.is_can_upgrade(),
.anonymous = data.is_name_hidden(),
.hidden = data.is_unsaved(),
.mine = to->isSelf(),
};
}
Data::UniqueGiftModel FromTL(
not_null<Main::Session*> session,
const MTPDstarGiftAttributeModel &data) {
auto result = Data::UniqueGiftModel{
.document = session->data().processDocument(data.vdocument()),
};
result.name = qs(data.vname());
result.rarityPermille = data.vrarity_permille().v;
return result;
}
Data::UniqueGiftPattern FromTL(
not_null<Main::Session*> session,
const MTPDstarGiftAttributePattern &data) {
auto result = Data::UniqueGiftPattern{
.document = session->data().processDocument(data.vdocument()),
};
result.document->overrideEmojiUsesTextColor(true);
result.name = qs(data.vname());
result.rarityPermille = data.vrarity_permille().v;
return result;
}
Data::UniqueGiftBackdrop FromTL(const MTPDstarGiftAttributeBackdrop &data) {
auto result = Data::UniqueGiftBackdrop();
result.name = qs(data.vname());
result.rarityPermille = data.vrarity_permille().v;
result.centerColor = Ui::ColorFromSerialized(
data.vcenter_color());
result.edgeColor = Ui::ColorFromSerialized(
data.vedge_color());
result.patternColor = Ui::ColorFromSerialized(
data.vpattern_color());
result.textColor = Ui::ColorFromSerialized(
data.vtext_color());
return result;
}
Data::UniqueGiftOriginalDetails FromTL(
not_null<Main::Session*> session,
const MTPDstarGiftAttributeOriginalDetails &data) {
auto result = Data::UniqueGiftOriginalDetails();
result.date = data.vdate().v;
result.senderId = peerFromUser(
UserId(data.vsender_id().value_or_empty()));
result.recipientId = peerFromUser(
UserId(data.vrecipient_id().v));
result.message = data.vmessage()
? ParseTextWithEntities(session, *data.vmessage())
: TextWithEntities();
return result;
}
} // namespace Api

View file

@ -263,4 +263,16 @@ enum class RequirePremiumState {
not_null<UserData*> to,
const MTPuserStarGift &gift);
[[nodiscard]] Data::UniqueGiftModel FromTL(
not_null<Main::Session*> session,
const MTPDstarGiftAttributeModel &data);
[[nodiscard]] Data::UniqueGiftPattern FromTL(
not_null<Main::Session*> session,
const MTPDstarGiftAttributePattern &data);
[[nodiscard]] Data::UniqueGiftBackdrop FromTL(
const MTPDstarGiftAttributeBackdrop &data);
[[nodiscard]] Data::UniqueGiftOriginalDetails FromTL(
not_null<Main::Session*> session,
const MTPDstarGiftAttributeOriginalDetails &data);
} // namespace Api

View file

@ -338,13 +338,58 @@ void AddTableRow(
: 0;
label->resizeToNaturalWidth(width - toggleSkip);
label->moveToLeft(0, 0, width);
if (toggle) {
toggle->moveToLeft(
label->width() + st::normalFont->spacew,
(st::giveawayGiftCodeValue.style.font->ascent
- st::starGiftSmallButton.style.font->ascent),
width);
}
toggle->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;
}
[[nodiscard]] object_ptr<Ui::RpWidget> MakeNonUniqueStatusTableValue(
not_null<QWidget*> parent,
not_null<Window::SessionNavigation*> controller,
Fn<void()> startUpgrade) {
auto result = object_ptr<Ui::RpWidget>(parent);
const auto raw = result.data();
const auto label = Ui::CreateChild<Ui::FlatLabel>(
raw,
tr::lng_gift_unique_status_non(),
st::giveawayGiftCodeValue,
st::defaultPopupMenu);
const auto upgrade = Ui::CreateChild<Ui::RoundButton>(
raw,
tr::lng_gift_unique_status_upgrade(),
st::starGiftSmallButton);
upgrade->setTextTransform(Ui::RoundButton::TextTransform::NoTransform);
upgrade->setClickedCallback(startUpgrade);
rpl::combine(
raw->widthValue(),
upgrade->widthValue()
) | rpl::start_with_next([=](int width, int toggleWidth) {
const auto toggleSkip = toggleWidth
? (st::normalFont->spacew + toggleWidth)
: 0;
label->resizeToNaturalWidth(width - toggleSkip);
label->moveToLeft(0, 0, width);
upgrade->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) {
@ -1092,7 +1137,8 @@ void AddStarGiftTable(
not_null<Ui::VerticalLayout*> container,
const Data::CreditsHistoryEntry &entry,
Fn<void(bool)> toggleVisibility,
Fn<void()> convertToStars) {
Fn<void()> convertToStars,
Fn<void()> startUpgrade) {
auto table = container->add(
object_ptr<Ui::TableLayout>(
container,
@ -1178,6 +1224,16 @@ void AddStarGiftTable(
std::move(amount),
Ui::Text::WithEntities)));
}
if (!entry.uniqueGift && startUpgrade) {
AddTableRow(
table,
tr::lng_gift_unique_status(),
MakeNonUniqueStatusTableValue(
table,
controller,
std::move(startUpgrade)),
marginWithButton);
}
if (!entry.description.empty()) {
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{

View file

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

View file

@ -463,7 +463,7 @@ void SendCreditsBox(
}),
session,
st::creditsBoxButtonLabel,
box->getDelegate()->style().button.textFg->c);
&box->getDelegate()->style().button.textFg);
const auto buttonWidth = st::boxWidth
- rect::m::sum::h(stBox.buttonPadding);
@ -524,7 +524,7 @@ not_null<FlatLabel*> SetButtonMarkedLabel(
rpl::producer<TextWithEntities> text,
Fn<std::any(Fn<void()> update)> context,
const style::FlatLabel &st,
std::optional<QColor> textFg) {
const style::color *textFg) {
const auto buttonLabel = Ui::CreateChild<Ui::FlatLabel>(
button,
rpl::single(QString()),
@ -539,7 +539,10 @@ not_null<FlatLabel*> SetButtonMarkedLabel(
context([=] { buttonLabel->update(); }));
}, buttonLabel->lifetime());
if (textFg) {
buttonLabel->setTextColorOverride(textFg);
buttonLabel->setTextColorOverride((*textFg)->c);
style::PaletteChanged() | rpl::start_with_next([=] {
buttonLabel->setTextColorOverride((*textFg)->c);
}, buttonLabel->lifetime());
}
button->sizeValue(
) | rpl::start_with_next([=](const QSize &size) {
@ -561,7 +564,7 @@ not_null<FlatLabel*> SetButtonMarkedLabel(
rpl::producer<TextWithEntities> text,
not_null<Main::Session*> session,
const style::FlatLabel &st,
std::optional<QColor> textFg) {
const style::color *textFg) {
return SetButtonMarkedLabel(button, text, [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,

View file

@ -43,14 +43,14 @@ not_null<FlatLabel*> SetButtonMarkedLabel(
rpl::producer<TextWithEntities> text,
Fn<std::any(Fn<void()> update)> context,
const style::FlatLabel &st,
std::optional<QColor> textFg = {});
const style::color *textFg = nullptr);
not_null<FlatLabel*> SetButtonMarkedLabel(
not_null<RpWidget*> button,
rpl::producer<TextWithEntities> text,
not_null<Main::Session*> session,
const style::FlatLabel &st,
std::optional<QColor> textFg = {});
const style::color *textFg = nullptr);
void SendStarGift(
not_null<Main::Session*> session,

File diff suppressed because it is too large Load diff

View file

@ -7,12 +7,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
namespace Data {
struct UniqueGift;
} // namespace Data
namespace Window {
class SessionController;
} // namespace Window
namespace Ui {
class VerticalLayout;
void ChooseStarGiftRecipient(
not_null<Window::SessionController*> controller);
@ -20,4 +26,17 @@ void ShowStarGiftBox(
not_null<Window::SessionController*> controller,
not_null<PeerData*> peer);
void AddUniqueGiftCover(
not_null<VerticalLayout*> container,
rpl::producer<Data::UniqueGift> data,
rpl::producer<QString> subtitleOverride = nullptr);
void ShowStarGiftUpgradeBox(
not_null<Window::SessionController*> controller,
uint64 stargiftId,
not_null<UserData*> user,
MsgId itemId,
int stars,
Fn<void(bool)> ready);
} // namespace Ui

View file

@ -65,6 +65,7 @@ struct CreditsHistoryEntry final {
uint64 bareGiveawayMsgId = 0;
uint64 bareGiftStickerId = 0;
uint64 bareActorId = 0;
uint64 stargiftId = 0;
std::shared_ptr<UniqueGift> uniqueGift;
StarsAmount starrefAmount;
int starrefCommission = 0;
@ -76,6 +77,7 @@ struct CreditsHistoryEntry final {
int limitedCount = 0;
int limitedLeft = 0;
int starsConverted = 0;
int starsUpgraded = 0;
int floodSkip = 0;
bool converted : 1 = false;
bool anonymous : 1 = false;
@ -83,6 +85,7 @@ struct CreditsHistoryEntry final {
bool savedToProfile : 1 = false;
bool fromGiftsList : 1 = false;
bool soldOutInfo : 1 = false;
bool canUpgradeGift : 1 = false;
bool reaction : 1 = false;
bool refunded : 1 = false;
bool pending : 1 = false;

View file

@ -136,20 +136,24 @@ enum class GiftType : uchar {
struct GiftCode {
QString slug;
DocumentId stickerId = 0;
uint64 stargiftId = 0;
DocumentData *document = nullptr;
std::shared_ptr<UniqueGift> unique;
TextWithEntities message;
ChannelData *channel = nullptr;
MsgId giveawayMsgId = 0;
int starsConverted = 0;
int starsUpgraded = 0;
int limitedCount = 0;
int limitedLeft = 0;
int count = 0;
GiftType type = GiftType::Premium;
bool viaGiveaway : 1 = false;
bool upgradable : 1 = false;
bool unclaimed : 1 = false;
bool anonymous : 1 = false;
bool converted : 1 = false;
bool upgraded : 1 = false;
bool saved : 1 = false;
};

View file

@ -15,10 +15,11 @@ struct UniqueGiftAttribute {
};
struct UniqueGiftModel : UniqueGiftAttribute {
not_null<DocumentData*> document;
};
struct UniqueGiftPattern : UniqueGiftAttribute {
DocumentId documentId = 0;
not_null<DocumentData*> document;
};
struct UniqueGiftBackdrop : UniqueGiftAttribute {
@ -50,11 +51,13 @@ struct StarGift {
std::shared_ptr<UniqueGift> unique;
int64 stars = 0;
int64 starsConverted = 0;
DocumentId stickerId = 0;
int64 starsUpgraded = 0;
not_null<DocumentData*> document;
int limitedLeft = 0;
int limitedCount = 0;
TimeId firstSaleDate = 0;
TimeId lastSaleDate = 0;
bool upgradable = false;
bool birthday = false;
friend inline bool operator==(
@ -66,9 +69,11 @@ struct UserStarGift {
StarGift info;
TextWithEntities message;
int64 starsConverted = 0;
int64 starsUpgraded = 0;
PeerId fromId = 0;
MsgId messageId = 0;
TimeId date = 0;
bool upgradable = false;
bool anonymous = false;
bool hidden = false;
bool mine = false;

View file

@ -1692,6 +1692,18 @@ ServiceAction ParseServiceAction(
.anonymous = data.is_name_hidden(),
};
});
}, [&](const MTPDmessageActionStarGiftUnique &data) {
data.vgift().match([&](const MTPDstarGift &gift) {
result.content = ActionStarGift{
.giftId = uint64(gift.vid().v),
.stars = int64(gift.vstars().v),
.limited = gift.is_limited(),
};
}, [&](const MTPDstarGiftUnique &gift) {
result.content = ActionStarGift{
.giftId = uint64(gift.vid().v),
};
});
}, [](const MTPDmessageActionEmpty &data) {});
return result;
}

View file

@ -5424,6 +5424,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
lt_user,
Ui::Text::Link(peer->shortName(), 1), // Link 1.
Ui::Text::WithEntities);
return result;
}
const auto cost = TextWithEntities{
tr::lng_action_gift_for_stars(tr::now, lt_count, stars),
@ -5455,6 +5456,22 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
return result;
};
auto prepareStarGiftUnique = [&](
const MTPDmessageActionStarGiftUnique &action) {
auto result = PreparedServiceText();
const auto isSelf = _from->isSelf();
const auto peer = isSelf ? _history->peer : _from;
result.links.push_back(peer->createOpenLink());
result.text = (isSelf
? tr::lng_action_gift_upgraded_mine
: tr::lng_action_gift_upgraded)(
tr::now,
lt_user,
Ui::Text::Link(peer->shortName(), 1), // Link 1.
Ui::Text::WithEntities);
return result;
};
setServiceText(action.match(
prepareChatAddUserText,
prepareChatJoinedByLink,
@ -5501,6 +5518,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
prepareGiftStars,
prepareGiftPrize,
prepareStarGift,
prepareStarGiftUnique,
PrepareEmptyText<MTPDmessageActionRequestedPeerSentMe>,
PrepareErrorText<MTPDmessageActionEmpty>));
@ -5639,18 +5657,44 @@ void HistoryItem::applyAction(const MTPMessageAction &action) {
}
: TextWithEntities()),
.starsConverted = int(data.vconvert_stars().value_or_empty()),
.starsUpgraded = int(data.vupgrade_stars().value_or_empty()),
.type = Data::GiftType::StarGift,
.upgradable = data.is_can_upgrade(),
.anonymous = data.is_name_hidden(),
.converted = data.is_converted(),
.upgraded = data.is_upgraded(),
.saved = data.is_saved(),
};
if (auto gift = Api::FromTL(&history()->session(), data.vgift())) {
fields.stickerId = gift->stickerId;
fields.stargiftId = gift->id;
fields.document = gift->document;
fields.limitedCount = gift->limitedCount;
fields.limitedLeft = gift->limitedLeft;
fields.count = gift->stars;
fields.unique = gift->unique;
}
_media = std::make_unique<Data::MediaGiftBox>(
this,
_from,
std::move(fields));
}, [&](const MTPDmessageActionStarGiftUnique &data) {
using Fields = Data::GiftCode;
auto fields = Fields{
.type = Data::GiftType::StarGift,
.saved = data.is_saved(),
};
if (auto gift = Api::FromTL(&history()->session(), data.vgift())) {
fields.stargiftId = gift->id;
fields.document = gift->document;
fields.limitedCount = gift->limitedCount;
fields.limitedLeft = gift->limitedLeft;
fields.count = gift->stars;
fields.unique = gift->unique;
}
_media = std::make_unique<Data::MediaGiftBox>(
this,
_from,
std::move(fields));
}, [](const auto &) {
});
}

View file

@ -294,20 +294,13 @@ int PremiumGift::credits() const {
void PremiumGift::ensureStickerCreated() const {
if (_sticker) {
return;
} else if (const auto stickerId = _data.stickerId) {
if (!_lifetime) {
const auto owner = &_parent->history()->owner();
_lifetime = owner->customEmojiManager().resolve(
stickerId
) | rpl::start_with_next([=](not_null<DocumentData*> document) {
const auto sticker = document->sticker();
Assert(sticker != nullptr);
_sticker.emplace(_parent, document, false, _parent);
_sticker->setPlayingOnce(true);
_sticker->initSize(st::msgServiceGiftBoxStickerSize);
_parent->repaint();
});
}
} else if (const auto document = _data.document) {
const auto sticker = document->sticker();
Assert(sticker != nullptr);
_sticker.emplace(_parent, document, false, _parent);
_sticker->setPlayingOnce(true);
_sticker->initSize(st::msgServiceGiftBoxStickerSize);
_parent->repaint();
return;
}
const auto &session = _parent->history()->session();

View file

@ -60,7 +60,6 @@ private:
const not_null<Data::MediaGiftBox*> _gift;
const Data::GiftCode &_data;
mutable std::optional<Sticker> _sticker;
mutable rpl::lifetime _lifetime;
};

View file

@ -452,16 +452,15 @@ not_null<StickerPremiumMark*> Delegate::hiddenMark() {
return _hiddenMark.get();
}
DocumentId GiftStickerId(
DocumentData *LookupGiftSticker(
not_null<Main::Session*> session,
const GiftDescriptor &descriptor) {
return v::match(descriptor, [&](GiftTypePremium data) {
auto &packs = session->giftBoxStickersPacks();
packs.load();
const auto document = packs.lookup(data.months);
return document ? document->id : DocumentId();
return packs.lookup(data.months);
}, [&](GiftTypeStars data) {
return data.info.stickerId;
return data.info.document.get();
});
}
@ -486,9 +485,7 @@ rpl::producer<not_null<DocumentData*>> GiftStickerValue(
return not_null(document);
}) | rpl::type_erased();
}, [&](GiftTypeStars data) {
return session->data().customEmojiManager().resolve(
data.info.stickerId
) | rpl::map_error_to_done();
return rpl::single(data.info.document) | rpl::type_erased();
});
}

View file

@ -132,7 +132,7 @@ private:
};
[[nodiscard]] DocumentId GiftStickerId(
[[nodiscard]] DocumentData *LookupGiftSticker(
not_null<Main::Session*> session,
const GiftDescriptor &descriptor);

View file

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/timer_rpl.h"
#include "base/unixtime.h"
#include "boxes/gift_premium_box.h"
#include "boxes/star_gift_box.h"
#include "chat_helpers/stickers_gift_box_pack.h"
#include "chat_helpers/stickers_lottie.h"
#include "core/application.h"
@ -174,7 +175,6 @@ void ToggleStarGiftSaved(
const auto weak = base::make_weak(window);
api->request(MTPpayments_SaveStarGift(
MTP_flags(save ? Flag(0) : Flag::f_unsave),
sender->inputUser,
MTP_int(itemId.bare)
)).done([=] {
done(true);
@ -232,7 +232,6 @@ void ConvertStarGift(
const auto api = &window->session().api();
const auto weak = base::make_weak(window);
api->request(MTPpayments_ConvertStarGift(
sender->inputUser,
MTP_int(itemId)
)).done([=] {
if (const auto strong = weak.get()) {
@ -1329,14 +1328,36 @@ void ReceiptCreditsBox(
}
});
};
const auto upgradeGuard = std::make_shared<bool>();
const auto upgrade = [=] {
if (const auto window = weakWindow.get()) {
const auto itemId = MsgId(e.bareMsgId);
if (*upgradeGuard) {
return;
}
*upgradeGuard = true;
using namespace Ui;
ShowStarGiftUpgradeBox(
window,
e.stargiftId,
starGiftSender,
itemId,
e.starsUpgraded,
[=](bool) { *upgradeGuard = false; });
}
};
const auto canToggle = canConvert || couldConvert || nonConvertible;
const auto canUpgrade = e.stargiftId
&& e.canUpgradeGift
&& !e.uniqueGift;
AddStarGiftTable(
controller,
content,
e,
canToggle ? toggleVisibility : Fn<void(bool)>(),
canConvert ? convert : Fn<void()>());
canConvert ? convert : Fn<void()>(),
canUpgrade ? upgrade : Fn<void()>());
} else {
AddCreditsHistoryEntryTable(controller, content, e);
AddSubscriptionEntryTable(controller, content, s);
@ -1584,16 +1605,19 @@ void UserStarGiftBox(
.credits = StarsAmount(data.info.stars),
.bareMsgId = uint64(data.messageId.bare),
.barePeerId = data.fromId.value,
.bareGiftStickerId = data.info.stickerId,
.bareGiftStickerId = data.info.document->id,
.stargiftId = data.info.id,
.peerType = Data::CreditsHistoryEntry::PeerType::Peer,
.limitedCount = data.info.limitedCount,
.limitedLeft = data.info.limitedLeft,
.starsConverted = int(data.info.starsConverted),
.starsUpgraded = int(data.starsUpgraded),
.converted = false,
.anonymous = data.anonymous,
.stargift = true,
.savedToProfile = !data.hidden,
.fromGiftsList = true,
.canUpgradeGift = data.upgradable,
.in = data.mine,
.gift = true,
},
@ -1615,15 +1639,18 @@ void StarGiftViewBox(
.credits = StarsAmount(data.count),
.bareMsgId = uint64(item->id.bare),
.barePeerId = item->history()->peer->id.value,
.bareGiftStickerId = data.stickerId,
.bareGiftStickerId = data.document ? data.document->id : 0,
.stargiftId = data.stargiftId,
.peerType = Data::CreditsHistoryEntry::PeerType::Peer,
.limitedCount = data.limitedCount,
.limitedLeft = data.limitedLeft,
.starsConverted = data.starsConverted,
.starsUpgraded = data.starsUpgraded,
.converted = data.converted,
.anonymous = data.anonymous,
.stargift = true,
.savedToProfile = data.saved,
.canUpgradeGift = data.upgradable,
.in = true,
.gift = true,
},

View file

@ -173,3 +173,15 @@ creditsHistoryEntriesList: PeerList(defaultPeerList) {
}
subscriptionCreditsBadgePadding: margins(10px, 1px, 8px, 3px);
uniqueGiftModelTop: 20px;
uniqueGiftTitle: FlatLabel(boxTitle) {
align: align(top);
}
uniqueGiftTitleTop: 140px;
uniqueGiftSubtitle: FlatLabel(defaultFlatLabel) {
minWidth: 256px;
align: align(top);
}
uniqueGiftSubtitleTop: 170px;
uniqueGiftBottom: 20px;

View file

@ -25,6 +25,7 @@ not_null<Ui::RpWidget*> CreateNewBadge(
std::move(text),
st::settingsPremiumNewBadge),
st::settingsPremiumNewBadgePadding);
badge->show();
badge->setAttribute(Qt::WA_TransparentForMouseEvents);
badge->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(badge);