From b79c306bfea023d2b7b5865a0bbb2a1cfcd00cef Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 23 Jun 2024 05:10:28 +0300 Subject: [PATCH] Added list of credits history to section of channel earn. --- .../earn/info_earn_inner_widget.cpp | 138 ++++++++++++++++-- .../earn/info_earn_widget.h | 5 +- 2 files changed, 129 insertions(+), 14 deletions(-) diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp b/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp index 018ecb00a..38c4dabd0 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_inner_widget.cpp @@ -26,11 +26,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "info/info_controller.h" #include "info/profile/info_profile_values.h" // Info::Profile::NameValue. #include "info/statistics/info_statistics_inner_widget.h" // FillLoading. +#include "info/statistics/info_statistics_list_controllers.h" #include "iv/iv_instance.h" #include "lang/lang_keys.h" #include "main/main_account.h" #include "main/main_app_config.h" #include "main/main_session.h" +#include "settings/settings_credits_graphics.h" #include "statistics/chart_widget.h" #include "ui/basic_click_handlers.h" #include "ui/boxes/boost_box.h" @@ -46,6 +48,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/fields/input_field.h" #include "ui/widgets/label_with_custom_emoji.h" #include "ui/widgets/popup_menu.h" +#include "ui/widgets/slider_natural_width.h" #include "ui/wrap/slide_wrap.h" #include "styles/style_boxes.h" #include "styles/style_channel_earn.h" @@ -54,6 +57,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_layers.h" #include "styles/style_settings.h" #include "styles/style_statistics.h" +#include "styles/style_credits.h" #include "styles/style_window.h" // mainMenuToggleFourStrokes. #include @@ -263,12 +267,15 @@ void InnerWidget::load() { struct State final { State(not_null peer) : api(peer->asChannel()) - , apiCredits(peer) { + , apiCredits(peer) + , apiCreditsHistory(peer, true, true) { } Api::ChannelEarnStatistics api; Api::CreditsEarnStatistics apiCredits; + Api::CreditsHistory apiCreditsHistory; rpl::lifetime apiLifetime; rpl::lifetime apiCreditsLifetime; + rpl::lifetime apiPremiumBotLifetime; }; const auto state = lifetime().make_state(_peer); const auto api = lifetime().make_state( @@ -326,14 +333,24 @@ void InnerWidget::load() { state->api.request( ) | rpl::start_with_error_done(fail, [=] { _state.currencyEarn = state->api.data(); - state->apiCredits.request( - ) | rpl::start_with_error_done([=](const QString &error) { - fail(error); - finish(); - }, [=] { - _state.creditsEarn = state->apiCredits.data(); - finish(); - }, state->apiCreditsLifetime); + state->apiCreditsHistory.request({}, [=]( + const Data::CreditsStatusSlice &data) { + _state.creditsStatusSlice = data; + ::Api::PremiumPeerBot( + &_peer->session() + ) | rpl::start_with_next([=](not_null bot) { + _state.premiumBotId = bot->id; + state->apiCredits.request( + ) | rpl::start_with_error_done([=](const QString &error) { + fail(error); + finish(); + }, [=] { + _state.creditsEarn = state->apiCredits.data(); + finish(); + }, state->apiCreditsLifetime); + state->apiPremiumBotLifetime.destroy(); + }, state->apiPremiumBotLifetime); + }); }, state->apiLifetime); }, lifetime()); } @@ -894,12 +911,79 @@ void InnerWidget::fill() { : tr::lng_channel_earn_balance_about_temp); Ui::AddSkip(container); } - if (!data.firstHistorySlice.list.empty()) { - AddHeader(container, tr::lng_channel_earn_history_title); + + const auto hasCurrencyTab = !data.firstHistorySlice.list.empty(); + const auto hasCreditsTab = !_state.creditsStatusSlice.list.empty() + && _state.premiumBotId; + const auto hasOneTab = (hasCurrencyTab || hasCreditsTab) + && (hasCurrencyTab != hasCreditsTab); + + const auto currencyTabText = tr::lng_channel_earn_currency_history( + tr::now); + const auto creditsTabText = tr::lng_channel_earn_credits_history(tr::now); + + const auto slider = container->add( + object_ptr>( + container, + object_ptr( + container, + st::defaultTabsSlider)), + st::boxRowPadding); + slider->toggle(!hasOneTab, anim::type::instant); + + if (hasCurrencyTab) { + slider->entity()->addSection(currencyTabText); + } + if (hasCreditsTab) { + slider->entity()->addSection(creditsTabText); + } + + { + const auto &st = st::defaultTabsSlider; + slider->entity()->setNaturalWidth(0 + + (hasCurrencyTab + ? st.labelStyle.font->width(currencyTabText) + : 0) + + (hasCreditsTab + ? st.labelStyle.font->width(creditsTabText) + : 0) + + rect::m::sum::h(st::boxRowPadding)); + } + + if (hasOneTab) { + if (hasCurrencyTab) { + AddHeader(container, tr::lng_channel_earn_history_title); + } else if (hasCreditsTab) { + AddHeader(container, tr::lng_channel_earn_credits_history); + slider->entity()->setActiveSectionFast(1); + } + } + + const auto historyCurrencyList = container->add( + object_ptr>( + container, + object_ptr(container))); + const auto historyCreditsList = container->add( + object_ptr>( + container, + object_ptr(container))); + + rpl::single(slider->entity()->activeSection()) | rpl::then( + slider->entity()->sectionActivated() + ) | rpl::start_with_next([=](int index) { + if (index == 0) { + historyCurrencyList->toggle(true, anim::type::instant); + historyCreditsList->toggle(false, anim::type::instant); + } else if (index == 1) { + historyCurrencyList->toggle(false, anim::type::instant); + historyCreditsList->toggle(true, anim::type::instant); + } + }, container->lifetime()); + + if (hasCurrencyTab) { Ui::AddSkip(container); - const auto historyList = container->add( - object_ptr(container)); + const auto historyList = historyCurrencyList->entity(); const auto addHistoryEntry = [=]( const Data::EarnHistoryEntry &entry, const tr::phrase<> &text) { @@ -1208,6 +1292,34 @@ void InnerWidget::fill() { Ui::AddDivider(container); Ui::AddSkip(container); } + if (hasCreditsTab) { + const auto controller = _controller->parentController(); + const auto show = controller->uiShow(); + const auto premiumBot = _peer->owner().peer(_state.premiumBotId); + const auto entryClicked = [=](const Data::CreditsHistoryEntry &e) { + show->show(Box( + ::Settings::ReceiptCreditsBox, + controller, + premiumBot.get(), + e)); + }; + + const auto star = historyCreditsList->lifetime().make_state( + Ui::GenerateStars(st::creditsTopupButton.height, 1)); + + Info::Statistics::AddCreditsHistoryList( + show, + _state.creditsStatusSlice, + historyCreditsList->entity(), + entryClicked, + premiumBot, + star, + true, + true); + Ui::AddSkip(container); + Ui::AddDivider(container); + Ui::AddSkip(container); + } if (channel) { //constexpr auto kMaxCPM = 50; // Debug. const auto requiredLevel = Data::LevelLimits(session) diff --git a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.h b/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.h index 40e0f3f2c..5979c5c37 100644 --- a/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.h +++ b/Telegram/SourceFiles/info/channel_statistics/earn/info_earn_widget.h @@ -7,8 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once -#include "data/data_channel_earn.h" #include "data/data_bot_earn.h" +#include "data/data_channel_earn.h" +#include "data/data_credits.h" #include "info/info_content_widget.h" namespace Info::ChannelEarn { @@ -31,6 +32,8 @@ public: struct SavedState final { Data::EarnStatistics currencyEarn; Data::CreditsEarnStatistics creditsEarn; + Data::CreditsStatusSlice creditsStatusSlice; + PeerId premiumBotId = PeerId(0); }; void setState(SavedState states);