Added initial support of channel earn data in appropriate info section.

This commit is contained in:
23rd 2024-03-24 21:41:09 +03:00 committed by John Preston
parent a278aa0f89
commit a14c0f5253
3 changed files with 77 additions and 84 deletions

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "info/channel_statistics/earn/info_earn_inner_widget.h" #include "info/channel_statistics/earn/info_earn_inner_widget.h"
#include "api/api_statistics.h"
#include "base/random.h" #include "base/random.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "boxes/peers/edit_peer_color_box.h" // AddLevelBadge. #include "boxes/peers/edit_peer_color_box.h" // AddLevelBadge.
@ -15,8 +16,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer.h" #include "data/data_peer.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "info/channel_statistics/earn/info_earn_widget.h"
#include "info/info_controller.h" #include "info/info_controller.h"
#include "info/profile/info_profile_values.h" // Info::Profile::NameValue. #include "info/profile/info_profile_values.h" // Info::Profile::NameValue.
#include "info/statistics/info_statistics_inner_widget.h" // FillLoading.
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "ui/controls/userpic_button.h" #include "ui/controls/userpic_button.h"
@ -37,12 +40,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_settings.h" #include "styles/style_settings.h"
#include "styles/style_statistics.h" #include "styles/style_statistics.h"
#include <QUuid>
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
namespace Info::ChannelEarn { namespace Info::ChannelEarn {
namespace { namespace {
constexpr auto kMinorPartLength = 9;
void AddHeader( void AddHeader(
not_null<Ui::VerticalLayout*> content, not_null<Ui::VerticalLayout*> content,
tr::phrase<> text) { tr::phrase<> text) {
@ -105,14 +109,13 @@ void AddRecipient(not_null<Ui::GenericBox*> box, const TextWithEntities &t) {
return emoji; return emoji;
} }
[[nodiscard]] QString FormatDate(TimeId date) { [[nodiscard]] QString FormatDate(const QDateTime &date) {
const auto parsedDate = base::unixtime::parse(date);
return tr::lng_group_call_starts_short_date( return tr::lng_group_call_starts_short_date(
tr::now, tr::now,
lt_date, lt_date,
langDayOfMonth(parsedDate.date()), langDayOfMonth(date.date()),
lt_time, lt_time,
QLocale().toString(parsedDate.time(), QLocale::ShortFormat)); QLocale().toString(date.time(), QLocale::ShortFormat));
} }
} // namespace } // namespace
@ -128,15 +131,34 @@ InnerWidget::InnerWidget(
} }
void InnerWidget::load() { void InnerWidget::load() {
const auto api = lifetime().make_state<Api::EarnStatistics>(
_peer->asChannel());
Info::Statistics::FillLoading(
this,
_loaded.events_starting_with(false) | rpl::map(!rpl::mappers::_1),
_showFinished.events());
_showFinished.events(
) | rpl::take(1) | rpl::start_with_next([=] {
api->request(
) | rpl::start_with_error_done([](const QString &error) {
}, [=] {
_state = api->data();
_loaded.fire(true);
fill();
}, lifetime());
}, lifetime());
} }
void InnerWidget::fill() { void InnerWidget::fill() {
const auto container = this; const auto container = this;
const auto &data = _state;
constexpr auto kMinus = QChar(0x2212); constexpr auto kMinus = QChar(0x2212);
constexpr auto kApproximately = QChar(0x2248); constexpr auto kApproximately = QChar(0x2248);
const auto currency = u"TON"_q; const auto currency = u"TON"_q;
const auto multiplier = 3.8; // Debug. const auto multiplier = data.usdRate;
const auto session = &_peer->session(); const auto session = &_peer->session();
const auto makeContext = [=](not_null<Ui::FlatLabel*> l) { const auto makeContext = [=](not_null<Ui::FlatLabel*> l) {
@ -150,7 +172,7 @@ void InnerWidget::fill() {
float64 value) { float64 value) {
auto emoji = EmojiCurrency(session); auto emoji = EmojiCurrency(session);
label->setMarkedText( label->setMarkedText(
emoji.append(' ').append(QString::number(int64(value))), emoji.append(' ').append(QString::number(uint64(value))),
makeContext(label)); makeContext(label));
}; };
@ -334,10 +356,9 @@ void InnerWidget::fill() {
AddHeader(container, tr::lng_channel_earn_overview_title); AddHeader(container, tr::lng_channel_earn_overview_title);
Ui::AddSkip(container, st::channelEarnOverviewTitleSkip); Ui::AddSkip(container, st::channelEarnOverviewTitleSkip);
const auto addOverviewEntry = [&]( const auto addOverview = [&](
float64 value, float64 value,
const tr::phrase<> &text) { const tr::phrase<> &text) {
value = base::RandomIndex(1000000) / 1000.; // Debug.
const auto line = container->add( const auto line = container->add(
Ui::CreateSkipWidget(container, 0), Ui::CreateSkipWidget(container, 0),
st::boxRowPadding); st::boxRowPadding);
@ -347,7 +368,7 @@ void InnerWidget::fill() {
addEmojiToMajor(majorLabel, value); addEmojiToMajor(majorLabel, value);
const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>(
line, line,
QString::number(value - int64(value)).mid(1), QString::number(value - uint64(value)).mid(1),
st::channelEarnOverviewMinorLabel); st::channelEarnOverviewMinorLabel);
const auto secondMinorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto secondMinorLabel = Ui::CreateChild<Ui::FlatLabel>(
line, line,
@ -371,6 +392,7 @@ void InnerWidget::fill() {
+ st::channelEarnOverviewSubMinorLabelPos.x(), + st::channelEarnOverviewSubMinorLabelPos.x(),
st::channelEarnOverviewSubMinorLabelPos.y()); st::channelEarnOverviewSubMinorLabelPos.y());
}, minorLabel->lifetime()); }, minorLabel->lifetime());
Ui::ToggleChildrenVisibility(line, true);
Ui::AddSkip(container); Ui::AddSkip(container);
const auto sub = container->add( const auto sub = container->add(
@ -381,20 +403,20 @@ void InnerWidget::fill() {
st::boxRowPadding); st::boxRowPadding);
sub->setTextColorOverride(st::windowSubTextFg->c); sub->setTextColorOverride(st::windowSubTextFg->c);
}; };
addOverviewEntry(0, tr::lng_channel_earn_available); addOverview(data.availableBalance, tr::lng_channel_earn_available);
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddSkip(container); Ui::AddSkip(container);
addOverviewEntry(0, tr::lng_channel_earn_reward); addOverview(data.currentBalance, tr::lng_channel_earn_reward);
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddSkip(container); Ui::AddSkip(container);
addOverviewEntry(0, tr::lng_channel_earn_total); addOverview(data.overallRevenue, tr::lng_channel_earn_total);
Ui::AddSkip(container); Ui::AddSkip(container);
} }
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddDivider(container); Ui::AddDivider(container);
Ui::AddSkip(container); Ui::AddSkip(container);
{ {
const auto value = 54.12; // Debug. const auto value = data.availableBalance;
Ui::AddSkip(container); Ui::AddSkip(container);
AddHeader(container, tr::lng_channel_earn_balance_title); AddHeader(container, tr::lng_channel_earn_balance_title);
Ui::AddSkip(container); Ui::AddSkip(container);
@ -411,7 +433,7 @@ void InnerWidget::fill() {
majorLabel->setAttribute(Qt::WA_TransparentForMouseEvents); majorLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>(
labels, labels,
QString::number(value - int64(value)).mid(1), QString::number(value - uint64(value)).mid(1),
st::channelEarnBalanceMinorLabel); st::channelEarnBalanceMinorLabel);
minorLabel->setAttribute(Qt::WA_TransparentForMouseEvents); minorLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
rpl::combine( rpl::combine(
@ -428,6 +450,7 @@ void InnerWidget::fill() {
0, 0,
st::channelEarnBalanceMinorLabelSkip); st::channelEarnBalanceMinorLabelSkip);
}, labels->lifetime()); }, labels->lifetime());
Ui::ToggleChildrenVisibility(labels, true);
Ui::AddSkip(container); Ui::AddSkip(container);
container->add( container->add(
@ -532,6 +555,7 @@ void InnerWidget::fill() {
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); }); box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
})); }));
}); });
Ui::ToggleChildrenVisibility(button, true);
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddSkip(container); Ui::AddSkip(container);
@ -545,16 +569,8 @@ void InnerWidget::fill() {
AddHeader(container, tr::lng_channel_earn_history_title); AddHeader(container, tr::lng_channel_earn_history_title);
Ui::AddSkip(container); Ui::AddSkip(container);
struct HistoryEntry final {
TimeId from = 0;
TimeId to = 0;
float64 value = 0;
QString recipient;
bool in = false;
};
const auto addHistoryEntry = [&]( const auto addHistoryEntry = [&](
const HistoryEntry &entry, const Data::EarnHistoryEntry &entry,
const tr::phrase<> &text) { const tr::phrase<> &text) {
const auto wrap = container->add( const auto wrap = container->add(
object_ptr<Ui::PaddingWrap<Ui::VerticalLayout>>( object_ptr<Ui::PaddingWrap<Ui::VerticalLayout>>(
@ -568,10 +584,11 @@ void InnerWidget::fill() {
text(), text(),
st::channelEarnSemiboldLabel)); st::channelEarnSemiboldLabel));
const auto isIn = entry.type == Data::EarnHistoryEntry::Type::In;
const auto recipient = Ui::Text::Wrapped( const auto recipient = Ui::Text::Wrapped(
{ entry.recipient }, { entry.provider },
EntityType::Code); EntityType::Code);
if (!entry.recipient.isEmpty()) { if (!recipient.text.isEmpty()) {
Ui::AddSkip(inner, st::channelEarnHistoryThreeSkip); Ui::AddSkip(inner, st::channelEarnHistoryThreeSkip);
const auto label = inner->add(object_ptr<Ui::FlatLabel>( const auto label = inner->add(object_ptr<Ui::FlatLabel>(
inner, inner,
@ -584,23 +601,23 @@ void InnerWidget::fill() {
Ui::AddSkip(inner, st::channelEarnHistoryTwoSkip); Ui::AddSkip(inner, st::channelEarnHistoryTwoSkip);
} }
const auto dateText = entry.to const auto dateText = !entry.dateTo.isNull()
? (FormatDate(entry.from) ? (FormatDate(entry.date)
+ ' ' + ' '
+ QChar(8212) + QChar(8212)
+ ' ' + ' '
+ FormatDate(entry.to)) + FormatDate(entry.dateTo))
: FormatDate(entry.from); : FormatDate(entry.date);
inner->add(object_ptr<Ui::FlatLabel>( inner->add(object_ptr<Ui::FlatLabel>(
inner, inner,
dateText, dateText,
st::channelEarnHistorySubLabel)); st::channelEarnHistorySubLabel));
const auto color = (entry.in const auto color = (isIn
? st::boxTextFgGood ? st::boxTextFgGood
: st::menuIconAttentionColor)->c; : st::menuIconAttentionColor)->c;
const auto majorText = (entry.in ? '+' : kMinus) const auto majorText = (isIn ? '+' : kMinus)
+ QString::number(int64(entry.value)); + QString::number(uint64(entry.amount));
const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>(
wrap, wrap,
majorText, majorText,
@ -608,7 +625,7 @@ void InnerWidget::fill() {
majorLabel->setAttribute(Qt::WA_TransparentForMouseEvents); majorLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
majorLabel->setTextColorOverride(color); majorLabel->setTextColorOverride(color);
const auto minorText = const auto minorText =
QString::number(entry.value - int64(entry.value)).mid(1) QString::number(entry.amount - uint64(entry.amount)).mid(1)
+ ' ' + ' '
+ currency; + currency;
const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>(
@ -620,6 +637,7 @@ void InnerWidget::fill() {
const auto button = Ui::CreateChild<Ui::SettingsButton>( const auto button = Ui::CreateChild<Ui::SettingsButton>(
wrap, wrap,
rpl::single(QString())); rpl::single(QString()));
Ui::ToggleChildrenVisibility(wrap, true);
const auto detailsBox = [=, peer = _peer]( const auto detailsBox = [=, peer = _peer](
not_null<Ui::GenericBox*> box) { not_null<Ui::GenericBox*> box) {
@ -671,19 +689,19 @@ void InnerWidget::fill() {
box, box,
object_ptr<Ui::FlatLabel>( object_ptr<Ui::FlatLabel>(
box, box,
entry.in isIn
? tr::lng_channel_earn_history_in_about() ? tr::lng_channel_earn_history_in_about()
: tr::lng_channel_earn_history_out(), : tr::lng_channel_earn_history_out(),
st::channelEarnHistoryMajorLabel))); st::channelEarnHistoryMajorLabel)));
Ui::AddSkip(box->verticalLayout()); Ui::AddSkip(box->verticalLayout());
if (entry.in) { if (isIn) {
Ui::AddSkip(box->verticalLayout()); Ui::AddSkip(box->verticalLayout());
} }
if (!entry.recipient.isEmpty()) { if (!recipient.text.isEmpty()) {
AddRecipient(box, recipient); AddRecipient(box, recipient);
} }
if (entry.in) { if (isIn) {
const auto peerBubble = box->addRow( const auto peerBubble = box->addRow(
object_ptr<Ui::CenterWrap<>>( object_ptr<Ui::CenterWrap<>>(
box, box,
@ -763,41 +781,13 @@ void InnerWidget::fill() {
button->lower(); button->lower();
}, wrap->lifetime()); }, wrap->lifetime());
}; };
const auto randomRecipient = [&] { // Debug. for (const auto &entry : data.firstHistorySlice.list) {
const auto format = QUuid::StringFormat::Id128; addHistoryEntry(
return (QUuid::createUuid().toString(format) entry,
+ QUuid::createUuid().toString(format)).mid(0, 48); (entry.type == Data::EarnHistoryEntry::Type::In)
}; ? tr::lng_channel_earn_history_in
addHistoryEntry( : tr::lng_channel_earn_history_out);
{ }
.from = base::unixtime::now(),
.to = base::unixtime::now() - base::RandomIndex(200000),
.value = base::RandomIndex(1000000) / 1000.,
.in = true,
},
tr::lng_channel_earn_history_in);
addHistoryEntry(
{
.from = base::unixtime::now(),
.recipient = randomRecipient(),
.value = base::RandomIndex(1000000) / 1000.,
},
tr::lng_channel_earn_history_out);
addHistoryEntry(
{
.from = base::unixtime::now(),
.to = base::unixtime::now() - base::RandomIndex(200000),
.value = base::RandomIndex(1000000) / 1000.,
.in = true,
},
tr::lng_channel_earn_history_in);
addHistoryEntry(
{
.from = base::unixtime::now(),
.recipient = randomRecipient(),
.value = base::RandomIndex(1000000) / 1000.,
},
tr::lng_channel_earn_history_out);
} }
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddDivider(container); Ui::AddDivider(container);
@ -916,21 +906,25 @@ void InnerWidget::fill() {
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::AddDividerText(container, tr::lng_channel_earn_off_about()); Ui::AddDividerText(container, tr::lng_channel_earn_off_about());
Ui::ToggleChildrenVisibility(line, true);
} }
Ui::AddSkip(container); Ui::AddSkip(container);
Ui::ToggleChildrenVisibility(container, true);
Ui::RpWidget::resizeToWidth(width());
} }
void InnerWidget::saveState(not_null<Memento*> memento) { void InnerWidget::saveState(not_null<Memento*> memento) {
// memento->setState(base::take(_state)); memento->setState(base::take(_state));
} }
void InnerWidget::restoreState(not_null<Memento*> memento) { void InnerWidget::restoreState(not_null<Memento*> memento) {
// _state = memento->state(); _state = memento->state();
// if (!_state.link.isEmpty()) { if (_state) {
fill(); fill();
// } else { } else {
// load(); load();
// } }
Ui::RpWidget::resizeToWidth(width()); Ui::RpWidget::resizeToWidth(width());
} }

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "data/data_statistics.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
@ -51,7 +52,7 @@ private:
not_null<PeerData*> _peer; not_null<PeerData*> _peer;
std::shared_ptr<Ui::Show> _show; std::shared_ptr<Ui::Show> _show;
// Data::ChannelEarnStatus _state; Data::EarnStatistics _state;
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests; rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
rpl::event_stream<ShowRequest> _showRequests; rpl::event_stream<ShowRequest> _showRequests;

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
#include "data/data_statistics.h"
#include "info/info_content_widget.h" #include "info/info_content_widget.h"
namespace Info::ChannelEarn { namespace Info::ChannelEarn {
@ -26,10 +27,7 @@ public:
Section section() const override; Section section() const override;
struct ChannelEarnStatus{ using SavedState = Data::EarnStatistics;
};
using SavedState = ChannelEarnStatus;
void setState(SavedState states); void setState(SavedState states);
[[nodiscard]] SavedState state(); [[nodiscard]] SavedState state();