Added support of special sticker pack for currency history entries.

This commit is contained in:
23rd 2025-06-29 20:58:40 +03:00
parent d1796a515e
commit a809ccf229
4 changed files with 82 additions and 36 deletions

View file

@ -36,38 +36,61 @@ int GiftBoxPack::monthsForStars(int stars) const {
} }
} }
DocumentData *GiftBoxPack::lookup(int months) const { DocumentData *GiftBoxPack::lookup(int months, Type type) const {
const auto it = ranges::lower_bound(_localMonths, months); const auto it = _setsData.find(type);
const auto fallback = _documents.empty() ? nullptr : _documents[0]; if (it == _setsData.end() || it->second.documents.empty()) {
if (it == begin(_localMonths)) { return nullptr;
return fallback;
} else if (it == end(_localMonths)) {
return _documents.back();
} }
const auto left = *(it - 1);
const auto right = *it; const auto& documents = it->second.documents;
const auto itMonths = ranges::lower_bound(_localMonths, months);
const auto fallback = documents[0];
if (itMonths == begin(_localMonths)) {
return fallback;
} else if (itMonths == end(_localMonths)) {
return documents.back();
}
const auto left = *(itMonths - 1);
const auto right = *itMonths;
const auto shift = (std::abs(months - left) < std::abs(months - right)) const auto shift = (std::abs(months - left) < std::abs(months - right))
? -1 ? -1
: 0; : 0;
const auto index = int(std::distance(begin(_localMonths), it - shift)); const auto index = int(
return (index >= _documents.size()) ? fallback : _documents[index]; std::distance(begin(_localMonths), itMonths - shift));
return (index >= documents.size()) ? fallback : documents[index];
} }
Data::FileOrigin GiftBoxPack::origin() const { Data::FileOrigin GiftBoxPack::origin(Type type) const {
return Data::FileOriginStickerSet(_setId, _accessHash); const auto it = _setsData.find(type);
if (it == _setsData.end()) {
return Data::FileOrigin();
}
return Data::FileOriginStickerSet(
it->second.setId,
it->second.accessHash);
} }
void GiftBoxPack::load() { void GiftBoxPack::load(Type type) {
if (_requestId || !_documents.empty()) { if (_requestId) {
return; return;
} }
const auto it = _setsData.find(type);
if (it != _setsData.end() && !it->second.documents.empty()) {
return;
}
_requestId = _session->api().request(MTPmessages_GetStickerSet( _requestId = _session->api().request(MTPmessages_GetStickerSet(
MTP_inputStickerSetPremiumGifts(), type == Type::Currency
? MTP_inputStickerSetTonGifts()
: MTP_inputStickerSetPremiumGifts(),
MTP_int(0) // Hash. MTP_int(0) // Hash.
)).done([=](const MTPmessages_StickerSet &result) { )).done([=](const MTPmessages_StickerSet &result) {
_requestId = 0; _requestId = 0;
result.match([&](const MTPDmessages_stickerSet &data) { result.match([&](const MTPDmessages_stickerSet &data) {
applySet(data); applySet(data, type);
}, [](const MTPDmessages_stickerSetNotModified &) { }, [](const MTPDmessages_stickerSetNotModified &) {
LOG(("API Error: Unexpected messages.stickerSetNotModified.")); LOG(("API Error: Unexpected messages.stickerSetNotModified."));
}); });
@ -76,21 +99,24 @@ void GiftBoxPack::load() {
}).send(); }).send();
} }
void GiftBoxPack::applySet(const MTPDmessages_stickerSet &data) { void GiftBoxPack::applySet(const MTPDmessages_stickerSet &data, Type type) {
_setId = data.vset().data().vid().v; auto setData = SetData();
_accessHash = data.vset().data().vaccess_hash().v; setData.setId = data.vset().data().vid().v;
setData.accessHash = data.vset().data().vaccess_hash().v;
auto documents = base::flat_map<DocumentId, not_null<DocumentData*>>(); auto documents = base::flat_map<DocumentId, not_null<DocumentData*>>();
for (const auto &sticker : data.vdocuments().v) { for (const auto &sticker : data.vdocuments().v) {
const auto document = _session->data().processDocument(sticker); const auto document = _session->data().processDocument(sticker);
if (document->sticker()) { if (document->sticker()) {
documents.emplace(document->id, document); documents.emplace(document->id, document);
if (_documents.empty()) { if (setData.documents.empty()) {
// Fallback. // Fallback.
_documents.resize(1); setData.documents.resize(1);
_documents[0] = document; setData.documents[0] = document;
} }
} }
} }
for (const auto &pack : data.vpacks().v) { for (const auto &pack : data.vpacks().v) {
pack.match([&](const MTPDstickerPack &data) { pack.match([&](const MTPDstickerPack &data) {
const auto emoji = qs(data.vemoticon()); const auto emoji = qs(data.vemoticon());
@ -106,16 +132,18 @@ void GiftBoxPack::applySet(const MTPDmessages_stickerSet &data) {
if (index < 0 || index >= _localMonths.size()) { if (index < 0 || index >= _localMonths.size()) {
return; return;
} }
if ((index + 1) > _documents.size()) { if ((index + 1) > setData.documents.size()) {
_documents.resize((index + 1)); setData.documents.resize((index + 1));
} }
_documents[index] = (*document); setData.documents[index] = (*document);
} }
} }
} }
} }
}); });
} }
_setsData[type] = std::move(setData);
_updated.fire({}); _updated.fire({});
} }

View file

@ -21,26 +21,37 @@ namespace Stickers {
class GiftBoxPack final { class GiftBoxPack final {
public: public:
enum class Type {
Gifts,
Currency,
};
explicit GiftBoxPack(not_null<Main::Session*> session); explicit GiftBoxPack(not_null<Main::Session*> session);
~GiftBoxPack(); ~GiftBoxPack();
void load(); void load(Type type = Type::Gifts);
[[nodiscard]] int monthsForStars(int stars) const; [[nodiscard]] int monthsForStars(int stars) const;
[[nodiscard]] DocumentData *lookup(int months) const; [[nodiscard]] DocumentData *lookup(
[[nodiscard]] Data::FileOrigin origin() const; int months,
Type type = Type::Gifts) const;
[[nodiscard]] Data::FileOrigin origin(Type type = Type::Gifts) const;
[[nodiscard]] rpl::producer<> updated() const; [[nodiscard]] rpl::producer<> updated() const;
private: private:
using SetId = uint64; using SetId = uint64;
void applySet(const MTPDmessages_stickerSet &data); struct SetData {
SetId setId = 0;
uint64 accessHash = 0;
std::vector<DocumentData*> documents;
};
void applySet(const MTPDmessages_stickerSet &data, Type type);
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
const std::vector<int> _localMonths; const std::vector<int> _localMonths;
rpl::event_stream<> _updated; rpl::event_stream<> _updated;
std::vector<DocumentData*> _documents; base::flat_map<Type, SetData> _setsData;
SetId _setId = 0;
uint64 _accessHash = 0;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
}; };

View file

@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/star_gift_box.h" #include "boxes/star_gift_box.h"
#include "boxes/gift_credits_box.h" #include "boxes/gift_credits_box.h"
#include "boxes/gift_premium_box.h" #include "boxes/gift_premium_box.h"
#include "chat_helpers/stickers_gift_box_pack.h"
#include "core/click_handler_types.h" #include "core/click_handler_types.h"
#include "data/components/credits.h" #include "data/components/credits.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
@ -120,6 +121,8 @@ Credits::Credits(
st::tonFieldIconSize, st::tonFieldIconSize,
st::windowActiveTextFg->c) st::windowActiveTextFg->c)
: Ui::GenerateStars(st::creditsBalanceStarHeight, 1)) { : Ui::GenerateStars(st::creditsBalanceStarHeight, 1)) {
_controller->session().giftBoxStickersPacks().load(
Stickers::GiftBoxPack::Type::Currency);
setupContent(); setupContent();
_controller->session().premiumPossibleValue( _controller->session().premiumPossibleValue(

View file

@ -1311,9 +1311,13 @@ void GenericCreditsEntryBox(
auto &packs = session->giftBoxStickersPacks(); auto &packs = session->giftBoxStickersPacks();
const auto document = starGiftSticker const auto document = starGiftSticker
? starGiftSticker ? starGiftSticker
: packs.lookup(e.premiumMonthsForStars : packs.lookup(
? e.premiumMonthsForStars e.premiumMonthsForStars
: packs.monthsForStars(e.credits.whole())); ? e.premiumMonthsForStars
: packs.monthsForStars(e.credits.whole()),
e.credits.stars()
? Stickers::GiftBoxPack::Type::Gifts
: Stickers::GiftBoxPack::Type::Currency);
if (document && document->sticker()) { if (document && document->sticker()) {
state->sticker = document; state->sticker = document;
state->media = document->createMediaView(); state->media = document->createMediaView();