diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index d138d5f913..8cf16783d3 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -2319,6 +2319,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_credits_summary_in_toast_title" = "Stars Acquired"; "lng_credits_summary_in_toast_about#one" = "**{count}** Star added to your balance."; "lng_credits_summary_in_toast_about#other" = "**{count}** Stars added to your balance."; +"lng_credits_box_history_entry_peer" = "Recipient"; +"lng_credits_box_history_entry_id" = "Transaction ID"; +"lng_credits_box_history_entry_id_copied" = "Transaction ID copied to clipboard."; +"lng_credits_box_history_entry_about" = "You can dispute this transaction {link}."; +"lng_credits_box_history_entry_about_link" = "here"; "lng_location_title" = "Location"; "lng_location_about" = "Display the location of your business on your account."; diff --git a/Telegram/SourceFiles/boxes/gift_premium_box.cpp b/Telegram/SourceFiles/boxes/gift_premium_box.cpp index 339e7ee303..ef87c64236 100644 --- a/Telegram/SourceFiles/boxes/gift_premium_box.cpp +++ b/Telegram/SourceFiles/boxes/gift_premium_box.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_boosts.h" #include "data/data_changes.h" #include "data/data_channel.h" +#include "data/data_credits.h" #include "data/data_media_types.h" // Data::GiveawayStart. #include "data/data_peer_values.h" // Data::PeerPremiumValue. #include "data/data_session.h" @@ -1633,3 +1634,50 @@ void ResolveGiveawayInfo( messageId, crl::guard(controller, show)); } + +void AddCreditsHistoryEntryTable( + not_null controller, + not_null container, + const Data::CreditsHistoryEntry &entry) { + auto table = container->add( + object_ptr( + container, + st::giveawayGiftCodeTable), + st::giveawayGiftCodeTableMargin); + if (entry.bareId) { + AddTableRow( + table, + tr::lng_credits_box_history_entry_peer(), + controller, + PeerId(entry.bareId)); + } + if (!entry.id.isEmpty()) { + constexpr auto kOneLineCount = 18; + const auto oneLine = entry.id.length() <= kOneLineCount; + auto label = object_ptr( + table, + rpl::single( + Ui::Text::Wrapped({ entry.id }, EntityType::Code, {})), + oneLine + ? st::giveawayGiftCodeValue + : st::giveawayGiftCodeValueMultiline); + label->setClickHandlerFilter([=](const auto &...) { + TextUtilities::SetClipboardText( + TextForMimeData::Simple(entry.id)); + controller->showToast( + tr::lng_credits_box_history_entry_id_copied(tr::now)); + return false; + }); + AddTableRow( + table, + tr::lng_credits_box_history_entry_id(), + std::move(label), + st::giveawayGiftCodeValueMargin); + } + if (!entry.date.isNull()) { + AddTableRow( + table, + tr::lng_gift_link_label_date(), + rpl::single(Ui::Text::WithEntities(langDateTime(entry.date)))); + } +} diff --git a/Telegram/SourceFiles/boxes/gift_premium_box.h b/Telegram/SourceFiles/boxes/gift_premium_box.h index b054bc3a21..e3194b2736 100644 --- a/Telegram/SourceFiles/boxes/gift_premium_box.h +++ b/Telegram/SourceFiles/boxes/gift_premium_box.h @@ -16,12 +16,14 @@ struct GiftCode; } // namespace Api namespace Data { +struct CreditsHistoryEntry; struct GiveawayStart; struct GiveawayResults; } // namespace Data namespace Ui { class GenericBox; +class VerticalLayout; } // namespace Ui namespace Window { @@ -71,3 +73,8 @@ void ResolveGiveawayInfo( MsgId messageId, std::optional start, std::optional results); + +void AddCreditsHistoryEntryTable( + not_null controller, + not_null container, + const Data::CreditsHistoryEntry &entry); diff --git a/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway.style b/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway.style index 2368a616fe..ef705ab2a8 100644 --- a/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway.style +++ b/Telegram/SourceFiles/info/channel_statistics/boosts/giveaway/giveaway.style @@ -95,6 +95,10 @@ giveawayGiftCodeValue: FlatLabel(defaultFlatLabel) { linkUnderline: kLinkUnderlineNever; } } +giveawayGiftCodeValueMultiline: FlatLabel(giveawayGiftCodeValue) { + minWidth: 100px; + maxHeight: 0px; +} giveawayGiftCodeValueMargin: margins(13px, 9px, 13px, 9px); giveawayGiftCodePeerMargin: margins(11px, 6px, 11px, 4px); giveawayGiftCodeUserpic: UserpicButton(defaultUserpicButton) { diff --git a/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp b/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp index 5a7c7e1bc4..5154a30440 100644 --- a/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp +++ b/Telegram/SourceFiles/info/statistics/info_statistics_list_controllers.cpp @@ -783,9 +783,7 @@ const Data::CreditsHistoryEntry &CreditsRow::entry() const { QString CreditsRow::generateName() { return !PeerListRow::special() ? PeerListRow::generateName() - : (_entry.peerType == Data::CreditsHistoryEntry::PeerType::Fragment) - ? tr::lng_bot_username_description1_link(tr::now) - : tr::lng_credits_summary_history_entry_inner_in(tr::now); + : Ui::GenerateEntryName(_entry).text; } PaintRoundImageCallback CreditsRow::generatePaintUserpicCallback(bool force) { diff --git a/Telegram/SourceFiles/settings/settings_credits.cpp b/Telegram/SourceFiles/settings/settings_credits.cpp index a1fde01f49..44326a9afb 100644 --- a/Telegram/SourceFiles/settings/settings_credits.cpp +++ b/Telegram/SourceFiles/settings/settings_credits.cpp @@ -8,7 +8,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_credits.h" #include "api/api_credits.h" +#include "boxes/gift_premium_box.h" #include "core/click_handler_types.h" +#include "data/data_session.h" #include "data/data_user.h" #include "info/settings/info_settings_widget.h" // SectionCustomTopBarData. #include "info/statistics/info_statistics_list_controllers.h" @@ -19,9 +21,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_common_session.h" #include "statistics/widgets/chart_header_widget.h" #include "ui/boxes/boost_box.h" // Ui::StartFireworks. +#include "ui/controls/userpic_button.h" +#include "ui/effects/credits_graphics.h" #include "ui/effects/premium_graphics.h" #include "ui/effects/premium_top_bar.h" #include "ui/image/image_prepare.h" +#include "ui/layers/generic_box.h" #include "ui/painter.h" #include "ui/rect.h" #include "ui/text/format_values.h" @@ -32,12 +37,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/widgets/tooltip.h" #include "ui/wrap/fade_wrap.h" +#include "ui/wrap/padding_wrap.h" #include "ui/wrap/slide_wrap.h" #include "ui/wrap/vertical_layout.h" #include "window/window_session_controller.h" #include "styles/style_credits.h" +#include "styles/style_giveaway.h" #include "styles/style_info.h" #include "styles/style_layers.h" +#include "styles/style_premium.h" #include "styles/style_settings.h" #include "styles/style_statistics.h" @@ -455,7 +463,117 @@ void Credits::setupHistory(not_null container) { } }, inner->lifetime()); + const auto controller = _controller->parentController(); + const auto entryBox = [=]( + not_null box, + const Data::CreditsHistoryEntry &e) { + box->setStyle(st::giveawayGiftCodeBox); + box->setNoContentMargin(true); + + const auto content = box->verticalLayout(); + Ui::AddSkip(content); + Ui::AddSkip(content); + Ui::AddSkip(content); + + const auto &stUser = st::boostReplaceUserpic; + const auto peer = e.bareId + ? _controller->session().data().peer(PeerId(e.bareId)) + : nullptr; + if (peer) { + content->add(object_ptr>( + content, + object_ptr(content, peer, stUser))); + } else { + const auto widget = content->add( + object_ptr>( + content, + object_ptr(content)))->entity(); + using Draw = Fn; + const auto draw = widget->lifetime().make_state( + Ui::GenerateCreditsPaintUserpicCallback(e)); + widget->resize(Size(stUser.photoSize)); + widget->paintRequest( + ) | rpl::start_with_next([=] { + auto p = Painter(widget); + (*draw)(p, 0, 0, stUser.photoSize, stUser.photoSize); + }, widget->lifetime()); + } + + Ui::AddSkip(content); + Ui::AddSkip(content); + + + box->addRow(object_ptr>( + box, + object_ptr( + box, + rpl::single(peer + ? peer->name() + : Ui::GenerateEntryName(e).text), + st::creditsBoxAboutTitle))); + + Ui::AddSkip(content); + + { + constexpr auto kMinus = QChar(0x2212); + auto &lifetime = content->lifetime(); + const auto text = lifetime.make_state( + st::semiboldTextStyle, + (!e.bareId ? QChar('+') : kMinus) + + Lang::FormatCountDecimal(e.credits)); + + const auto amount = content->add( + object_ptr( + content, + _star.height() / style::DevicePixelRatio())); + const auto font = text->style()->font; + amount->paintRequest( + ) | rpl::start_with_next([=] { + auto p = Painter(amount); + const auto starWidth = _star.width() + / style::DevicePixelRatio(); + const auto fullWidth = text->maxWidth() + + font->spacew * 2 + + starWidth; + p.setPen(!e.bareId + ? st::boxTextFgGood + : st::menuIconAttentionColor); + const auto x = (amount->width() - fullWidth) / 2; + text->draw(p, Ui::Text::PaintContext{ + .position = QPoint( + x, + (amount->height() - font->height) / 2), + .outerWidth = amount->width(), + .availableWidth = amount->width(), + });; + p.drawImage( + x + fullWidth - starWidth, + 0, + _star); + }, amount->lifetime()); + } + + Ui::AddSkip(content); + Ui::AddSkip(content); + + AddCreditsHistoryEntryTable( + controller, + box->verticalLayout(), + e); + + const auto button = box->addButton(tr::lng_box_ok(), [=] { + box->closeBox(); + }); + const auto buttonWidth = st::boxWidth + - rect::m::sum::h(st::giveawayGiftCodeBox.buttonPadding); + button->widthValue() | rpl::filter([=] { + return (button->widthNoMargins() != buttonWidth); + }) | rpl::start_with_next([=] { + button->resizeToWidth(buttonWidth); + }, button->lifetime()); + }; const auto entryClicked = [=](const Data::CreditsHistoryEntry &e) { + controller->uiShow()->show(Box(entryBox, e)); }; Info::Statistics::AddCreditsHistoryList( diff --git a/Telegram/SourceFiles/ui/effects/credits.style b/Telegram/SourceFiles/ui/effects/credits.style index 19c73c7ba2..9f6866f964 100644 --- a/Telegram/SourceFiles/ui/effects/credits.style +++ b/Telegram/SourceFiles/ui/effects/credits.style @@ -30,3 +30,7 @@ creditsBoxAbout: FlatLabel(defaultFlatLabel) { minWidth: 256px; align: align(top); } + +creditsBoxAboutTitle: FlatLabel(settingsPremiumUserTitle) { + minWidth: 256px; +} diff --git a/Telegram/SourceFiles/ui/effects/credits_graphics.cpp b/Telegram/SourceFiles/ui/effects/credits_graphics.cpp index 555ee44c0d..fd465f6b33 100644 --- a/Telegram/SourceFiles/ui/effects/credits_graphics.cpp +++ b/Telegram/SourceFiles/ui/effects/credits_graphics.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include #include "data/data_credits.h" +#include "lang/lang_keys.h" #include "ui/empty_userpic.h" #include "ui/painter.h" #include "styles/style_credits.h" @@ -52,4 +53,12 @@ PaintRoundImageCallback GenerateCreditsPaintUserpicCallback( }; } +TextWithEntities GenerateEntryName(const Data::CreditsHistoryEntry &entry) { + return ((entry.peerType == Data::CreditsHistoryEntry::PeerType::Fragment) + ? tr::lng_bot_username_description1_link + : tr::lng_credits_summary_history_entry_inner_in)( + tr::now, + TextWithEntities::Simple); +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/effects/credits_graphics.h b/Telegram/SourceFiles/ui/effects/credits_graphics.h index c7d8584df8..44d848748a 100644 --- a/Telegram/SourceFiles/ui/effects/credits_graphics.h +++ b/Telegram/SourceFiles/ui/effects/credits_graphics.h @@ -16,4 +16,7 @@ namespace Ui { Fn GenerateCreditsPaintUserpicCallback( const Data::CreditsHistoryEntry &entry); +[[nodiscard]] TextWithEntities GenerateEntryName( + const Data::CreditsHistoryEntry &entry); + } // namespace Ui