Handle links to replies section.

This commit is contained in:
John Preston 2020-09-22 18:05:07 +03:00
parent 247b1f64ca
commit 889139f31f
11 changed files with 308 additions and 259 deletions

View file

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item.h" #include "history/history_item.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "window/window_session_controller.h"
#include "facades.h" #include "facades.h"
#include "app.h" #include "app.h"
@ -112,7 +113,11 @@ void MentionClickHandler::onClick(ClickContext context) const {
const auto button = context.button; const auto button = context.button;
if (button == Qt::LeftButton || button == Qt::MiddleButton) { if (button == Qt::LeftButton || button == Qt::MiddleButton) {
if (const auto m = App::main()) { // multi good 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
});
} }
} }
} }

View file

@ -273,25 +273,30 @@ bool ResolveUsername(
} }
const auto commentParam = params.value(qsl("comment")); const auto commentParam = params.value(qsl("comment"));
const auto commentId = commentParam.toInt(); const auto commentId = commentParam.toInt();
const auto threadParam = params.value(qsl("thread"));
const auto threadId = threadParam.toInt();
const auto gameParam = params.value(qsl("game")); const auto gameParam = params.value(qsl("game"));
if (!gameParam.isEmpty() && valid(gameParam)) { if (!gameParam.isEmpty() && valid(gameParam)) {
startToken = gameParam; startToken = gameParam;
post = ShowAtGameShareMsgId; post = ShowAtGameShareMsgId;
} }
const auto clickFromMessageId = context.value<FullMsgId>(); const auto clickFromMessageId = context.value<FullMsgId>();
if (commentId) { using Navigation = Window::SessionNavigation;
controller->content()->openCommentByName( controller->showPeerByLink(Navigation::PeerByLinkInfo{
domain, .usernameOrId = domain,
post, .messageId = post,
commentId, .repliesInfo = commentId
clickFromMessageId); ? Navigation::RepliesByLinkInfo{
} else { Navigation::CommentId{ commentId }
controller->content()->openPeerByName( }
domain, : threadId
post, ? Navigation::RepliesByLinkInfo{
startToken, Navigation::ThreadId{ threadId }
clickFromMessageId); }
} : Navigation::RepliesByLinkInfo{ v::null },
.startToken = startToken,
.clickFromMessageId = clickFromMessageId,
});
return true; return true;
} }
@ -307,46 +312,29 @@ bool ResolvePrivatePost(
qthelp::UrlParamNameTransform::ToLower); qthelp::UrlParamNameTransform::ToLower);
const auto channelId = params.value(qsl("channel")).toInt(); const auto channelId = params.value(qsl("channel")).toInt();
const auto msgId = params.value(qsl("post")).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)) { if (!channelId || !IsServerMsgId(msgId)) {
return false; return false;
} }
const auto clickFromMessageId = context.value<FullMsgId>(); const auto clickFromMessageId = context.value<FullMsgId>();
const auto done = crl::guard(controller, [=](not_null<PeerData*> peer) { using Navigation = Window::SessionNavigation;
auto params = Window::SectionShow{ controller->showPeerByLink(Navigation::PeerByLinkInfo{
Window::SectionShow::Way::Forward .usernameOrId = channelId,
}; .messageId = msgId,
params.origin = Window::SectionShow::OriginMessage{ .repliesInfo = commentId
clickFromMessageId ? Navigation::RepliesByLinkInfo{
}; Navigation::CommentId{ commentId }
controller->showPeerHistory(
peer->id,
Window::SectionShow::Way::Forward,
msgId);
});
const auto fail = [=] {
Ui::show(Box<InformBox>(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<MTPInputChannel>(
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();
} }
}); : threadId
}).fail([=](const RPCError &error) { ? Navigation::RepliesByLinkInfo{
fail(); Navigation::ThreadId{ threadId }
}).send(); }
: Navigation::RepliesByLinkInfo{ v::null },
.clickFromMessageId = clickFromMessageId,
});
return true; return true;
} }

View file

@ -67,27 +67,28 @@ struct PeerUpdate {
OnlineStatus = (1 << 12), OnlineStatus = (1 << 12),
BotCommands = (1 << 13), BotCommands = (1 << 13),
BotCanBeInvited = (1 << 14), BotCanBeInvited = (1 << 14),
CommonChats = (1 << 15), BotStartToken = (1 << 15),
HasCalls = (1 << 16), CommonChats = (1 << 16),
SupportInfo = (1 << 17), HasCalls = (1 << 17),
IsBot = (1 << 18), SupportInfo = (1 << 18),
IsBot = (1 << 19),
// For chats and channels // For chats and channels
InviteLink = (1 << 19), InviteLink = (1 << 20),
Members = (1 << 20), Members = (1 << 21),
Admins = (1 << 21), Admins = (1 << 22),
BannedUsers = (1 << 22), BannedUsers = (1 << 23),
Rights = (1 << 23), Rights = (1 << 24),
// For channels // For channels
ChannelAmIn = (1 << 24), ChannelAmIn = (1 << 25),
StickersSet = (1 << 25), StickersSet = (1 << 26),
ChannelLinkedChat = (1 << 26), ChannelLinkedChat = (1 << 27),
ChannelLocation = (1 << 27), ChannelLocation = (1 << 28),
Slowmode = (1 << 28), Slowmode = (1 << 29),
// For iteration // For iteration
LastUsedBit = (1 << 28), LastUsedBit = (1 << 29),
}; };
using Flags = base::flags<Flag>; using Flags = base::flags<Flag>;
friend inline constexpr auto is_flag_type(Flag) { return true; } friend inline constexpr auto is_flag_type(Flag) { return true; }

View file

@ -570,6 +570,7 @@ HistoryWidget::HistoryWidget(
| UpdateFlag::ChannelAmIn | UpdateFlag::ChannelAmIn
| UpdateFlag::ChannelLinkedChat | UpdateFlag::ChannelLinkedChat
| UpdateFlag::Slowmode | UpdateFlag::Slowmode
| UpdateFlag::BotStartToken
) | rpl::filter([=](const Data::PeerUpdate &update) { ) | rpl::filter([=](const Data::PeerUpdate &update) {
return (update.peer.get() == _peer); return (update.peer.get() == _peer);
}) | rpl::map([](const Data::PeerUpdate &update) { }) | rpl::map([](const Data::PeerUpdate &update) {
@ -594,6 +595,10 @@ HistoryWidget::HistoryWidget(
return; return;
} }
} }
if (flags & UpdateFlag::BotStartToken) {
updateControlsVisibility();
updateControlsGeometry();
}
if (flags & UpdateFlag::PinnedMessage) { if (flags & UpdateFlag::PinnedMessage) {
if (pinnedMsgVisibilityUpdated()) { if (pinnedMsgVisibilityUpdated()) {
updateHistoryGeometry(); updateHistoryGeometry();

View file

@ -1210,7 +1210,8 @@ bool RepliesWidget::showInternal(
not_null<Window::SectionMemento*> memento, not_null<Window::SectionMemento*> memento,
const Window::SectionShow &params) { const Window::SectionShow &params) {
if (auto logMemento = dynamic_cast<RepliesMemento*>(memento.get())) { if (auto logMemento = dynamic_cast<RepliesMemento*>(memento.get())) {
if (logMemento->getHistory() == history()) { if (logMemento->getHistory() == history()
&& logMemento->getRootId() == _rootId) {
restoreState(logMemento); restoreState(logMemento);
return true; return true;
} }

View file

@ -133,6 +133,13 @@ void AbstractController::showBackFromStack(
return parentController()->showBackFromStack(params); return parentController()->showBackFromStack(params);
} }
void AbstractController::showPeerHistory(
PeerId peerId,
const Window::SectionShow &params,
MsgId msgId) {
return parentController()->showPeerHistory(peerId, params, msgId);
}
Controller::Controller( Controller::Controller(
not_null<WrapWidget*> widget, not_null<WrapWidget*> widget,
not_null<Window::SessionController*> window, not_null<Window::SessionController*> window,

View file

@ -140,6 +140,12 @@ public:
const Window::SectionShow &params = Window::SectionShow()) override; const Window::SectionShow &params = Window::SectionShow()) override;
void showBackFromStack( void showBackFromStack(
const Window::SectionShow &params = Window::SectionShow()) override; const Window::SectionShow &params = Window::SectionShow()) override;
void showPeerHistory(
PeerId peerId,
const Window::SectionShow &params = Window::SectionShow::Way::ClearStack,
MsgId msgId = ShowAtUnreadMsgId) override;
not_null<Window::SessionController*> parentController() override { not_null<Window::SessionController*> parentController() override {
return _parent; return _parent;
} }

View file

@ -2597,136 +2597,12 @@ void MainWidget::searchInChat(Dialogs::Key chat) {
} }
} }
void MainWidget::openPeerResolved(
not_null<PeerData*> 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<PeerData*> 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<PeerData*> 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) { bool MainWidget::contentOverlapped(const QRect &globalRect) {
return (_history->contentOverlapped(globalRect) return (_history->contentOverlapped(globalRect)
|| _playerPlaylist->overlaps(globalRect) || _playerPlaylist->overlaps(globalRect)
|| (_playerVolume && _playerVolume->overlaps(globalRect))); || (_playerVolume && _playerVolume->overlaps(globalRect)));
} }
void MainWidget::resolveUsername(
const QString &username,
Fn<void(not_null<PeerData*>)> 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<InformBox>(
tr::lng_username_not_found(tr::now, lt_user, username)));
}
}).send();
}
void MainWidget::activate() { void MainWidget::activate() {
if (_a_show.animating()) { if (_a_show.animating()) {
return; return;

View file

@ -122,17 +122,6 @@ public:
void showAnimated(const QPixmap &bgAnimCache, bool back = false); 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 activate();
void windowShown(); void windowShown();
@ -294,15 +283,6 @@ private:
void saveSectionInStack(); void saveSectionInStack();
void resolveUsername(
const QString &username,
Fn<void(not_null<PeerData*>)> done);
void openPeerResolved(
not_null<PeerData*> peer,
MsgId msgId,
const QString &startToken,
FullMsgId clickFromMessageId);
int getMainSectionTop() const; int getMainSectionTop() const;
int getThirdSectionTop() const; int getThirdSectionTop() const;
@ -406,7 +386,6 @@ private:
base::flat_map<not_null<PeerData*>, mtpRequestId> _viewsIncrementRequests; base::flat_map<not_null<PeerData*>, mtpRequestId> _viewsIncrementRequests;
base::flat_map<mtpRequestId, not_null<PeerData*>> _viewsIncrementByRequest; base::flat_map<mtpRequestId, not_null<PeerData*>> _viewsIncrementByRequest;
base::Timer _viewsIncrementTimer; base::Timer _viewsIncrementTimer;
mtpRequestId _resolveRequestId = 0;
struct SettingBackground; struct SettingBackground;
std::unique_ptr<SettingBackground> _background; std::unique_ptr<SettingBackground> _background;

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "boxes/peers/edit_peer_info_box.h" #include "boxes/peers/edit_peer_info_box.h"
#include "boxes/peer_list_controllers.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/main_window.h" #include "window/main_window.h"
#include "window/window_filters_menu.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_folder.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.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_chat_filters.h"
#include "data/data_photo.h" // requestAttachedStickerSets. #include "data/data_photo.h" // requestAttachedStickerSets.
#include "passport/passport_form_controller.h" #include "passport/passport_form_controller.h"
@ -85,12 +88,155 @@ SessionNavigation::SessionNavigation(not_null<Main::Session*> session)
SessionNavigation::~SessionNavigation() { SessionNavigation::~SessionNavigation() {
_session->api().request(base::take(_showingRepliesRequestId)).cancel(); _session->api().request(base::take(_showingRepliesRequestId)).cancel();
_session->api().request(base::take(_resolveRequestId)).cancel();
} }
Main::Session &SessionNavigation::session() const { Main::Session &SessionNavigation::session() const {
return *_session; return *_session;
} }
void SessionNavigation::showPeerByLink(const PeerByLinkInfo &info) {
Core::App().hideMediaView();
if (const auto username = std::get_if<QString>(&info.usernameOrId)) {
resolveUsername(*username, [=](not_null<PeerData*> peer) {
showPeerByLinkResolved(peer, info);
});
} else if (const auto id = std::get_if<ChannelId>(&info.usernameOrId)) {
resolveChannelById(*id, [=](not_null<ChannelData*> channel) {
showPeerByLinkResolved(channel, info);
});
}
}
void SessionNavigation::resolveUsername(
const QString &username,
Fn<void(not_null<PeerData*>)> 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<InformBox>(
tr::lng_username_not_found(tr::now, lt_user, username)));
}
}).send();
}
void SessionNavigation::resolveChannelById(
ChannelId channelId,
Fn<void(not_null<ChannelData*>)> done) {
if (const auto channel = _session->data().channelLoaded(channelId)) {
done(channel);
return;
}
const auto fail = [=] {
Ui::show(Box<InformBox>(tr::lng_error_post_link_invalid(tr::now)));
};
_session->api().request(base::take(_resolveRequestId)).cancel();
_resolveRequestId = _session->api().request(MTPchannels_GetChannels(
MTP_vector<MTPInputChannel>(
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<PeerData*> 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<ThreadId>(&replies)) {
showRepliesForMessage(
session().data().history(peer),
threadId->id,
info.messageId,
params);
} else if (const auto commentId = std::get_if<CommentId>(&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( void SessionNavigation::showRepliesForMessage(
not_null<History*> history, not_null<History*> history,
MsgId rootId, MsgId rootId,
@ -104,17 +250,17 @@ void SessionNavigation::showRepliesForMessage(
_session->api().request(base::take(_showingRepliesRequestId)).cancel(); _session->api().request(base::take(_showingRepliesRequestId)).cancel();
const auto channelId = history->channelId(); const auto channelId = history->channelId();
const auto item = _session->data().message(channelId, rootId); //const auto item = _session->data().message(channelId, rootId);
if (!commentId && (!item || !item->repliesAreComments())) { //if (!commentId && (!item || !item->repliesAreComments())) {
showSection(HistoryView::RepliesMemento(history, rootId)); // showSection(HistoryView::RepliesMemento(history, rootId));
return; // return;
} else if (const auto id = item ? item->commentsItemId() : FullMsgId()) { //} else if (const auto id = item ? item->commentsItemId() : FullMsgId()) {
if (const auto commentsItem = _session->data().message(id)) { // if (const auto commentsItem = _session->data().message(id)) {
showSection( // showSection(
HistoryView::RepliesMemento(commentsItem)); // HistoryView::RepliesMemento(commentsItem));
return; // return;
} // }
} //}
_showingRepliesHistory = history; _showingRepliesHistory = history;
_showingRepliesRootId = rootId; _showingRepliesRootId = rootId;
_showingRepliesRequestId = _session->api().request( _showingRepliesRequestId = _session->api().request(
@ -155,7 +301,7 @@ void SessionNavigation::showRepliesForMessage(
item->setRepliesOutboxReadTill(readTill->v); item->setRepliesOutboxReadTill(readTill->v);
} }
const auto post = _session->data().message(channelId, rootId); const auto post = _session->data().message(channelId, rootId);
if (post) { if (post && item->history()->channelId() != channelId) {
post->setCommentsItemId(item->fullId()); post->setCommentsItemId(item->fullId());
if (const auto maxId = data.vmax_id()) { if (const auto maxId = data.vmax_id()) {
post->setRepliesMaxId(maxId->v); post->setRepliesMaxId(maxId->v);
@ -199,6 +345,26 @@ void SessionNavigation::showPeerInfo(
showPeerInfo(history->peer->id, params); showPeerInfo(history->peer->id, params);
} }
void SessionNavigation::showPeerHistory(
not_null<PeerData*> peer,
const SectionShow &params,
MsgId msgId) {
showPeerHistory(
peer->id,
params,
msgId);
}
void SessionNavigation::showPeerHistory(
not_null<History*> history,
const SectionShow &params,
MsgId msgId) {
showPeerHistory(
history->peer->id,
params,
msgId);
}
void SessionNavigation::showSettings( void SessionNavigation::showSettings(
Settings::Type type, Settings::Type type,
const SectionShow &params) { const SectionShow &params) {
@ -905,26 +1071,6 @@ void SessionController::showPeerHistory(
msgId); msgId);
} }
void SessionController::showPeerHistory(
not_null<PeerData*> peer,
const SectionShow &params,
MsgId msgId) {
showPeerHistory(
peer->id,
params,
msgId);
}
void SessionController::showPeerHistory(
not_null<History*> history,
const SectionShow &params,
MsgId msgId) {
showPeerHistory(
history->peer->id,
params,
msgId);
}
void SessionController::showSection( void SessionController::showSection(
SectionMemento &&memento, SectionMemento &&memento,
const SectionShow &params) { const SectionShow &params) {

View file

@ -138,6 +138,22 @@ public:
const SectionShow &params = SectionShow()) = 0; const SectionShow &params = SectionShow()) = 0;
virtual not_null<SessionController*> parentController() = 0; virtual not_null<SessionController*> parentController() = 0;
struct CommentId {
MsgId id = 0;
};
struct ThreadId {
MsgId id = 0;
};
using RepliesByLinkInfo = std::variant<v::null_t, CommentId, ThreadId>;
struct PeerByLinkInfo {
std::variant<QString, ChannelId> usernameOrId;
MsgId messageId = ShowAtUnreadMsgId;
RepliesByLinkInfo repliesInfo;
QString startToken;
FullMsgId clickFromMessageId;
};
void showPeerByLink(const PeerByLinkInfo &info);
void showRepliesForMessage( void showRepliesForMessage(
not_null<History*> history, not_null<History*> history,
MsgId rootId, MsgId rootId,
@ -154,6 +170,27 @@ public:
not_null<History*> history, not_null<History*> history,
const SectionShow &params = SectionShow()); const SectionShow &params = SectionShow());
virtual void showPeerHistory(
PeerId peerId,
const SectionShow &params = SectionShow::Way::ClearStack,
MsgId msgId = ShowAtUnreadMsgId) = 0;
void showPeerHistory(
not_null<PeerData*> peer,
const SectionShow &params = SectionShow::Way::ClearStack,
MsgId msgId = ShowAtUnreadMsgId);
void showPeerHistory(
not_null<History*> history,
const SectionShow &params = SectionShow::Way::ClearStack,
MsgId msgId = ShowAtUnreadMsgId);
void clearSectionStack(
const SectionShow &params = SectionShow::Way::ClearStack) {
showPeerHistory(
PeerId(0),
params,
ShowAtUnreadMsgId);
}
void showSettings( void showSettings(
Settings::Type type, Settings::Type type,
const SectionShow &params = SectionShow()); const SectionShow &params = SectionShow());
@ -166,8 +203,21 @@ public:
private: private:
void resolveUsername(
const QString &username,
Fn<void(not_null<PeerData*>)> done);
void resolveChannelById(
ChannelId channelId,
Fn<void(not_null<ChannelData*>)> done);
void showPeerByLinkResolved(
not_null<PeerData*> peer,
const PeerByLinkInfo &info);
const not_null<Main::Session*> _session; const not_null<Main::Session*> _session;
mtpRequestId _resolveRequestId = 0;
History *_showingRepliesHistory = nullptr; History *_showingRepliesHistory = nullptr;
MsgId _showingRepliesRootId = 0; MsgId _showingRepliesRootId = 0;
mtpRequestId _showingRepliesRequestId = 0; mtpRequestId _showingRepliesRequestId = 0;
@ -251,26 +301,11 @@ public:
void showBackFromStack( void showBackFromStack(
const SectionShow &params = SectionShow()) override; const SectionShow &params = SectionShow()) override;
using SessionNavigation::showPeerHistory;
void showPeerHistory( void showPeerHistory(
PeerId peerId, PeerId peerId,
const SectionShow &params = SectionShow::Way::ClearStack, const SectionShow &params = SectionShow::Way::ClearStack,
MsgId msgId = ShowAtUnreadMsgId); MsgId msgId = ShowAtUnreadMsgId) override;
void showPeerHistory(
not_null<PeerData*> peer,
const SectionShow &params = SectionShow::Way::ClearStack,
MsgId msgId = ShowAtUnreadMsgId);
void showPeerHistory(
not_null<History*> history,
const SectionShow &params = SectionShow::Way::ClearStack,
MsgId msgId = ShowAtUnreadMsgId);
void clearSectionStack(
const SectionShow &params = SectionShow::Way::ClearStack) {
showPeerHistory(
PeerId(0),
params,
ShowAtUnreadMsgId);
}
void showSpecialLayer( void showSpecialLayer(
object_ptr<Ui::LayerWidget> &&layer, object_ptr<Ui::LayerWidget> &&layer,