Generalize gift sending.

This commit is contained in:
John Preston 2024-10-02 14:43:03 +04:00
parent 42dd08ace5
commit 0282786b4c
11 changed files with 168 additions and 104 deletions

View file

@ -1868,6 +1868,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_action_gift_sent_subtitle" = "Gift for {user}"; "lng_action_gift_sent_subtitle" = "Gift for {user}";
"lng_action_gift_sent_text#one" = "{user} can display this gift on their page or convert it to {count} Star."; "lng_action_gift_sent_text#one" = "{user} can display this gift on their page or convert it to {count} Star.";
"lng_action_gift_sent_text#other" = "{user} can display this gift on their page or convert it to {count} Stars."; "lng_action_gift_sent_text#other" = "{user} can display this gift on their page or convert it to {count} Stars.";
"lng_action_gift_premium_months#one" = "{count} Month Premium";
"lng_action_gift_premium_months#other" = "{count} Months Premium";
"lng_action_gift_premium_about" = "Subscription for exclusive Telegram features.";
"lng_action_suggested_photo_me" = "You suggested this photo for {user}'s Telegram profile."; "lng_action_suggested_photo_me" = "You suggested this photo for {user}'s Telegram profile.";
"lng_action_suggested_photo" = "{user} suggests this photo for your Telegram profile."; "lng_action_suggested_photo" = "{user} suggests this photo for your Telegram profile.";
"lng_action_suggested_photo_button" = "View Photo"; "lng_action_suggested_photo_button" = "View Photo";
@ -3014,6 +3017,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_gift_send_message" = "Enter Message"; "lng_gift_send_message" = "Enter Message";
"lng_gift_send_anonymous" = "Hide My Name"; "lng_gift_send_anonymous" = "Hide My Name";
"lng_gift_send_anonymous_about" = "You can hide your name and message from visitors to {user}'s profile. {recipient} will still see your name and message."; "lng_gift_send_anonymous_about" = "You can hide your name and message from visitors to {user}'s profile. {recipient} will still see your name and message.";
"lng_gift_send_premium_about" = "Only {user} will see your message.";
"lng_gift_send_button" = "Send a Gift for {cost}"; "lng_gift_send_button" = "Send a Gift for {cost}";
"lng_gift_sent_title" = "Gift Sent!"; "lng_gift_sent_title" = "Gift Sent!";
"lng_gift_sent_about#one" = "You spent **{count}** Star from your balance."; "lng_gift_sent_about#one" = "You spent **{count}** Star from your balance.";

View file

@ -92,6 +92,7 @@ struct GiftsDescriptor {
struct GiftDetails { struct GiftDetails {
GiftDescriptor descriptor; GiftDescriptor descriptor;
TextWithEntities text; TextWithEntities text;
uint64 randomId = 0;
bool anonymous = false; bool anonymous = false;
}; };
@ -161,8 +162,6 @@ auto GenerateGiftMedia(
Element *replacing, Element *replacing,
const GiftDetails &data) const GiftDetails &data)
-> Fn<void(Fn<void(std::unique_ptr<MediaGenericPart>)>)> { -> Fn<void(Fn<void(std::unique_ptr<MediaGenericPart>)>)> {
Expects(v::is<GiftTypeStars>(data.descriptor));
return [=](Fn<void(std::unique_ptr<MediaGenericPart>)> push) { return [=](Fn<void(std::unique_ptr<MediaGenericPart>)> push) {
const auto &descriptor = data.descriptor; const auto &descriptor = data.descriptor;
auto pushText = [&]( auto pushText = [&](
@ -181,16 +180,8 @@ auto GenerateGiftMedia(
}; };
const auto sticker = [=] { const auto sticker = [=] {
using Tag = ChatHelpers::StickerLottieSize; using Tag = ChatHelpers::StickerLottieSize;
const auto &session = parent->history()->session(); const auto session = &parent->history()->session();
auto &packs = session.giftBoxStickersPacks(); const auto sticker = LookupGiftSticker(session, descriptor);
packs.load();
auto sticker = v::match(descriptor, [&](GiftTypePremium data) {
return packs.lookup(data.months);
}, [&](GiftTypeStars data) {
return data.document
? data.document
: packs.lookup(packs.monthsForStars(data.stars));
});
return StickerInBubblePart::Data{ return StickerInBubblePart::Data{
.sticker = sticker, .sticker = sticker,
.size = st::chatIntroStickerSize, .size = st::chatIntroStickerSize,
@ -203,15 +194,28 @@ auto GenerateGiftMedia(
replacing, replacing,
sticker, sticker,
st::giftBoxPreviewStickerPadding)); st::giftBoxPreviewStickerPadding));
const auto title = tr::lng_action_gift_got_subtitle( const auto title = v::match(descriptor, [&](GiftTypePremium gift) {
tr::now, return tr::lng_action_gift_premium_months(
lt_user, tr::now,
parent->data()->history()->session().user()->shortName()); lt_count,
auto textFallback = tr::lng_action_gift_got_stars_text( gift.months);
tr::now, }, [&](const GiftTypeStars &gift) {
lt_count, return tr::lng_action_gift_got_subtitle(
v::get<GiftTypeStars>(descriptor).convertStars, tr::now,
Ui::Text::RichLangValue); lt_user,
parent->history()->session().user()->shortName());
});
auto textFallback = v::match(descriptor, [&](GiftTypePremium gift) {
return tr::lng_action_gift_premium_about(
tr::now,
Ui::Text::RichLangValue);
}, [&](const GiftTypeStars &gift) {
return tr::lng_action_gift_got_stars_text(
tr::now,
lt_count,
gift.convertStars,
Ui::Text::RichLangValue);
});
auto description = data.text.empty() auto description = data.text.empty()
? std::move(textFallback) ? std::move(textFallback)
: data.text; : data.text;
@ -221,7 +225,7 @@ auto GenerateGiftMedia(
st::giftBoxPreviewTextPadding, st::giftBoxPreviewTextPadding,
{}, {},
Core::MarkedTextContext{ Core::MarkedTextContext{
.session = &parent->data()->history()->session(), .session = &parent->history()->session(),
.customEmojiRepaint = [parent] { parent->repaint(); }, .customEmojiRepaint = [parent] { parent->repaint(); },
}); });
}; };
@ -260,24 +264,34 @@ PreviewWrap::PreviewWrap(
void ShowSentToast( void ShowSentToast(
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,
GiftTypeStars gift) { const GiftDescriptor &descriptor) {
const auto &st = st::historyPremiumToast; const auto &st = st::historyPremiumToast;
const auto skip = st.padding.top(); const auto skip = st.padding.top();
const auto size = st.style.font->height * 2; const auto size = st.style.font->height * 2;
const auto leftSkip = skip + size + skip - st.padding.left(); const auto document = LookupGiftSticker(&window->session(), descriptor);
const auto strong = window->showToast({ const auto leftSkip = document
.title = tr::lng_gift_sent_title(tr::now), ? (skip + size + skip - st.padding.left())
.text = tr::lng_gift_sent_about( : 0;
auto text = v::match(descriptor, [&](const GiftTypePremium &gift) {
return tr::lng_action_gift_premium_about(
tr::now,
Ui::Text::RichLangValue);
}, [&](const GiftTypeStars &gift) {
return tr::lng_gift_sent_about(
tr::now, tr::now,
lt_count, lt_count,
gift.stars, gift.stars,
Ui::Text::RichLangValue), Ui::Text::RichLangValue);
});
const auto strong = window->showToast({
.title = tr::lng_gift_sent_title(tr::now),
.text = std::move(text),
.padding = rpl::single(QMargins(leftSkip, 0, 0, 0)), .padding = rpl::single(QMargins(leftSkip, 0, 0, 0)),
.st = &st, .st = &st,
.attach = RectPart::Top, .attach = RectPart::Top,
.duration = kSentToastDuration, .duration = kSentToastDuration,
}).get(); }).get();
if (!strong) { if (!strong || !document) {
return; return;
} }
const auto widget = strong->widget(); const auto widget = strong->widget();
@ -286,7 +300,6 @@ void ShowSentToast(
preview->resize(size, size); preview->resize(size, size);
preview->show(); preview->show();
const auto document = gift.document;
const auto bytes = document->createMediaView()->bytes(); const auto bytes = document->createMediaView()->bytes();
const auto filepath = document->filepath(); const auto filepath = document->filepath();
const auto ratio = style::DevicePixelRatio(); const auto ratio = style::DevicePixelRatio();
@ -807,14 +820,38 @@ struct GiftPriceTabs {
return field; return field;
} }
void SendGift(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer,
std::shared_ptr<Api::PremiumGiftCodeOptions> api,
const GiftDetails &details,
Fn<void(Payments::CheckoutResult)> done) {
v::match(details.descriptor, [&](const GiftTypePremium &gift) {
auto invoice = api->invoice(1, gift.months);
invoice.purpose = Payments::InvoicePremiumGiftCodeUsers{
.users = { peer->asUser() },
.message = details.text,
};
Payments::CheckoutProcess::Start(std::move(invoice), done);
}, [&](const GiftTypeStars &gift) {
const auto processNonPanelPaymentFormFactory
= Payments::ProcessNonPanelPaymentFormFactory(window, done);
Payments::CheckoutProcess::Start(Payments::InvoiceStarGift{
.giftId = gift.id,
.randomId = details.randomId,
.message = details.text,
.user = peer->asUser(),
.anonymous = details.anonymous,
}, done, processNonPanelPaymentFormFactory);
});
}
void SendGiftBox( void SendGiftBox(
not_null<Ui::GenericBox*> box, not_null<Ui::GenericBox*> box,
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,
not_null<PeerData*> peer, not_null<PeerData*> peer,
std::shared_ptr<Api::PremiumGiftCodeOptions> api,
const GiftDescriptor &descriptor) { const GiftDescriptor &descriptor) {
Expects(v::is<GiftTypeStars>(descriptor));
const auto gift = v::get<GiftTypeStars>(descriptor);
box->setStyle(st::giftBox); box->setStyle(st::giftBox);
box->setWidth(st::boxWideWidth); box->setWidth(st::boxWideWidth);
box->setTitle(tr::lng_gift_send_title()); box->setTitle(tr::lng_gift_send_title());
@ -841,15 +878,17 @@ void SendGiftBox(
struct State { struct State {
rpl::variable<GiftDetails> details; rpl::variable<GiftDetails> details;
std::shared_ptr<Data::DocumentMedia> media; std::shared_ptr<Data::DocumentMedia> media;
uint64 randomId = 0;
bool submitting = false; bool submitting = false;
}; };
const auto state = box->lifetime().make_state<State>(); const auto state = box->lifetime().make_state<State>();
state->details = GiftDetails{ state->details = GiftDetails{
.descriptor = descriptor, .descriptor = descriptor,
.randomId = base::RandomValue<uint64>(),
}; };
state->media = gift.document->createMediaView(); const auto document = LookupGiftSticker(&window->session(), descriptor);
state->media->checkStickerLarge(); if ((state->media = document ? document->createMediaView() : nullptr)) {
state->media->checkStickerLarge();
}
const auto container = box->verticalLayout(); const auto container = box->verticalLayout();
container->add(object_ptr<PreviewWrap>( container->add(object_ptr<PreviewWrap>(
@ -901,25 +940,33 @@ void SendGiftBox(
&window->session(), &window->session(),
{ .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow }); { .suggestCustomEmoji = true, .allowCustomWithoutPremium = allow });
AddDivider(container); if (v::is<GiftTypeStars>(descriptor)) {
AddSkip(container); AddDivider(container);
container->add( AddSkip(container);
object_ptr<Ui::SettingsButton>( container->add(
container, object_ptr<Ui::SettingsButton>(
tr::lng_gift_send_anonymous(), container,
st::settingsButtonNoIcon) tr::lng_gift_send_anonymous(),
)->toggleOn(rpl::single(false))->toggledValue( st::settingsButtonNoIcon)
) | rpl::start_with_next([=](bool toggled) { )->toggleOn(rpl::single(false))->toggledValue(
auto now = state->details.current(); ) | rpl::start_with_next([=](bool toggled) {
now.anonymous = toggled; auto now = state->details.current();
state->details = std::move(now); now.anonymous = toggled;
}, container->lifetime()); state->details = std::move(now);
AddSkip(container); }, container->lifetime());
AddDividerText(container, tr::lng_gift_send_anonymous_about( AddSkip(container);
lt_user, }
rpl::single(peer->shortName()), v::match(descriptor, [&](const GiftTypePremium &) {
lt_recipient, AddDividerText(container, tr::lng_gift_send_premium_about(
rpl::single(peer->shortName()))); lt_user,
rpl::single(peer->shortName())));
}, [&](const GiftTypeStars &) {
AddDividerText(container, tr::lng_gift_send_anonymous_about(
lt_user,
rpl::single(peer->shortName()),
lt_recipient,
rpl::single(peer->shortName())));
});
const auto buttonWidth = st::boxWideWidth const auto buttonWidth = st::boxWideWidth
- st::giftBox.buttonPadding.left() - st::giftBox.buttonPadding.left()
@ -929,26 +976,19 @@ void SendGiftBox(
return; return;
} }
state->submitting = true; state->submitting = true;
state->randomId = base::RandomValue<uint64>();
const auto details = state->details.current(); const auto details = state->details.current();
const auto weak = Ui::MakeWeak(box); const auto weak = Ui::MakeWeak(box);
const auto done = [=](Payments::CheckoutResult result) { const auto done = [=](Payments::CheckoutResult result) {
if (result == Payments::CheckoutResult::Paid) { if (result == Payments::CheckoutResult::Paid) {
const auto copy = state->media; const auto copy = state->media;
window->showPeerHistory(peer); window->showPeerHistory(peer);
ShowSentToast(window, gift); ShowSentToast(window, descriptor);
} }
if (const auto strong = weak.data()) { if (const auto strong = weak.data()) {
box->closeBox(); box->closeBox();
} }
}; };
Payments::CheckoutProcess::Start(Payments::InvoiceStarGift{ SendGift(window, peer, api, details, done);
.giftId = gift.id,
.randomId = state->randomId,
.message = details.text,
.user = peer->asUser(),
.anonymous = details.anonymous,
}, done, Payments::ProcessNonPanelPaymentFormFactory(window, done));
}); });
SetButtonMarkedLabel( SetButtonMarkedLabel(
button, button,
@ -967,19 +1007,6 @@ void SendGiftBox(
}, button->lifetime()); }, button->lifetime());
} }
void SendPremiumGift(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer,
std::shared_ptr<Api::PremiumGiftCodeOptions> api,
const GiftTypePremium &gift,
Fn<void(Payments::CheckoutResult)> done) {
auto invoice = api->invoice(1, gift.months);
invoice.purpose = Payments::InvoicePremiumGiftCodeUsers{
{ peer->asUser() }
};
Payments::CheckoutProcess::Start(std::move(invoice), done);
}
[[nodiscard]] object_ptr<RpWidget> MakeGiftsList( [[nodiscard]] object_ptr<RpWidget> MakeGiftsList(
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,
not_null<PeerData*> peer, not_null<PeerData*> peer,
@ -999,6 +1026,13 @@ void SendPremiumGift(
const auto shadow = st::defaultDropdownMenu.wrap.shadow; const auto shadow = st::defaultDropdownMenu.wrap.shadow;
const auto extend = shadow.extend; const auto extend = shadow.extend;
auto &packs = window->session().giftBoxStickersPacks();
packs.updated() | rpl::start_with_next([=] {
for (const auto &button : state->buttons) {
button->update();
}
}, raw->lifetime());
std::move( std::move(
gifts gifts
) | rpl::start_with_next([=](const GiftsDescriptor &gifts) { ) | rpl::start_with_next([=](const GiftsDescriptor &gifts) {
@ -1049,14 +1083,15 @@ void SendPremiumGift(
} else { } else {
state->sending = true; state->sending = true;
} }
SendPremiumGift( SendGift(
window, window,
peer, peer,
api, api,
v::get<GiftTypePremium>(descriptor), GiftDetails{ descriptor },
premiumSent); premiumSent);
} else { } else {
window->show(Box(SendGiftBox, window, peer, descriptor)); window->show(
Box(SendGiftBox, window, peer, api, descriptor));
} }
}); });
} }

View file

@ -22,6 +22,10 @@ GiftBoxPack::GiftBoxPack(not_null<Main::Session*> session)
GiftBoxPack::~GiftBoxPack() = default; GiftBoxPack::~GiftBoxPack() = default;
rpl::producer<> GiftBoxPack::updated() const {
return _updated.events();
}
int GiftBoxPack::monthsForStars(int stars) const { int GiftBoxPack::monthsForStars(int stars) const {
if (stars <= 1000) { if (stars <= 1000) {
return 3; return 3;
@ -112,6 +116,7 @@ void GiftBoxPack::applySet(const MTPDmessages_stickerSet &data) {
} }
}); });
} }
_updated.fire({});
} }
} // namespace Stickers } // namespace Stickers

View file

@ -28,6 +28,7 @@ public:
[[nodiscard]] int monthsForStars(int stars) const; [[nodiscard]] int monthsForStars(int stars) const;
[[nodiscard]] DocumentData *lookup(int months) const; [[nodiscard]] DocumentData *lookup(int months) const;
[[nodiscard]] Data::FileOrigin origin() const; [[nodiscard]] Data::FileOrigin origin() const;
[[nodiscard]] rpl::producer<> updated() const;
private: private:
using SetId = uint64; using SetId = uint64;
@ -36,6 +37,7 @@ private:
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
const std::vector<int> _localMonths; const std::vector<int> _localMonths;
rpl::event_stream<> _updated;
std::vector<DocumentData*> _documents; std::vector<DocumentData*> _documents;
SetId _setId = 0; SetId _setId = 0;
uint64 _accessHash = 0; uint64 _accessHash = 0;

View file

@ -463,10 +463,6 @@ bool UserData::canAddContact() const {
return canShareThisContact() && !isContact(); return canShareThisContact() && !isContact();
} }
bool UserData::canReceiveGifts() const {
return flags() & UserDataFlag::CanReceiveGifts;
}
bool UserData::canShareThisContactFast() const { bool UserData::canShareThisContactFast() const {
return !_phone.isEmpty(); return !_phone.isEmpty();
} }
@ -584,14 +580,10 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
if (const auto pinned = update.vpinned_msg_id()) { if (const auto pinned = update.vpinned_msg_id()) {
SetTopPinnedMessageId(user, pinned->v); SetTopPinnedMessageId(user, pinned->v);
} }
const auto canReceiveGifts = (update.vflags().v
& MTPDuserFull::Flag::f_premium_gifts)
&& update.vpremium_gifts();
using Flag = UserDataFlag; using Flag = UserDataFlag;
const auto mask = Flag::Blocked const auto mask = Flag::Blocked
| Flag::HasPhoneCalls | Flag::HasPhoneCalls
| Flag::PhoneCallsPrivate | Flag::PhoneCallsPrivate
| Flag::CanReceiveGifts
| Flag::CanPinMessages | Flag::CanPinMessages
| Flag::VoiceMessagesForbidden | Flag::VoiceMessagesForbidden
| Flag::ReadDatesPrivate | Flag::ReadDatesPrivate
@ -602,7 +594,6 @@ void ApplyUserUpdate(not_null<UserData*> user, const MTPDuserFull &update) {
? Flag::PhoneCallsPrivate ? Flag::PhoneCallsPrivate
: Flag()) : Flag())
| (update.is_phone_calls_available() ? Flag::HasPhoneCalls : Flag()) | (update.is_phone_calls_available() ? Flag::HasPhoneCalls : Flag())
| (canReceiveGifts ? Flag::CanReceiveGifts : Flag())
| (update.is_can_pin_message() ? Flag::CanPinMessages : Flag()) | (update.is_can_pin_message() ? Flag::CanPinMessages : Flag())
| (update.is_blocked() ? Flag::Blocked : Flag()) | (update.is_blocked() ? Flag::Blocked : Flag())
| (update.is_voice_messages_forbidden() | (update.is_voice_messages_forbidden()

View file

@ -67,7 +67,7 @@ enum class UserDataFlag : uint32 {
DiscardMinPhoto = (1 << 12), DiscardMinPhoto = (1 << 12),
Self = (1 << 13), Self = (1 << 13),
Premium = (1 << 14), Premium = (1 << 14),
CanReceiveGifts = (1 << 15), //CanReceiveGifts = (1 << 15),
VoiceMessagesForbidden = (1 << 16), VoiceMessagesForbidden = (1 << 16),
PersonalPhoto = (1 << 17), PersonalPhoto = (1 << 17),
StoriesHidden = (1 << 18), StoriesHidden = (1 << 18),
@ -146,8 +146,6 @@ public:
[[nodiscard]] bool canShareThisContact() const; [[nodiscard]] bool canShareThisContact() const;
[[nodiscard]] bool canAddContact() const; [[nodiscard]] bool canAddContact() const;
[[nodiscard]] bool canReceiveGifts() const;
// In Data::Session::processUsers() we check only that. // In Data::Session::processUsers() we check only that.
// When actually trying to share contact we perform // When actually trying to share contact we perform
// a full check by canShareThisContact() call. // a full check by canShareThisContact() call.

View file

@ -43,7 +43,7 @@ PremiumGift::PremiumGift(
PremiumGift::~PremiumGift() = default; PremiumGift::~PremiumGift() = default;
int PremiumGift::top() { int PremiumGift::top() {
return st::msgServiceGiftBoxStickerTop; return starGift() ? 0 : st::msgServiceGiftBoxStickerTop;
} }
QSize PremiumGift::size() { QSize PremiumGift::size() {
@ -66,7 +66,7 @@ QString PremiumGift::title() {
return tr::lng_gift_stars_title(tr::now, lt_count, count); return tr::lng_gift_stars_title(tr::now, lt_count, count);
} }
return gift() return gift()
? tr::lng_premium_summary_title(tr::now) ? tr::lng_action_gift_premium_months(tr::now, lt_count, _data.count)
: _data.unclaimed : _data.unclaimed
? tr::lng_prize_unclaimed_title(tr::now) ? tr::lng_prize_unclaimed_title(tr::now)
: tr::lng_prize_title(tr::now); : tr::lng_prize_title(tr::now);
@ -99,10 +99,14 @@ TextWithEntities PremiumGift::subtitle() {
tr::now, tr::now,
lt_user, lt_user,
Ui::Text::Bold(_parent->history()->peer->shortName()), Ui::Text::Bold(_parent->history()->peer->shortName()),
Ui::Text::WithEntities) Ui::Text::RichLangValue)
: tr::lng_gift_stars_incoming(tr::now, Ui::Text::WithEntities); : tr::lng_gift_stars_incoming(tr::now, Ui::Text::WithEntities);
} else if (gift()) { } else if (gift()) {
return { GiftDuration(_data.count) }; return !_data.message.empty()
? _data.message
: tr::lng_action_gift_premium_about(
tr::now,
Ui::Text::RichLangValue);
} }
const auto name = _data.channel ? _data.channel->name() : "channel"; const auto name = _data.channel ? _data.channel->name() : "channel";
auto result = (_data.unclaimed auto result = (_data.unclaimed

View file

@ -109,6 +109,10 @@ void GiftButton::setDescriptor(const GiftDescriptor &descriptor) {
_button = QRect(skipx, skipy, outer, inner.height()); _button = QRect(skipx, skipy, outer, inner.height());
} }
bool GiftButton::documentResolved() const {
return _player || _mediaLifetime;
}
void GiftButton::setDocument(not_null<DocumentData*> document) { void GiftButton::setDocument(not_null<DocumentData*> document) {
const auto media = document->createMediaView(); const auto media = document->createMediaView();
media->checkStickerLarge(); media->checkStickerLarge();
@ -159,6 +163,12 @@ void GiftButton::resizeEvent(QResizeEvent *e) {
} }
void GiftButton::paintEvent(QPaintEvent *e) { void GiftButton::paintEvent(QPaintEvent *e) {
if (!documentResolved()) {
if (const auto document = _delegate->lookupSticker(_descriptor)) {
setDocument(document);
}
}
auto p = QPainter(this); auto p = QPainter(this);
const auto hidden = v::is<GiftTypeStars>(_descriptor) const auto hidden = v::is<GiftTypeStars>(_descriptor)
&& v::get<GiftTypeStars>(_descriptor).hidden;; && v::get<GiftTypeStars>(_descriptor).hidden;;
@ -399,8 +409,17 @@ QImage Delegate::background() {
} }
DocumentData *Delegate::lookupSticker(const GiftDescriptor &descriptor) { DocumentData *Delegate::lookupSticker(const GiftDescriptor &descriptor) {
const auto &session = _window->session(); return LookupGiftSticker(&_window->session(), descriptor);
auto &packs = session.giftBoxStickersPacks(); }
not_null<StickerPremiumMark*> Delegate::hiddenMark() {
return _hiddenMark.get();
}
DocumentData *LookupGiftSticker(
not_null<Main::Session*> session,
const GiftDescriptor &descriptor) {
auto &packs = session->giftBoxStickersPacks();
packs.load(); packs.load();
return v::match(descriptor, [&](GiftTypePremium data) { return v::match(descriptor, [&](GiftTypePremium data) {
return packs.lookup(data.months); return packs.lookup(data.months);
@ -411,8 +430,4 @@ DocumentData *Delegate::lookupSticker(const GiftDescriptor &descriptor) {
}); });
} }
not_null<StickerPremiumMark*> Delegate::hiddenMark() {
return _hiddenMark.get();
}
} // namespace Info::PeerGifts } // namespace Info::PeerGifts

View file

@ -16,6 +16,10 @@ namespace HistoryView {
class StickerPlayer; class StickerPlayer;
} // namespace HistoryView } // namespace HistoryView
namespace Main {
class Session;
} // namespace Main
namespace Ui { namespace Ui {
class DynamicImage; class DynamicImage;
} // namespace Ui } // namespace Ui
@ -86,6 +90,8 @@ private:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
void setDocument(not_null<DocumentData*> document); void setDocument(not_null<DocumentData*> document);
[[nodiscard]] bool documentResolved() const;
void unsubscribe(); void unsubscribe();
const not_null<GiftButtonDelegate*> _delegate; const not_null<GiftButtonDelegate*> _delegate;
@ -126,4 +132,8 @@ private:
}; };
[[nodiscard]] DocumentData *LookupGiftSticker(
not_null<Main::Session*> session,
const GiftDescriptor &descriptor);
} // namespace Info::PeerGifts } // namespace Info::PeerGifts

View file

@ -143,6 +143,7 @@ struct InvoicePremiumGiftCodeGiveaway {
struct InvoicePremiumGiftCodeUsers { struct InvoicePremiumGiftCodeUsers {
std::vector<not_null<UserData*>> users; std::vector<not_null<UserData*>> users;
ChannelData *boostPeer = nullptr; ChannelData *boostPeer = nullptr;
TextWithEntities message;
}; };
struct InvoicePremiumGiftCode { struct InvoicePremiumGiftCode {

View file

@ -1231,7 +1231,6 @@ void Filler::addGiftPremium() {
|| user->isSelf() || user->isSelf()
|| user->isBot() || user->isBot()
|| user->isNotificationsUser() || user->isNotificationsUser()
|| !user->canReceiveGifts()
|| user->isRepliesChat() || user->isRepliesChat()
|| user->isVerifyCodes() || user->isVerifyCodes()
|| !user->session().premiumCanBuy()) { || !user->session().premiumCanBuy()) {
@ -1240,7 +1239,7 @@ void Filler::addGiftPremium() {
const auto navigation = _controller; const auto navigation = _controller;
_addAction(tr::lng_profile_gift_premium(tr::now), [=] { _addAction(tr::lng_profile_gift_premium(tr::now), [=] {
Ui::ChooseStarGiftRecipient(navigation); Ui::ShowStarGiftBox(navigation, user);
}, &st::menuIconGiftPremium); }, &st::menuIconGiftPremium);
} }