Added ability to inspect earn balance from channel info.

This commit is contained in:
23rd 2025-05-05 02:15:17 +03:00
parent 14328eb601
commit a8afc62db7
8 changed files with 119 additions and 54 deletions

View file

@ -7,7 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "data/data_channel.h" #include "data/data_channel.h"
#include "api/api_credits.h"
#include "api/api_global_privacy.h" #include "api/api_global_privacy.h"
#include "api/api_statistics.h"
#include "data/components/credits.h" #include "data/components/credits.h"
#include "data/data_changes.h" #include "data/data_changes.h"
#include "data/data_channel_admins.h" #include "data/data_channel_admins.h"
@ -1357,6 +1359,34 @@ void ApplyChannelUpdate(
channel->setWallPaper({}); channel->setWallPaper({});
} }
if (channel->flags() & Flag::CanViewRevenue) {
const auto id = channel->id;
const auto weak = base::make_weak(&channel->session());
const auto creditsLoadLifetime = std::make_shared<rpl::lifetime>();
const auto creditsLoad
= creditsLoadLifetime->make_state<Api::CreditsStatus>(channel);
creditsLoad->request({}, [=](Data::CreditsStatusSlice slice) {
if (const auto strong = weak.get()) {
strong->credits().apply(id, slice.balance);
creditsLoadLifetime->destroy();
}
});
const auto currencyLoadLifetime = std::make_shared<rpl::lifetime>();
const auto currencyLoad
= currencyLoadLifetime->make_state<Api::EarnStatistics>(channel);
currencyLoad->request(
) | rpl::start_with_error_done([=](const QString &error) {
currencyLoadLifetime->destroy();
}, [=] {
if (const auto strong = weak.get()) {
strong->credits().applyCurrency(
id,
currencyLoad->data().currentBalance);
currencyLoadLifetime->destroy();
}
}, *currencyLoadLifetime);
}
// For clearUpTill() call. // For clearUpTill() call.
channel->owner().sendHistoryChangeNotifications(); channel->owner().sendHistoryChangeNotifications();
} }

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/channel_statistics/earn/earn_icons.h" #include "info/channel_statistics/earn/earn_icons.h"
#include "ui/effects/premium_graphics.h" #include "ui/effects/premium_graphics.h"
#include "ui/text/text_custom_emoji.h"
#include "ui/rect.h" #include "ui/rect.h"
#include "styles/style_menu_icons.h" #include "styles/style_menu_icons.h"
#include "styles/style_widgets.h" #include "styles/style_widgets.h"
@ -136,4 +137,12 @@ QImage MenuIconCredits() {
return image; return image;
} }
std::unique_ptr<Ui::Text::CustomEmoji> MakeCurrencyIconEmoji(
const style::font &font,
const QColor &c) {
return std::make_unique<Ui::Text::StaticCustomEmoji>(
IconCurrencyColored(font, c),
u"currency_icon:%1:%2"_q.arg(font->height).arg(c.name()));
}
} // namespace Ui::Earn } // namespace Ui::Earn

View file

@ -7,6 +7,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#pragma once #pragma once
namespace Ui::Text {
class CustomEmoji;
} // namespace Ui::Text
namespace Ui::Earn { namespace Ui::Earn {
[[nodiscard]] QImage IconCurrencyColored( [[nodiscard]] QImage IconCurrencyColored(
@ -17,4 +21,8 @@ namespace Ui::Earn {
[[nodiscard]] QImage MenuIconCurrency(const QSize &size); [[nodiscard]] QImage MenuIconCurrency(const QSize &size);
[[nodiscard]] QImage MenuIconCredits(); [[nodiscard]] QImage MenuIconCredits();
std::unique_ptr<Ui::Text::CustomEmoji> MakeCurrencyIconEmoji(
const style::font &font,
const QColor &c);
} // namespace Ui::Earn } // namespace Ui::Earn

View file

@ -70,6 +70,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/boxes/peer_qr_box.h" #include "ui/boxes/peer_qr_box.h"
#include "ui/boxes/report_box_graphics.h" #include "ui/boxes/report_box_graphics.h"
#include "ui/controls/userpic_button.h" #include "ui/controls/userpic_button.h"
#include "ui/effects/credits_graphics.h"
#include "ui/effects/toggle_arrow.h" #include "ui/effects/toggle_arrow.h"
#include "ui/painter.h" #include "ui/painter.h"
#include "ui/rect.h" #include "ui/rect.h"
@ -2832,6 +2833,68 @@ object_ptr<Ui::RpWidget> SetupChannelMembersAndManage(
st::menuIconAdmin, st::menuIconAdmin,
st::infoChannelAdminsIconPosition); st::infoChannelAdminsIconPosition);
if (channel->session().credits().balanceCurrency(channel->id) > 0
|| channel->session().credits().balance(channel->id)) {
const auto balanceWrap = result->entity()->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
result->entity(),
object_ptr<Ui::VerticalLayout>(result->entity())));
balanceWrap->toggle(true, anim::type::instant);
const auto &st = st::infoSharedMediaButton;
auto customEmojiFactory = [height = st.style.font->height,
font = st.rightLabel.style.font,
color = st.rightLabel.textFg->c](
QStringView data,
const Ui::Text::MarkedContext &context
) -> std::unique_ptr<Ui::Text::CustomEmoji> {
return (data == Ui::kCreditsCurrency)
? Ui::MakeCreditsIconEmoji(height, 1)
: std::make_unique<Ui::Text::ShiftedEmoji>(
Ui::Earn::MakeCurrencyIconEmoji(font, color),
QPoint(0, st::channelEarnCurrencyCommonMargins.top()));
};
const auto context = Ui::Text::MarkedContext{
.customEmojiFactory = std::move(customEmojiFactory),
};
const auto balance = balanceWrap->entity();
const auto button = AddActionButton(
balance,
tr::lng_manage_peer_bot_balance(),
rpl::single(true),
[=] { controller->showSection(Info::ChannelEarn::Make(peer)); },
nullptr);
const auto credits = channel->session().credits().balance(
channel->id).whole();
const auto currency = channel->session().credits().balanceCurrency(
channel->id);
auto creditsText = (credits > 0)
? Ui::Text::SingleCustomEmoji(Ui::kCreditsCurrency)
.append(QChar(' '))
.append(QString::number(credits))
: TextWithEntities();
auto currencyText = (currency > 0)
? Ui::Text::SingleCustomEmoji("_")
.append(QChar(' '))
.append(Info::ChannelEarn::MajorPart(currency))
.append(Info::ChannelEarn::MinorPart(currency))
: TextWithEntities();
::Settings::CreateRightLabel(
button->entity(),
currencyText.append(QChar(' ')).append(std::move(creditsText)),
st,
tr::lng_manage_peer_bot_balance(),
context);
object_ptr<FloatingIcon>(
balance,
st::menuIconEarn,
st::infoChannelAdminsIconPosition);
}
if (EditPeerInfoBox::Available(channel)) { if (EditPeerInfoBox::Available(channel)) {
const auto sessionController = controller->parentController(); const auto sessionController = controller->parentController();
const auto button = AddActionButton( const auto button = AddActionButton(

View file

@ -130,7 +130,8 @@ void CreateRightLabel(
not_null<Button*> button, not_null<Button*> button,
v::text::data &&label, v::text::data &&label,
const style::SettingsButton &st, const style::SettingsButton &st,
rpl::producer<QString> buttonText) { rpl::producer<QString> buttonText,
Ui::Text::MarkedContext context) {
const auto name = Ui::CreateChild<Ui::FlatLabel>( const auto name = Ui::CreateChild<Ui::FlatLabel>(
button.get(), button.get(),
st.rightLabel); st.rightLabel);
@ -167,7 +168,7 @@ void CreateRightLabel(
- st.padding.right() - st.padding.right()
- st.style.font->width(button) - st.style.font->width(button)
- st::settingsButtonRightSkip; - st::settingsButtonRightSkip;
name->setMarkedText(text); name->setMarkedText(text, context);
name->resizeToNaturalWidth(available); name->resizeToNaturalWidth(available);
name->moveToRight(st::settingsButtonRightSkip, st.padding.top()); name->moveToRight(st::settingsButtonRightSkip, st.padding.top());
}, name->lifetime()); }, name->lifetime());

View file

@ -180,7 +180,8 @@ void CreateRightLabel(
not_null<Button*> button, not_null<Button*> button,
v::text::data &&label, v::text::data &&label,
const style::SettingsButton &st, const style::SettingsButton &st,
rpl::producer<QString> buttonText); rpl::producer<QString> buttonText,
Ui::Text::MarkedContext context = {});
struct DividerWithLottieDescriptor { struct DividerWithLottieDescriptor {
QString lottie; QString lottie;

View file

@ -43,55 +43,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui { namespace Ui {
namespace { namespace {
class CreditsIconEmoji final : public Ui::Text::CustomEmoji {
public:
CreditsIconEmoji(int height, int count);
int width() override;
QString entityData() override;
void paint(QPainter &p, const Context &context) override;
void unload() override;
bool ready() override;
bool readyInDefaultState() override;
private:
const int _height;
const int _count;
QImage _image;
};
CreditsIconEmoji::CreditsIconEmoji(int height, int count)
: _height(height)
, _count(count)
, _image(GenerateStars(height, count)) {
}
int CreditsIconEmoji::width() {
return _image.width() / style::DevicePixelRatio();
}
QString CreditsIconEmoji::entityData() {
return u"credits_icon:%1:%2"_q.arg(_height).arg(_count);
}
void CreditsIconEmoji::paint(QPainter &p, const Context &context) {
p.drawImage(context.position, _image);
}
void CreditsIconEmoji::unload() {
_image = QImage();
}
bool CreditsIconEmoji::ready() {
return true;
}
bool CreditsIconEmoji::readyInDefaultState() {
return true;
}
PaintRoundImageCallback MultiThumbnail( PaintRoundImageCallback MultiThumbnail(
PaintRoundImageCallback first, PaintRoundImageCallback first,
PaintRoundImageCallback second, PaintRoundImageCallback second,
@ -735,7 +686,9 @@ QImage CreditsWhiteDoubledIcon(int size, float64 outlineRatio) {
std::unique_ptr<Ui::Text::CustomEmoji> MakeCreditsIconEmoji( std::unique_ptr<Ui::Text::CustomEmoji> MakeCreditsIconEmoji(
int height, int height,
int count) { int count) {
return std::make_unique<CreditsIconEmoji>(height, count); return std::make_unique<Ui::Text::StaticCustomEmoji>(
GenerateStars(height, count),
u"credits_icon:%1:%2"_q.arg(height).arg(count));
} }
} // namespace Ui } // namespace Ui

@ -1 +1 @@
Subproject commit 0afa1babbf74b3602d8a0175830e77b98b5a27d8 Subproject commit 0b324ce83c219c817fdd3c94a23b55fec6fec637