diff --git a/Telegram/SourceFiles/core/click_handler_types.cpp b/Telegram/SourceFiles/core/click_handler_types.cpp index a73fe0b046..b0b71bfa5b 100644 --- a/Telegram/SourceFiles/core/click_handler_types.cpp +++ b/Telegram/SourceFiles/core/click_handler_types.cpp @@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item.h" #include "data/data_user.h" #include "data/data_session.h" +#include "window/window_session_controller.h" #include "facades.h" #include "app.h" @@ -112,7 +113,11 @@ void MentionClickHandler::onClick(ClickContext context) const { const auto button = context.button; if (button == Qt::LeftButton || button == Qt::MiddleButton) { if (const auto m = App::main()) { // multi good - m->openPeerByName(_tag.mid(1), ShowAtProfileMsgId); + using Info = Window::SessionNavigation::PeerByLinkInfo; + m->controller()->showPeerByLink(Info{ + .usernameOrId = _tag.mid(1), + .messageId = ShowAtProfileMsgId + }); } } } diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp index 450b21c9c8..0c709a8d0c 100644 --- a/Telegram/SourceFiles/core/local_url_handlers.cpp +++ b/Telegram/SourceFiles/core/local_url_handlers.cpp @@ -273,25 +273,30 @@ bool ResolveUsername( } const auto commentParam = params.value(qsl("comment")); const auto commentId = commentParam.toInt(); + const auto threadParam = params.value(qsl("thread")); + const auto threadId = threadParam.toInt(); const auto gameParam = params.value(qsl("game")); if (!gameParam.isEmpty() && valid(gameParam)) { startToken = gameParam; post = ShowAtGameShareMsgId; } const auto clickFromMessageId = context.value(); - if (commentId) { - controller->content()->openCommentByName( - domain, - post, - commentId, - clickFromMessageId); - } else { - controller->content()->openPeerByName( - domain, - post, - startToken, - clickFromMessageId); - } + using Navigation = Window::SessionNavigation; + controller->showPeerByLink(Navigation::PeerByLinkInfo{ + .usernameOrId = domain, + .messageId = post, + .repliesInfo = commentId + ? Navigation::RepliesByLinkInfo{ + Navigation::CommentId{ commentId } + } + : threadId + ? Navigation::RepliesByLinkInfo{ + Navigation::ThreadId{ threadId } + } + : Navigation::RepliesByLinkInfo{ v::null }, + .startToken = startToken, + .clickFromMessageId = clickFromMessageId, + }); return true; } @@ -307,46 +312,29 @@ bool ResolvePrivatePost( qthelp::UrlParamNameTransform::ToLower); const auto channelId = params.value(qsl("channel")).toInt(); const auto msgId = params.value(qsl("post")).toInt(); + const auto commentParam = params.value(qsl("comment")); + const auto commentId = commentParam.toInt(); + const auto threadParam = params.value(qsl("thread")); + const auto threadId = threadParam.toInt(); if (!channelId || !IsServerMsgId(msgId)) { return false; } const auto clickFromMessageId = context.value(); - const auto done = crl::guard(controller, [=](not_null peer) { - auto params = Window::SectionShow{ - Window::SectionShow::Way::Forward - }; - params.origin = Window::SectionShow::OriginMessage{ - clickFromMessageId - }; - controller->showPeerHistory( - peer->id, - Window::SectionShow::Way::Forward, - msgId); - }); - const auto fail = [=] { - Ui::show(Box(tr::lng_error_post_link_invalid(tr::now))); - }; - const auto session = &controller->session(); - if (const auto channel = session->data().channelLoaded(channelId)) { - done(channel); - return true; - } - session->api().request(MTPchannels_GetChannels( - MTP_vector( - 1, - MTP_inputChannel(MTP_int(channelId), MTP_long(0))) - )).done([=](const MTPmessages_Chats &result) { - result.match([&](const auto &data) { - const auto peer = session->data().processChats(data.vchats()); - if (peer && peer->id == peerFromChannel(channelId)) { - done(peer); - } else { - fail(); + using Navigation = Window::SessionNavigation; + controller->showPeerByLink(Navigation::PeerByLinkInfo{ + .usernameOrId = channelId, + .messageId = msgId, + .repliesInfo = commentId + ? Navigation::RepliesByLinkInfo{ + Navigation::CommentId{ commentId } } - }); - }).fail([=](const RPCError &error) { - fail(); - }).send(); + : threadId + ? Navigation::RepliesByLinkInfo{ + Navigation::ThreadId{ threadId } + } + : Navigation::RepliesByLinkInfo{ v::null }, + .clickFromMessageId = clickFromMessageId, + }); return true; } diff --git a/Telegram/SourceFiles/data/data_changes.h b/Telegram/SourceFiles/data/data_changes.h index 72908d445b..3a363ee6ee 100644 --- a/Telegram/SourceFiles/data/data_changes.h +++ b/Telegram/SourceFiles/data/data_changes.h @@ -67,27 +67,28 @@ struct PeerUpdate { OnlineStatus = (1 << 12), BotCommands = (1 << 13), BotCanBeInvited = (1 << 14), - CommonChats = (1 << 15), - HasCalls = (1 << 16), - SupportInfo = (1 << 17), - IsBot = (1 << 18), + BotStartToken = (1 << 15), + CommonChats = (1 << 16), + HasCalls = (1 << 17), + SupportInfo = (1 << 18), + IsBot = (1 << 19), // For chats and channels - InviteLink = (1 << 19), - Members = (1 << 20), - Admins = (1 << 21), - BannedUsers = (1 << 22), - Rights = (1 << 23), + InviteLink = (1 << 20), + Members = (1 << 21), + Admins = (1 << 22), + BannedUsers = (1 << 23), + Rights = (1 << 24), // For channels - ChannelAmIn = (1 << 24), - StickersSet = (1 << 25), - ChannelLinkedChat = (1 << 26), - ChannelLocation = (1 << 27), - Slowmode = (1 << 28), + ChannelAmIn = (1 << 25), + StickersSet = (1 << 26), + ChannelLinkedChat = (1 << 27), + ChannelLocation = (1 << 28), + Slowmode = (1 << 29), // For iteration - LastUsedBit = (1 << 28), + LastUsedBit = (1 << 29), }; using Flags = base::flags; friend inline constexpr auto is_flag_type(Flag) { return true; } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index aaa93c06e8..c6480b3c83 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -570,6 +570,7 @@ HistoryWidget::HistoryWidget( | UpdateFlag::ChannelAmIn | UpdateFlag::ChannelLinkedChat | UpdateFlag::Slowmode + | UpdateFlag::BotStartToken ) | rpl::filter([=](const Data::PeerUpdate &update) { return (update.peer.get() == _peer); }) | rpl::map([](const Data::PeerUpdate &update) { @@ -594,6 +595,10 @@ HistoryWidget::HistoryWidget( return; } } + if (flags & UpdateFlag::BotStartToken) { + updateControlsVisibility(); + updateControlsGeometry(); + } if (flags & UpdateFlag::PinnedMessage) { if (pinnedMsgVisibilityUpdated()) { updateHistoryGeometry(); diff --git a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp index 1fdb27598f..7494d2c841 100644 --- a/Telegram/SourceFiles/history/view/history_view_replies_section.cpp +++ b/Telegram/SourceFiles/history/view/history_view_replies_section.cpp @@ -1210,7 +1210,8 @@ bool RepliesWidget::showInternal( not_null memento, const Window::SectionShow ¶ms) { if (auto logMemento = dynamic_cast(memento.get())) { - if (logMemento->getHistory() == history()) { + if (logMemento->getHistory() == history() + && logMemento->getRootId() == _rootId) { restoreState(logMemento); return true; } diff --git a/Telegram/SourceFiles/info/info_controller.cpp b/Telegram/SourceFiles/info/info_controller.cpp index 12484caa5f..9def98def0 100644 --- a/Telegram/SourceFiles/info/info_controller.cpp +++ b/Telegram/SourceFiles/info/info_controller.cpp @@ -133,6 +133,13 @@ void AbstractController::showBackFromStack( return parentController()->showBackFromStack(params); } +void AbstractController::showPeerHistory( + PeerId peerId, + const Window::SectionShow ¶ms, + MsgId msgId) { + return parentController()->showPeerHistory(peerId, params, msgId); +} + Controller::Controller( not_null widget, not_null window, diff --git a/Telegram/SourceFiles/info/info_controller.h b/Telegram/SourceFiles/info/info_controller.h index 741fa59fb7..c0f117efe5 100644 --- a/Telegram/SourceFiles/info/info_controller.h +++ b/Telegram/SourceFiles/info/info_controller.h @@ -140,6 +140,12 @@ public: const Window::SectionShow ¶ms = Window::SectionShow()) override; void showBackFromStack( const Window::SectionShow ¶ms = Window::SectionShow()) override; + + void showPeerHistory( + PeerId peerId, + const Window::SectionShow ¶ms = Window::SectionShow::Way::ClearStack, + MsgId msgId = ShowAtUnreadMsgId) override; + not_null parentController() override { return _parent; } diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index d91f4d9739..87bb87e8d9 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -2597,136 +2597,12 @@ void MainWidget::searchInChat(Dialogs::Key chat) { } } -void MainWidget::openPeerResolved( - not_null peer, - MsgId msgId, - const QString &startToken, - FullMsgId clickFromMessageId) { - if (msgId == ShowAtGameShareMsgId) { - if (peer->isUser() && peer->asUser()->isBot() && !startToken.isEmpty()) { - peer->asUser()->botInfo->shareGameShortName = startToken; - AddBotToGroupBoxController::Start( - _controller, - peer->asUser()); - } else { - InvokeQueued(this, [this, peer] { - _controller->showPeerHistory( - peer->id, - SectionShow::Way::Forward); - }); - } - } else if (msgId == ShowAtProfileMsgId && !peer->isChannel()) { - if (peer->isUser() && peer->asUser()->isBot() && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) { - peer->asUser()->botInfo->startGroupToken = startToken; - AddBotToGroupBoxController::Start( - _controller, - peer->asUser()); - } else if (peer->isUser() && peer->asUser()->isBot()) { - // Always open bot chats, even from mention links. - InvokeQueued(this, [this, peer] { - _controller->showPeerHistory( - peer->id, - SectionShow::Way::Forward); - }); - } else { - _controller->showPeerInfo(peer); - } - } else { - if (msgId == ShowAtProfileMsgId || !peer->isChannel()) { // show specific posts only in channels / supergroups - msgId = ShowAtUnreadMsgId; - } - if (peer->isUser() && peer->asUser()->isBot()) { - peer->asUser()->botInfo->startToken = startToken; - if (peer == _history->peer()) { - _history->updateControlsVisibility(); - _history->updateControlsGeometry(); - } - } - InvokeQueued(this, [=] { - auto params = SectionShow{ - SectionShow::Way::Forward - }; - params.origin = SectionShow::OriginMessage{ - clickFromMessageId - }; - _controller->showPeerHistory(peer->id, params, msgId); - }); - } -} - -void MainWidget::openPeerByName( - const QString &username, - MsgId msgId, - const QString &startToken, - FullMsgId clickFromMessageId) { - Core::App().hideMediaView(); - resolveUsername(username, [=](not_null peer) { - openPeerResolved(peer, msgId, startToken, clickFromMessageId); - }); -} - -void MainWidget::openCommentByName( - const QString &username, - MsgId msgId, - MsgId commentId, - FullMsgId clickFromMessageId) { - Core::App().hideMediaView(); - resolveUsername(username, [=](not_null peer) { - InvokeQueued(this, [=] { - auto params = SectionShow{ - SectionShow::Way::Forward - }; - params.origin = SectionShow::OriginMessage{ - clickFromMessageId - }; - _controller->showRepliesForMessage( - session().data().history(peer), - msgId, - commentId, - params); - }); - }); - Core::App().hideMediaView(); -} - bool MainWidget::contentOverlapped(const QRect &globalRect) { return (_history->contentOverlapped(globalRect) || _playerPlaylist->overlaps(globalRect) || (_playerVolume && _playerVolume->overlaps(globalRect))); } -void MainWidget::resolveUsername( - const QString &username, - Fn)> done) { - if (const auto peer = session().data().peerByUsername(username)) { - done(peer); - return; - } - _api.request(base::take(_resolveRequestId)).cancel(); - _resolveRequestId = _api.request(MTPcontacts_ResolveUsername( - MTP_string(username) - )).done([=](const MTPcontacts_ResolvedPeer &result) { - _resolveRequestId = 0; - Ui::hideLayer(); - if (result.type() != mtpc_contacts_resolvedPeer) { - return; - } - - const auto &d(result.c_contacts_resolvedPeer()); - session().data().processUsers(d.vusers()); - session().data().processChats(d.vchats()); - if (const auto peerId = peerFromMTP(d.vpeer())) { - done(session().data().peer(peerId)); - } - }).fail([=](const RPCError &error) { - _resolveRequestId = 0; - if (error.code() == 400) { - Ui::show(Box( - tr::lng_username_not_found(tr::now, lt_user, username))); - } - }).send(); -} - void MainWidget::activate() { if (_a_show.animating()) { return; diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 1d459ed471..c2d0e6adc5 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -122,17 +122,6 @@ public: void showAnimated(const QPixmap &bgAnimCache, bool back = false); - void openPeerByName( - const QString &name, - MsgId msgId = ShowAtUnreadMsgId, - const QString &startToken = QString(), - FullMsgId clickFromMessageId = FullMsgId()); - void openCommentByName( - const QString &name, - MsgId msgId, - MsgId commentId, - FullMsgId clickFromMessageId = FullMsgId()); - void activate(); void windowShown(); @@ -294,15 +283,6 @@ private: void saveSectionInStack(); - void resolveUsername( - const QString &username, - Fn)> done); - void openPeerResolved( - not_null peer, - MsgId msgId, - const QString &startToken, - FullMsgId clickFromMessageId); - int getMainSectionTop() const; int getThirdSectionTop() const; @@ -406,7 +386,6 @@ private: base::flat_map, mtpRequestId> _viewsIncrementRequests; base::flat_map> _viewsIncrementByRequest; base::Timer _viewsIncrementTimer; - mtpRequestId _resolveRequestId = 0; struct SettingBackground; std::unique_ptr _background; diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp index fdfd09e3c4..43752613d5 100644 --- a/Telegram/SourceFiles/window/window_session_controller.cpp +++ b/Telegram/SourceFiles/window/window_session_controller.cpp @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_session_controller.h" #include "boxes/peers/edit_peer_info_box.h" +#include "boxes/peer_list_controllers.h" #include "window/window_controller.h" #include "window/main_window.h" #include "window/window_filters_menu.h" @@ -24,6 +25,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_folder.h" #include "data/data_channel.h" #include "data/data_chat.h" +#include "data/data_user.h" +#include "data/data_changes.h" #include "data/data_chat_filters.h" #include "data/data_photo.h" // requestAttachedStickerSets. #include "passport/passport_form_controller.h" @@ -85,12 +88,155 @@ SessionNavigation::SessionNavigation(not_null session) SessionNavigation::~SessionNavigation() { _session->api().request(base::take(_showingRepliesRequestId)).cancel(); + _session->api().request(base::take(_resolveRequestId)).cancel(); } Main::Session &SessionNavigation::session() const { return *_session; } +void SessionNavigation::showPeerByLink(const PeerByLinkInfo &info) { + Core::App().hideMediaView(); + if (const auto username = std::get_if(&info.usernameOrId)) { + resolveUsername(*username, [=](not_null peer) { + showPeerByLinkResolved(peer, info); + }); + } else if (const auto id = std::get_if(&info.usernameOrId)) { + resolveChannelById(*id, [=](not_null channel) { + showPeerByLinkResolved(channel, info); + }); + } +} + +void SessionNavigation::resolveUsername( + const QString &username, + Fn)> done) { + if (const auto peer = _session->data().peerByUsername(username)) { + done(peer); + return; + } + _session->api().request(base::take(_resolveRequestId)).cancel(); + _resolveRequestId = _session->api().request(MTPcontacts_ResolveUsername( + MTP_string(username) + )).done([=](const MTPcontacts_ResolvedPeer &result) { + _resolveRequestId = 0; + Ui::hideLayer(); + if (result.type() != mtpc_contacts_resolvedPeer) { + return; + } + + const auto &d(result.c_contacts_resolvedPeer()); + _session->data().processUsers(d.vusers()); + _session->data().processChats(d.vchats()); + if (const auto peerId = peerFromMTP(d.vpeer())) { + done(_session->data().peer(peerId)); + } + }).fail([=](const RPCError &error) { + _resolveRequestId = 0; + if (error.code() == 400) { + Ui::show(Box( + tr::lng_username_not_found(tr::now, lt_user, username))); + } + }).send(); +} + +void SessionNavigation::resolveChannelById( + ChannelId channelId, + Fn)> done) { + if (const auto channel = _session->data().channelLoaded(channelId)) { + done(channel); + return; + } + const auto fail = [=] { + Ui::show(Box(tr::lng_error_post_link_invalid(tr::now))); + }; + _session->api().request(base::take(_resolveRequestId)).cancel(); + _resolveRequestId = _session->api().request(MTPchannels_GetChannels( + MTP_vector( + 1, + MTP_inputChannel(MTP_int(channelId), MTP_long(0))) + )).done([=](const MTPmessages_Chats &result) { + result.match([&](const auto &data) { + const auto peer = _session->data().processChats(data.vchats()); + if (peer && peer->id == peerFromChannel(channelId)) { + done(peer->asChannel()); + } else { + fail(); + } + }); + }).fail([=](const RPCError &error) { + fail(); + }).send(); +} + +void SessionNavigation::showPeerByLinkResolved( + not_null peer, + const PeerByLinkInfo &info) { + auto params = SectionShow{ + SectionShow::Way::Forward + }; + params.origin = SectionShow::OriginMessage{ + info.clickFromMessageId + }; + const auto &replies = info.repliesInfo; + if (const auto threadId = std::get_if(&replies)) { + showRepliesForMessage( + session().data().history(peer), + threadId->id, + info.messageId, + params); + } else if (const auto commentId = std::get_if(&replies)) { + showRepliesForMessage( + session().data().history(peer), + info.messageId, + commentId->id, + params); + } else if (info.messageId == ShowAtGameShareMsgId) { + const auto user = peer->asUser(); + if (user && user->isBot() && !info.startToken.isEmpty()) { + user->botInfo->shareGameShortName = info.startToken; + AddBotToGroupBoxController::Start(this, user); + } else { + crl::on_main(this, [=] { + showPeerHistory(peer->id, params); + }); + } + } else if (info.messageId == ShowAtProfileMsgId && !peer->isChannel()) { + const auto user = peer->asUser(); + if (user + && user->isBot() + && !user->botInfo->cantJoinGroups + && !info.startToken.isEmpty()) { + user->botInfo->startGroupToken = info.startToken; + AddBotToGroupBoxController::Start(this, user); + } else if (user && user->isBot()) { + // Always open bot chats, even from mention links. + crl::on_main(this, [=] { + showPeerHistory(peer->id, params); + }); + } else { + showPeerInfo(peer, params); + } + } else { + const auto user = peer->asUser(); + auto msgId = info.messageId; + if (msgId == ShowAtProfileMsgId || !peer->isChannel()) { + // Show specific posts only in channels / supergroups. + msgId = ShowAtUnreadMsgId; + } + if (user && user->isBot()) { + user->botInfo->startToken = info.startToken; + user->session().changes().peerUpdated( + user, + Data::PeerUpdate::Flag::BotStartToken); + } + crl::on_main(this, [=] { + showPeerHistory(peer->id, params, msgId); + }); + } + +} + void SessionNavigation::showRepliesForMessage( not_null history, MsgId rootId, @@ -104,17 +250,17 @@ void SessionNavigation::showRepliesForMessage( _session->api().request(base::take(_showingRepliesRequestId)).cancel(); const auto channelId = history->channelId(); - const auto item = _session->data().message(channelId, rootId); - if (!commentId && (!item || !item->repliesAreComments())) { - showSection(HistoryView::RepliesMemento(history, rootId)); - return; - } else if (const auto id = item ? item->commentsItemId() : FullMsgId()) { - if (const auto commentsItem = _session->data().message(id)) { - showSection( - HistoryView::RepliesMemento(commentsItem)); - return; - } - } + //const auto item = _session->data().message(channelId, rootId); + //if (!commentId && (!item || !item->repliesAreComments())) { + // showSection(HistoryView::RepliesMemento(history, rootId)); + // return; + //} else if (const auto id = item ? item->commentsItemId() : FullMsgId()) { + // if (const auto commentsItem = _session->data().message(id)) { + // showSection( + // HistoryView::RepliesMemento(commentsItem)); + // return; + // } + //} _showingRepliesHistory = history; _showingRepliesRootId = rootId; _showingRepliesRequestId = _session->api().request( @@ -155,7 +301,7 @@ void SessionNavigation::showRepliesForMessage( item->setRepliesOutboxReadTill(readTill->v); } const auto post = _session->data().message(channelId, rootId); - if (post) { + if (post && item->history()->channelId() != channelId) { post->setCommentsItemId(item->fullId()); if (const auto maxId = data.vmax_id()) { post->setRepliesMaxId(maxId->v); @@ -199,6 +345,26 @@ void SessionNavigation::showPeerInfo( showPeerInfo(history->peer->id, params); } +void SessionNavigation::showPeerHistory( + not_null peer, + const SectionShow ¶ms, + MsgId msgId) { + showPeerHistory( + peer->id, + params, + msgId); +} + +void SessionNavigation::showPeerHistory( + not_null history, + const SectionShow ¶ms, + MsgId msgId) { + showPeerHistory( + history->peer->id, + params, + msgId); +} + void SessionNavigation::showSettings( Settings::Type type, const SectionShow ¶ms) { @@ -905,26 +1071,6 @@ void SessionController::showPeerHistory( msgId); } -void SessionController::showPeerHistory( - not_null peer, - const SectionShow ¶ms, - MsgId msgId) { - showPeerHistory( - peer->id, - params, - msgId); -} - -void SessionController::showPeerHistory( - not_null history, - const SectionShow ¶ms, - MsgId msgId) { - showPeerHistory( - history->peer->id, - params, - msgId); -} - void SessionController::showSection( SectionMemento &&memento, const SectionShow ¶ms) { diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h index f0976210b4..980b7d2e75 100644 --- a/Telegram/SourceFiles/window/window_session_controller.h +++ b/Telegram/SourceFiles/window/window_session_controller.h @@ -138,6 +138,22 @@ public: const SectionShow ¶ms = SectionShow()) = 0; virtual not_null parentController() = 0; + struct CommentId { + MsgId id = 0; + }; + struct ThreadId { + MsgId id = 0; + }; + using RepliesByLinkInfo = std::variant; + struct PeerByLinkInfo { + std::variant usernameOrId; + MsgId messageId = ShowAtUnreadMsgId; + RepliesByLinkInfo repliesInfo; + QString startToken; + FullMsgId clickFromMessageId; + }; + void showPeerByLink(const PeerByLinkInfo &info); + void showRepliesForMessage( not_null history, MsgId rootId, @@ -154,6 +170,27 @@ public: not_null history, const SectionShow ¶ms = SectionShow()); + virtual void showPeerHistory( + PeerId peerId, + const SectionShow ¶ms = SectionShow::Way::ClearStack, + MsgId msgId = ShowAtUnreadMsgId) = 0; + void showPeerHistory( + not_null peer, + const SectionShow ¶ms = SectionShow::Way::ClearStack, + MsgId msgId = ShowAtUnreadMsgId); + void showPeerHistory( + not_null history, + const SectionShow ¶ms = SectionShow::Way::ClearStack, + MsgId msgId = ShowAtUnreadMsgId); + + void clearSectionStack( + const SectionShow ¶ms = SectionShow::Way::ClearStack) { + showPeerHistory( + PeerId(0), + params, + ShowAtUnreadMsgId); + } + void showSettings( Settings::Type type, const SectionShow ¶ms = SectionShow()); @@ -166,8 +203,21 @@ public: private: + void resolveUsername( + const QString &username, + Fn)> done); + void resolveChannelById( + ChannelId channelId, + Fn)> done); + + void showPeerByLinkResolved( + not_null peer, + const PeerByLinkInfo &info); + const not_null _session; + mtpRequestId _resolveRequestId = 0; + History *_showingRepliesHistory = nullptr; MsgId _showingRepliesRootId = 0; mtpRequestId _showingRepliesRequestId = 0; @@ -251,26 +301,11 @@ public: void showBackFromStack( const SectionShow ¶ms = SectionShow()) override; + using SessionNavigation::showPeerHistory; void showPeerHistory( PeerId peerId, const SectionShow ¶ms = SectionShow::Way::ClearStack, - MsgId msgId = ShowAtUnreadMsgId); - void showPeerHistory( - not_null peer, - const SectionShow ¶ms = SectionShow::Way::ClearStack, - MsgId msgId = ShowAtUnreadMsgId); - void showPeerHistory( - not_null history, - const SectionShow ¶ms = SectionShow::Way::ClearStack, - MsgId msgId = ShowAtUnreadMsgId); - - void clearSectionStack( - const SectionShow ¶ms = SectionShow::Way::ClearStack) { - showPeerHistory( - PeerId(0), - params, - ShowAtUnreadMsgId); - } + MsgId msgId = ShowAtUnreadMsgId) override; void showSpecialLayer( object_ptr &&layer,