diff --git a/Telegram/SourceFiles/data/data_replies_list.cpp b/Telegram/SourceFiles/data/data_replies_list.cpp index 62104e616..73ea150fa 100644 --- a/Telegram/SourceFiles/data/data_replies_list.cpp +++ b/Telegram/SourceFiles/data/data_replies_list.cpp @@ -139,7 +139,8 @@ bool RepliesList::applyUpdate( not_null viewer, const MessageUpdate &update) { if (update.item->history() != _history - || update.item->replyToTop() != _rootId) { + || update.item->replyToTop() != _rootId + || !IsServerMsgId(update.item->id)) { return false; } const auto id = update.item->id; diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 1daacd11c..b2aac1e50 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -21,7 +21,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_service_message.h" #include "history/view/history_view_cursor_state.h" #include "history/view/history_view_context_menu.h" -#include "history/view/history_view_replies_section.h" #include "ui/widgets/popup_menu.h" #include "ui/image/image.h" #include "ui/toast/toast.h" @@ -1546,16 +1545,14 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { ? tr::lng_comments_view : tr::lng_replies_view; _menu->addAction(phrase(tr::now, lt_count, item->repliesCount()), [=] { - controller->showSection( - HistoryView::RepliesMemento(_history, itemId.msg)); + controller->showRepliesForMessage(_history, itemId.msg); }); } else if (const auto replyToTop = item->replyToTop()) { const auto &phrase = item->repliesAreComments() ? tr::lng_comments_view_thread : tr::lng_replies_view_thread; _menu->addAction(phrase(tr::now), [=] { - controller->showSection( - HistoryView::RepliesMemento(_history, replyToTop)); + controller->showRepliesForMessage(_history, replyToTop); }); } if (item->allowsEdit(base::unixtime::now())) { diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index 91fe98fb2..b0540d764 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -198,6 +198,11 @@ public: [[nodiscard]] virtual bool repliesAreComments() const { return false; } + [[nodiscard]] virtual FullMsgId commentsItemId() const { + return FullMsgId(); + } + virtual void setCommentsItemId(FullMsgId id) { + } [[nodiscard]] virtual bool needCheck() const; diff --git a/Telegram/SourceFiles/history/history_item_components.h b/Telegram/SourceFiles/history/history_item_components.h index bd9296b67..a2ffb4829 100644 --- a/Telegram/SourceFiles/history/history_item_components.h +++ b/Telegram/SourceFiles/history/history_item_components.h @@ -34,6 +34,8 @@ struct HistoryMessageVia : public RuntimeComponent { + static constexpr auto kMaxRecentRepliers = 3; + struct Part { QString text; int textWidth = 0; @@ -42,8 +44,8 @@ struct HistoryMessageViews : public RuntimeComponent recentRepliers; Part views; Part replies; - ChannelId repliesChannelId = 0; - static constexpr auto kMaxRecentRepliers = 3; + ChannelId commentsChannelId = 0; + MsgId commentsRootId = 0; }; struct HistoryMessageSigned : public RuntimeComponent { diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp index 3c04f0b3c..0abfa0ea4 100644 --- a/Telegram/SourceFiles/history/history_message.cpp +++ b/Telegram/SourceFiles/history/history_message.cpp @@ -747,10 +747,10 @@ int HistoryMessage::viewsCount() const { int HistoryMessage::repliesCount() const { if (const auto views = Get()) { - if (views->repliesChannelId) { + if (views->commentsChannelId) { if (const auto channel = history()->peer->asChannel()) { const auto linked = channel->linkedChat(); - if (!linked || linked->bareId() != views->repliesChannelId) { + if (!linked || linked->bareId() != views->commentsChannelId) { return 0; } } else { @@ -764,11 +764,11 @@ int HistoryMessage::repliesCount() const { bool HistoryMessage::repliesAreComments() const { if (const auto views = Get()) { - if (!views->repliesChannelId) { + if (!views->commentsChannelId) { return false; } else if (const auto channel = history()->peer->asChannel()) { const auto linked = channel->linkedChat(); - if (!linked || linked->bareId() != views->repliesChannelId) { + if (!linked || linked->bareId() != views->commentsChannelId) { return false; } } else { @@ -779,6 +779,21 @@ bool HistoryMessage::repliesAreComments() const { return HistoryItem::repliesAreComments(); } +FullMsgId HistoryMessage::commentsItemId() const { + if (const auto views = Get()) { + return FullMsgId(views->commentsChannelId, views->commentsRootId); + } + return FullMsgId(); +} + +void HistoryMessage::setCommentsItemId(FullMsgId id) { + if (const auto views = Get()) { + if (views->commentsChannelId == id.channel) { + views->commentsRootId = id.msg; + } + } +} + bool HistoryMessage::updateDependencyItem() { if (const auto reply = Get()) { const auto documentId = reply->replyToDocumentId; @@ -1468,7 +1483,7 @@ void HistoryMessage::setReplies(const MTPMessageReplies &data) { const auto count = data.vreplies().v; const auto channelId = data.vchannel_id().value_or_empty(); const auto countChanged = (views->replies.count != count); - const auto channelChanged = (views->repliesChannelId != channelId); + const auto channelChanged = (views->commentsChannelId != channelId); const auto recentChanged = (views->recentRepliers != repliers); if (!countChanged && !channelChanged && !recentChanged) { return; @@ -1477,7 +1492,7 @@ void HistoryMessage::setReplies(const MTPMessageReplies &data) { if (recentChanged) { views->recentRepliers = repliers; } - views->repliesChannelId = channelId; + views->commentsChannelId = channelId; refreshRepliesText(views, channelChanged); }); } @@ -1486,7 +1501,7 @@ void HistoryMessage::refreshRepliesText( not_null views, bool forceResize) { const auto was = views->replies.textWidth; - if (views->repliesChannelId) { + if (views->commentsChannelId) { views->replies.text = (views->replies.count > 0) ? tr::lng_comments_open_count( tr::now, @@ -1517,7 +1532,7 @@ void HistoryMessage::changeRepliesCount(int delta, UserId replier) { return; } views->replies.count = std::max(views->replies.count + delta, 0); - if (replier && views->repliesChannelId) { + if (replier && views->commentsChannelId) { if (delta < 0) { views->recentRepliers.erase( ranges::remove(views->recentRepliers, replier), diff --git a/Telegram/SourceFiles/history/history_message.h b/Telegram/SourceFiles/history/history_message.h index 924d1a733..f1857b79c 100644 --- a/Telegram/SourceFiles/history/history_message.h +++ b/Telegram/SourceFiles/history/history_message.h @@ -168,6 +168,8 @@ public: [[nodiscard]] int viewsCount() const override; [[nodiscard]] int repliesCount() const override; [[nodiscard]] bool repliesAreComments() const override; + [[nodiscard]] FullMsgId commentsItemId() const override; + void setCommentsItemId(FullMsgId id) override; bool updateDependencyItem() override; [[nodiscard]] MsgId dependencyMsgId() const override { return replyToId(); diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index ab746e30f..e25e4a799 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -12,7 +12,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_message.h" #include "history/view/media/history_view_media.h" #include "history/view/media/history_view_web_page.h" -#include "history/view/history_view_replies_section.h" #include "history/history.h" #include "ui/effects/ripple_animation.h" #include "core/application.h" @@ -1191,8 +1190,7 @@ bool Message::getStateCommentsButton( if (const auto window = App::wnd()) { if (const auto controller = window->sessionController()) { if (const auto item = controller->session().data().message(fullId)) { - controller->showSection( - HistoryView::RepliesMemento(item->history(), item->id)); + controller->showRepliesForMessage(item->history(), item->id); } } } @@ -1608,7 +1606,7 @@ void Message::drawInfo( auto left = infoRight - infoW; const auto iconTop = infoBottom + st::historyViewsTop; const auto textTop = infoBottom - st::msgDateFont->descent; - if (views->replies.count > 0 && !views->repliesChannelId) { + if (views->replies.count > 0 && !views->commentsChannelId) { auto icon = [&] { if (item->id > 0) { if (outbg) { @@ -1725,7 +1723,7 @@ int Message::infoWidth() const { + views->views.textWidth + st::historyViewsWidth; } - if (views->replies.count > 0 && !views->repliesChannelId) { + if (views->replies.count > 0 && !views->commentsChannelId) { result += st::historyViewsSpace + views->replies.textWidth + st::historyViewsWidth; @@ -1771,7 +1769,7 @@ int Message::timeLeft() const { if (views->views.count >= 0) { result += st::historyViewsSpace + views->views.textWidth + st::historyViewsWidth; } - if (views->replies.count > 0 && !views->repliesChannelId) { + if (views->replies.count > 0 && !views->commentsChannelId) { result += st::historyViewsSpace + views->replies.textWidth + st::historyViewsWidth; } } else if (item->id < 0 && item->history()->peer->isSelf()) { diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index 2f40803c9..57bd18aba 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history.h" #include "history/history_item.h" #include "history/view/history_view_element.h" +#include "history/view/history_view_replies_section.h" //#include "history/feed/history_feed_section.h" // #feed #include "media/player/media_player_instance.h" #include "data/data_media_types.h" @@ -82,10 +83,82 @@ SessionNavigation::SessionNavigation(not_null session) : _session(session) { } +SessionNavigation::~SessionNavigation() { + _session->api().request(base::take(_showingRepliesRequestId)).cancel(); +} + Main::Session &SessionNavigation::session() const { return *_session; } +void SessionNavigation::showRepliesForMessage( + not_null history, + MsgId rootId, + const SectionShow ¶ms) { + if (_showingRepliesRequestId + && _showingRepliesHistory == history.get() + && _showingRepliesRootId == rootId) { + return; + } + _session->api().request(base::take(_showingRepliesRequestId)).cancel(); + + const auto channelId = history->channelId(); + const auto item = _session->data().message(channelId, rootId); + if (!item || !item->repliesAreComments()) { + if (item->repliesCount() > 0) { + showSection(HistoryView::RepliesMemento(history, rootId)); + } + return; + } else if (const auto id = item->commentsItemId()) { + if (const auto item = _session->data().message(id)) { + showSection( + HistoryView::RepliesMemento(item->history(), item->id)); + return; + } + } + _showingRepliesHistory = history; + _showingRepliesRootId = rootId; + _showingRepliesRequestId = _session->api().request( + MTPmessages_GetDiscussionMessage( + history->peer->input, + MTP_int(rootId)) + ).done([=](const MTPmessages_DiscussionMessage &result) { + _showingRepliesRequestId = 0; + result.match([&](const MTPDmessages_discussionMessage &data) { + _session->data().processUsers(data.vusers()); + _session->data().processChats(data.vchats()); + _session->data().processMessages( + data.vmessages(), + NewMessageType::Existing); + const auto list = data.vmessages().v; + if (list.isEmpty()) { + return; + } + const auto id = IdFromMessage(list.front()); + const auto peer = PeerFromMessage(list.front()); + if (!peer || !id) { + return; + } + auto item = _session->data().message( + peerToChannel(peer), + id); + if (const auto group = _session->data().groups().find(item)) { + item = group->items.front(); + } + if (item) { + const auto post = _session->data().message(channelId, rootId); + if (post) { + post->setCommentsItemId(item->fullId()); + } + showSection( + HistoryView::RepliesMemento(item->history(), item->id)); + } + }); + }).fail([=](const RPCError &error) { + _showingRepliesRequestId = 0; + }).send(); +} + void SessionNavigation::showPeerInfo( PeerId peerId, const SectionShow ¶ms) { diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index c9b073a77..abf12066e 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -127,6 +127,7 @@ class SessionController; class SessionNavigation : public base::has_weak_ptr { public: explicit SessionNavigation(not_null session); + virtual ~SessionNavigation(); Main::Session &session() const; @@ -137,6 +138,11 @@ public: const SectionShow ¶ms = SectionShow()) = 0; virtual not_null parentController() = 0; + void showRepliesForMessage( + not_null history, + MsgId rootId, + const SectionShow ¶ms = SectionShow()); + void showPeerInfo( PeerId peerId, const SectionShow ¶ms = SectionShow()); @@ -157,11 +163,15 @@ public: FullMsgId contextId, const SectionShow ¶ms = SectionShow()); - virtual ~SessionNavigation() = default; private: const not_null _session; + History *_showingRepliesHistory = nullptr; + MsgId _showingRepliesRootId = 0; + mtpRequestId _showingRepliesRequestId = 0; + + }; class SessionController : public SessionNavigation, private base::Subscriber {