From d0132c0f7bc2f33adba53b2f29bde52fafbd9314 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 9 Jan 2025 11:24:54 +0400 Subject: [PATCH] Update API scheme to layer 198. --- Telegram/SourceFiles/api/api_editing.cpp | 1 + Telegram/SourceFiles/api/api_media.cpp | 1 + Telegram/SourceFiles/api/api_sending.cpp | 4 + Telegram/SourceFiles/apiwrap.cpp | 1 + .../boxes/peers/edit_peer_color_box.cpp | 28 +++-- .../SourceFiles/data/data_emoji_statuses.cpp | 118 ++++++++++++------ .../SourceFiles/data/data_emoji_statuses.h | 57 ++++++--- Telegram/SourceFiles/data/data_peer.cpp | 6 +- Telegram/SourceFiles/data/data_peer.h | 6 +- Telegram/SourceFiles/data/data_session.cpp | 4 +- Telegram/SourceFiles/data/data_types.h | 18 +++ .../admin_log/history_admin_log_item.cpp | 10 +- .../view/history_view_contact_status.cpp | 8 +- .../history/view/history_view_message.cpp | 4 +- .../info/profile/info_profile_badge.cpp | 12 +- .../info/profile/info_profile_badge.h | 2 +- .../info_profile_emoji_status_panel.cpp | 26 ++-- .../profile/info_profile_emoji_status_panel.h | 4 +- .../info/profile/info_profile_values.cpp | 4 +- .../info/profile/info_profile_values.h | 2 +- .../inline_bots/bot_attach_web_view.cpp | 2 +- Telegram/SourceFiles/mtproto/scheme/api.tl | 14 ++- .../SourceFiles/settings/settings_premium.cpp | 12 +- Telegram/SourceFiles/ui/unread_badge.cpp | 19 ++- .../SourceFiles/window/window_main_menu.cpp | 2 +- 25 files changed, 251 insertions(+), 114 deletions(-) diff --git a/Telegram/SourceFiles/api/api_editing.cpp b/Telegram/SourceFiles/api/api_editing.cpp index 662bfc980..2d9a86e13 100644 --- a/Telegram/SourceFiles/api/api_editing.cpp +++ b/Telegram/SourceFiles/api/api_editing.cpp @@ -283,6 +283,7 @@ mtpRequestId EditTextMessage( return MTP_inputMediaDocument( MTP_flags(flags), document->mtpInput(), + MTPInputPhoto(), // video_cover MTP_int(media->ttlSeconds()), MTPstring()); // query }; diff --git a/Telegram/SourceFiles/api/api_media.cpp b/Telegram/SourceFiles/api/api_media.cpp index 22fc37631..3d82f7ce0 100644 --- a/Telegram/SourceFiles/api/api_media.cpp +++ b/Telegram/SourceFiles/api/api_media.cpp @@ -121,6 +121,7 @@ MTPInputMedia PrepareUploadedDocument( ComposeSendingDocumentAttributes(document), MTP_vector( ranges::to>(info.attachedStickers)), + MTPInputPhoto(), // video_cover MTP_int(ttlSeconds)); } diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index d0b897a07..f926b0468 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -272,6 +272,7 @@ void SendExistingDocument( return MTP_inputMediaDocument( MTP_flags(0), document->mtpInput(), + MTPInputPhoto(), // video_cover MTPint(), // ttl_seconds MTPstring()); // query }; @@ -550,6 +551,7 @@ void SendConfirmedFile( | (file->spoiler ? Flag::f_spoiler : Flag())), file->document, MTPVector(), // alt_documents + MTPPhoto(), // video_cover MTPint()); } else if (file->type == SendMediaType::Audio) { const auto ttlSeconds = file->to.options.ttlSeconds; @@ -560,6 +562,7 @@ void SendConfirmedFile( | (ttlSeconds ? Flag::f_ttl_seconds : Flag())), file->document, MTPVector(), // alt_documents + MTPPhoto(), // video_cover MTP_int(ttlSeconds)); } else if (file->type == SendMediaType::Round) { using Flag = MTPDmessageMediaDocument::Flag; @@ -571,6 +574,7 @@ void SendConfirmedFile( | (file->spoiler ? Flag::f_spoiler : Flag())), file->document, MTPVector(), // alt_documents + MTPPhoto(), // video_cover MTP_int(ttlSeconds)); } else { Unexpected("Type in sendFilesConfirmed."); diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index fb9584523..fc9958c47 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -4146,6 +4146,7 @@ void ApiWrap::uploadAlbumMedia( fields.vid(), fields.vaccess_hash(), fields.vfile_reference()), + MTPInputPhoto(), // video_cover MTP_int(data.vttl_seconds().value_or_empty()), MTPstring()); // query sendAlbumWithUploaded(item, groupId, media); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp index 589e0613a..6cd4eb607 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp @@ -526,7 +526,7 @@ void LevelBadge::paintEvent(QPaintEvent *e) { struct SetValues { uint8 colorIndex = 0; DocumentId backgroundEmojiId = 0; - DocumentId statusId = 0; + EmojiStatusId statusId; TimeId statusUntil = 0; bool statusChanged = false; }; @@ -808,7 +808,7 @@ int ColorSelector::resizeGetHeight(int newWidth) { const auto state = right->lifetime().make_state(); state->panel.someCustomChosen( ) | rpl::start_with_next([=](EmojiStatusPanel::CustomChosen chosen) { - emojiIdChosen(chosen.id); + emojiIdChosen(chosen.id.documentId); }, raw->lifetime()); std::move(colorIndexValue) | rpl::start_with_next([=](uint8 index) { @@ -901,8 +901,8 @@ int ColorSelector::resizeGetHeight(int newWidth) { not_null parent, std::shared_ptr show, not_null channel, - rpl::producer statusIdValue, - Fn statusIdChosen, + rpl::producer statusIdValue, + Fn statusIdChosen, bool group) { const auto button = ButtonStyleWithRightEmoji( parent, @@ -924,20 +924,24 @@ int ColorSelector::resizeGetHeight(int newWidth) { struct State { EmojiStatusPanel panel; std::unique_ptr emoji; - DocumentId statusId = 0; + EmojiStatusId statusId; }; const auto state = right->lifetime().make_state(); state->panel.someCustomChosen( ) | rpl::start_with_next([=](EmojiStatusPanel::CustomChosen chosen) { - statusIdChosen(chosen.id, chosen.until); + statusIdChosen({ chosen.id }, chosen.until); }, raw->lifetime()); const auto session = &show->session(); - std::move(statusIdValue) | rpl::start_with_next([=](DocumentId id) { + std::move(statusIdValue) | rpl::start_with_next([=](EmojiStatusId id) { state->statusId = id; - state->emoji = id + state->emoji = id.collectible // todo collectibles ? session->data().customEmojiManager().create( - id, + id.collectible->documentId, + [=] { right->update(); }) + : id.documentId + ? session->data().customEmojiManager().create( + id.documentId, [=] { right->update(); }) : nullptr; right->resize( @@ -990,7 +994,7 @@ int ColorSelector::resizeGetHeight(int newWidth) { state->panel.show({ .controller = controller, .button = right, - .ensureAddedEmojiId = state->statusId, + .ensureAddedEmojiId = state->statusId.documentId, .channelStatusMode = true, }); } @@ -1182,7 +1186,7 @@ void EditPeerColorBox( struct State { rpl::variable index; rpl::variable emojiId; - rpl::variable statusId; + rpl::variable statusId; TimeId statusUntil = 0; bool statusChanged = false; bool changing = false; @@ -1319,7 +1323,7 @@ void EditPeerColorBox( show, channel, state->statusId.value(), - [=](DocumentId id, TimeId until) { + [=](EmojiStatusId id, TimeId until) { state->statusId = id; state->statusUntil = until; state->statusChanged = true; diff --git a/Telegram/SourceFiles/data/data_emoji_statuses.cpp b/Telegram/SourceFiles/data/data_emoji_statuses.cpp index e00dd8910..63ef7e76a 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_user.h" #include "data/data_session.h" #include "data/data_document.h" +#include "data/data_wall_paper.h" #include "data/stickers/data_stickers.h" #include "base/unixtime.h" #include "base/timer_rpl.h" @@ -26,20 +27,19 @@ constexpr auto kRefreshDefaultListEach = 60 * 60 * crl::time(1000); constexpr auto kRecentRequestTimeout = 10 * crl::time(1000); constexpr auto kMaxTimeout = 6 * 60 * 60 * crl::time(1000); -[[nodiscard]] std::vector ListFromMTP( - const MTPDaccount_emojiStatuses &data) { - const auto &list = data.vstatuses().v; - auto result = std::vector(); - result.reserve(list.size()); - for (const auto &status : list) { - const auto parsed = ParseEmojiStatus(status); - if (!parsed.id) { - LOG(("API Error: emojiStatusEmpty in account.emojiStatuses.")); - } else { - result.push_back(parsed.id); - } - } - return result; +[[nodiscard]] EmojiStatusCollectible ParseEmojiStatusCollectible( + const MTPDemojiStatusCollectible &data) { + return EmojiStatusCollectible{ + .id = data.vcollectible_id().v, + .documentId = data.vdocument_id().v, + .title = qs(data.vtitle()), + .slug = qs(data.vslug()), + .patternDocumentId = data.vpattern_document_id().v, + .centerColor = Ui::ColorFromSerialized(data.vcenter_color()), + .edgeColor = Ui::ColorFromSerialized(data.vedge_color()), + .patternColor = Ui::ColorFromSerialized(data.vpattern_color()), + .textColor = Ui::ColorFromSerialized(data.vtext_color()), + }; } } // namespace @@ -96,7 +96,7 @@ void EmojiStatuses::refreshRecentDelayed() { }); } -const std::vector &EmojiStatuses::list(Type type) const { +const std::vector &EmojiStatuses::list(Type type) const { switch (type) { case Type::Recent: return _recent; case Type::Default: return _default; @@ -107,6 +107,30 @@ const std::vector &EmojiStatuses::list(Type type) const { Unexpected("Type in EmojiStatuses::list."); } +EmojiStatusData EmojiStatuses::parse(const MTPEmojiStatus &status) { + return status.match([](const MTPDemojiStatus &data) { + return EmojiStatusData{ + .id = { .documentId = data.vdocument_id().v }, + .until = data.vuntil().value_or_empty(), + }; + }, [&](const MTPDemojiStatusCollectible &data) { + const auto collectibleId = data.vcollectible_id().v; + auto &collectible = _collectibleData[collectibleId]; + if (!collectible) { + collectible = std::make_shared( + ParseEmojiStatusCollectible(data)); + } + return EmojiStatusData{ + .id = { .collectible = collectible }, + .until = data.vuntil().value_or_empty(), + }; + }, [](const MTPDinputEmojiStatusCollectible &) { + return EmojiStatusData(); + }, [](const MTPDemojiStatusEmpty &) { + return EmojiStatusData(); + }); +} + rpl::producer<> EmojiStatuses::recentUpdates() const { return _recentUpdated.events(); } @@ -119,6 +143,10 @@ rpl::producer<> EmojiStatuses::channelDefaultUpdates() const { return _channelDefaultUpdated.events(); } +rpl::producer<> EmojiStatuses::collectiblesUpdates() const { + return _collectiblesUpdated.events(); +} + void EmojiStatuses::registerAutomaticClear( not_null peer, TimeId until) { @@ -253,7 +281,7 @@ void EmojiStatuses::processClearing() { } ++i; } else { - i->first->setEmojiStatus(0, 0); + i->first->setEmojiStatus(EmojiStatusId()); i = clearing.erase(i); } } @@ -271,6 +299,22 @@ void EmojiStatuses::processClearing() { } } +std::vector EmojiStatuses::parse( + const MTPDaccount_emojiStatuses &data) { + const auto &list = data.vstatuses().v; + auto result = std::vector(); + result.reserve(list.size()); + for (const auto &status : list) { + const auto parsed = parse(status); + if (!parsed.id) { + LOG(("API Error: empty status in account.emojiStatuses.")); + } else { + result.push_back(parsed.id); + } + } + return result; +} + void EmojiStatuses::processClearingIn(TimeId wait) { const auto waitms = wait * crl::time(1000); _clearingTimer.callOnce(std::min(waitms, kMaxTimeout)); @@ -376,13 +420,13 @@ void EmojiStatuses::requestChannelColored() { void EmojiStatuses::updateRecent(const MTPDaccount_emojiStatuses &data) { _recentHash = data.vhash().v; - _recent = ListFromMTP(data); + _recent = parse(data); _recentUpdated.fire({}); } void EmojiStatuses::updateDefault(const MTPDaccount_emojiStatuses &data) { _defaultHash = data.vhash().v; - _default = ListFromMTP(data); + _default = parse(data); _defaultUpdated.fire({}); } @@ -391,7 +435,9 @@ void EmojiStatuses::updateColored(const MTPDmessages_stickerSet &data) { _colored.clear(); _colored.reserve(list.size()); for (const auto &sticker : data.vdocuments().v) { - _colored.push_back(_owner->processDocument(sticker)->id); + _colored.push_back({ + .documentId = _owner->processDocument(sticker)->id, + }); } _coloredUpdated.fire({}); } @@ -399,7 +445,7 @@ void EmojiStatuses::updateColored(const MTPDmessages_stickerSet &data) { void EmojiStatuses::updateChannelDefault( const MTPDaccount_emojiStatuses &data) { _channelDefaultHash = data.vhash().v; - _channelDefault = ListFromMTP(data); + _channelDefault = parse(data); _channelDefaultUpdated.fire({}); } @@ -409,18 +455,20 @@ void EmojiStatuses::updateChannelColored( _channelColored.clear(); _channelColored.reserve(list.size()); for (const auto &sticker : data.vdocuments().v) { - _channelColored.push_back(_owner->processDocument(sticker)->id); + _channelColored.push_back({ + .documentId = _owner->processDocument(sticker)->id, + }); } _channelColoredUpdated.fire({}); } -void EmojiStatuses::set(DocumentId id, TimeId until) { +void EmojiStatuses::set(EmojiStatusId id, TimeId until) { set(_owner->session().user(), id, until); } void EmojiStatuses::set( not_null peer, - DocumentId id, + EmojiStatusId id, TimeId until) { auto &api = _owner->session().api(); auto &requestId = _sentRequests[peer]; @@ -437,11 +485,19 @@ void EmojiStatuses::set( _sentRequests.remove(peer); }).send(); }; + using EFlag = MTPDemojiStatus::Flag; + using CFlag = MTPDinputEmojiStatusCollectible::Flag; const auto status = !id ? MTP_emojiStatusEmpty() - : !until - ? MTP_emojiStatus(MTP_long(id)) - : MTP_emojiStatusUntil(MTP_long(id), MTP_int(until)); + : id.collectible + ? MTP_inputEmojiStatusCollectible( + MTP_flags(until ? CFlag::f_until : CFlag()), + MTP_long(id.collectible->id), + MTP_int(until)) + : MTP_emojiStatus( + MTP_flags(until ? EFlag::f_until : EFlag()), + MTP_long(id.documentId), + MTP_int(until)); if (peer->isSelf()) { send(MTPaccount_UpdateEmojiStatus(status)); } else if (const auto channel = peer->asChannel()) { @@ -449,14 +505,4 @@ void EmojiStatuses::set( } } -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 0a0b75ba2..203017219 100644 --- a/Telegram/SourceFiles/data/data_emoji_statuses.h +++ b/Telegram/SourceFiles/data/data_emoji_statuses.h @@ -22,6 +22,26 @@ namespace Data { class DocumentMedia; class Session; +struct EmojiStatusCollectible { + CollectibleId id = 0; + DocumentId documentId = 0; + QString title; + QString slug; + DocumentId patternDocumentId = 0; + QColor centerColor; + QColor edgeColor; + QColor patternColor; + QColor textColor; + + explicit operator bool() const { + return id != 0; + } +}; +struct EmojiStatusData { + EmojiStatusId id; + TimeId until = 0; +}; + class EmojiStatuses final { public: explicit EmojiStatuses(not_null owner); @@ -45,15 +65,19 @@ public: Colored, ChannelDefault, ChannelColored, + Collectibles, }; - [[nodiscard]] const std::vector &list(Type type) const; + [[nodiscard]] const std::vector &list(Type type) const; + + [[nodiscard]] EmojiStatusData parse(const MTPEmojiStatus &status); [[nodiscard]] rpl::producer<> recentUpdates() const; [[nodiscard]] rpl::producer<> defaultUpdates() const; [[nodiscard]] rpl::producer<> channelDefaultUpdates() const; + [[nodiscard]] rpl::producer<> collectiblesUpdates() const; - void set(DocumentId id, TimeId until = 0); - void set(not_null peer, DocumentId id, TimeId until = 0); + void set(EmojiStatusId id, TimeId until = 0); + void set(not_null peer, EmojiStatusId id, TimeId until = 0); void registerAutomaticClear(not_null peer, TimeId until); @@ -89,21 +113,30 @@ private: void processClearingIn(TimeId wait); void processClearing(); + [[nodiscard]] std::vector parse( + const MTPDaccount_emojiStatuses &data); + template void requestGroups(not_null type, Request &&request); const not_null _owner; - std::vector _recent; - std::vector _default; - std::vector _colored; - std::vector _channelDefault; - std::vector _channelColored; + std::vector _recent; + std::vector _default; + std::vector _colored; + std::vector _channelDefault; + std::vector _channelColored; + std::vector _collectibles; rpl::event_stream<> _recentUpdated; rpl::event_stream<> _defaultUpdated; rpl::event_stream<> _coloredUpdated; rpl::event_stream<> _channelDefaultUpdated; rpl::event_stream<> _channelColoredUpdated; + rpl::event_stream<> _collectiblesUpdated; + + base::flat_map< + CollectibleId, + std::shared_ptr> _collectibleData; mtpRequestId _recentRequestId = 0; bool _recentRequestScheduled = false; @@ -119,6 +152,8 @@ private: mtpRequestId _channelColoredRequestId = 0; + mtpRequestId _collectiblesRequestId = 0; + base::flat_map, mtpRequestId> _sentRequests; base::flat_map, TimeId> _clearing; @@ -133,10 +168,4 @@ private: }; -struct EmojiStatusData { - DocumentId id = 0; - TimeId until = 0; -}; -[[nodiscard]] EmojiStatusData ParseEmojiStatus(const MTPEmojiStatus &status); - } // namespace Data diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 901d7b7c8..52673acb9 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -1115,11 +1115,11 @@ bool PeerData::changeBackgroundEmojiId(DocumentId id) { } void PeerData::setEmojiStatus(const MTPEmojiStatus &status) { - const auto parsed = Data::ParseEmojiStatus(status); + const auto parsed = owner().emojiStatuses().parse(status); setEmojiStatus(parsed.id, parsed.until); } -void PeerData::setEmojiStatus(DocumentId emojiStatusId, TimeId until) { +void PeerData::setEmojiStatus(EmojiStatusId emojiStatusId, TimeId until) { if (_emojiStatusId != emojiStatusId) { _emojiStatusId = emojiStatusId; session().changes().peerUpdated(this, UpdateFlag::EmojiStatus); @@ -1127,7 +1127,7 @@ void PeerData::setEmojiStatus(DocumentId emojiStatusId, TimeId until) { owner().emojiStatuses().registerAutomaticClear(this, until); } -DocumentId PeerData::emojiStatusId() const { +EmojiStatusId PeerData::emojiStatusId() const { return _emojiStatusId; } diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 8c3bf4b2a..1c1cca3dc 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -206,8 +206,8 @@ public: bool changeBackgroundEmojiId(DocumentId id); void setEmojiStatus(const MTPEmojiStatus &status); - void setEmojiStatus(DocumentId emojiStatusId, TimeId until = 0); - [[nodiscard]] DocumentId emojiStatusId() const; + void setEmojiStatus(EmojiStatusId emojiStatusId, TimeId until = 0); + [[nodiscard]] EmojiStatusId emojiStatusId() const; [[nodiscard]] bool isUser() const { return peerIsUser(id); @@ -523,7 +523,7 @@ private: base::flat_set _nameWords; // for filtering base::flat_set _nameFirstLetters; - DocumentId _emojiStatusId = 0; + EmojiStatusId _emojiStatusId; DocumentId _backgroundEmojiId = 0; crl::time _lastFullUpdate = 0; diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 4c4c2bc23..42bc9b3c8 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -695,7 +695,7 @@ not_null Session::processUser(const MTPUser &data) { if (const auto &status = data.vemoji_status()) { result->setEmojiStatus(*status); } else { - result->setEmojiStatus(0); + result->setEmojiStatus(EmojiStatusId()); } if (!minimal) { if (const auto botInfoVersion = data.vbot_info_version()) { @@ -886,7 +886,7 @@ not_null Session::processChat(const MTPChat &data) { if (const auto &status = data.vemoji_status()) { channel->setEmojiStatus(*status); } else { - channel->setEmojiStatus(0); + channel->setEmojiStatus(EmojiStatusId()); } if (minimal) { if (channel->input.type() == mtpc_inputPeerEmpty diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index 5113eb6a8..cf9f6870a 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -37,6 +37,7 @@ using Options = base::flags