From 0a3077b9a5e2a4f2e1569c6fafd9f6dbc7973c8e Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 1 Sep 2022 09:58:04 +0400 Subject: [PATCH] Update API scheme on layer 145. --- Telegram/Resources/tl/api.tl | 2 + Telegram/SourceFiles/api/api_updates.cpp | 30 +++++++ .../SourceFiles/data/data_emoji_statuses.cpp | 82 ++++++++++++++++--- .../SourceFiles/data/data_emoji_statuses.h | 13 +++ Telegram/SourceFiles/data/data_user.cpp | 11 ++- Telegram/SourceFiles/data/data_user.h | 2 +- 6 files changed, 122 insertions(+), 18 deletions(-) diff --git a/Telegram/Resources/tl/api.tl b/Telegram/Resources/tl/api.tl index c4352b762..c5f2fe6b1 100644 --- a/Telegram/Resources/tl/api.tl +++ b/Telegram/Resources/tl/api.tl @@ -396,6 +396,7 @@ updateReadFeaturedEmojiStickers#fb4c496c = Update; updateUserEmojiStatus#28373599 user_id:long emoji_status:EmojiStatus = Update; updateRecentEmojiStatuses#30f443db = Update; updateRecentReactions#6f7863f4 = Update; +updateMoveStickerSetToTop#86fccf85 flags:# masks:flags.0?true emojis:flags.1?true stickerset:long = Update; updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State; @@ -1411,6 +1412,7 @@ paymentFormMethod#88f8f21b url:string title:string = PaymentFormMethod; emojiStatusEmpty#2de11aae = EmojiStatus; emojiStatus#929b619d document_id:long = EmojiStatus; +emojiStatusUntil#fa30a8c7 document_id:long until:int = EmojiStatus; account.emojiStatusesNotModified#d08ce645 = account.EmojiStatuses; account.emojiStatuses#90c467d1 hash:long statuses:Vector = account.EmojiStatuses; diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index 4bdea7355..cef69bd80 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -2345,6 +2345,36 @@ void Updates::feedUpdate(const MTPUpdate &update) { } } break; + case mtpc_updateMoveStickerSetToTop: { + const auto &d = update.c_updateMoveStickerSetToTop(); + auto &stickers = session().data().stickers(); + const auto isEmoji = d.is_emojis(); + const auto setId = d.vstickerset().v; + auto &order = isEmoji + ? stickers.emojiSetsOrderRef() + : stickers.setsOrderRef(); + const auto i = ranges::find(order, setId); + if (i == order.end()) { + if (isEmoji) { + stickers.setLastEmojiUpdate(0); + session().api().updateCustomEmoji(); + } else { + stickers.setLastUpdate(0); + session().api().updateStickers(); + } + } else if (i != order.begin()) { + std::rotate(order.begin(), i, i + 1); + if (isEmoji) { + session().local().writeInstalledCustomEmoji(); + } else { + session().local().writeInstalledStickers(); + } + stickers.notifyUpdated(isEmoji + ? Data::StickersType::Emoji + : Data::StickersType::Stickers); + } + } break; + case mtpc_updateStickerSets: { const auto &d = update.c_updateStickerSets(); if (d.is_emojis()) { diff --git a/Telegram/SourceFiles/data/data_emoji_statuses.cpp b/Telegram/SourceFiles/data/data_emoji_statuses.cpp index 8a8df9b5f..21345dcc0 100644 --- a/Telegram/SourceFiles/data/data_emoji_statuses.cpp +++ b/Telegram/SourceFiles/data/data_emoji_statuses.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_document.h" #include "data/stickers/data_stickers.h" +#include "base/unixtime.h" #include "base/timer_rpl.h" #include "base/call_delayed.h" #include "apiwrap.h" @@ -21,14 +22,7 @@ namespace { constexpr auto kRefreshDefaultListEach = 60 * 60 * crl::time(1000); constexpr auto kRecentRequestTimeout = 10 * crl::time(1000); - -[[nodiscard]] DocumentId Parse(const MTPEmojiStatus &status) { - return status.match([&](const MTPDemojiStatus &data) { - return DocumentId(data.vdocument_id().v); - }, [](const MTPDemojiStatusEmpty &) { - return DocumentId(); - }); -} +constexpr auto kMaxTimeout = 6 * 60 * 60 * crl::time(1000); [[nodiscard]] std::vector ListFromMTP( const MTPDaccount_emojiStatuses &data) { @@ -36,11 +30,11 @@ constexpr auto kRecentRequestTimeout = 10 * crl::time(1000); auto result = std::vector(); result.reserve(list.size()); for (const auto &status : list) { - const auto id = Parse(status); - if (!id) { + const auto parsed = ParseEmojiStatus(status); + if (!parsed.id) { LOG(("API Error: emojiStatusEmpty in account.emojiStatuses.")); } else { - result.push_back(id); + result.push_back(parsed.id); } } return result; @@ -102,6 +96,62 @@ rpl::producer<> EmojiStatuses::defaultUpdates() const { return _defaultUpdated.events(); } +void EmojiStatuses::registerAutomaticClear( + not_null user, + TimeId until) { + if (!until) { + _clearing.remove(user); + if (_clearing.empty()) { + _clearingTimer.cancel(); + } + } else if (auto &already = _clearing[user]; already != until) { + already = until; + const auto i = ranges::min_element(_clearing, {}, [](auto &&pair) { + return pair.second; + }); + if (i->first == user) { + const auto now = base::unixtime::now(); + if (now < until) { + const auto waitms = (until - now) * crl::time(1000); + _clearingTimer.callOnce(std::min(waitms, kMaxTimeout)); + } else { + processClearing(); + } + } + } +} + +void EmojiStatuses::processClearing() { + auto minWait = TimeId(0); + const auto now = base::unixtime::now(); + auto clearing = base::take(_clearing); + for (auto i = begin(clearing); i != end(clearing);) { + const auto until = i->second; + if (now < until) { + const auto wait = (until - now); + if (!minWait || minWait > wait) { + minWait = wait; + } + ++i; + } else { + i->first->setEmojiStatus(0, 0); + i = clearing.erase(i); + } + } + if (_clearing.empty()) { + _clearing = std::move(clearing); + } else { + for (const auto &[user, until] : clearing) { + _clearing.emplace(user, until); + } + } + if (minWait) { + _clearingTimer.callOnce(minWait * crl::time(1000)); + } else { + _clearingTimer.cancel(); + } +} + void EmojiStatuses::requestRecent() { if (_recentRequestId) { return; @@ -172,4 +222,14 @@ bool EmojiStatuses::setting() const { return _sentRequestId != 0;; } +EmojiStatusData ParseEmojiStatus(const MTPEmojiStatus &status) { + return status.match([](const MTPDemojiStatus &data) { + return EmojiStatusData{ data.vdocument_id().v }; + }, [](const MTPDemojiStatusUntil &data) { + return EmojiStatusData{ data.vdocument_id().v, data.vuntil().v }; + }, [](const MTPDemojiStatusEmpty &) { + return EmojiStatusData(); + }); +} + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_emoji_statuses.h b/Telegram/SourceFiles/data/data_emoji_statuses.h index c1293e332..2685a50f0 100644 --- a/Telegram/SourceFiles/data/data_emoji_statuses.h +++ b/Telegram/SourceFiles/data/data_emoji_statuses.h @@ -48,6 +48,8 @@ public: void set(DocumentId id); [[nodiscard]] bool setting() const; + void registerAutomaticClear(not_null user, TimeId until); + private: void requestRecent(); void requestDefault(); @@ -55,6 +57,8 @@ private: void updateRecent(const MTPDaccount_emojiStatuses &data); void updateDefault(const MTPDaccount_emojiStatuses &data); + void processClearing(); + const not_null _owner; std::vector _recent; @@ -72,8 +76,17 @@ private: mtpRequestId _sentRequestId = 0; + base::flat_map, crl::time> _clearing; + base::Timer _clearingTimer; + rpl::lifetime _lifetime; }; +struct EmojiStatusData { + DocumentId id = 0; + TimeId until = 0; +}; +[[nodiscard]] EmojiStatusData ParseEmojiStatus(const MTPEmojiStatus &status); + } // namespace Data diff --git a/Telegram/SourceFiles/data/data_user.cpp b/Telegram/SourceFiles/data/data_user.cpp index 72c57fb34..64edc3ae0 100644 --- a/Telegram/SourceFiles/data/data_user.cpp +++ b/Telegram/SourceFiles/data/data_user.cpp @@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_changes.h" #include "data/data_peer_bot_command.h" +#include "data/data_emoji_statuses.h" #include "ui/text/text_options.h" #include "apiwrap.h" #include "lang/lang_keys.h" @@ -58,18 +59,16 @@ void UserData::setPhoto(const MTPUserProfilePhoto &photo) { } void UserData::setEmojiStatus(const MTPEmojiStatus &status) { - setEmojiStatus(status.match([&](const MTPDemojiStatus &data) { - return DocumentId(data.vdocument_id().v); - }, [&](const MTPDemojiStatusEmpty &) { - return DocumentId(); - })); + const auto parsed = Data::ParseEmojiStatus(status); + setEmojiStatus(parsed.id, parsed.until); } -void UserData::setEmojiStatus(DocumentId emojiStatusId) { +void UserData::setEmojiStatus(DocumentId emojiStatusId, TimeId until) { if (_emojiStatusId != emojiStatusId) { _emojiStatusId = emojiStatusId; session().changes().peerUpdated(this, UpdateFlag::EmojiStatus); } + owner().emojiStatuses().registerAutomaticClear(this, until); } DocumentId UserData::emojiStatusId() const { diff --git a/Telegram/SourceFiles/data/data_user.h b/Telegram/SourceFiles/data/data_user.h index f8f28592a..9b138b621 100644 --- a/Telegram/SourceFiles/data/data_user.h +++ b/Telegram/SourceFiles/data/data_user.h @@ -72,7 +72,7 @@ public: const QString &newPhoneName, const QString &newUsername); - void setEmojiStatus(DocumentId emojiStatusId); + void setEmojiStatus(DocumentId emojiStatusId, TimeId until = 0); [[nodiscard]] DocumentId emojiStatusId() const; void setPhone(const QString &newPhone);