Added support of api update to history lists in section of channel earn.

This commit is contained in:
23rd 2024-06-23 06:48:57 +03:00 committed by John Preston
parent b79c306bfe
commit a84ac933dd
2 changed files with 426 additions and 372 deletions

View file

@ -5214,6 +5214,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_channel_earn_chart_revenue" = "Ad revenue"; "lng_channel_earn_chart_revenue" = "Ad revenue";
"lng_channel_earn_chart_overriden_detail_currency" = "Revenue in TON"; "lng_channel_earn_chart_overriden_detail_currency" = "Revenue in TON";
"lng_channel_earn_chart_overriden_detail_usd" = "Revenue in USD"; "lng_channel_earn_chart_overriden_detail_usd" = "Revenue in USD";
"lng_channel_earn_currency_history" = "TON Transactions";
"lng_channel_earn_credits_history" = "Stars Transactions";
"lng_bot_earn_title" = "Stars Balance"; "lng_bot_earn_title" = "Stars Balance";
"lng_bot_earn_chart_revenue" = "Revenue"; "lng_bot_earn_chart_revenue" = "Revenue";

View file

@ -697,7 +697,11 @@ void InnerWidget::fill() {
const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>(
line, line,
st::channelEarnOverviewMajorLabel); st::channelEarnOverviewMajorLabel);
addEmojiToMajor(majorLabel, rpl::duplicate(currencyValue), {}, {}); addEmojiToMajor(
majorLabel,
rpl::duplicate(currencyValue),
{},
{});
const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>(
line, line,
rpl::duplicate(currencyValue) | rpl::map(MinorPart), rpl::duplicate(currencyValue) | rpl::map(MinorPart),
@ -912,414 +916,462 @@ void InnerWidget::fill() {
Ui::AddSkip(container); Ui::AddSkip(container);
} }
const auto hasCurrencyTab = !data.firstHistorySlice.list.empty(); const auto sectionIndex = container->lifetime().make_state<int>(0);
const auto hasCreditsTab = !_state.creditsStatusSlice.list.empty() const auto rebuildLists = [=](
&& _state.premiumBotId; const Memento::SavedState &data,
const auto hasOneTab = (hasCurrencyTab || hasCreditsTab) not_null<Ui::VerticalLayout*> listsContainer) {
&& (hasCurrencyTab != hasCreditsTab); const auto hasCurrencyTab
= !data.currencyEarn.firstHistorySlice.list.empty();
const auto hasCreditsTab = !data.creditsStatusSlice.list.empty()
&& data.premiumBotId;
const auto hasOneTab = (hasCurrencyTab || hasCreditsTab)
&& (hasCurrencyTab != hasCreditsTab);
const auto currencyTabText = tr::lng_channel_earn_currency_history( const auto currencyTabText = tr::lng_channel_earn_currency_history(
tr::now); tr::now);
const auto creditsTabText = tr::lng_channel_earn_credits_history(tr::now); const auto creditsTabText = tr::lng_channel_earn_credits_history(
tr::now);
const auto slider = container->add( const auto slider = listsContainer->add(
object_ptr<Ui::SlideWrap<Ui::CustomWidthSlider>>( object_ptr<Ui::SlideWrap<Ui::CustomWidthSlider>>(
container, listsContainer,
object_ptr<Ui::CustomWidthSlider>( object_ptr<Ui::CustomWidthSlider>(
container, listsContainer,
st::defaultTabsSlider)), st::defaultTabsSlider)),
st::boxRowPadding); st::boxRowPadding);
slider->toggle(!hasOneTab, anim::type::instant); 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) { if (hasCurrencyTab) {
AddHeader(container, tr::lng_channel_earn_history_title); slider->entity()->addSection(currencyTabText);
} else if (hasCreditsTab) {
AddHeader(container, tr::lng_channel_earn_credits_history);
slider->entity()->setActiveSectionFast(1);
} }
} if (hasCreditsTab) {
slider->entity()->addSection(creditsTabText);
const auto historyCurrencyList = container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
object_ptr<Ui::VerticalLayout>(container)));
const auto historyCreditsList = container->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
container,
object_ptr<Ui::VerticalLayout>(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 &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));
}
const auto historyList = historyCurrencyList->entity(); if (hasOneTab) {
const auto addHistoryEntry = [=]( if (hasCurrencyTab) {
const Data::EarnHistoryEntry &entry, AddHeader(listsContainer, tr::lng_channel_earn_history_title);
const tr::phrase<> &text) { } else if (hasCreditsTab) {
const auto wrap = historyList->add( AddHeader(
object_ptr<Ui::PaddingWrap<Ui::VerticalLayout>>( listsContainer,
historyList, tr::lng_channel_earn_credits_history);
object_ptr<Ui::VerticalLayout>(historyList), slider->entity()->setActiveSectionFast(1);
QMargins()));
const auto inner = wrap->entity();
inner->setAttribute(Qt::WA_TransparentForMouseEvents);
inner->add(object_ptr<Ui::FlatLabel>(
inner,
text(),
st::channelEarnSemiboldLabel));
const auto isIn = entry.type == Data::EarnHistoryEntry::Type::In;
const auto recipient = Ui::Text::Wrapped(
{ entry.provider },
EntityType::Code);
if (!recipient.text.isEmpty()) {
Ui::AddSkip(inner, st::channelEarnHistoryThreeSkip);
const auto label = inner->add(object_ptr<Ui::FlatLabel>(
inner,
rpl::single(recipient),
st::channelEarnHistoryRecipientLabel));
label->setBreakEverywhere(true);
label->setTryMakeSimilarLines(true);
Ui::AddSkip(inner, st::channelEarnHistoryThreeSkip);
} else {
Ui::AddSkip(inner, st::channelEarnHistoryTwoSkip);
} }
} else {
slider->entity()->setActiveSectionFast(*sectionIndex);
}
const auto isFailed = entry.status const auto tabCurrencyList = listsContainer->add(
== Data::EarnHistoryEntry::Status::Failed; object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
const auto isPending = entry.status listsContainer,
== Data::EarnHistoryEntry::Status::Pending; object_ptr<Ui::VerticalLayout>(listsContainer)));
const auto dateText = (!entry.dateTo.isNull() || isFailed) const auto tabCreditsList = listsContainer->add(
? (FormatDate(entry.date) object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
+ ' ' listsContainer,
+ QChar(8212) object_ptr<Ui::VerticalLayout>(listsContainer)));
+ ' '
+ (isFailed
? tr::lng_channel_earn_history_out_failed(tr::now)
: FormatDate(entry.dateTo)))
: isPending
? tr::lng_channel_earn_history_pending(tr::now)
: FormatDate(entry.date);
inner->add(object_ptr<Ui::FlatLabel>(
inner,
dateText,
st::channelEarnHistorySubLabel)
)->setTextColorOverride(isFailed
? std::make_optional<QColor>(st::menuIconAttentionColor->c)
: std::nullopt);
const auto color = (isIn rpl::single(slider->entity()->activeSection()) | rpl::then(
? st::boxTextFgGood slider->entity()->sectionActivated()
: st::menuIconAttentionColor)->c; ) | rpl::start_with_next([=](int index) {
const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>( if (index == 0) {
wrap, tabCurrencyList->toggle(true, anim::type::instant);
st::channelEarnHistoryMajorLabel); tabCreditsList->toggle(false, anim::type::instant);
addEmojiToMajor(majorLabel, rpl::single(entry.amount), isIn, {}); } else if (index == 1) {
majorLabel->setAttribute(Qt::WA_TransparentForMouseEvents); tabCurrencyList->toggle(false, anim::type::instant);
majorLabel->setTextColorOverride(color); tabCreditsList->toggle(true, anim::type::instant);
const auto minorText = MinorPart(entry.amount); }
const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>( *sectionIndex = index;
wrap, }, listsContainer->lifetime());
rpl::single(minorText),
st::channelEarnHistoryMinorLabel);
minorLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
minorLabel->setTextColorOverride(color);
const auto button = Ui::CreateChild<Ui::SettingsButton>(
wrap,
rpl::single(QString()));
Ui::ToggleChildrenVisibility(wrap, true);
const auto detailsBox = [=, amount = entry.amount, peer = _peer]( if (hasCurrencyTab) {
not_null<Ui::GenericBox*> box) { Ui::AddSkip(listsContainer);
box->addTopButton(
st::boxTitleClose,
[=] { box->closeBox(); });
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
const auto labels = box->addRow(
object_ptr<Ui::CenterWrap<Ui::RpWidget>>(
box,
object_ptr<Ui::RpWidget>(box)))->entity();
const auto historyList = tabCurrencyList->entity();
const auto addHistoryEntry = [=](
const Data::EarnHistoryEntry &entry,
const tr::phrase<> &text) {
const auto wrap = historyList->add(
object_ptr<Ui::PaddingWrap<Ui::VerticalLayout>>(
historyList,
object_ptr<Ui::VerticalLayout>(historyList),
QMargins()));
const auto inner = wrap->entity();
inner->setAttribute(Qt::WA_TransparentForMouseEvents);
inner->add(object_ptr<Ui::FlatLabel>(
inner,
text(),
st::channelEarnSemiboldLabel));
const auto isIn
= (entry.type == Data::EarnHistoryEntry::Type::In);
const auto recipient = Ui::Text::Wrapped(
{ entry.provider },
EntityType::Code);
if (!recipient.text.isEmpty()) {
Ui::AddSkip(inner, st::channelEarnHistoryThreeSkip);
const auto label = inner->add(object_ptr<Ui::FlatLabel>(
inner,
rpl::single(recipient),
st::channelEarnHistoryRecipientLabel));
label->setBreakEverywhere(true);
label->setTryMakeSimilarLines(true);
Ui::AddSkip(inner, st::channelEarnHistoryThreeSkip);
} else {
Ui::AddSkip(inner, st::channelEarnHistoryTwoSkip);
}
const auto isFailed = entry.status
== Data::EarnHistoryEntry::Status::Failed;
const auto isPending = entry.status
== Data::EarnHistoryEntry::Status::Pending;
const auto dateText = (!entry.dateTo.isNull() || isFailed)
? (FormatDate(entry.date)
+ ' '
+ QChar(8212)
+ ' '
+ (isFailed
? tr::lng_channel_earn_history_out_failed(tr::now)
: FormatDate(entry.dateTo)))
: isPending
? tr::lng_channel_earn_history_pending(tr::now)
: FormatDate(entry.date);
inner->add(object_ptr<Ui::FlatLabel>(
inner,
dateText,
st::channelEarnHistorySubLabel)
)->setTextColorOverride(isFailed
? std::make_optional<QColor>(
st::menuIconAttentionColor->c)
: std::nullopt);
const auto color = (isIn
? st::boxTextFgGood
: st::menuIconAttentionColor)->c;
const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>(
labels, wrap,
st::channelEarnOverviewMajorLabel); st::channelEarnHistoryMajorLabel);
addEmojiToMajor(majorLabel, rpl::single(amount), isIn, {}); addEmojiToMajor(
majorLabel,
rpl::single(entry.amount),
isIn,
{});
majorLabel->setAttribute(Qt::WA_TransparentForMouseEvents); majorLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
majorLabel->setTextColorOverride(color); majorLabel->setTextColorOverride(color);
const auto minorText = MinorPart(entry.amount);
const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>( const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>(
labels, wrap,
minorText, rpl::single(minorText),
st::channelEarnOverviewMinorLabel); st::channelEarnHistoryMinorLabel);
minorLabel->setAttribute(Qt::WA_TransparentForMouseEvents); minorLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
minorLabel->setTextColorOverride(color); minorLabel->setTextColorOverride(color);
rpl::combine( const auto button = Ui::CreateChild<Ui::SettingsButton>(
majorLabel->sizeValue(), wrap,
minorLabel->sizeValue() rpl::single(QString()));
) | rpl::start_with_next([=]( Ui::ToggleChildrenVisibility(wrap, true);
const QSize &majorSize,
const QSize &minorSize) {
labels->resize(
majorSize.width() + minorSize.width(),
majorSize.height());
majorLabel->moveToLeft(0, 0);
minorLabel->moveToRight(
0,
st::channelEarnOverviewMinorLabelSkip);
}, box->lifetime());
Ui::AddSkip(box->verticalLayout()); const auto detailsBox = [=, peer = _peer](
box->addRow(object_ptr<Ui::CenterWrap<>>( not_null<Ui::GenericBox*> box) {
box, box->addTopButton(
object_ptr<Ui::FlatLabel>( st::boxTitleClose,
box, [=] { box->closeBox(); });
dateText,
st::channelEarnHistorySubLabel)));
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
box->addRow(object_ptr<Ui::CenterWrap<>>(
box,
object_ptr<Ui::FlatLabel>(
box,
isIn
? tr::lng_channel_earn_history_in_about()
: tr::lng_channel_earn_history_out(),
st::channelEarnHistoryDescriptionLabel)));
Ui::AddSkip(box->verticalLayout());
if (isIn) {
Ui::AddSkip(box->verticalLayout()); Ui::AddSkip(box->verticalLayout());
} Ui::AddSkip(box->verticalLayout());
const auto labels = box->addRow(
if (!recipient.text.isEmpty()) { object_ptr<Ui::CenterWrap<Ui::RpWidget>>(
AddRecipient(box, recipient);
}
if (isIn) {
const auto peerBubble = box->addRow(
object_ptr<Ui::CenterWrap<>>(
box, box,
object_ptr<Ui::RpWidget>(box)))->entity(); object_ptr<Ui::RpWidget>(box)))->entity();
peerBubble->setAttribute(
const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>(
labels,
st::channelEarnOverviewMajorLabel);
addEmojiToMajor(
majorLabel,
rpl::single(entry.amount),
isIn,
{});
majorLabel->setAttribute(
Qt::WA_TransparentForMouseEvents); Qt::WA_TransparentForMouseEvents);
const auto left = Ui::CreateChild<Ui::UserpicButton>( majorLabel->setTextColorOverride(color);
peerBubble, const auto minorLabel = Ui::CreateChild<Ui::FlatLabel>(
peer, labels,
st::uploadUserpicButton); minorText,
const auto right = Ui::CreateChild<Ui::FlatLabel>( st::channelEarnOverviewMinorLabel);
peerBubble, minorLabel->setAttribute(
Info::Profile::NameValue(peer), Qt::WA_TransparentForMouseEvents);
st::channelEarnSemiboldLabel); minorLabel->setTextColorOverride(color);
rpl::combine( rpl::combine(
left->sizeValue(), majorLabel->sizeValue(),
right->sizeValue() minorLabel->sizeValue()
) | rpl::start_with_next([=]( ) | rpl::start_with_next([=](
const QSize &leftSize, const QSize &majorSize,
const QSize &rightSize) { const QSize &minorSize) {
const auto padding = QMargins( labels->resize(
st::chatGiveawayPeerPadding.left() * 2, majorSize.width() + minorSize.width(),
st::chatGiveawayPeerPadding.top(), majorSize.height());
st::chatGiveawayPeerPadding.right(), majorLabel->moveToLeft(0, 0);
st::chatGiveawayPeerPadding.bottom()); minorLabel->moveToRight(
peerBubble->resize( 0,
leftSize.width() st::channelEarnOverviewMinorLabelSkip);
+ rightSize.width() }, box->lifetime());
+ rect::m::sum::h(padding),
leftSize.height()); Ui::AddSkip(box->verticalLayout());
left->moveToLeft(0, 0); box->addRow(object_ptr<Ui::CenterWrap<>>(
right->moveToRight(padding.right(), padding.top()); box,
const auto maxRightSize = box->width() object_ptr<Ui::FlatLabel>(
- rect::m::sum::h(st::boxRowPadding) box,
- rect::m::sum::h(padding) dateText,
- leftSize.width(); st::channelEarnHistorySubLabel)));
if (rightSize.width() > maxRightSize) { Ui::AddSkip(box->verticalLayout());
right->resizeToWidth(maxRightSize); Ui::AddSkip(box->verticalLayout());
} Ui::AddSkip(box->verticalLayout());
}, peerBubble->lifetime()); box->addRow(object_ptr<Ui::CenterWrap<>>(
peerBubble->paintRequest( box,
) | rpl::start_with_next([=] { object_ptr<Ui::FlatLabel>(
auto p = QPainter(peerBubble); box,
auto hq = PainterHighQualityEnabler(p); isIn
p.setPen(Qt::NoPen); ? tr::lng_channel_earn_history_in_about()
p.setBrush(st::windowBgOver); : tr::lng_channel_earn_history_out(),
const auto rect = peerBubble->rect(); st::channelEarnHistoryDescriptionLabel)));
const auto radius = rect.height() / 2; Ui::AddSkip(box->verticalLayout());
p.drawRoundedRect(rect, radius, radius); if (isIn) {
}, peerBubble->lifetime()); Ui::AddSkip(box->verticalLayout());
}
{
const auto &st = st::premiumPreviewDoubledLimitsBox;
box->setStyle(st);
auto button = object_ptr<Ui::RoundButton>(
container,
(!entry.successLink.isEmpty())
? tr::lng_channel_earn_history_out_button()
: tr::lng_box_ok(),
st::defaultActiveButton);
button->resizeToWidth(box->width()
- st.buttonPadding.left()
- st.buttonPadding.left());
if (!entry.successLink.isEmpty()) {
button->setAcceptBoth();
button->addClickHandler([=](Qt::MouseButton button) {
if (button == Qt::LeftButton) {
UrlClickHandler::Open(entry.successLink);
} else if (button == Qt::RightButton) {
ShowMenu(box, entry.successLink);
}
});
} else {
button->setClickedCallback([=] { box->closeBox(); });
} }
box->addButton(std::move(button));
}
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
box->addButton(tr::lng_box_ok(), [=] { box->closeBox(); });
};
button->setClickedCallback([=] { if (!recipient.text.isEmpty()) {
_show->showBox(Box(detailsBox)); AddRecipient(box, recipient);
}); }
wrap->geometryValue( if (isIn) {
) | rpl::start_with_next([=](const QRect &g) { const auto peerBubble = box->addRow(
const auto &padding = st::boxRowPadding; object_ptr<Ui::CenterWrap<>>(
const auto majorTop = (g.height() - majorLabel->height()) / 2; box,
minorLabel->moveToRight( object_ptr<Ui::RpWidget>(box)))->entity();
padding.right(), peerBubble->setAttribute(
majorTop + st::channelEarnHistoryMinorLabelSkip); Qt::WA_TransparentForMouseEvents);
majorLabel->moveToRight( const auto left = Ui::CreateChild<Ui::UserpicButton>(
padding.right() + minorLabel->width(), peerBubble,
majorTop); peer,
const auto rightWrapPadding = rect::m::sum::h(padding) st::uploadUserpicButton);
+ minorLabel->width() const auto right = Ui::CreateChild<Ui::FlatLabel>(
+ majorLabel->width(); peerBubble,
wrap->setPadding( Info::Profile::NameValue(peer),
st::channelEarnHistoryOuter st::channelEarnSemiboldLabel);
rpl::combine(
left->sizeValue(),
right->sizeValue()
) | rpl::start_with_next([=](
const QSize &leftSize,
const QSize &rightSize) {
const auto padding = QMargins(
st::chatGiveawayPeerPadding.left() * 2,
st::chatGiveawayPeerPadding.top(),
st::chatGiveawayPeerPadding.right(),
st::chatGiveawayPeerPadding.bottom());
peerBubble->resize(
leftSize.width()
+ rightSize.width()
+ rect::m::sum::h(padding),
leftSize.height());
left->moveToLeft(0, 0);
right->moveToRight(
padding.right(),
padding.top());
const auto maxRightSize = box->width()
- rect::m::sum::h(st::boxRowPadding)
- rect::m::sum::h(padding)
- leftSize.width();
if (rightSize.width() > maxRightSize) {
right->resizeToWidth(maxRightSize);
}
}, peerBubble->lifetime());
peerBubble->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(peerBubble);
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(st::windowBgOver);
const auto rect = peerBubble->rect();
const auto radius = rect.height() / 2;
p.drawRoundedRect(rect, radius, radius);
}, peerBubble->lifetime());
}
const auto closeBox = [=] { box->closeBox(); };
{
const auto &st = st::premiumPreviewDoubledLimitsBox;
box->setStyle(st);
auto button = object_ptr<Ui::RoundButton>(
box,
(!entry.successLink.isEmpty())
? tr::lng_channel_earn_history_out_button()
: tr::lng_box_ok(),
st::defaultActiveButton);
button->resizeToWidth(box->width()
- st.buttonPadding.left()
- st.buttonPadding.left());
if (!entry.successLink.isEmpty()) {
button->setAcceptBoth();
button->addClickHandler([=](
Qt::MouseButton button) {
if (button == Qt::LeftButton) {
UrlClickHandler::Open(entry.successLink);
} else if (button == Qt::RightButton) {
ShowMenu(box, entry.successLink);
}
});
} else {
button->setClickedCallback(closeBox);
}
box->addButton(std::move(button));
}
Ui::AddSkip(box->verticalLayout());
Ui::AddSkip(box->verticalLayout());
box->addButton(tr::lng_box_ok(), closeBox);
};
button->setClickedCallback([=] {
_show->showBox(Box(detailsBox));
});
wrap->geometryValue(
) | rpl::start_with_next([=](const QRect &g) {
const auto &padding = st::boxRowPadding;
const auto majorTop = (g.height() - majorLabel->height())
/ 2;
minorLabel->moveToRight(
padding.right(),
majorTop + st::channelEarnHistoryMinorLabelSkip);
majorLabel->moveToRight(
padding.right() + minorLabel->width(),
majorTop);
const auto rightWrapPadding = rect::m::sum::h(padding)
+ minorLabel->width()
+ majorLabel->width();
wrap->setPadding(st::channelEarnHistoryOuter
+ QMargins(padding.left(), 0, rightWrapPadding, 0)); + QMargins(padding.left(), 0, rightWrapPadding, 0));
button->resize(g.size()); button->resize(g.size());
button->lower(); button->lower();
}, wrap->lifetime()); }, wrap->lifetime());
}; };
const auto handleSlice = [=](const Data::EarnHistorySlice &slice) { const auto handleSlice = [=](const Data::EarnHistorySlice &s) {
for (const auto &entry : slice.list) { using Type = Data::EarnHistoryEntry::Type;
addHistoryEntry( for (const auto &entry : s.list) {
entry, addHistoryEntry(
(entry.type == Data::EarnHistoryEntry::Type::In) entry,
? tr::lng_channel_earn_history_in (entry.type == Type::In)
: (entry.type == Data::EarnHistoryEntry::Type::Return) ? tr::lng_channel_earn_history_in
? tr::lng_channel_earn_history_return : (entry.type == Type::Return)
: tr::lng_channel_earn_history_out); ? tr::lng_channel_earn_history_return
} : tr::lng_channel_earn_history_out);
historyList->resizeToWidth(container->width());
};
handleSlice(data.firstHistorySlice);
if (!data.firstHistorySlice.allLoaded) {
struct ShowMoreState final {
ShowMoreState(not_null<ChannelData*> channel)
: api(channel) {
} }
Api::ChannelEarnStatistics api; historyList->resizeToWidth(listsContainer->width());
bool loading = false;
Data::EarnHistorySlice::OffsetToken token;
rpl::variable<int> showed = 0;
}; };
const auto state = lifetime().make_state<ShowMoreState>(channel); const auto &firstSlice = data.currencyEarn.firstHistorySlice;
state->token = data.firstHistorySlice.token; handleSlice(firstSlice);
state->showed = data.firstHistorySlice.list.size(); if (!firstSlice.allLoaded) {
const auto max = data.firstHistorySlice.total; struct ShowMoreState final {
const auto wrap = container->add( ShowMoreState(not_null<ChannelData*> channel)
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>( : api(channel) {
container, }
object_ptr<Ui::SettingsButton>( Api::ChannelEarnStatistics api;
container, bool loading = false;
tr::lng_channel_earn_history_show_more( Data::EarnHistorySlice::OffsetToken token;
lt_count, rpl::variable<int> showed = 0;
state->showed.value( };
) | rpl::map( const auto state
max - rpl::mappers::_1 = lifetime().make_state<ShowMoreState>(channel);
) | tr::to_count()), state->token = firstSlice.token;
st::statisticsShowMoreButton))); state->showed = firstSlice.list.size();
const auto button = wrap->entity(); const auto max = firstSlice.total;
AddArrow(button); const auto wrap = listsContainer->add(
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
listsContainer,
object_ptr<Ui::SettingsButton>(
listsContainer,
tr::lng_channel_earn_history_show_more(
lt_count,
state->showed.value(
) | rpl::map(
max - rpl::mappers::_1
) | tr::to_count()),
st::statisticsShowMoreButton)));
const auto button = wrap->entity();
AddArrow(button);
wrap->toggle(true, anim::type::instant); wrap->toggle(true, anim::type::instant);
const auto handleReceived = [=](Data::EarnHistorySlice slice) { const auto handleReceived = [=](
state->loading = false; Data::EarnHistorySlice slice) {
handleSlice(slice); state->loading = false;
wrap->toggle(!slice.allLoaded, anim::type::instant); handleSlice(slice);
state->token = slice.token; wrap->toggle(!slice.allLoaded, anim::type::instant);
state->showed = state->showed.current() + slice.list.size(); state->token = slice.token;
}; state->showed = state->showed.current()
button->setClickedCallback([=] { + slice.list.size();
if (!state->loading) { };
button->setClickedCallback([=] {
if (state->loading) {
return;
}
state->loading = true; state->loading = true;
state->api.requestHistory(state->token, handleReceived); state->api.requestHistory(state->token, handleReceived);
} });
}); }
} }
Ui::AddSkip(container); if (hasCreditsTab) {
Ui::AddDivider(container); const auto controller = _controller->parentController();
Ui::AddSkip(container); const auto show = controller->uiShow();
} const auto premiumBot = _peer->owner().peer(data.premiumBotId);
if (hasCreditsTab) { const auto entryClicked = [=](
const auto controller = _controller->parentController(); const Data::CreditsHistoryEntry &e) {
const auto show = controller->uiShow(); show->show(Box(
const auto premiumBot = _peer->owner().peer(_state.premiumBotId); ::Settings::ReceiptCreditsBox,
const auto entryClicked = [=](const Data::CreditsHistoryEntry &e) { controller,
show->show(Box( premiumBot.get(),
::Settings::ReceiptCreditsBox, e));
controller, };
premiumBot.get(),
e));
};
const auto star = historyCreditsList->lifetime().make_state<QImage>( const auto star = tabCreditsList->lifetime().make_state<QImage>(
Ui::GenerateStars(st::creditsTopupButton.height, 1)); Ui::GenerateStars(st::creditsTopupButton.height, 1));
Info::Statistics::AddCreditsHistoryList(
show,
data.creditsStatusSlice,
tabCreditsList->entity(),
entryClicked,
premiumBot,
star,
true,
true);
}
if (hasCurrencyTab || hasCreditsTab) {
Ui::AddSkip(listsContainer);
Ui::AddDivider(listsContainer);
Ui::AddSkip(listsContainer);
}
};
const auto historyContainer = container->add(
object_ptr<Ui::VerticalLayout>(container));
rpl::single(rpl::empty) | rpl::then(
_stateUpdated.events()
) | rpl::start_with_next([=] {
const auto listsContainer = historyContainer->add(
object_ptr<Ui::VerticalLayout>(container));
rebuildLists(_state, listsContainer);
while (historyContainer->count() > 1) {
delete historyContainer->widgetAt(0);
}
}, historyContainer->lifetime());
Info::Statistics::AddCreditsHistoryList(
show,
_state.creditsStatusSlice,
historyCreditsList->entity(),
entryClicked,
premiumBot,
star,
true,
true);
Ui::AddSkip(container);
Ui::AddDivider(container);
Ui::AddSkip(container);
}
if (channel) { if (channel) {
//constexpr auto kMaxCPM = 50; // Debug. //constexpr auto kMaxCPM = 50; // Debug.
const auto requiredLevel = Data::LevelLimits(session) const auto requiredLevel = Data::LevelLimits(session)