Update API scheme to layer 195.

This commit is contained in:
John Preston 2024-11-21 22:42:58 +04:00
parent 42142d819a
commit 51ddfbc340
43 changed files with 358 additions and 154 deletions

View file

@ -468,6 +468,7 @@ PRIVATE
core/sandbox.h
core/shortcuts.cpp
core/shortcuts.h
core/stars_amount.h
core/ui_integration.cpp
core/ui_integration.h
core/update_checker.cpp

View file

@ -74,7 +74,8 @@ constexpr auto kTransactionsLimit = 100;
}).value;
const auto stargift = tl.data().vstargift();
const auto reaction = tl.data().is_reaction();
const auto incoming = (int64(tl.data().vstars().v) >= 0);
const auto amount = Data::FromTL(tl.data().vstars());
const auto incoming = (amount >= StarsAmount());
const auto saveActorId = (reaction || !extended.empty()) && incoming;
return Data::CreditsHistoryEntry{
.id = qs(tl.data().vid()),
@ -83,7 +84,7 @@ constexpr auto kTransactionsLimit = 100;
.date = base::unixtime::parse(tl.data().vdate().v),
.photoId = photo ? photo->id : 0,
.extended = std::move(extended),
.credits = tl.data().vstars().v,
.credits = Data::FromTL(tl.data().vstars()),
.bareMsgId = uint64(tl.data().vmsg_id().value_or_empty()),
.barePeerId = saveActorId ? peer->id.value : barePeerId,
.bareGiveawayMsgId = uint64(
@ -181,7 +182,7 @@ constexpr auto kTransactionsLimit = 100;
return Data::CreditsStatusSlice{
.list = std::move(entries),
.subscriptions = std::move(subscriptions),
.balance = status.data().vbalance().v,
.balance = Data::FromTL(status.data().vbalance()),
.subscriptionsMissingBalance
= status.data().vsubscriptions_missing_balance().value_or_empty(),
.allLoaded = !status.data().vnext_offset().has_value()
@ -268,8 +269,8 @@ void CreditsStatus::request(
_peer->isSelf() ? MTP_inputPeerSelf() : _peer->input
)).done([=](const TLResult &result) {
_requestId = 0;
const auto balance = result.data().vbalance().v;
_peer->session().credits().apply(_peer->id, balance);
const auto &balance = result.data().vbalance();
_peer->session().credits().apply(_peer->id, Data::FromTL(balance));
if (const auto onstack = done) {
onstack(StatusFromTL(result, _peer));
}
@ -348,7 +349,9 @@ rpl::producer<not_null<PeerData*>> PremiumPeerBot(
const auto api = lifetime.make_state<MTP::Sender>(&session->mtp());
api->request(MTPcontacts_ResolveUsername(
MTP_string(username)
MTP_flags(0),
MTP_string(username),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
session->data().processUsers(result.data().vusers());
session->data().processChats(result.data().vchats());
@ -380,12 +383,13 @@ rpl::producer<rpl::no_value, QString> CreditsEarnStatistics::request() {
)).done([=](const MTPpayments_StarsRevenueStats &result) {
const auto &data = result.data();
const auto &status = data.vstatus().data();
using Data::FromTL;
_data = Data::CreditsEarnStatistics{
.revenueGraph = StatisticalGraphFromTL(
data.vrevenue_graph()),
.currentBalance = status.vcurrent_balance().v,
.availableBalance = status.vavailable_balance().v,
.overallRevenue = status.voverall_revenue().v,
.currentBalance = FromTL(status.vcurrent_balance()),
.availableBalance = FromTL(status.vavailable_balance()),
.overallRevenue = FromTL(status.voverall_revenue()),
.usdRate = data.vusd_rate().v,
.isWithdrawalEnabled = status.is_withdrawal_enabled(),
.nextWithdrawalAt = status.vnext_withdrawal_at()

View file

@ -181,7 +181,9 @@ std::optional<HistoryItem*> SingleMessageSearch::performLookupByUsername(
ready();
};
_requestId = _session->api().request(MTPcontacts_ResolveUsername(
MTP_string(username)
MTP_flags(0),
MTP_string(username),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
result.match([&](const MTPDcontacts_resolvedPeer &data) {
_session->data().processUsers(data.vusers());

View file

@ -122,7 +122,7 @@ void GiftCreditsBox(
Main::MakeSessionShow(box->uiShow(), &peer->session()),
box->verticalLayout(),
peer,
0,
StarsAmount(),
[=] { gifted(); box->uiShow()->hideLayer(); },
tr::lng_credits_summary_options_subtitle(),
{});

View file

@ -255,8 +255,8 @@ object_ptr<Ui::RpWidget> MakeStarGiftStarsValue(
auto star = session->data().customEmojiManager().creditsEmoji();
const auto label = Ui::CreateChild<Ui::FlatLabel>(
raw,
rpl::single(
star.append(' ' + Lang::FormatCountDecimal(entry.credits))),
rpl::single(star.append(
' ' + Lang::FormatStarsAmountDecimal(entry.credits))),
st::giveawayGiftCodeValue,
st::defaultPopupMenu,
std::move(makeContext));
@ -1229,7 +1229,7 @@ void AddCreditsHistoryEntryTable(
tr::lng_gift_link_label_gift(),
tr::lng_gift_stars_title(
lt_count,
rpl::single(float64(entry.credits)),
rpl::single(entry.credits.value()),
Ui::Text::RichLangValue));
}
{

View file

@ -1664,7 +1664,7 @@ void Controller::fillBotCreditsButton() {
auto &lifetime = _controls.buttonsLayout->lifetime();
const auto state = lifetime.make_state<State>();
if (const auto balance = _peer->session().credits().balance(_peer->id)) {
state->balance = Lang::FormatCountDecimal(balance);
state->balance = Lang::FormatStarsAmountDecimal(balance);
}
const auto wrap = _controls.buttonsLayout->add(
@ -1689,7 +1689,7 @@ void Controller::fillBotCreditsButton() {
if (data.balance) {
wrap->toggle(true, anim::type::normal);
}
state->balance = Lang::FormatCountDecimal(data.balance);
state->balance = Lang::FormatStarsAmountDecimal(data.balance);
});
}
{
@ -2227,7 +2227,9 @@ void Controller::saveHistoryVisibility() {
void Controller::toggleBotManager(const QString &command) {
const auto controller = _navigation->parentController();
_api.request(MTPcontacts_ResolveUsername(
MTP_string(kBotManagerUsername.utf16())
MTP_flags(0),
MTP_string(kBotManagerUsername.utf16()),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
_peer->owner().processUsers(result.data().vusers());
_peer->owner().processChats(result.data().vchats());

View file

@ -875,7 +875,7 @@ void SoldOutBox(
Data::CreditsHistoryEntry{
.firstSaleDate = base::unixtime::parse(gift.info.firstSaleDate),
.lastSaleDate = base::unixtime::parse(gift.info.lastSaleDate),
.credits = uint64(gift.info.stars),
.credits = StarsAmount(gift.info.stars),
.bareGiftStickerId = gift.info.document->id,
.peerType = Data::CreditsHistoryEntry::PeerType::Peer,
.limitedCount = gift.info.limitedCount,

View file

@ -899,7 +899,9 @@ void GifsListWidget::searchForGifs(const QString &query) {
if (!_searchBot && !_searchBotRequestId) {
const auto username = session().serverConfig().gifSearchUsername;
_searchBotRequestId = _api.request(MTPcontacts_ResolveUsername(
MTP_string(username)
MTP_flags(0),
MTP_string(username),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
auto &data = result.data();
session().data().processUsers(data.vusers());

View file

@ -0,0 +1,99 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "base/basic_types.h"
inline constexpr auto kOneStarInNano = int64(1'000'000'000);
class StarsAmount {
public:
StarsAmount() = default;
explicit StarsAmount(int64 whole) : _whole(whole) {}
StarsAmount(int64 whole, int64 nano) : _whole(whole), _nano(nano) {
normalize();
}
[[nodiscard]] int64 whole() const {
return _whole;
}
[[nodiscard]] int64 nano() const {
return _nano;
}
[[nodiscard]] double value() const {
return double(_whole) + double(_nano) / kOneStarInNano;
}
[[nodiscard]] bool empty() const {
return !_whole && !_nano;
}
[[nodiscard]] inline bool operator!() const {
return empty();
}
[[nodiscard]] inline explicit operator bool() const {
return !empty();
}
inline StarsAmount &operator+=(StarsAmount other) {
_whole += other._whole;
_nano += other._nano;
normalize();
return *this;
}
inline StarsAmount &operator-=(StarsAmount other) {
_whole -= other._whole;
_nano -= other._nano;
normalize();
return *this;
}
inline StarsAmount &operator*=(int64 multiplier) {
_whole *= multiplier;
_nano *= multiplier;
normalize();
return *this;
}
friend inline auto operator<=>(StarsAmount, StarsAmount) = default;
friend inline bool operator==(StarsAmount, StarsAmount) = default;
[[nodiscard]] StarsAmount abs() const {
return (_whole < 0) ? StarsAmount(-_whole, -_nano) : *this;
}
private:
int64 _whole = 0;
int64 _nano = 0;
void normalize() {
if (_nano < 0) {
const auto shifts = (-_nano + kOneStarInNano - 1)
/ kOneStarInNano;
_nano += shifts * kOneStarInNano;
_whole -= shifts;
} else if (_nano >= kOneStarInNano) {
const auto shifts = _nano / kOneStarInNano;
_nano -= shifts * kOneStarInNano;
_whole += shifts;
}
}
};
[[nodiscard]] inline StarsAmount operator+(StarsAmount a, StarsAmount b) {
return a += b;
}
[[nodiscard]] inline StarsAmount operator-(StarsAmount a, StarsAmount b) {
return a -= b;
}
[[nodiscard]] inline StarsAmount operator*(StarsAmount a, int64 b) {
return a *= b;
}

View file

@ -19,6 +19,11 @@ constexpr auto kReloadThreshold = 60 * crl::time(1000);
} // namespace
StarsAmount FromTL(const MTPStarsAmount &value) {
const auto &data = value.data();
return StarsAmount(data.vamount().v, data.vnanos().v);
}
Credits::Credits(not_null<Main::Session*> session)
: _session(session)
, _reload([=] { load(true); }) {
@ -27,7 +32,7 @@ Credits::Credits(not_null<Main::Session*> session)
Credits::~Credits() = default;
void Credits::apply(const MTPDupdateStarsBalance &data) {
apply(data.vbalance().v);
apply(FromTL(data.vbalance()));
}
rpl::producer<float64> Credits::rateValue(
@ -65,13 +70,13 @@ rpl::producer<bool> Credits::loadedValue() const {
) | rpl::then(_loadedChanges.events() | rpl::map_to(true));
}
uint64 Credits::balance() const {
StarsAmount Credits::balance() const {
return _nonLockedBalance.current();
}
uint64 Credits::balance(PeerId peerId) const {
StarsAmount Credits::balance(PeerId peerId) const {
const auto it = _cachedPeerBalances.find(peerId);
return (it != _cachedPeerBalances.end()) ? it->second : 0;
return (it != _cachedPeerBalances.end()) ? it->second : StarsAmount();
}
uint64 Credits::balanceCurrency(PeerId peerId) const {
@ -79,17 +84,19 @@ uint64 Credits::balanceCurrency(PeerId peerId) const {
return (it != _cachedPeerCurrencyBalances.end()) ? it->second : 0;
}
rpl::producer<uint64> Credits::balanceValue() const {
rpl::producer<StarsAmount> Credits::balanceValue() const {
return _nonLockedBalance.value();
}
void Credits::updateNonLockedValue() {
_nonLockedBalance = (_balance >= _locked) ? (_balance - _locked) : 0;
_nonLockedBalance = (_balance >= _locked)
? (_balance - _locked)
: StarsAmount();
}
void Credits::lock(int count) {
void Credits::lock(StarsAmount count) {
Expects(loaded());
Expects(count >= 0);
Expects(count >= StarsAmount(0));
Expects(_locked + count <= _balance);
_locked += count;
@ -97,8 +104,8 @@ void Credits::lock(int count) {
updateNonLockedValue();
}
void Credits::unlock(int count) {
Expects(count >= 0);
void Credits::unlock(StarsAmount count) {
Expects(count >= StarsAmount(0));
Expects(_locked >= count);
_locked -= count;
@ -106,12 +113,12 @@ void Credits::unlock(int count) {
updateNonLockedValue();
}
void Credits::withdrawLocked(int count) {
Expects(count >= 0);
void Credits::withdrawLocked(StarsAmount count) {
Expects(count >= StarsAmount(0));
Expects(_locked >= count);
_locked -= count;
apply(_balance >= count ? (_balance - count) : 0);
apply(_balance >= count ? (_balance - count) : StarsAmount(0));
invalidate();
}
@ -119,7 +126,7 @@ void Credits::invalidate() {
_reload.call();
}
void Credits::apply(uint64 balance) {
void Credits::apply(StarsAmount balance) {
_balance = balance;
updateNonLockedValue();
@ -129,7 +136,7 @@ void Credits::apply(uint64 balance) {
}
}
void Credits::apply(PeerId peerId, uint64 balance) {
void Credits::apply(PeerId peerId, StarsAmount balance) {
_cachedPeerBalances[peerId] = balance;
}

View file

@ -17,30 +17,32 @@ class Session;
namespace Data {
[[nodiscard]] StarsAmount FromTL(const MTPStarsAmount &value);
class Credits final {
public:
explicit Credits(not_null<Main::Session*> session);
~Credits();
void load(bool force = false);
void apply(uint64 balance);
void apply(PeerId peerId, uint64 balance);
void apply(StarsAmount balance);
void apply(PeerId peerId, StarsAmount balance);
[[nodiscard]] bool loaded() const;
[[nodiscard]] rpl::producer<bool> loadedValue() const;
[[nodiscard]] uint64 balance() const;
[[nodiscard]] uint64 balance(PeerId peerId) const;
[[nodiscard]] rpl::producer<uint64> balanceValue() const;
[[nodiscard]] StarsAmount balance() const;
[[nodiscard]] StarsAmount balance(PeerId peerId) const;
[[nodiscard]] rpl::producer<StarsAmount> balanceValue() const;
[[nodiscard]] rpl::producer<float64> rateValue(
not_null<PeerData*> ownedBotOrChannel);
void applyCurrency(PeerId peerId, uint64 balance);
[[nodiscard]] uint64 balanceCurrency(PeerId peerId) const;
void lock(int count);
void unlock(int count);
void withdrawLocked(int count);
void lock(StarsAmount count);
void unlock(StarsAmount count);
void withdrawLocked(StarsAmount count);
void invalidate();
void apply(const MTPDupdateStarsBalance &data);
@ -52,12 +54,12 @@ private:
std::unique_ptr<Api::CreditsStatus> _loader;
base::flat_map<PeerId, uint64> _cachedPeerBalances;
base::flat_map<PeerId, StarsAmount> _cachedPeerBalances;
base::flat_map<PeerId, uint64> _cachedPeerCurrencyBalances;
uint64 _balance = 0;
uint64 _locked = 0;
rpl::variable<uint64> _nonLockedBalance;
StarsAmount _balance;
StarsAmount _locked;
rpl::variable<StarsAmount> _nonLockedBalance;
rpl::event_stream<> _loadedChanges;
crl::time _lastLoaded = 0;
float64 _rate = 0.;

View file

@ -57,7 +57,7 @@ struct CreditsHistoryEntry final {
QDateTime lastSaleDate;
PhotoId photoId = 0;
std::vector<CreditsHistoryMedia> extended;
uint64 credits = 0;
StarsAmount credits;
uint64 bareMsgId = 0;
uint64 barePeerId = 0;
uint64 bareGiveawayMsgId = 0;
@ -89,7 +89,7 @@ struct CreditsStatusSlice final {
using OffsetToken = QString;
std::vector<CreditsHistoryEntry> list;
std::vector<SubscriptionEntry> subscriptions;
uint64 balance = 0;
StarsAmount balance;
uint64 subscriptionsMissingBalance = 0;
bool allLoaded = false;
OffsetToken token;

View file

@ -13,16 +13,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Data {
using CreditsEarnInt = uint64;
struct CreditsEarnStatistics final {
explicit operator bool() const {
return !!usdRate;
}
Data::StatisticalGraph revenueGraph;
CreditsEarnInt currentBalance = 0;
CreditsEarnInt availableBalance = 0;
CreditsEarnInt overallRevenue = 0;
StarsAmount currentBalance;
StarsAmount availableBalance;
StarsAmount overallRevenue;
float64 usdRate = 0.;
bool isWithdrawalEnabled = false;
QDateTime nextWithdrawalAt;

View file

@ -2220,7 +2220,7 @@ void MessageReactions::scheduleSendPaid(
_paid->scheduledPrivacySet = anonymous.has_value();
}
if (count > 0) {
_item->history()->session().credits().lock(count);
_item->history()->session().credits().lock(StarsAmount(count));
}
_item->history()->owner().reactions().schedulePaid(_item);
}
@ -2233,7 +2233,8 @@ void MessageReactions::cancelScheduledPaid() {
if (_paid) {
if (_paid->scheduledFlag) {
if (const auto amount = int(_paid->scheduled)) {
_item->history()->session().credits().unlock(amount);
_item->history()->session().credits().unlock(
StarsAmount(amount));
}
_paid->scheduled = 0;
_paid->scheduledFlag = 0;
@ -2296,9 +2297,9 @@ void MessageReactions::finishPaidSending(
if (const auto amount = send.count) {
const auto credits = &_item->history()->session().credits();
if (success) {
credits->withdrawLocked(amount);
credits->withdrawLocked(StarsAmount(amount));
} else {
credits->unlock(amount);
credits->unlock(StarsAmount(amount));
}
}
}

View file

@ -1561,7 +1561,10 @@ void HistoryWidget::updateInlineBotQuery() {
_inlineLookingUpBot = true;
const auto username = _inlineBotUsername;
_inlineBotResolveRequestId = _api.request(
MTPcontacts_ResolveUsername(MTP_string(username))
MTPcontacts_ResolveUsername(
MTP_flags(0),
MTP_string(username),
MTP_string())
).done([=](const MTPcontacts_ResolvedPeer &result) {
const auto &data = result.data();
const auto resolvedBot = [&]() -> UserData* {

View file

@ -3265,7 +3265,10 @@ void ComposeControls::updateInlineBotQuery() {
_inlineLookingUpBot = true;
const auto username = _inlineBotUsername;
_inlineBotResolveRequestId = api.request(
MTPcontacts_ResolveUsername(MTP_string(username))
MTPcontacts_ResolveUsername(
MTP_flags(0),
MTP_string(username),
MTP_string())
).done([=](const MTPcontacts_ResolvedPeer &result) {
Expects(result.type() == mtpc_contacts_resolvedPeer);

View file

@ -125,7 +125,9 @@ void InnerWidget::fill() {
return _state.availableBalance;
})
);
auto valueToString = [](uint64 v) { return Lang::FormatCountDecimal(v); };
auto valueToString = [](StarsAmount v) {
return Lang::FormatStarsAmountDecimal(v);
};
if (data.revenueGraph.chart) {
Ui::AddSkip(container);
@ -149,7 +151,7 @@ void InnerWidget::fill() {
Ui::AddSkip(container, st::channelEarnOverviewTitleSkip);
const auto addOverview = [&](
rpl::producer<uint64> value,
rpl::producer<StarsAmount> value,
const tr::phrase<> &text) {
const auto line = container->add(
Ui::CreateSkipWidget(container, 0),
@ -165,7 +167,7 @@ void InnerWidget::fill() {
line,
std::move(
value
) | rpl::map([=](uint64 v) {
) | rpl::map([=](StarsAmount v) {
return v ? ToUsd(v, multiplier, kMinorLength) : QString();
}),
st::channelEarnOverviewSubMinorLabel);
@ -242,7 +244,9 @@ void InnerWidget::fill() {
rpl::duplicate(dateValue) | rpl::map([=](const QDateTime &dt) {
return !dt.isNull() || (!_state.isWithdrawalEnabled);
}),
rpl::duplicate(availableBalanceValue) | rpl::map([=](uint64 v) {
rpl::duplicate(
availableBalanceValue
) | rpl::map([=](StarsAmount v) {
return v ? ToUsd(v, multiplier, kMinorLength) : QString();
}));
}

View file

@ -50,12 +50,16 @@ QString ToUsd(
Data::EarnInt value,
float64 rate,
int afterFloat) {
return ToUsd(StarsAmount(value), rate, afterFloat);
}
QString ToUsd(
StarsAmount value,
float64 rate,
int afterFloat) {
constexpr auto kApproximately = QChar(0x2248);
const auto result = value
/ float64(Data::kEarnMultiplier)
* rate
* Data::kEarnMultiplier;
const auto result = int64(base::SafeRound(value.value() * rate));
return QString(kApproximately)
+ QChar('$')
+ MajorPart(result)

View file

@ -17,5 +17,9 @@ namespace Info::ChannelEarn {
Data::EarnInt value,
float64 rate,
int afterFloat);
[[nodiscard]] QString ToUsd(
StarsAmount value,
float64 rate,
int afterFloat);
} // namespace Info::ChannelEarn

View file

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_color_box.h" // AddLevelBadge.
#include "chat_helpers/stickers_emoji_pack.h"
#include "core/application.h"
#include "data/components/credits.h"
#include "data/data_channel.h"
#include "data/data_premium_limits.h"
#include "data/data_session.h"
@ -252,10 +253,9 @@ void InnerWidget::load() {
}
const auto &data = d.vstatus().data();
auto &e = _state.creditsEarn;
e.currentBalance = data.vcurrent_balance().v;
e.availableBalance = data.vavailable_balance().v;
e.overallRevenue = data.voverall_revenue().v;
e.overallRevenue = data.voverall_revenue().v;
e.currentBalance = Data::FromTL(data.vcurrent_balance());
e.availableBalance = Data::FromTL(data.vavailable_balance());
e.overallRevenue = Data::FromTL(data.voverall_revenue());
e.isWithdrawalEnabled = data.is_withdrawal_enabled();
e.nextWithdrawalAt = data.vnext_withdrawal_at()
? base::unixtime::parse(
@ -359,7 +359,7 @@ void InnerWidget::fill() {
//constexpr auto kApproximately = QChar(0x2248);
const auto multiplier = data.usdRate;
const auto creditsToUsdMap = [=](EarnInt c) {
const auto creditsToUsdMap = [=](StarsAmount c) {
const auto creditsMultiplier = _state.creditsEarn.usdRate
* Data::kEarnMultiplier;
return c ? ToUsd(c, creditsMultiplier, 0) : QString();
@ -679,7 +679,7 @@ void InnerWidget::fill() {
const auto addOverview = [&](
rpl::producer<EarnInt> currencyValue,
rpl::producer<EarnInt> creditsValue,
rpl::producer<StarsAmount> creditsValue,
const tr::phrase<> &text,
bool showCurrency,
bool showCredits) {
@ -713,8 +713,8 @@ void InnerWidget::fill() {
const auto creditsLabel = Ui::CreateChild<Ui::FlatLabel>(
line,
rpl::duplicate(creditsValue) | rpl::map([](EarnInt value) {
return QString::number(value);
rpl::duplicate(creditsValue) | rpl::map([](StarsAmount value) {
return Lang::FormatStarsAmountDecimal(value);
}),
st::channelEarnOverviewMajorLabel);
const auto icon = Ui::CreateSingleStarWidget(
@ -733,7 +733,7 @@ void InnerWidget::fill() {
int available,
const QSize &size,
const QSize &creditsSize,
EarnInt credits) {
StarsAmount credits) {
const auto skip = st::channelEarnOverviewSubMinorLabelPos.x();
line->resize(line->width(), size.height());
minorLabel->moveToLeft(
@ -922,7 +922,7 @@ void InnerWidget::fill() {
: tr::lng_channel_earn_balance_about_temp);
Ui::AddSkip(container);
}
if (creditsData.availableBalance > 0) {
if (creditsData.availableBalance.value() > 0) {
AddHeader(container, tr::lng_bot_earn_balance_title);
auto availableBalanceValue = rpl::single(
creditsData.availableBalance

View file

@ -866,19 +866,19 @@ rpl::producer<uint64> AddCurrencyAction(
return state->balance.value();
}
rpl::producer<uint64> AddCreditsAction(
rpl::producer<StarsAmount> AddCreditsAction(
not_null<UserData*> user,
not_null<Ui::VerticalLayout*> wrap,
not_null<Controller*> controller) {
struct State final {
rpl::variable<uint64> balance;
rpl::variable<StarsAmount> balance;
};
const auto state = wrap->lifetime().make_state<State>();
const auto parentController = controller->parentController();
const auto wrapButton = AddActionButton(
wrap,
tr::lng_manage_peer_bot_balance_credits(),
state->balance.value() | rpl::map(rpl::mappers::_1 > 0),
state->balance.value() | rpl::map(rpl::mappers::_1 > StarsAmount(0)),
[=] { parentController->showSection(Info::BotEarn::Make(user)); },
nullptr);
{
@ -918,7 +918,7 @@ rpl::producer<uint64> AddCreditsAction(
) | rpl::start_with_next([=, &st](
int width,
const QString &button,
uint64 balance) {
StarsAmount balance) {
const auto available = width
- rect::m::sum::h(st.padding)
- st.style.font->width(button)
@ -926,7 +926,7 @@ rpl::producer<uint64> AddCreditsAction(
name->setMarkedText(
base::duplicate(icon)
.append(QChar(' '))
.append(Lang::FormatCountDecimal(balance)),
.append(Lang::FormatStarsAmountDecimal(balance)),
Core::MarkedTextContext{
.session = &user->session(),
.customEmojiRepaint = [=] { name->update(); },
@ -2130,7 +2130,8 @@ void ActionsFiller::addBalanceActions(not_null<UserData*> user) {
rpl::combine(
std::move(currencyBalance),
std::move(creditsBalance)
) | rpl::map((rpl::mappers::_1 + rpl::mappers::_2) > 0));
) | rpl::map((rpl::mappers::_1 > 0)
|| (rpl::mappers::_2 > StarsAmount(0))));
}
void ActionsFiller::addInviteToGroupAction(not_null<UserData*> user) {

View file

@ -916,8 +916,7 @@ void CreditsRow::init() {
st::semiboldTextStyle,
TextWithEntities()
.append(_entry.in ? QChar('+') : kMinus)
.append(
Lang::FormatCountDecimal(std::abs(int64(_entry.credits))))
.append(Lang::FormatStarsAmountDecimal(_entry.credits.abs()))
.append(QChar(' '))
.append(manager.creditsEmoji()),
kMarkupTextOptions,

View file

@ -2346,7 +2346,9 @@ void AttachWebView::resolveUsername(
}
_session->api().request(base::take(_requestId)).cancel();
_requestId = _session->api().request(MTPcontacts_ResolveUsername(
MTP_string(_botUsername)
MTP_flags(0),
MTP_string(_botUsername),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
_requestId = 0;
result.match([&](const MTPDcontacts_resolvedPeer &data) {

View file

@ -241,7 +241,9 @@ void Shown::fillChannelJoinedValues(const Prepared &result) {
const auto channel = _session->data().channel(channelId);
if (!channel->isLoaded() && !channel->username().isEmpty()) {
channel->session().api().request(MTPcontacts_ResolveUsername(
MTP_string(channel->username())
MTP_flags(0),
MTP_string(channel->username()),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
channel->owner().processUsers(result.data().vusers());
channel->owner().processChats(result.data().vchats());

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "lang/lang_tag.h"
#include "core/stars_amount.h"
#include "lang/lang_keys.h"
#include "ui/text/text.h"
#include "base/qt/qt_common_adapters.h"
@ -945,6 +946,21 @@ QString FormatCountDecimal(int64 number) {
return QString("%L1").arg(number);
}
QString FormatExactCountDecimal(float64 number) {
return QString("%L1").arg(number);
}
ShortenedCount FormatStarsAmountToShort(StarsAmount amount) {
const auto attempt = FormatCountToShort(amount.whole());
return attempt.shortened ? attempt : ShortenedCount{
.string = FormatStarsAmountDecimal(amount),
};
}
QString FormatStarsAmountDecimal(StarsAmount amount) {
return FormatExactCountDecimal(amount.value());
}
PluralResult Plural(
ushort keyBase,
float64 value,

View file

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
class StarsAmount;
enum lngtag_count : int;
namespace Lang {
@ -26,6 +28,9 @@ struct ShortenedCount {
};
[[nodiscard]] ShortenedCount FormatCountToShort(int64 number);
[[nodiscard]] QString FormatCountDecimal(int64 number);
[[nodiscard]] QString FormatExactCountDecimal(float64 number);
[[nodiscard]] ShortenedCount FormatStarsAmountToShort(StarsAmount amount);
[[nodiscard]] QString FormatStarsAmountDecimal(StarsAmount amount);
struct PluralResult {
int keyShift = 0;

View file

@ -416,10 +416,11 @@ void ResolveChannel(
).arg(QString::number(error.code()) + ':' + error.type()));
fail();
};
mtp->send(
MTPcontacts_ResolveUsername(MTP_string(username)),
doneHandler,
failHandler);
mtp->send(MTPcontacts_ResolveUsername(
MTP_flags(0),
MTP_string(username),
MTP_string()
), doneHandler, failHandler);
}
std::optional<MTPMessage> GetMessagesElement(

View file

@ -151,8 +151,8 @@ messageActionChannelMigrateFrom#ea3948e9 title:string chat_id:long = MessageActi
messageActionPinMessage#94bd38ed = MessageAction;
messageActionHistoryClear#9fbab604 = MessageAction;
messageActionGameScore#92a72876 game_id:long score:int = MessageAction;
messageActionPaymentSentMe#8f31b327 flags:# recurring_init:flags.2?true recurring_used:flags.3?true currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
messageActionPaymentSent#96163f56 flags:# recurring_init:flags.2?true recurring_used:flags.3?true currency:string total_amount:long invoice_slug:flags.0?string = MessageAction;
messageActionPaymentSentMe#ffa00ccc flags:# recurring_init:flags.2?true recurring_used:flags.3?true currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge subscription_until_date:flags.4?int = MessageAction;
messageActionPaymentSent#c624b16e flags:# recurring_init:flags.2?true recurring_used:flags.3?true currency:string total_amount:long invoice_slug:flags.0?string subscription_until_date:flags.4?int = MessageAction;
messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
messageActionScreenshotTaken#4792929b = MessageAction;
messageActionCustomAction#fae69f56 message:string = MessageAction;
@ -235,7 +235,7 @@ inputReportReasonFake#f5ddd6e7 = ReportReason;
inputReportReasonIllegalDrugs#a8eb2be = ReportReason;
inputReportReasonPersonalDetails#9ec7863d = ReportReason;
userFull#1f58e369 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int = UserFull;
userFull#979d2376 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true voice_messages_forbidden:flags.20?true translations_disabled:flags.23?true stories_pinned_available:flags.26?true blocked_my_stories_from:flags.27?true wallpaper_overridden:flags.28?true contact_require_premium:flags.29?true read_dates_private:flags.30?true flags2:# sponsored_enabled:flags2.7?true can_view_revenue:flags2.9?true bot_can_manage_emoji_status:flags2.10?true id:long about:flags.1?string settings:PeerSettings personal_photo:flags.21?Photo profile_photo:flags.2?Photo fallback_photo:flags.22?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string bot_group_admin_rights:flags.17?ChatAdminRights bot_broadcast_admin_rights:flags.18?ChatAdminRights premium_gifts:flags.19?Vector<PremiumGiftOption> wallpaper:flags.24?WallPaper stories:flags.25?PeerStories business_work_hours:flags2.0?BusinessWorkHours business_location:flags2.1?BusinessLocation business_greeting_message:flags2.2?BusinessGreetingMessage business_away_message:flags2.3?BusinessAwayMessage business_intro:flags2.4?BusinessIntro birthday:flags2.5?Birthday personal_channel_id:flags2.6?long personal_channel_message:flags2.6?int stargifts_count:flags2.8?int starref_program:flags2.11?StarRefProgram = UserFull;
contact#145ade0b user_id:long mutual:Bool = Contact;
@ -421,12 +421,11 @@ updateBotEditBusinessMessage#7df587c flags:# connection_id:string message:Messag
updateBotDeleteBusinessMessage#a02a982e connection_id:string peer:Peer messages:Vector<int> qts:int = Update;
updateNewStoryReaction#1824e40b story_id:int peer:Peer reaction:Reaction = Update;
updateBroadcastRevenueTransactions#dfd961f5 peer:Peer balances:BroadcastRevenueBalances = Update;
updateStarsBalance#fb85198 balance:long = Update;
updateStarsBalance#4e80a379 balance:StarsAmount = Update;
updateBusinessBotCallbackQuery#1ea2fda7 flags:# query_id:long user_id:long connection_id:string message:Message reply_to_message:flags.2?Message chat_instance:long data:flags.0?bytes = Update;
updateStarsRevenueStatus#a584b019 peer:Peer status:StarsRevenueStatus = Update;
updateBotPurchasedPaidMedia#283bd312 user_id:long payload:string qts:int = Update;
updatePaidReactionPrivacy#51ca7aec private:Bool = Update;
updateBotSubscriptionExpire#2d13c6ee user_id:long payload:string invoice_slug:string until_date:int qts:int = Update;
updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;
@ -1832,9 +1831,9 @@ starsTransactionPeerAPI#f9677aad = StarsTransactionPeer;
starsTopupOption#bd915c0 flags:# extended:flags.1?true stars:long store_product:flags.0?string currency:string amount:long = StarsTopupOption;
starsTransaction#35d4f276 flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true reaction:flags.11?true id:string stars:long date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector<MessageMedia> subscription_period:flags.12?int giveaway_post_id:flags.13?int stargift:flags.14?StarGift floodskip_number:flags.15?int = StarsTransaction;
starsTransaction#64dfc926 flags:# refund:flags.3?true pending:flags.4?true failed:flags.6?true gift:flags.10?true reaction:flags.11?true id:string stars:StarsAmount date:int peer:StarsTransactionPeer title:flags.0?string description:flags.1?string photo:flags.2?WebDocument transaction_date:flags.5?int transaction_url:flags.5?string bot_payload:flags.7?bytes msg_id:flags.8?int extended_media:flags.9?Vector<MessageMedia> subscription_period:flags.12?int giveaway_post_id:flags.13?int stargift:flags.14?StarGift floodskip_number:flags.15?int starref_commission_permille:flags.16?int starref_peer:flags.17?Peer starref_amount:flags.17?StarsAmount = StarsTransaction;
payments.starsStatus#bbfa316c flags:# balance:long subscriptions:flags.1?Vector<StarsSubscription> subscriptions_next_offset:flags.2?string subscriptions_missing_balance:flags.4?long history:flags.3?Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
payments.starsStatus#6c9ce8ed flags:# balance:StarsAmount subscriptions:flags.1?Vector<StarsSubscription> subscriptions_next_offset:flags.2?string subscriptions_missing_balance:flags.4?long history:flags.3?Vector<StarsTransaction> next_offset:flags.0?string chats:Vector<Chat> users:Vector<User> = payments.StarsStatus;
foundStory#e87acbc0 peer:Peer story:StoryItem = FoundStory;
@ -1842,7 +1841,7 @@ stories.foundStories#e2de7737 flags:# count:int stories:Vector<FoundStory> next_
geoPointAddress#de4c5d93 flags:# country_iso2:string state:flags.0?string city:flags.1?string street:flags.2?string = GeoPointAddress;
starsRevenueStatus#79342946 flags:# withdrawal_enabled:flags.0?true current_balance:long available_balance:long overall_revenue:long next_withdrawal_at:flags.1?int = StarsRevenueStatus;
starsRevenueStatus#febe5491 flags:# withdrawal_enabled:flags.0?true current_balance:StarsAmount available_balance:StarsAmount overall_revenue:StarsAmount next_withdrawal_at:flags.1?int = StarsRevenueStatus;
payments.starsRevenueStats#c92bb73b revenue_graph:StatsGraph status:StarsRevenueStatus usd_rate:double = payments.StarsRevenueStats;
@ -1891,6 +1890,19 @@ messages.preparedInlineMessage#ff57708d query_id:long result:BotInlineResult pee
botAppSettings#c99b1950 flags:# placeholder_path:flags.0?bytes background_color:flags.1?int background_dark_color:flags.2?int header_color:flags.3?int header_dark_color:flags.4?int = BotAppSettings;
starRefProgram#dd0c66f2 flags:# bot_id:long commission_permille:int duration_months:flags.0?int end_date:flags.1?int daily_revenue_per_user:flags.2?StarsAmount = StarRefProgram;
connectedBotStarRef#19a13f71 flags:# revoked:flags.1?true url:string date:int bot_id:long commission_permille:int duration_months:flags.0?int participants:long revenue:long = ConnectedBotStarRef;
payments.connectedStarRefBots#98d5ea1d count:int connected_bots:Vector<ConnectedBotStarRef> users:Vector<User> = payments.ConnectedStarRefBots;
payments.suggestedStarRefBots#b4d5d859 flags:# count:int suggested_bots:Vector<StarRefProgram> users:Vector<User> next_offset:flags.0?string = payments.SuggestedStarRefBots;
starsAmount#bbb6b4a3 amount:long nanos:int = StarsAmount;
messages.foundStickersNotModified#6010c534 flags:# next_offset:flags.0?int = messages.FoundStickers;
messages.foundStickers#82c9e290 flags:# next_offset:flags.0?int hash:long stickers:Vector<Document> = messages.FoundStickers;
---functions---
invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
@ -2056,7 +2068,7 @@ contacts.block#2e2e8734 flags:# my_stories_from:flags.0?true id:InputPeer = Bool
contacts.unblock#b550d328 flags:# my_stories_from:flags.0?true id:InputPeer = Bool;
contacts.getBlocked#9a868f80 flags:# my_stories_from:flags.0?true offset:int limit:int = contacts.Blocked;
contacts.search#11f812d8 q:string limit:int = contacts.Found;
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
contacts.resolveUsername#725afbbc flags:# username:string referer:flags.0?string = contacts.ResolvedPeer;
contacts.getTopPeers#973478b6 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true bots_app:flags.16?true offset:int limit:int hash:long = contacts.TopPeers;
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
contacts.resetSaved#879537f1 = Bool;
@ -2296,6 +2308,7 @@ messages.reportSponsoredMessage#1af3dbb8 peer:InputPeer random_id:bytes option:b
messages.getSponsoredMessages#9bd2f439 peer:InputPeer = messages.SponsoredMessages;
messages.savePreparedInlineMessage#f21f7f2f flags:# result:InputBotInlineResult user_id:InputUser peer_types:flags.0?Vector<InlineQueryPeerType> = messages.BotPreparedInlineMessage;
messages.getPreparedInlineMessage#857ebdb8 bot:InputUser id:string = messages.PreparedInlineMessage;
messages.searchStickers#29b1c66a flags:# emojis:flags.0?true q:string emoticon:string lang_code:Vector<string> offset:int limit:int hash:long = messages.FoundStickers;
updates.getState#edd4882a = updates.State;
updates.getDifference#19c2f763 flags:# pts:int pts_limit:flags.1?int pts_total_limit:flags.0?int date:int qts:int qts_limit:flags.2?int = updates.Difference;
@ -2430,6 +2443,8 @@ bots.getPreviewMedias#a2a5594d bot:InputUser = Vector<BotPreviewMedia>;
bots.updateUserEmojiStatus#ed9f30c5 user_id:InputUser emoji_status:EmojiStatus = Bool;
bots.toggleUserEmojiStatusPermission#6de6392 bot:InputUser enabled:Bool = Bool;
bots.checkDownloadFileParams#50077589 bot:InputUser file_name:string url:string = Bool;
bots.getAdminedBots#b0711d83 = Vector<User>;
bots.updateStarRefProgram#778b5ab3 flags:# bot:InputUser commission_permille:int duration_months:flags.0?int = StarRefProgram;
payments.getPaymentForm#37148dbb flags:# invoice:InputInvoice theme_params:flags.0?DataJSON = payments.PaymentForm;
payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt;
@ -2465,7 +2480,12 @@ payments.getStarGifts#c4563590 hash:int = payments.StarGifts;
payments.getUserStarGifts#5e72c7e1 user_id:InputUser offset:string limit:int = payments.UserStarGifts;
payments.saveStarGift#87acf08e flags:# unsave:flags.0?true user_id:InputUser msg_id:int = Bool;
payments.convertStarGift#421e027 user_id:InputUser msg_id:int = Bool;
payments.botCancelStarsSubscription#57f9ece6 flags:# restore:flags.0?true user_id:InputUser invoice_slug:flags.1?string charge_id:flags.2?string = Bool;
payments.botCancelStarsSubscription#6dfa0622 flags:# restore:flags.0?true user_id:InputUser charge_id:string = Bool;
payments.getConnectedStarRefBots#5869a553 flags:# peer:InputPeer offset_date:flags.2?int offset_link:flags.2?string limit:int = payments.ConnectedStarRefBots;
payments.getConnectedStarRefBot#b7d998f0 peer:InputPeer bot:InputUser = payments.ConnectedStarRefBots;
payments.getSuggestedStarRefBots#d6b48f7 flags:# order_by_revenue:flags.0?true order_by_date:flags.1?true peer:InputPeer offset:string limit:int = payments.SuggestedStarRefBots;
payments.connectStarRefBot#7ed5348a peer:InputPeer bot:InputUser = payments.ConnectedStarRefBots;
payments.editConnectedStarRefBot#e4fca4a3 flags:# revoked:flags.0?true peer:InputPeer link:string = payments.ConnectedStarRefBots;
stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
@ -2585,4 +2605,4 @@ smsjobs.finishJob#4f1ebf24 flags:# job_id:string error:flags.0?string = Bool;
fragment.getCollectibleInfo#be1e85ba collectible:InputCollectible = fragment.CollectibleInfo;
// LAYER 193
// LAYER 195

View file

@ -611,7 +611,7 @@ void Form::processReceipt(const MTPDpayments_paymentReceiptStars &data) {
ImageLocation())
: nullptr,
.peerId = peerFromUser(data.vbot_id().v),
.credits = data.vtotal_amount().v,
.credits = StarsAmount(data.vtotal_amount().v),
.date = data.vdate().v,
};
_updates.fire(CreditsReceiptReady{ .data = receiptData });

View file

@ -210,7 +210,7 @@ struct CreditsReceiptData {
QString description;
PhotoData *photo = nullptr;
PeerId peerId = PeerId(0);
uint64 credits = 0;
StarsAmount credits;
TimeId date = 0;
};

View file

@ -29,7 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Settings {
[[nodiscard]] not_null<Ui::RpWidget*> AddBalanceWidget(
not_null<Ui::RpWidget*> parent,
rpl::producer<uint64> balanceValue,
rpl::producer<StarsAmount> balanceValue,
bool rightAlign,
rpl::producer<float64> opacityValue = nullptr);
} // namespace Settings

View file

@ -36,7 +36,7 @@ struct PaidReactionBoxArgs {
QString channel;
Fn<rpl::producer<TextWithContext>(rpl::producer<int> amount)> submit;
rpl::producer<uint64> balanceValue;
rpl::producer<StarsAmount> balanceValue;
Fn<void(int, bool)> send;
};

View file

@ -272,7 +272,9 @@ Main::Session &PreviewController::session() const {
const auto requestId = result.make_state<mtpRequestId>();
*requestId = session->api().request(MTPcontacts_ResolveUsername(
MTP_string(extracted)
MTP_flags(0),
MTP_string(extracted),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
const auto &data = result.data();
session->data().processUsers(data.vusers());

View file

@ -380,7 +380,7 @@ void Credits::setupContent() {
const auto balanceAmount = Ui::CreateChild<Ui::FlatLabel>(
balanceLine,
_controller->session().credits().balanceValue(
) | rpl::map(Lang::FormatCountDecimal),
) | rpl::map(Lang::FormatStarsAmountDecimal),
st::creditsSettingsBigBalance);
balanceAmount->sizeValue() | rpl::start_with_next([=] {
balanceLine->resize(
@ -430,7 +430,8 @@ void Credits::setupContent() {
const auto options = state->api
? state->api->options()
: Data::CreditTopupOptions();
FillCreditOptions(show, inner, self, 0, paid, nullptr, options);
const auto amount = StarsAmount();
FillCreditOptions(show, inner, self, amount, paid, nullptr, options);
const auto button = box->addButton(tr::lng_close(), [=] {
box->closeBox();

View file

@ -129,13 +129,13 @@ class Balance final
public:
using Ui::RpWidget::RpWidget;
void setBalance(uint64 balance) {
void setBalance(StarsAmount balance) {
_balance = balance;
_tooltip = Lang::FormatCountDecimal(balance);
_tooltip = Lang::FormatStarsAmountDecimal(balance);
}
void enterEventHook(QEnterEvent *e) override {
if (_balance >= 10'000) {
if (_balance >= StarsAmount(10'000)) {
Ui::Tooltip::Show(1000, this);
}
}
@ -158,7 +158,7 @@ public:
private:
QString _tooltip;
uint64 _balance = 0;
StarsAmount _balance;
};
@ -305,7 +305,7 @@ void AddViewMediaHandler(
state->item->overrideMedia(std::make_unique<Data::MediaInvoice>(
state->item,
Data::Invoice{
.amount = uint64(std::abs(int64(e.credits))),
.amount = uint64(e.credits.abs().whole()),
.currency = Ui::kCreditsCurrency,
.extendedMedia = std::move(fake),
.isPaidMedia = true,
@ -429,7 +429,7 @@ void FillCreditOptions(
std::shared_ptr<Main::SessionShow> show,
not_null<Ui::VerticalLayout*> container,
not_null<PeerData*> peer,
int minimumCredits,
StarsAmount minimumCredits,
Fn<void()> paid,
rpl::producer<QString> subtitle,
std::vector<Data::CreditTopupOption> preloadedTopupOptions) {
@ -475,12 +475,12 @@ void FillCreditOptions(
- int(singleStarWidth * 1.5);
const auto buttonHeight = st.height + rect::m::sum::v(st.padding);
const auto minCredits = (!options.empty()
&& (minimumCredits > options.back().credits))
? 0
&& (minimumCredits > StarsAmount(options.back().credits)))
? StarsAmount()
: minimumCredits;
for (auto i = 0; i < options.size(); i++) {
const auto &option = options[i];
if (option.credits < minCredits) {
if (StarsAmount(option.credits) < minCredits) {
continue;
}
const auto button = [&] {
@ -607,7 +607,7 @@ void FillCreditOptions(
not_null<Ui::RpWidget*> AddBalanceWidget(
not_null<Ui::RpWidget*> parent,
rpl::producer<uint64> balanceValue,
rpl::producer<StarsAmount> balanceValue,
bool rightAlign,
rpl::producer<float64> opacityValue) {
struct State final {
@ -641,10 +641,12 @@ not_null<Ui::RpWidget*> AddBalanceWidget(
+ diffBetweenStarAndCount),
state->label.style()->font->height + starSize.height());
};
std::move(balanceValue) | rpl::start_with_next([=](uint64 value) {
std::move(
balanceValue
) | rpl::start_with_next([=](StarsAmount value) {
state->count.setText(
st::semiboldTextStyle,
Lang::FormatCountToShort(value).string);
Lang::FormatStarsAmountToShort(value).string);
balance->setBalance(value);
resize();
}, balance->lifetime());
@ -929,7 +931,7 @@ void ReceiptCreditsBox(
auto &packs = session->giftBoxStickersPacks();
const auto document = starGiftSticker
? starGiftSticker
: packs.lookup(packs.monthsForStars(e.credits));
: packs.lookup(packs.monthsForStars(e.credits.whole()));
if (document && document->sticker()) {
state->sticker = document;
state->media = document->createMediaView();
@ -1075,7 +1077,7 @@ void ReceiptCreditsBox(
: (e.gift && !creditsHistoryStarGift)
? QString()
: QString(kMinus))
.append(Lang::FormatCountDecimal(std::abs(int64(e.credits))))
.append(Lang::FormatStarsAmountDecimal(e.credits.abs()))
.append(QChar(' '))
.append(session->data().customEmojiManager().creditsEmoji());
text->setMarkedText(
@ -1532,7 +1534,7 @@ void GiftedCreditsBox(
? tr::lng_credits_box_history_entry_gift_name
: tr::lng_credits_box_history_entry_gift_sent)(tr::now),
.date = base::unixtime::parse(date),
.credits = uint64(count),
.credits = StarsAmount(count),
.bareMsgId = uint64(),
.barePeerId = (anonymous ? uint64() : peer->id.value),
.peerType = (anonymous ? PeerType::Fragment : PeerType::Peer),
@ -1555,7 +1557,7 @@ void CreditsPrizeBox(
.title = QString(),
.description = TextWithEntities(),
.date = base::unixtime::parse(date),
.credits = uint64(data.count),
.credits = StarsAmount(data.count),
.barePeerId = data.channel
? data.channel->id.value
: 0,
@ -1576,7 +1578,7 @@ void UserStarGiftBox(
Data::CreditsHistoryEntry{
.description = data.message,
.date = base::unixtime::parse(data.date),
.credits = uint64(data.info.stars),
.credits = StarsAmount(data.info.stars),
.bareMsgId = uint64(data.messageId.bare),
.barePeerId = data.fromId.value,
.bareGiftStickerId = data.info.document->id,
@ -1607,7 +1609,7 @@ void StarGiftViewBox(
.id = data.slug,
.description = data.message,
.date = base::unixtime::parse(item->date()),
.credits = uint64(data.count),
.credits = StarsAmount(data.count),
.bareMsgId = uint64(item->id.bare),
.barePeerId = item->history()->peer->id.value,
.bareGiftStickerId = data.document ? data.document->id : 0,
@ -1640,7 +1642,7 @@ void ShowRefundInfoBox(
auto info = Data::CreditsHistoryEntry();
info.id = refund->transactionId;
info.date = base::unixtime::parse(item->date());
info.credits = refund->amount;
info.credits = StarsAmount(refund->amount);
info.barePeerId = refund->peer->id.value;
info.peerType = Data::CreditsHistoryEntry::PeerType::Peer;
info.refunded = true;
@ -1733,11 +1735,13 @@ object_ptr<Ui::RpWidget> SubscriptionUserpic(
void SmallBalanceBox(
not_null<Ui::GenericBox*> box,
std::shared_ptr<Main::SessionShow> show,
uint64 credits,
uint64 wholeCredits,
SmallBalanceSource source,
Fn<void()> paid) {
Expects(show->session().credits().loaded());
auto credits = StarsAmount(wholeCredits);
box->setWidth(st::boxWideWidth);
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
const auto done = [=] {
@ -1761,8 +1765,8 @@ void SmallBalanceBox(
});
auto needed = show->session().credits().balanceValue(
) | rpl::map([=](uint64 balance) {
return (balance < credits) ? (credits - balance) : 0;
) | rpl::map([=](StarsAmount balance) {
return (balance < credits) ? (credits - balance) : StarsAmount();
});
const auto content = [&]() -> Ui::Premium::TopBarAbstract* {
return box->setPinnedToTopContent(object_ptr<Ui::Premium::TopBar>(
@ -1773,7 +1777,11 @@ void SmallBalanceBox(
lt_count,
rpl::duplicate(
needed
) | rpl::filter(rpl::mappers::_1 > 0) | tr::to_count()),
) | rpl::filter(
rpl::mappers::_1 > StarsAmount(0)
) | rpl::map([](StarsAmount amount) {
return amount.value();
})),
.about = (v::is<SmallBalanceSubscription>(source)
? tr::lng_credits_small_balance_subscribe(
lt_channel,
@ -1857,7 +1865,7 @@ void AddWithdrawalWidget(
not_null<Window::SessionController*> controller,
not_null<PeerData*> peer,
rpl::producer<QString> secondButtonUrl,
rpl::producer<uint64> availableBalanceValue,
rpl::producer<StarsAmount> availableBalanceValue,
rpl::producer<QDateTime> dateValue,
rpl::producer<bool> lockedValue,
rpl::producer<QString> usdValue) {
@ -1870,8 +1878,10 @@ void AddWithdrawalWidget(
const auto majorLabel = Ui::CreateChild<Ui::FlatLabel>(
labels,
rpl::duplicate(availableBalanceValue) | rpl::map([](uint64 v) {
return Lang::FormatCountDecimal(v);
rpl::duplicate(
availableBalanceValue
) | rpl::map([](StarsAmount v) {
return Lang::FormatStarsAmountDecimal(v);
}),
st::channelEarnBalanceMajorLabel);
const auto icon = Ui::CreateSingleStarWidget(
@ -1965,12 +1975,12 @@ void AddWithdrawalWidget(
.session = session,
.customEmojiRepaint = [=] { label->update(); },
};
using Balance = rpl::variable<uint64>;
using Balance = rpl::variable<StarsAmount>;
const auto currentBalance = input->lifetime().make_state<Balance>(
rpl::duplicate(availableBalanceValue));
const auto process = [=] {
const auto amount = input->getLastText().toDouble();
if (amount >= currentBalance->current()) {
if (amount >= currentBalance->current().value()) {
label->setText(
tr::lng_bot_earn_balance_button_all(tr::now));
} else {
@ -2179,7 +2189,7 @@ void MaybeRequestBalanceIncrease(
state->lifetime.destroy();
const auto balance = session->credits().balance();
if (credits <= balance) {
if (StarsAmount(credits) <= balance) {
if (const auto onstack = done) {
onstack(SmallBalanceResult::Already);
}

View file

@ -58,14 +58,14 @@ void FillCreditOptions(
std::shared_ptr<Main::SessionShow> show,
not_null<Ui::VerticalLayout*> container,
not_null<PeerData*> peer,
int minCredits,
StarsAmount minCredits,
Fn<void()> paid,
rpl::producer<QString> subtitle,
std::vector<Data::CreditTopupOption> preloadedTopupOptions);
[[nodiscard]] not_null<Ui::RpWidget*> AddBalanceWidget(
not_null<Ui::RpWidget*> parent,
rpl::producer<uint64> balanceValue,
rpl::producer<StarsAmount> balanceValue,
bool rightAlign,
rpl::producer<float64> opacityValue = nullptr);
@ -74,7 +74,7 @@ void AddWithdrawalWidget(
not_null<Window::SessionController*> controller,
not_null<PeerData*> peer,
rpl::producer<QString> secondButtonUrl,
rpl::producer<uint64> availableBalanceValue,
rpl::producer<StarsAmount> availableBalanceValue,
rpl::producer<QDateTime> dateValue,
rpl::producer<bool> lockedValue,
rpl::producer<QString> usdValue);
@ -162,7 +162,7 @@ struct SmallBalanceSource : std::variant<
void SmallBalanceBox(
not_null<Ui::GenericBox*> box,
std::shared_ptr<Main::SessionShow> show,
uint64 credits,
uint64 wholeCredits,
SmallBalanceSource source,
Fn<void()> paid);

View file

@ -515,8 +515,10 @@ void SetupPremium(
container,
tr::lng_settings_credits(),
controller->session().credits().balanceValue(
) | rpl::map([=](uint64 c) {
return c ? Lang::FormatCountToShort(c).string : QString{};
) | rpl::map([=](StarsAmount c) {
return c
? Lang::FormatStarsAmountToShort(c).string
: QString();
}),
st::settingsButton),
true

View file

@ -133,6 +133,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/palette.h"
#include "styles/style_basic.h"
#include "core/stars_amount.h"
#include "core/utils.h"
#include "logs.h"
#include "config.h"

View file

@ -1155,7 +1155,9 @@ void LocationPicker::venuesRequest(
}
const auto username = _session->serverConfig().venueSearchUsername;
_venuesBotRequestId = _api.request(MTPcontacts_ResolveUsername(
MTP_string(username)
MTP_flags(0),
MTP_string(username),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
auto &data = result.data();
_session->data().processUsers(data.vusers());

View file

@ -162,23 +162,23 @@ not_null<RpWidget*> CreateSingleStarWidget(
not_null<MaskedInputField*> AddInputFieldForCredits(
not_null<VerticalLayout*> container,
rpl::producer<uint64> value) {
rpl::producer<StarsAmount> value) {
const auto &st = st::botEarnInputField;
const auto inputContainer = container->add(
CreateSkipWidget(container, st.heightMin));
const auto currentValue = rpl::variable<uint64>(
const auto currentValue = rpl::variable<StarsAmount>(
rpl::duplicate(value));
const auto input = CreateChild<NumberInput>(
inputContainer,
st,
tr::lng_bot_earn_out_ph(),
QString::number(currentValue.current()),
currentValue.current());
QString::number(currentValue.current().whole()),
currentValue.current().whole());
rpl::duplicate(
value
) | rpl::start_with_next([=](uint64 v) {
input->changeLimit(v);
input->setText(QString::number(v));
) | rpl::start_with_next([=](StarsAmount v) {
input->changeLimit(v.whole());
input->setText(QString::number(v.whole()));
}, input->lifetime());
const auto icon = CreateSingleStarWidget(
inputContainer,

View file

@ -40,7 +40,7 @@ using PaintRoundImageCallback = Fn<void(
[[nodiscard]] not_null<Ui::MaskedInputField*> AddInputFieldForCredits(
not_null<Ui::VerticalLayout*> container,
rpl::producer<uint64> value);
rpl::producer<StarsAmount> value);
PaintRoundImageCallback GenerateCreditsPaintUserpicCallback(
const Data::CreditsHistoryEntry &entry);

View file

@ -34,6 +34,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/flat_map.h"
#include "base/flat_set.h"
#include "core/stars_amount.h"
#include "ui/arc_angles.h"
#include "ui/text/text.h"
#include "ui/effects/animations.h"

View file

@ -461,7 +461,9 @@ void SessionNavigation::resolveUsername(
}
_api.request(base::take(_resolveRequestId)).cancel();
_resolveRequestId = _api.request(MTPcontacts_ResolveUsername(
MTP_string(username)
MTP_flags(0),
MTP_string(username),
MTP_string()
)).done([=](const MTPcontacts_ResolvedPeer &result) {
resolveDone(result, done);
}).fail([=](const MTP::Error &error) {