Update API scheme on layer 144.

This commit is contained in:
John Preston 2022-07-05 23:36:25 +04:00
parent c01d9747e7
commit b87fd601ab
5 changed files with 79 additions and 88 deletions

View file

@ -629,7 +629,7 @@ messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity;
messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity;
messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity;
messageEntitySpoiler#32ca960f offset:int length:int = MessageEntity;
messageEntityCustomEmoji#d4a00ed5 offset:int length:int stickerset:InputStickerSet document_id:long = MessageEntity;
messageEntityCustomEmoji#c8cf05f8 offset:int length:int document_id:long = MessageEntity;
inputChannelEmpty#ee8c1e86 = InputChannel;
inputChannel#f35aec28 channel_id:long access_hash:long = InputChannel;
@ -1696,6 +1696,7 @@ messages.sendWebViewResultMessage#a4314f5 bot_query_id:string result:InputBotInl
messages.sendWebViewData#dc0242c8 bot:InputUser random_id:long button_text:string data:string = Updates;
messages.transcribeAudio#269e9a49 peer:InputPeer msg_id:int = messages.TranscribedAudio;
messages.rateTranscribedAudio#7f1d072f peer:InputPeer msg_id:int transcription_id:long good:Bool = Bool;
messages.getCustomEmojiDocuments#d9ab0f54 document_id:Vector<long> = Vector<Document>;
updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
@ -1800,7 +1801,7 @@ payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?t
payments.getBankCardData#2e79d779 number:string = payments.BankCardData;
payments.exportInvoice#f91b065 invoice_media:InputMedia = payments.ExportedInvoice;
payments.assignAppStoreTransaction#80ed747d receipt:bytes purpose:InputStorePaymentPurpose = Updates;
payments.assignPlayMarketTransaction#f546d3fe purchase_token:string purpose:InputStorePaymentPurpose = Updates;
payments.assignPlayMarketTransaction#dffd50d3 receipt:DataJSON purpose:InputStorePaymentPurpose = Updates;
payments.canPurchasePremium#aa6a90c8 = Bool;
payments.requestRecurringPayment#146e958d user_id:InputUser recurring_init_charge:string invoice_media:InputMedia = Updates;

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/stickers/data_custom_emoji.h"
#include "data/stickers/data_stickers_set.h"
#include "data/data_session.h"
#include "data/data_document.h"
#include "data/data_user.h"
namespace Api {
@ -24,7 +25,6 @@ using namespace TextUtilities;
return Data::SerializeCustomEmojiId({
.selfId = session->userId().bare,
.id = data.vdocument_id().v,
.set = Data::FromInputSet(data.vstickerset()),
});
}
@ -37,11 +37,14 @@ using namespace TextUtilities;
if (!parsed.id || parsed.selfId != session->userId().bare) {
return {};
}
const auto document = session->data().document(parsed.id);
if (!document->sticker()) {
return {};
}
return MTP_messageEntityCustomEmoji(
offset,
length,
Data::InputStickerSet(parsed.set),
MTP_long(parsed.id));
MTP_long(document->id));
}
[[nodiscard]] std::optional<MTPMessageEntity> MentionNameEntity(

View file

@ -22,10 +22,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "data/stickers/data_stickers.h"
#include "ui/widgets/input_fields.h"
#include "ui/text/text_block.h"
namespace Data {
namespace {
constexpr auto kMaxPerRequest = 100;
using SizeTag = CustomEmojiManager::SizeTag;
[[nodiscard]] ChatHelpers::StickerLottieSize LottieSizeFromTag(SizeTag tag) {
@ -306,7 +310,7 @@ auto CustomEmojiLoader::InitialState(
const CustomEmojiId &id)
-> std::variant<Resolve, Lookup, Load> {
const auto document = owner->document(id.id);
if (!document->isNull()) {
if (document->sticker()) {
return Lookup{ document };
}
return Resolve{ .entityData = SerializeCustomEmojiId(id) };
@ -353,15 +357,11 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
QStringView data,
Fn<void()> update) {
const auto parsed = ParseCustomEmojiData(data);
if (!parsed.id || !parsed.set.id) {
if (!parsed.id) {
return nullptr;
}
auto i = _instances.find(parsed.set.id);
auto i = _instances.find(parsed.id);
if (i == end(_instances)) {
i = _instances.emplace(parsed.set.id).first;
}
auto j = i->second.find(parsed.id);
if (j == end(i->second)) {
using Loading = Ui::CustomEmoji::Loading;
auto loader = std::make_unique<CustomEmojiLoader>(
_owner,
@ -369,76 +369,69 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
SizeTag::Normal);
if (loader->resolving()) {
_loaders[parsed.id].push_back(base::make_weak(loader.get()));
_pendingForRequest.emplace(parsed.id);
if (!_requestId && _pendingForRequest.size() == 1) {
crl::on_main(this, [=] { request(); });
}
}
const auto repaint = [=](
not_null<Ui::CustomEmoji::Instance*> instance,
Ui::CustomEmoji::RepaintRequest request) {
repaintLater(instance, request);
};
j = i->second.emplace(
i = _instances.emplace(
parsed.id,
std::make_unique<Ui::CustomEmoji::Instance>(Loading{
std::move(loader),
Ui::CustomEmoji::Preview()
}, std::move(repaint))).first;
}
requestSetIfNeeded(parsed);
return std::make_unique<Ui::CustomEmoji::Object>(
j->second.get(),
i->second.get(),
std::move(update));
}
void CustomEmojiManager::requestSetIfNeeded(const CustomEmojiId &id) {
const auto setId = id.set.id;
auto i = _sets.find(setId);
if (i == end(_sets)) {
i = _sets.emplace(setId).first;
void CustomEmojiManager::request() {
auto ids = QVector<MTPlong>();
ids.reserve(std::min(kMaxPerRequest, int(_pendingForRequest.size())));
while (!_pendingForRequest.empty() && ids.size() < kMaxPerRequest) {
const auto i = _pendingForRequest.end() - 1;
ids.push_back(MTP_long(*i));
_pendingForRequest.erase(i);
}
if (i->second.documents.contains(id.id)) {
return;
} else if (!i->second.waiting.emplace(id.id).second
|| i->second.requestId) {
if (ids.isEmpty()) {
return;
}
const auto api = &_owner->session().api();
i->second.requestId = api->request(MTPmessages_GetStickerSet(
InputStickerSet(id.set),
MTP_int(i->second.hash)
)).done([=](const MTPmessages_StickerSet &result) {
const auto i = _sets.find(setId);
Assert(i != end(_sets));
i->second.requestId = 0;
result.match([&](const MTPDmessages_stickerSet &data) {
data.vset().match([&](const MTPDstickerSet &data) {
i->second.hash = data.vhash().v;
});
for (const auto &entry : data.vdocuments().v) {
const auto document = _owner->processDocument(entry);
const auto id = document->id;
i->second.documents.emplace(id);
i->second.waiting.remove(id);
if (const auto loaders = _loaders.take(id)) {
for (const auto &weak : *loaders) {
if (const auto strong = weak.get()) {
strong->resolved(document);
}
_requestId = api->request(MTPmessages_GetCustomEmojiDocuments(
MTP_vector<MTPlong>(ids)
)).done([=](const MTPVector<MTPDocument> &result) {
for (const auto &entry : result.v) {
const auto document = _owner->processDocument(entry);
const auto id = document->id;
if (const auto loaders = _loaders.take(id)) {
for (const auto &weak : *loaders) {
if (const auto strong = weak.get()) {
strong->resolved(document);
}
}
}
}, [&](const MTPDmessages_stickerSetNotModified &) {
});
for (const auto &id : base::take(i->second.waiting)) {
DEBUG_LOG(("API Error: Sticker '%1' not found for emoji.").arg(id));
}
requestFinished();
}).fail([=] {
const auto i = _sets.find(setId);
Assert(i != end(_sets));
i->second.requestId = 0;
LOG(("API Error: Failed getting set '%1' for emoji.").arg(setId));
LOG(("API Error: Failed to get documents for emoji."));
requestFinished();
}).send();
}
void CustomEmojiManager::requestFinished() {
_requestId = 0;
if (!_pendingForRequest.empty()) {
request();
}
}
void CustomEmojiManager::repaintLater(
not_null<Ui::CustomEmoji::Instance*> instance,
Ui::CustomEmoji::RepaintRequest request) {
@ -506,45 +499,40 @@ Session &CustomEmojiManager::owner() const {
}
QString SerializeCustomEmojiId(const CustomEmojiId &id) {
return QString::number(id.set.id)
+ '.'
+ QString::number(id.set.accessHash)
return QString::number(id.id)
+ ':'
+ QString::number(id.selfId)
+ '/'
+ QString::number(id.id);
+ QString::number(id.selfId);
}
QString SerializeCustomEmojiId(not_null<DocumentData*> document) {
const auto sticker = document->sticker();
return SerializeCustomEmojiId({
.selfId = document->session().userId().bare,
.id = document->id,
.set = sticker ? sticker->set : StickerSetIdentifier(),
});
}
CustomEmojiId ParseCustomEmojiData(QStringView data) {
const auto components = data.split('.');
const auto components = data.split(':');
if (components.size() != 2) {
return {};
}
const auto parts = components[1].split(':');
if (parts.size() != 2) {
return {};
}
const auto endings = parts[1].split('/');
if (endings.size() != 2) {
return {};
}
return {
.selfId = endings[0].toULongLong(),
.id = endings[1].toULongLong(),
.set = {
.id = components[0].toULongLong(),
.accessHash = parts[0].toULongLong(),
},
.selfId = components[1].toULongLong(),
.id = components[0].toULongLong(),
};
}
void InsertCustomEmoji(
not_null<Ui::InputField*> field,
not_null<DocumentData*> document) {
const auto sticker = document->sticker();
if (!sticker || sticker->alt.isEmpty()) {
return;
}
Ui::InsertCustomEmojiAtCursor(
field->textCursor(),
sticker->alt,
Ui::InputField::CustomEmojiLink(SerializeCustomEmojiId(document)));
}
} // namespace Data

View file

@ -26,7 +26,6 @@ class CustomEmojiLoader;
struct CustomEmojiId {
uint64 selfId = 0;
uint64 id = 0;
StickerSetIdentifier set;
};
class CustomEmojiManager final : public base::has_weak_ptr {
@ -47,18 +46,13 @@ public:
[[nodiscard]] Session &owner() const;
private:
struct Set {
int32 hash = 0;
mtpRequestId requestId = 0;
base::flat_set<uint64> documents;
base::flat_set<uint64> waiting;
};
struct RepaintBunch {
crl::time when = 0;
std::vector<base::weak_ptr<Ui::CustomEmoji::Instance>> instances;
};
void requestSetIfNeeded(const CustomEmojiId &id);
void request();
void requestFinished();
void repaintLater(
not_null<Ui::CustomEmoji::Instance*> instance,
Ui::CustomEmoji::RepaintRequest request);
@ -67,13 +61,14 @@ private:
const not_null<Session*> _owner;
base::flat_map<uint64, base::flat_map<
base::flat_map<
uint64,
std::unique_ptr<Ui::CustomEmoji::Instance>>> _instances;
base::flat_map<uint64, Set> _sets;
std::unique_ptr<Ui::CustomEmoji::Instance>> _instances;
base::flat_map<
uint64,
std::vector<base::weak_ptr<CustomEmojiLoader>>> _loaders;
base::flat_set<uint64> _pendingForRequest;
mtpRequestId _requestId = 0;
base::flat_map<crl::time, RepaintBunch> _repaints;
crl::time _repaintNext = 0;
@ -87,4 +82,8 @@ private:
not_null<DocumentData*> document);
[[nodiscard]] CustomEmojiId ParseCustomEmojiData(QStringView data);
void InsertCustomEmoji(
not_null<Ui::InputField*> field,
not_null<DocumentData*> document);
} // namespace Data

@ -1 +1 @@
Subproject commit 464c6a61711fa7b66d45829bde582d36e23f0b1a
Subproject commit 9cb7bb58f658d7603f9493b9d051cf8a78a2cd41