credits.cpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "data/components/credits.h"
  8. #include "api/api_credits.h"
  9. #include "data/data_user.h"
  10. #include "main/main_app_config.h"
  11. #include "main/main_session.h"
  12. namespace Data {
  13. namespace {
  14. constexpr auto kReloadThreshold = 60 * crl::time(1000);
  15. } // namespace
  16. StarsAmount FromTL(const MTPStarsAmount &value) {
  17. const auto &data = value.data();
  18. return StarsAmount(data.vamount().v, data.vnanos().v);
  19. }
  20. Credits::Credits(not_null<Main::Session*> session)
  21. : _session(session)
  22. , _reload([=] { load(true); }) {
  23. }
  24. Credits::~Credits() = default;
  25. void Credits::apply(const MTPDupdateStarsBalance &data) {
  26. apply(FromTL(data.vbalance()));
  27. }
  28. rpl::producer<float64> Credits::rateValue(
  29. not_null<PeerData*> ownedBotOrChannel) {
  30. return rpl::single(_session->appConfig().starsWithdrawRate());
  31. }
  32. void Credits::load(bool force) {
  33. if (_loader
  34. || (!force
  35. && _lastLoaded
  36. && _lastLoaded + kReloadThreshold > crl::now())) {
  37. return;
  38. }
  39. _loader = std::make_unique<Api::CreditsStatus>(_session->user());
  40. _loader->request({}, [=](Data::CreditsStatusSlice slice) {
  41. _loader = nullptr;
  42. apply(slice.balance);
  43. });
  44. }
  45. bool Credits::loaded() const {
  46. return _lastLoaded != 0;
  47. }
  48. rpl::producer<bool> Credits::loadedValue() const {
  49. if (loaded()) {
  50. return rpl::single(true);
  51. }
  52. return rpl::single(
  53. false
  54. ) | rpl::then(_loadedChanges.events() | rpl::map_to(true));
  55. }
  56. StarsAmount Credits::balance() const {
  57. return _nonLockedBalance.current();
  58. }
  59. StarsAmount Credits::balance(PeerId peerId) const {
  60. const auto it = _cachedPeerBalances.find(peerId);
  61. return (it != _cachedPeerBalances.end()) ? it->second : StarsAmount();
  62. }
  63. uint64 Credits::balanceCurrency(PeerId peerId) const {
  64. const auto it = _cachedPeerCurrencyBalances.find(peerId);
  65. return (it != _cachedPeerCurrencyBalances.end()) ? it->second : 0;
  66. }
  67. rpl::producer<StarsAmount> Credits::balanceValue() const {
  68. return _nonLockedBalance.value();
  69. }
  70. void Credits::updateNonLockedValue() {
  71. _nonLockedBalance = (_balance >= _locked)
  72. ? (_balance - _locked)
  73. : StarsAmount();
  74. }
  75. void Credits::lock(StarsAmount count) {
  76. Expects(loaded());
  77. Expects(count >= StarsAmount(0));
  78. Expects(_locked + count <= _balance);
  79. _locked += count;
  80. updateNonLockedValue();
  81. }
  82. void Credits::unlock(StarsAmount count) {
  83. Expects(count >= StarsAmount(0));
  84. Expects(_locked >= count);
  85. _locked -= count;
  86. updateNonLockedValue();
  87. }
  88. void Credits::withdrawLocked(StarsAmount count) {
  89. Expects(count >= StarsAmount(0));
  90. Expects(_locked >= count);
  91. _locked -= count;
  92. apply(_balance >= count ? (_balance - count) : StarsAmount(0));
  93. invalidate();
  94. }
  95. void Credits::invalidate() {
  96. _reload.call();
  97. }
  98. void Credits::apply(StarsAmount balance) {
  99. _balance = balance;
  100. updateNonLockedValue();
  101. const auto was = std::exchange(_lastLoaded, crl::now());
  102. if (!was) {
  103. _loadedChanges.fire({});
  104. }
  105. }
  106. void Credits::apply(PeerId peerId, StarsAmount balance) {
  107. _cachedPeerBalances[peerId] = balance;
  108. }
  109. void Credits::applyCurrency(PeerId peerId, uint64 balance) {
  110. _cachedPeerCurrencyBalances[peerId] = balance;
  111. }
  112. } // namespace Data