mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-16 06:07:06 +02:00
Implemented list of credit history entries.
This commit is contained in:
parent
65384d54f1
commit
154fe63b43
3 changed files with 319 additions and 0 deletions
|
@ -7,9 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
*/
|
||||
#include "info/statistics/info_statistics_list_controllers.h"
|
||||
|
||||
#include "api/api_credits.h"
|
||||
#include "api/api_statistics.h"
|
||||
#include "boxes/peer_list_controllers.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_credits.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_stories.h"
|
||||
#include "data/data_user.h"
|
||||
|
@ -26,7 +28,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/popup_menu.h"
|
||||
#include "ui/wrap/slide_wrap.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "styles/style_credits.h"
|
||||
#include "styles/style_dialogs.h" // dialogsStoriesFull.
|
||||
#include "styles/style_intro.h" // introFragmentIcon.
|
||||
#include "styles/style_layers.h" // boxRowPadding.
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "styles/style_settings.h"
|
||||
#include "styles/style_statistics.h"
|
||||
|
@ -113,6 +118,15 @@ struct BoostsDescriptor final {
|
|||
not_null<PeerData*> peer;
|
||||
};
|
||||
|
||||
struct CreditsDescriptor final {
|
||||
Data::CreditsStatusSlice firstSlice;
|
||||
Fn<void(const Data::CreditsHistoryEntry &)> entryClickedCallback;
|
||||
not_null<PeerData*> peer;
|
||||
not_null<QImage*> creditIcon;
|
||||
bool in = false;
|
||||
bool out = false;
|
||||
};
|
||||
|
||||
class PeerListRowWithFullId : public PeerListRow {
|
||||
public:
|
||||
PeerListRowWithFullId(
|
||||
|
@ -692,6 +706,254 @@ rpl::producer<int> BoostsController::totalBoostsValue() const {
|
|||
return _totalBoosts.value();
|
||||
}
|
||||
|
||||
class CreditsRow final : public PeerListRow {
|
||||
public:
|
||||
struct Descriptor final {
|
||||
Data::CreditsHistoryEntry entry;
|
||||
not_null<QImage*> creditIcon;
|
||||
int rowHeight = 0;
|
||||
};
|
||||
|
||||
CreditsRow(not_null<PeerData*> peer, const Descriptor &descriptor);
|
||||
CreditsRow(const Descriptor &descriptor);
|
||||
|
||||
[[nodiscard]] const Data::CreditsHistoryEntry &entry() const;
|
||||
[[nodiscard]] QString generateName() override;
|
||||
|
||||
[[nodiscard]] PaintRoundImageCallback generatePaintUserpicCallback(
|
||||
bool forceRound) override;
|
||||
|
||||
QSize rightActionSize() const override;
|
||||
QMargins rightActionMargins() const override;
|
||||
bool rightActionDisabled() const override;
|
||||
void rightActionPaint(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
bool selected,
|
||||
bool actionSelected) override;
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
const Data::CreditsHistoryEntry _entry;
|
||||
not_null<QImage*> const _creditIcon;
|
||||
const int _rowHeight;
|
||||
Ui::EmptyUserpic _userpic;
|
||||
|
||||
Ui::Text::String _rightText;
|
||||
};
|
||||
|
||||
CreditsRow::CreditsRow(not_null<PeerData*> peer, const Descriptor &descriptor)
|
||||
: PeerListRow(peer, UniqueRowIdFromString(descriptor.entry.id))
|
||||
, _entry(descriptor.entry)
|
||||
, _creditIcon(descriptor.creditIcon)
|
||||
, _rowHeight(descriptor.rowHeight)
|
||||
, _userpic(Ui::EmptyUserpic::UserpicColor(0), QString()) {
|
||||
init();
|
||||
}
|
||||
|
||||
CreditsRow::CreditsRow(const Descriptor &descriptor)
|
||||
: PeerListRow(UniqueRowIdFromString(descriptor.entry.id))
|
||||
, _entry(descriptor.entry)
|
||||
, _creditIcon(descriptor.creditIcon)
|
||||
, _rowHeight(descriptor.rowHeight)
|
||||
, _userpic(
|
||||
[&]() -> Ui::EmptyUserpic::BgColors {
|
||||
switch (descriptor.entry.peerType) {
|
||||
case Data::CreditsHistoryEntry::PeerType::Peer:
|
||||
return Ui::EmptyUserpic::UserpicColor(0);
|
||||
case Data::CreditsHistoryEntry::PeerType::AppStore:
|
||||
return { st::historyPeer7UserpicBg, st::historyPeer7UserpicBg2 };
|
||||
case Data::CreditsHistoryEntry::PeerType::PlayMarket:
|
||||
return { st::historyPeer2UserpicBg, st::historyPeer2UserpicBg2 };
|
||||
case Data::CreditsHistoryEntry::PeerType::Fragment:
|
||||
return { st::historyPeer8UserpicBg, st::historyPeer8UserpicBg2 };
|
||||
}
|
||||
Unexpected("Unknown peer type.");
|
||||
}(),
|
||||
QString()) {
|
||||
init();
|
||||
}
|
||||
|
||||
void CreditsRow::init() {
|
||||
PeerListRow::setCustomStatus(langDateTimeFull(_entry.date));
|
||||
{
|
||||
constexpr auto kMinus = QChar(0x2212);
|
||||
_rightText.setText(
|
||||
st::semiboldTextStyle,
|
||||
(PeerListRow::special() ? QChar('+') : kMinus)
|
||||
+ Lang::FormatCountDecimal(_entry.credits));
|
||||
}
|
||||
}
|
||||
|
||||
const Data::CreditsHistoryEntry &CreditsRow::entry() const {
|
||||
return _entry;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
PaintRoundImageCallback CreditsRow::generatePaintUserpicCallback(bool force) {
|
||||
if (!PeerListRow::special()) {
|
||||
return PeerListRow::generatePaintUserpicCallback(force);
|
||||
}
|
||||
return [=](Painter &p, int x, int y, int outerWidth, int size) mutable {
|
||||
_userpic.paintCircle(p, x, y, outerWidth, size);
|
||||
using PeerType = Data::CreditsHistoryEntry::PeerType;
|
||||
((_entry.peerType == PeerType::AppStore)
|
||||
? st::sessionIconiPhone
|
||||
: (_entry.peerType == PeerType::PlayMarket)
|
||||
? st::sessionIconAndroid
|
||||
: st::introFragmentIcon).paintInCenter(p, { x, y, size, size });
|
||||
};
|
||||
}
|
||||
|
||||
QSize CreditsRow::rightActionSize() const {
|
||||
return QSize(
|
||||
_rightText.maxWidth()
|
||||
+ (_creditIcon->width() / style::DevicePixelRatio())
|
||||
+ st::creditsHistoryRightSkip
|
||||
+ _rightText.style()->font->spacew * 2,
|
||||
_rowHeight);
|
||||
}
|
||||
|
||||
QMargins CreditsRow::rightActionMargins() const {
|
||||
return QMargins(0, 0, st::boxRowPadding.right(), 0);
|
||||
}
|
||||
|
||||
bool CreditsRow::rightActionDisabled() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CreditsRow::rightActionPaint(
|
||||
Painter &p,
|
||||
int x,
|
||||
int y,
|
||||
int outerWidth,
|
||||
bool selected,
|
||||
bool actionSelected) {
|
||||
const auto &font = _rightText.style()->font;
|
||||
y += _rowHeight / 2;
|
||||
p.setPen(PeerListRow::special()
|
||||
? st::boxTextFgGood
|
||||
: st::menuIconAttentionColor);
|
||||
x += st::creditsHistoryRightSkip;
|
||||
_rightText.draw(p, Ui::Text::PaintContext{
|
||||
.position = QPoint(x, y - font->height / 2),
|
||||
.availableWidth = outerWidth,
|
||||
.outerWidth = outerWidth,
|
||||
});
|
||||
x += _rightText.maxWidth() + font->spacew * 2;
|
||||
p.drawImage(
|
||||
x,
|
||||
y -(_creditIcon->height() / style::DevicePixelRatio()) / 2,
|
||||
*_creditIcon);
|
||||
}
|
||||
|
||||
class CreditsController final : public PeerListController {
|
||||
public:
|
||||
explicit CreditsController(CreditsDescriptor d);
|
||||
|
||||
Main::Session &session() const override;
|
||||
void prepare() override;
|
||||
void rowClicked(not_null<PeerListRow*> row) override;
|
||||
void loadMoreRows() override;
|
||||
|
||||
[[nodiscard]] bool skipRequest() const;
|
||||
void requestNext();
|
||||
|
||||
[[nodiscard]] rpl::producer<bool> allLoadedValue() const;
|
||||
|
||||
private:
|
||||
void applySlice(const Data::CreditsStatusSlice &slice);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
Fn<void(const Data::CreditsHistoryEntry &)> _entryClickedCallback;
|
||||
not_null<QImage*> const _creditIcon;
|
||||
|
||||
Api::CreditsHistory _api;
|
||||
Data::CreditsStatusSlice _firstSlice;
|
||||
Data::CreditsStatusSlice::OffsetToken _apiToken;
|
||||
|
||||
rpl::variable<bool> _allLoaded = false;
|
||||
bool _requesting = false;
|
||||
|
||||
};
|
||||
|
||||
CreditsController::CreditsController(CreditsDescriptor d)
|
||||
: _session(&d.peer->session())
|
||||
, _entryClickedCallback(std::move(d.entryClickedCallback))
|
||||
, _creditIcon(d.creditIcon)
|
||||
, _api(d.peer, d.in, d.out)
|
||||
, _firstSlice(std::move(d.firstSlice)) {
|
||||
PeerListController::setStyleOverrides(&st::boostsListBox);
|
||||
}
|
||||
|
||||
Main::Session &CreditsController::session() const {
|
||||
return *_session;
|
||||
}
|
||||
|
||||
bool CreditsController::skipRequest() const {
|
||||
return _requesting || _allLoaded.current();
|
||||
}
|
||||
|
||||
void CreditsController::requestNext() {
|
||||
_requesting = true;
|
||||
_api.request(_apiToken, [=](const Data::CreditsStatusSlice &s) {
|
||||
_requesting = false;
|
||||
applySlice(s);
|
||||
});
|
||||
}
|
||||
|
||||
void CreditsController::prepare() {
|
||||
applySlice(base::take(_firstSlice));
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
||||
void CreditsController::loadMoreRows() {
|
||||
}
|
||||
|
||||
void CreditsController::applySlice(const Data::CreditsStatusSlice &slice) {
|
||||
_allLoaded = slice.allLoaded;
|
||||
_apiToken = slice.token;
|
||||
|
||||
for (const auto &item : slice.list) {
|
||||
auto row = [&] {
|
||||
const auto descriptor = CreditsRow::Descriptor{
|
||||
.entry = item,
|
||||
.creditIcon = _creditIcon,
|
||||
.rowHeight = computeListSt().item.height,
|
||||
};
|
||||
if (item.peerId) {
|
||||
const auto peer = session().data().peer(item.peerId);
|
||||
return std::make_unique<CreditsRow>(peer, descriptor);
|
||||
} else {
|
||||
return std::make_unique<CreditsRow>(descriptor);
|
||||
}
|
||||
}();
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
}
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
||||
void CreditsController::rowClicked(not_null<PeerListRow*> row) {
|
||||
if (_entryClickedCallback) {
|
||||
_entryClickedCallback(
|
||||
static_cast<const CreditsRow*>(row.get())->entry());
|
||||
}
|
||||
}
|
||||
|
||||
rpl::producer<bool> CreditsController::allLoadedValue() const {
|
||||
return _allLoaded.value();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AddPublicForwards(
|
||||
|
@ -843,4 +1105,48 @@ void AddBoostsList(
|
|||
button->setClickedCallback(showMore);
|
||||
}
|
||||
|
||||
void AddCreditsHistoryList(
|
||||
const Data::CreditsStatusSlice &firstSlice,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
Fn<void(const Data::CreditsHistoryEntry &)> callback,
|
||||
not_null<PeerData*> self,
|
||||
not_null<QImage*> icon,
|
||||
bool in,
|
||||
bool out) {
|
||||
struct State final {
|
||||
State(CreditsDescriptor d) : controller(std::move(d)) {
|
||||
}
|
||||
PeerListContentDelegateSimple delegate;
|
||||
CreditsController controller;
|
||||
};
|
||||
auto d = CreditsDescriptor{ firstSlice, callback, self, icon, in, out };
|
||||
const auto state = container->lifetime().make_state<State>(std::move(d));
|
||||
|
||||
state->delegate.setContent(container->add(
|
||||
object_ptr<PeerListContent>(container, &state->controller)));
|
||||
state->controller.setDelegate(&state->delegate);
|
||||
|
||||
const auto wrap = container->add(
|
||||
object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
|
||||
container,
|
||||
object_ptr<Ui::SettingsButton>(
|
||||
container,
|
||||
tr::lng_stories_show_more(),
|
||||
st::statisticsShowMoreButton)),
|
||||
{ 0, -st::settingsButton.padding.top(), 0, 0 });
|
||||
const auto button = wrap->entity();
|
||||
AddArrow(button);
|
||||
|
||||
const auto showMore = [=] {
|
||||
if (!state->controller.skipRequest()) {
|
||||
state->controller.requestNext();
|
||||
container->resizeToWidth(container->width());
|
||||
}
|
||||
};
|
||||
wrap->toggleOn(
|
||||
state->controller.allLoadedValue() | rpl::map(!rpl::mappers::_1),
|
||||
anim::type::instant);
|
||||
button->setClickedCallback(showMore);
|
||||
}
|
||||
|
||||
} // namespace Info::Statistics
|
||||
|
|
|
@ -16,6 +16,8 @@ class VerticalLayout;
|
|||
namespace Data {
|
||||
struct Boost;
|
||||
struct BoostsListSlice;
|
||||
struct CreditsHistoryEntry;
|
||||
struct CreditsStatusSlice;
|
||||
struct PublicForwardsSlice;
|
||||
struct RecentPostId;
|
||||
struct SupergroupStatistics;
|
||||
|
@ -44,4 +46,13 @@ void AddBoostsList(
|
|||
not_null<PeerData*> peer,
|
||||
rpl::producer<QString> title);
|
||||
|
||||
void AddCreditsHistoryList(
|
||||
const Data::CreditsStatusSlice &firstSlice,
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
Fn<void(const Data::CreditsHistoryEntry &)> entryClickedCallback,
|
||||
not_null<PeerData*> self,
|
||||
not_null<QImage*> creditIcon,
|
||||
bool in,
|
||||
bool out);
|
||||
|
||||
} // namespace Info::Statistics
|
||||
|
|
|
@ -22,3 +22,5 @@ creditsTopupButton: SettingsButton(settingsButton) {
|
|||
creditsTopupPrice: FlatLabel(defaultFlatLabel) {
|
||||
textFg: windowSubTextFg;
|
||||
}
|
||||
|
||||
creditsHistoryRightSkip: 10px;
|
||||
|
|
Loading…
Add table
Reference in a new issue