diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 256eb21bd..1ffc626c2 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2119,6 +2119,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_gift_link_used_title" = "Used Gift Link"; "lng_gift_link_used_about" = "This link was used to activate\na **Telegram Premium** subscription."; "lng_gift_link_used_footer" = "This link was used on {date}."; +"lng_gift_link_expired" = "Gift code link expired"; "lng_accounts_limit_title" = "Limit Reached"; "lng_accounts_limit1#one" = "You have reached the limit of **{count}** connected accounts."; diff --git a/Telegram/SourceFiles/api/api_premium.cpp b/Telegram/SourceFiles/api/api_premium.cpp index 936715834..05048e29f 100644 --- a/Telegram/SourceFiles/api/api_premium.cpp +++ b/Telegram/SourceFiles/api/api_premium.cpp @@ -24,7 +24,7 @@ namespace { .from = peerFromMTP(data.vfrom_id()), .to = data.vto_id() ? peerFromUser(*data.vto_id()) : PeerId(), .date = data.vdate().v, - .used = false,// data.vused_date().value_or_empty(), + .used = data.vused_date().value_or_empty(), .months = data.vmonths().v, }; } diff --git a/Telegram/SourceFiles/boxes/gift_premium_box.cpp b/Telegram/SourceFiles/boxes/gift_premium_box.cpp index 96be412ec..f797aa116 100644 --- a/Telegram/SourceFiles/boxes/gift_premium_box.cpp +++ b/Telegram/SourceFiles/boxes/gift_premium_box.cpp @@ -287,10 +287,7 @@ struct GiftCodeLink { const auto available = outer - skipRight - skipLeft; const auto use = std::min(textWidth, available); state->label.resizeToWidth(use); - const auto left = (outer >= 2 * skipRight + textWidth) - ? ((outer - textWidth) / 2) - : (outer - skipRight - use - skipLeft); - state->label.move(left, 0); + state->label.move(outer - skipRight - use - skipLeft, 0); }, raw->lifetime()); raw->paintRequest() | rpl::start_with_next([=] { @@ -516,10 +513,12 @@ void GiftCodeBox( table, tr::lng_gift_link_label_reason(), tr::lng_gift_link_reason_giveaway()); - AddTableRow( - table, - tr::lng_gift_link_label_date(), - rpl::single(langDateTime(base::unixtime::parse(current.date)))); + if (current.date) { + AddTableRow( + table, + tr::lng_gift_link_label_date(), + rpl::single(langDateTime(base::unixtime::parse(current.date)))); + } auto shareLink = tr::lng_gift_link_also_send_link( ) | rpl::map([](const QString &text) { @@ -584,3 +583,18 @@ void GiftCodeBox( button->resizeToWidth(buttonWidth); }, button->lifetime()); } + +void ResolveGiftCode( + not_null controller, + const QString &slug) { + const auto done = [=](Api::GiftCode code) { + if (!code) { + controller->showToast(tr::lng_gift_link_expired(tr::now)); + } else { + controller->show(Box(GiftCodeBox, controller, slug)); + } + }; + controller->session().api().premium().checkGiftCode( + slug, + crl::guard(controller, done)); +} diff --git a/Telegram/SourceFiles/boxes/gift_premium_box.h b/Telegram/SourceFiles/boxes/gift_premium_box.h index 9fe4c972e..6fbac2b76 100644 --- a/Telegram/SourceFiles/boxes/gift_premium_box.h +++ b/Telegram/SourceFiles/boxes/gift_premium_box.h @@ -42,3 +42,6 @@ void GiftCodeBox( not_null box, not_null controller, const QString &slug); +void ResolveGiftCode( + not_null controller, + const QString &slug); diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 799a192ec..e8121204d 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -351,17 +351,7 @@ bool ResolveUsernameOrPhone( const auto appnameParam = params.value(u"appname"_q); if (domainParam == u"giftcode"_q && !appnameParam.isEmpty()) { - const auto done = [=](Api::GiftCode code) { - if (!code) { - controller->showToast(u"Gift code link expired"_q); - } else { - controller->show( - Box(GiftCodeBox, controller, appnameParam)); - } - }; - controller->session().api().premium().checkGiftCode( - appnameParam, - crl::guard(controller, done)); + ResolveGiftCode(controller, appnameParam); return true; } diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp index ca947219d..916d9e5bc 100644 --- a/Telegram/SourceFiles/data/data_media_types.cpp +++ b/Telegram/SourceFiles/data/data_media_types.cpp @@ -1908,21 +1908,28 @@ MediaGiftBox::MediaGiftBox( not_null parent, not_null from, int months) +: MediaGiftBox(parent, from, GiftCode{ .months = months }) { +} + +MediaGiftBox::MediaGiftBox( + not_null parent, + not_null from, + GiftCode data) : Media(parent) , _from(from) -, _months(months) { +, _data(std::move(data)) { } std::unique_ptr MediaGiftBox::clone(not_null parent) { - return std::make_unique(parent, _from, _months); + return std::make_unique(parent, _from, _data); } not_null MediaGiftBox::from() const { return _from; } -int MediaGiftBox::months() const { - return _months; +const GiftCode &MediaGiftBox::data() const { + return _data; } TextWithEntities MediaGiftBox::notificationText() const { @@ -1954,14 +1961,6 @@ std::unique_ptr MediaGiftBox::createView( std::make_unique(message, this)); } -bool MediaGiftBox::activated() const { - return _activated; -} - -void MediaGiftBox::setActivated(bool activated) { - _activated = activated; -} - MediaWallPaper::MediaWallPaper( not_null parent, const WallPaper &paper) diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h index 0ab5f51a8..1704e2ad3 100644 --- a/Telegram/SourceFiles/data/data_media_types.h +++ b/Telegram/SourceFiles/data/data_media_types.h @@ -98,6 +98,13 @@ struct Giveaway { bool all = false; }; +struct GiftCode { + QString slug; + ChannelData *channel = nullptr; + int months = 0; + bool viaGiveaway = false; +}; + class Media { public: Media(not_null parent); @@ -526,14 +533,15 @@ public: not_null parent, not_null from, int months); + MediaGiftBox( + not_null parent, + not_null from, + GiftCode data); std::unique_ptr clone(not_null parent) override; [[nodiscard]] not_null from() const; - [[nodiscard]] int months() const; - - [[nodiscard]] bool activated() const; - void setActivated(bool activated); + [[nodiscard]] const GiftCode &data() const; TextWithEntities notificationText() const override; QString pinnedTextSubstring() const override; @@ -548,8 +556,7 @@ public: private: not_null _from; - int _months = 0; - bool _activated = false; + GiftCode _data; }; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index e84631f23..0c106f19f 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -4612,6 +4612,21 @@ void HistoryItem::applyAction(const MTPMessageAction &action) { if (const auto paper = Data::WallPaper::Create(session, attached)) { _media = std::make_unique(this, *paper); } + }, [&](const MTPDmessageActionGiftCode &data) { + const auto boostedId = data.vboost_peer() + ? peerToChannel(peerFromMTP(*data.vboost_peer())) + : ChannelId(); + _media = std::make_unique( + this, + _from, + Data::GiftCode{ + .slug = qs(data.vslug()), + .channel = (peerIsChannel(boostedId) + ? history()->owner().channel(boostedId).get() + : nullptr), + .months = data.vmonths().v, + .viaGiveaway = data.is_via_giveaway(), + }); }, [](const auto &) { }); } diff --git a/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp b/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp index 7df009fde..fdb3943b2 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_premium_gift.cpp @@ -7,15 +7,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "history/view/media/history_view_premium_gift.h" +#include "boxes/gift_premium_box.h" // ResolveGiftCode #include "chat_helpers/stickers_gift_box_pack.h" #include "core/click_handler_types.h" // ClickHandlerContext #include "data/data_document.h" +#include "data/data_channel.h" #include "history/history.h" #include "history/history_item.h" #include "history/view/history_view_element.h" #include "lang/lang_keys.h" #include "main/main_session.h" #include "settings/settings_premium.h" // Settings::ShowGiftPremium +#include "ui/text/text_utilities.h" #include "window/window_session_controller.h" #include "styles/style_chat.h" @@ -37,7 +40,8 @@ PremiumGift::PremiumGift( not_null parent, not_null gift) : _parent(parent) -, _gift(gift) { +, _gift(gift) +, _data(gift->data()) { } PremiumGift::~PremiumGift() = default; @@ -51,27 +55,59 @@ QSize PremiumGift::size() { } QString PremiumGift::title() { - return tr::lng_premium_summary_title(tr::now); + return _data.slug.isEmpty() + ? tr::lng_premium_summary_title(tr::now) + : tr::lng_prize_title(tr::now); } TextWithEntities PremiumGift::subtitle() { - return { FormatGiftMonths(_gift->months()) }; + if (_data.slug.isEmpty()) { + return { FormatGiftMonths(_data.months) }; + } + const auto duration = (_data.months < 12) + ? tr::lng_months(tr::now, lt_count, _data.months) + : tr::lng_years(tr::now, lt_count, _data.months / 12); + const auto name = _data.channel ? _data.channel->name() : "channel"; + auto result = (_data.viaGiveaway + ? tr::lng_prize_about + : tr::lng_prize_gift_about)( + tr::now, + lt_channel, + Ui::Text::Bold(name), + Ui::Text::RichLangValue); + result.append("\n\n"); + result.append((_data.viaGiveaway + ? tr::lng_prize_duration + : tr::lng_prize_gift_duration)( + tr::now, + lt_duration, + Ui::Text::Bold(duration), + Ui::Text::RichLangValue)); + return result; } QString PremiumGift::button() { - return tr::lng_sticker_premium_view(tr::now); + return _data.slug.isEmpty() + ? tr::lng_sticker_premium_view(tr::now) + : tr::lng_prize_open(tr::now); } ClickHandlerPtr PremiumGift::createViewLink() { const auto from = _gift->from(); const auto to = _parent->history()->peer; - const auto months = _gift->months(); + const auto data = _gift->data(); return std::make_shared([=](ClickContext context) { const auto my = context.other.value(); if (const auto controller = my.sessionWindow.get()) { - const auto me = (from->id == controller->session().userPeerId()); - const auto peer = me ? to : from; - Settings::ShowGiftPremium(controller, peer, months, me); + if (data.slug.isEmpty()) { + const auto selfId = controller->session().userPeerId(); + const auto self = (from->id == selfId); + const auto peer = self ? to : from; + const auto months = data.months; + Settings::ShowGiftPremium(controller, peer, months, self); + } else { + ResolveGiftCode(controller, data.slug); + } } }); } @@ -91,6 +127,10 @@ void PremiumGift::draw( } } +bool PremiumGift::hideServiceText() { + return !_data.slug.isEmpty(); +} + void PremiumGift::stickerClearLoopPlayed() { if (_sticker) { _sticker->stickerClearLoopPlayed(); @@ -120,8 +160,9 @@ void PremiumGift::ensureStickerCreated() const { return; } const auto &session = _parent->history()->session(); + const auto months = _gift->data().months; auto &packs = session.giftBoxStickersPacks(); - if (const auto document = packs.lookup(_gift->months())) { + if (const auto document = packs.lookup(months)) { if (const auto sticker = document->sticker()) { const auto skipPremiumEffect = false; _sticker.emplace(_parent, document, skipPremiumEffect, _parent); diff --git a/Telegram/SourceFiles/history/view/media/history_view_premium_gift.h b/Telegram/SourceFiles/history/view/media/history_view_premium_gift.h index f3839291d..e43c5f937 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_premium_gift.h +++ b/Telegram/SourceFiles/history/view/media/history_view_premium_gift.h @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Data { class MediaGiftBox; +struct GiftCode; } // namespace Data namespace HistoryView { @@ -35,10 +36,7 @@ public: const QRect &geometry) override; ClickHandlerPtr createViewLink() override; - bool hideServiceText() override { - return false; - } - + bool hideServiceText() override; void stickerClearLoopPlayed() override; std::unique_ptr stickerTakePlayer( not_null data, @@ -52,6 +50,7 @@ private: const not_null _parent; const not_null _gift; + const Data::GiftCode &_data; mutable std::optional _sticker; }; diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 8fb9be033..acb0af9a9 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -851,7 +851,7 @@ searchInChatPeerList: PeerList(defaultPeerList) { item: searchInChatPeerListItem; } -msgServiceGiftBoxSize: size(206px, 231px); // Plus msgServiceGiftBoxTopSkip. +msgServiceGiftBoxSize: size(236px, 231px); // Plus msgServiceGiftBoxTopSkip. msgServiceGiftBoxRadius: 20px; msgServiceGiftBoxTopSkip: 4px; msgServiceGiftBoxButtonHeight: 32px;