From c90f879c96f3e742575fc2d393b36a28fe2fc967 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 27 Sep 2022 10:25:26 +0400 Subject: [PATCH] Update API scheme on layer 148. --- Telegram/Resources/tl/api.tl | 10 ++- Telegram/SourceFiles/data/data_forum.cpp | 71 +++++++++++-------- Telegram/SourceFiles/data/data_forum.h | 6 ++ .../SourceFiles/data/data_forum_topic.cpp | 6 +- Telegram/SourceFiles/data/data_types.h | 31 ++++---- .../export/data/export_data_types.cpp | 10 ++- .../export/data/export_data_types.h | 14 +++- .../export/output/export_output_html.cpp | 12 +++- .../export/output/export_output_json.cpp | 10 ++- Telegram/SourceFiles/history/history_item.cpp | 3 +- Telegram/SourceFiles/history/history_item.h | 3 - .../SourceFiles/history/history_service.cpp | 28 +++++++- .../view/history_view_replies_section.cpp | 40 ++--------- 13 files changed, 149 insertions(+), 95 deletions(-) diff --git a/Telegram/Resources/tl/api.tl b/Telegram/Resources/tl/api.tl index c5ded1bcc..ad1d54edf 100644 --- a/Telegram/Resources/tl/api.tl +++ b/Telegram/Resources/tl/api.tl @@ -142,7 +142,7 @@ chatPhotoEmpty#37c1011c = ChatPhoto; chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto; messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message; -message#38116ee0 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true topic_start:flags.27?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector ttl_period:flags.25?int = Message; +message#38116ee0 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector ttl_period:flags.25?int = Message; messageService#2b085862 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction ttl_period:flags.25?int = Message; messageMediaEmpty#3ded6320 = MessageMedia; @@ -193,6 +193,8 @@ messageActionWebViewDataSentMe#47dd8079 text:string data:string = MessageAction; messageActionWebViewDataSent#b4c38cb5 text:string = MessageAction; messageActionGiftPremium#aba0f5c6 currency:string amount:long months:int = MessageAction; messageActionTopicCreate#4619708d title:string = MessageAction; +messageActionTopicEditTitle#ce0b23cd title:string = MessageAction; +messageActionTopicEditIcon#820a6e2b emoji_document_id:long = MessageAction; dialog#a8edd0f5 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int unread_reactions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog; dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog; @@ -1451,7 +1453,7 @@ messageExtendedMedia#ee479c64 media:MessageMedia = MessageExtendedMedia; stickerKeyword#fcfeb29c document_id:long keyword:Vector = StickerKeyword; -forumTopic#4a0005d9 flags:# pinned:flags.2?true id:int date:int title:string top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int = ForumTopic; +forumTopic#7068973b flags:# id:int date:int title:string icon_emoji_id:flags.0?long top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int = ForumTopic; messages.forumTopics#367617d3 flags:# order_by_create_date:flags.0?true count:int topics:Vector messages:Vector chats:Vector users:Vector pts:int = messages.ForumTopics; @@ -1854,9 +1856,11 @@ channels.deleteParticipantHistory#367544db channel:InputChannel participant:Inpu channels.toggleJoinToSend#e4cb9580 channel:InputChannel enabled:Bool = Updates; channels.toggleJoinRequest#4c2985b6 channel:InputChannel enabled:Bool = Updates; channels.toggleForum#a4298b29 channel:InputChannel enabled:Bool = Updates; -channels.createForumTopic#22cf4868 flags:# no_webpage:flags.3?true channel:InputChannel title:string media:flags.0?InputMedia message:string random_id:long entities:flags.1?Vector send_as:flags.2?InputPeer = Updates; +channels.createForumTopic#21289f15 flags:# no_webpage:flags.3?true channel:InputChannel title:string icon_emoji_id:flags.3?long media:flags.0?InputMedia message:string random_id:long entities:flags.1?Vector send_as:flags.2?InputPeer = Updates; channels.getForumTopics#de560d1 flags:# channel:InputChannel q:flags.0?string offset_date:int offset_id:int offset_topic:int limit:int = messages.ForumTopics; channels.getForumTopicsByID#b0831eb9 channel:InputChannel topics:Vector = messages.ForumTopics; +channels.editForumTitle#8881b9b1 channel:InputChannel topic_id:int title:string = Updates; +channels.editForumIcon#55cea2dd channel:InputChannel topic_id:int emoji_document_id:long = Updates; bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON; bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool; diff --git a/Telegram/SourceFiles/data/data_forum.cpp b/Telegram/SourceFiles/data/data_forum.cpp index cbba0135e..c1ea9c423 100644 --- a/Telegram/SourceFiles/data/data_forum.cpp +++ b/Telegram/SourceFiles/data/data_forum.cpp @@ -69,36 +69,7 @@ void Forum::requestTopics() { MTP_int(_offsetTopicId), MTP_int(loadCount) )).done([=](const MTPmessages_ForumTopics &result) { - const auto &data = result.data(); - const auto owner = &channel()->owner(); - owner->processUsers(data.vusers()); - owner->processChats(data.vchats()); - owner->processMessages(data.vmessages(), NewMessageType::Existing); - channel()->ptsReceived(data.vpts().v); - const auto &list = data.vtopics().v; - for (const auto &topic : list) { - const auto rootId = MsgId(topic.data().vid().v); - const auto i = _topics.find(rootId); - const auto creating = (i == end(_topics)); - const auto raw = creating - ? _topics.emplace( - rootId, - std::make_unique(_history, rootId) - ).first->second.get() - : i->second.get(); - raw->applyTopic(topic); - if (creating) { - raw->addToChatList(FilterId(), topicsList()); - } - if (const auto last = raw->lastServerMessage()) { - _offsetDate = last->date(); - _offsetId = last->id; - } - _offsetTopicId = rootId; - } - if (list.isEmpty() || list.size() == data.vcount().v) { - _allLoaded = true; - } + applyReceivedTopics(result, true); _requestId = 0; _chatsListChanges.fire({}); if (_allLoaded) { @@ -110,6 +81,45 @@ void Forum::requestTopics() { }).send(); } +void Forum::applyReceivedTopics(const MTPmessages_ForumTopics &result) { + applyReceivedTopics(result, false); +} + +void Forum::applyReceivedTopics( + const MTPmessages_ForumTopics &topics, + bool updateOffset) { + const auto &data = topics.data(); + const auto owner = &channel()->owner(); + owner->processUsers(data.vusers()); + owner->processChats(data.vchats()); + owner->processMessages(data.vmessages(), NewMessageType::Existing); + channel()->ptsReceived(data.vpts().v); + const auto &list = data.vtopics().v; + for (const auto &topic : list) { + const auto rootId = MsgId(topic.data().vid().v); + const auto i = _topics.find(rootId); + const auto creating = (i == end(_topics)); + const auto raw = creating + ? _topics.emplace( + rootId, + std::make_unique(_history, rootId) + ).first->second.get() + : i->second.get(); + raw->applyTopic(topic); + if (updateOffset) { + if (const auto last = raw->lastServerMessage()) { + _offsetDate = last->date(); + _offsetId = last->id; + } + _offsetTopicId = rootId; + } + } + if (updateOffset + && (list.isEmpty() || list.size() == data.vcount().v)) { + _allLoaded = true; + } +} + void Forum::applyTopicAdded(MsgId rootId, const QString &title) { if (const auto i = _topics.find(rootId); i != end(_topics)) { i->second->applyTitle(title); @@ -192,6 +202,7 @@ void ShowAddForumTopic( MTP_flags(0), forum->inputChannel, MTP_string(title->getLastText().trimmed()), + MTPlong(), // icon_emoji_id MTPInputMedia(), MTP_string(message->getLastText().trimmed()), MTP_long(randomId), diff --git a/Telegram/SourceFiles/data/data_forum.h b/Telegram/SourceFiles/data/data_forum.h index e44aae7ba..557646f3d 100644 --- a/Telegram/SourceFiles/data/data_forum.h +++ b/Telegram/SourceFiles/data/data_forum.h @@ -36,7 +36,13 @@ public: [[nodiscard]] ForumTopic *topicFor(not_null item); [[nodiscard]] ForumTopic *topicFor(MsgId rootId); + void applyReceivedTopics(const MTPmessages_ForumTopics &topics); + private: + void applyReceivedTopics( + const MTPmessages_ForumTopics &topics, + bool updateOffset); + const not_null _history; base::flat_map> _topics; diff --git a/Telegram/SourceFiles/data/data_forum_topic.cpp b/Telegram/SourceFiles/data/data_forum_topic.cpp index 70ed243dd..e6847e0a8 100644 --- a/Telegram/SourceFiles/data/data_forum_topic.cpp +++ b/Telegram/SourceFiles/data/data_forum_topic.cpp @@ -40,18 +40,22 @@ void ForumTopic::applyTopic(const MTPForumTopic &topic) { applyTitle(qs(data.vtitle())); const auto pinned = _list->pinned(); +#if 0 // #TODO forum pinned if (data.is_pinned()) { pinned->addPinned(Dialogs::Key(this)); } else { pinned->setPinned(Dialogs::Key(this), false); } +#endif applyTopicFields( data.vunread_count().v, data.vread_inbox_max_id().v, data.vread_outbox_max_id().v); applyTopicTopMessage(data.vtop_message().v); - //setUnreadMark(data.is_unread_mark()); +#if 0 // #TODO forum unread mark + setUnreadMark(data.is_unread_mark()); +#endif } void ForumTopic::indexTitleParts() { diff --git a/Telegram/SourceFiles/data/data_types.h b/Telegram/SourceFiles/data/data_types.h index 43c06cab8..3896ad2c6 100644 --- a/Telegram/SourceFiles/data/data_types.h +++ b/Telegram/SourceFiles/data/data_types.h @@ -239,53 +239,52 @@ enum class MessageFlag : uint64 { MentionsMe = (1ULL << 15), IsOrWasScheduled = (1ULL << 16), NoForwards = (1ULL << 17), - TopicStart = (1ULL << 18), // Needs to return back to inline mode. - HasSwitchInlineButton = (1ULL << 19), + HasSwitchInlineButton = (1ULL << 18), // For "shared links" indexing. - HasTextLinks = (1ULL << 20), + HasTextLinks = (1ULL << 19), // Group / channel create or migrate service message. - IsGroupEssential = (1ULL << 21), + IsGroupEssential = (1ULL << 20), // Edited media is generated on the client // and should not update media from server. - IsLocalUpdateMedia = (1ULL << 22), + IsLocalUpdateMedia = (1ULL << 21), // Sent from inline bot, need to re-set media when sent. - FromInlineBot = (1ULL << 23), + FromInlineBot = (1ULL << 22), // Generated on the client side and should be unread. - ClientSideUnread = (1ULL << 24), + ClientSideUnread = (1ULL << 23), // In a supergroup. - HasAdminBadge = (1ULL << 25), + HasAdminBadge = (1ULL << 24), // Outgoing message that is being sent. - BeingSent = (1ULL << 26), + BeingSent = (1ULL << 25), // Outgoing message and failed to be sent. - SendingFailed = (1ULL << 27), + SendingFailed = (1ULL << 26), // No media and only a several emoji or an only custom emoji text. - SpecialOnlyEmoji = (1ULL << 28), + SpecialOnlyEmoji = (1ULL << 27), // Message existing in the message history. - HistoryEntry = (1ULL << 29), + HistoryEntry = (1ULL << 28), // Local message, not existing on the server. - Local = (1ULL << 30), + Local = (1ULL << 29), // Fake message for some UI element. - FakeHistoryItem = (1ULL << 31), + FakeHistoryItem = (1ULL << 30), // Contact sign-up message, notification should be skipped for Silent. - IsContactSignUp = (1ULL << 32), + IsContactSignUp = (1ULL << 31), // Optimization for item text custom emoji repainting. - CustomEmojiRepainting = (1ULL << 33), + CustomEmojiRepainting = (1ULL << 32), }; inline constexpr bool is_flag_type(MessageFlag) { return true; } using MessageFlags = base::flags; diff --git a/Telegram/SourceFiles/export/data/export_data_types.cpp b/Telegram/SourceFiles/export/data/export_data_types.cpp index 2524e6ad3..e86bf5b4b 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.cpp +++ b/Telegram/SourceFiles/export/data/export_data_types.cpp @@ -1153,9 +1153,17 @@ ServiceAction ParseServiceAction( content.months = data.vmonths().v; result.content = content; }, [&](const MTPDmessageActionTopicCreate &data) { - auto content = ActionTopicCreated(); + auto content = ActionTopicCreate(); content.title = ParseString(data.vtitle()); result.content = content; + }, [&](const MTPDmessageActionTopicEditTitle &data) { + auto content = ActionTopicEditTitle(); + content.title = ParseString(data.vtitle()); + result.content = content; + }, [&](const MTPDmessageActionTopicEditIcon &data) { + auto content = ActionTopicEditIcon(); + content.emojiDocumentId = data.vemoji_document_id().v; + result.content = content; }, [](const MTPDmessageActionEmpty &data) {}); return result; } diff --git a/Telegram/SourceFiles/export/data/export_data_types.h b/Telegram/SourceFiles/export/data/export_data_types.h index 4e49d6be3..e6c9c1f4c 100644 --- a/Telegram/SourceFiles/export/data/export_data_types.h +++ b/Telegram/SourceFiles/export/data/export_data_types.h @@ -499,10 +499,18 @@ struct ActionGiftPremium { int months; }; -struct ActionTopicCreated { +struct ActionTopicCreate { Utf8String title; }; +struct ActionTopicEditTitle { + Utf8String title; +}; + +struct ActionTopicEditIcon { + uint64 emojiDocumentId = 0; +}; + struct ServiceAction { std::variant< v::null_t, @@ -536,7 +544,9 @@ struct ServiceAction { ActionChatJoinedByRequest, ActionWebViewDataSent, ActionGiftPremium, - ActionTopicCreated> content; + ActionTopicCreate, + ActionTopicEditTitle, + ActionTopicEditIcon> content; }; ServiceAction ParseServiceAction( diff --git a/Telegram/SourceFiles/export/output/export_output_html.cpp b/Telegram/SourceFiles/export/output/export_output_html.cpp index fd3f03e22..05c442e37 100644 --- a/Telegram/SourceFiles/export/output/export_output_html.cpp +++ b/Telegram/SourceFiles/export/output/export_output_html.cpp @@ -1145,11 +1145,21 @@ auto HtmlWriter::Wrap::pushMessage( + ": Telegram Premium for " + QString::number(data.months).toUtf8() + " months."; - }, [&](const ActionTopicCreated &data) { + }, [&](const ActionTopicCreate &data) { return serviceFrom + " created topic «" + SerializeString(data.title) + "»"; + }, [&](const ActionTopicEditTitle &data) { + return serviceFrom + + " changed topic title to «" + + SerializeString(data.title) + + "»"; + }, [&](const ActionTopicEditIcon &data) { + return serviceFrom + + " changed topic icon to «" + + QString::number(data.emojiDocumentId).toUtf8() + + "»"; }, [](v::null_t) { return QByteArray(); }); if (!serviceText.isEmpty()) { diff --git a/Telegram/SourceFiles/export/output/export_output_json.cpp b/Telegram/SourceFiles/export/output/export_output_json.cpp index 74298177c..98c9ae9e2 100644 --- a/Telegram/SourceFiles/export/output/export_output_json.cpp +++ b/Telegram/SourceFiles/export/output/export_output_json.cpp @@ -560,10 +560,18 @@ QByteArray SerializeMessage( if (data.months) { push("months", data.months); } - }, [&](const ActionTopicCreated &data) { + }, [&](const ActionTopicCreate &data) { pushActor(); pushAction("topic_created"); push("title", data.title); + }, [&](const ActionTopicEditTitle &data) { + pushActor(); + pushAction("topic_title_edit"); + push("title", data.title); + }, [&](const ActionTopicEditIcon &data) { + pushActor(); + pushAction("topic_icon_edit"); + push("emoji_document_id", data.emojiDocumentId); }, [](v::null_t) {}); if (v::is_null(message.action.content)) { diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 806acf6e1..7f1304968 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -1440,8 +1440,7 @@ MessageFlags FlagsFromMTP( | ((flags & MTP::f_reply_markup) ? Flag::HasReplyMarkup : Flag()) | ((flags & MTP::f_from_scheduled) ? Flag::IsOrWasScheduled : Flag()) | ((flags & MTP::f_views) ? Flag::HasViews : Flag()) - | ((flags & MTP::f_noforwards) ? Flag::NoForwards : Flag()) - | ((flags & MTP::f_topic_start) ? Flag::TopicStart : Flag()); + | ((flags & MTP::f_noforwards) ? Flag::NoForwards : Flag()); } MessageFlags FlagsFromMTP( diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index baa9259cb..f1cb3ad12 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -145,9 +145,6 @@ public: [[nodiscard]] bool isPinned() const { return _flags & MessageFlag::Pinned; } - [[nodiscard]] bool isTopicStart() const { - return _flags & MessageFlag::TopicStart; - } [[nodiscard]] bool unread() const; [[nodiscard]] bool showNotification() const; void markClientSideAsRead(); diff --git a/Telegram/SourceFiles/history/history_service.cpp b/Telegram/SourceFiles/history/history_service.cpp index cc4442d81..5841ee9e1 100644 --- a/Telegram/SourceFiles/history/history_service.cpp +++ b/Telegram/SourceFiles/history/history_service.cpp @@ -636,7 +636,29 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) { auto prepareTopicCreate = [&](const MTPDmessageActionTopicCreate &action) { auto result = PreparedText{}; - result.text = { "topic created" }; + // #TODO forum lang + result.text = { "topic created: " + qs(action.vtitle()) }; + return result; + }; + + auto prepareTopicEditTitle = [&](const MTPDmessageActionTopicEditTitle &action) { + auto result = PreparedText{}; + // #TODO forum lang + result.text = { "topic edited: " + qs(action.vtitle()) }; + return result; + }; + + auto prepareTopicEditIcon = [&](const MTPDmessageActionTopicEditIcon &action) { + auto result = PreparedText{}; + result.text = { "topic icon: " }; // #TODO forum lang + result.text.append(TextWithEntities{ + " ", + { EntityInText( + EntityType::CustomEmoji, + 0, + 1, + QString::number(+action.vemoji_document_id().v)) }, + }); return result; }; @@ -711,6 +733,10 @@ void HistoryService::setMessageByAction(const MTPmessageAction &action) { return prepareGiftPremium(data); }, [&](const MTPDmessageActionTopicCreate &data) { return prepareTopicCreate(data); + }, [&](const MTPDmessageActionTopicEditTitle &data) { + return prepareTopicEditTitle(data); + }, [&](const MTPDmessageActionTopicEditIcon &data) { + return prepareTopicEditIcon(data); }, [&](const MTPDmessageActionWebViewDataSentMe &data) { LOG(("API Error: messageActionWebViewDataSentMe received.")); return PreparedText{ diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 0f947b016..79067a927 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -451,41 +451,13 @@ Data::ForumTopic *RepliesWidget::lookupTopic() { forum->channel()->inputChannel, MTP_vector(1, MTP_int(_rootId.bare))) ).done([=](const MTPmessages_ForumTopics &result) { - const auto &data = result.data(); - const auto owner = &_history->owner(); - owner->processUsers(data.vusers()); - owner->processChats(data.vchats()); - owner->processMessages(data.vmessages(), NewMessageType::Existing); - channel()->ptsReceived(data.vpts().v); - const auto &list = data.vtopics().v; - for (const auto &topic : list) { - const auto rootId = MsgId(topic.data().vid().v); - const auto i = _topics.find(rootId); - const auto creating = (i == end(_topics)); - const auto raw = creating - ? _topics.emplace( - rootId, - std::make_unique(_history, rootId) - ).first->second.get() - : i->second.get(); - raw->applyTopic(topic); - if (creating) { - raw->addToChatList(FilterId(), topicsList()); - } - if (const auto last = raw->lastServerMessage()) { - _offsetDate = last->date(); - _offsetId = last->id; - } - _offsetTopicId = rootId; - } - if (list.isEmpty() || list.size() == data.vcount().v) { - _allLoaded = true; - } - _requestId = 0; - _chatsListChanges.fire({}); - if (_allLoaded) { - _chatsListLoadedEvents.fire({}); + if (const auto forum = _history->peer->forum()) { + forum->applyReceivedTopics(result); + _topic = forum->topicFor(_rootId); } + _resolveTopicRequestId = 0; + }).fail([=] { + _resolveTopicRequestId = 0; }).send(); } return result;