Improve notification Ctrl+Click to open a new window.

Fixes #29144.
This commit is contained in:
John Preston 2025-05-07 18:43:22 +04:00
parent 6c68bacaef
commit cae192682b
3 changed files with 89 additions and 55 deletions

View file

@ -1108,78 +1108,116 @@ void Manager::notificationActivated(
const TextWithTags &reply) { const TextWithTags &reply) {
onBeforeNotificationActivated(id); onBeforeNotificationActivated(id);
if (const auto session = system()->findSession(id.contextId.sessionId)) { if (const auto session = system()->findSession(id.contextId.sessionId)) {
if (session->windows().empty()) { const auto history = session->data().history(
Core::App().domain().activate(&session->account()); id.contextId.peerId);
} const auto item = history->owner().message(
if (!session->windows().empty()) { history->peer,
const auto window = session->windows().front(); id.msgId);
const auto history = session->data().history( const auto topic = item ? item->topic() : nullptr;
id.contextId.peerId); if (!reply.text.isEmpty()) {
const auto item = history->owner().message( const auto topicRootId = topic
history->peer, ? topic->rootId()
id.msgId); : id.contextId.topicRootId;
const auto topic = item ? item->topic() : nullptr; const auto replyToId = (id.msgId > 0
if (!reply.text.isEmpty()) { && !history->peer->isUser()
const auto topicRootId = topic && id.msgId != topicRootId)
? topic->rootId() ? FullMsgId(history->peer->id, id.msgId)
: id.contextId.topicRootId; : FullMsgId();
const auto replyToId = (id.msgId > 0 auto draft = std::make_unique<Data::Draft>(
&& !history->peer->isUser() reply,
&& id.msgId != topicRootId) FullReplyTo{
? FullMsgId(history->peer->id, id.msgId) .messageId = replyToId,
: FullMsgId(); .topicRootId = topicRootId,
auto draft = std::make_unique<Data::Draft>( },
reply, MessageCursor{
FullReplyTo{ int(reply.text.size()),
.messageId = replyToId, int(reply.text.size()),
.topicRootId = topicRootId, Ui::kQFixedMax,
}, },
MessageCursor{ Data::WebPageDraft());
int(reply.text.size()), history->setLocalDraft(std::move(draft));
int(reply.text.size()),
Ui::kQFixedMax,
},
Data::WebPageDraft());
history->setLocalDraft(std::move(draft));
}
window->widget()->showFromTray();
if (Core::App().passcodeLocked()) {
window->widget()->setInnerFocus();
system()->clearAll();
} else {
const auto openSeparated = base::IsCtrlPressed();
openNotificationMessage(history, id.msgId, openSeparated);
}
onAfterNotificationActivated(id, window);
} }
const auto openSeparated = base::IsCtrlPressed();
const auto window = openNotificationMessage(
history,
id.msgId,
openSeparated);
onAfterNotificationActivated(id, window);
} }
} }
void Manager::openNotificationMessage( Window::SessionController *Manager::openNotificationMessage(
not_null<History*> history, not_null<History*> history,
MsgId messageId, MsgId messageId,
bool openSeparated) { bool openSeparated) {
if (Core::App().passcodeLocked()) {
const auto window = history->session().tryResolveWindow();
if (window) {
window->widget()->showFromTray();
window->widget()->setInnerFocus();
system()->clearAll();
}
return window;
}
const auto item = history->owner().message(history->peer, messageId); const auto item = history->owner().message(history->peer, messageId);
const auto openExactlyMessage = !history->peer->isBroadcast() const auto openExactlyMessage = !history->peer->isBroadcast()
&& item && item
&& item->isRegular() && item->isRegular()
&& (item->out() || (item->mentionsMe() && !history->peer->isUser())); && (item->out() || (item->mentionsMe() && !history->peer->isUser()));
const auto topic = item ? item->topic() : nullptr; const auto topic = item ? item->topic() : nullptr;
const auto separate = Core::App().separateWindowFor(history->peer);
const auto guard = gsl::finally([&] {
if (topic) {
system()->clearFromTopic(topic);
} else {
system()->clearFromHistory(history);
}
});
const auto separateId = topic
? Window::SeparateId(Window::SeparateType::Forum, history)
: Window::SeparateId(history->peer);
const auto separate = Core::App().separateWindowFor(separateId);
const auto itemId = openExactlyMessage ? messageId : ShowAtUnreadMsgId; const auto itemId = openExactlyMessage ? messageId : ShowAtUnreadMsgId;
if (openSeparated && !separate && !topic) {
// In case we're opening a chat history we first try to open it like
// it is done from the main window context menu (that checks if the
// chat isn't restricted and also closes the chat we're opening
// in the window itself). If this couldn't be done, we open normally.
const auto tryInExisting = [&](bool primary) {
for (const auto &window : history->session().windows()) {
if (primary && !window->window().id().primary()) {
continue;
} else if (!primary && !window->window().id().folder()) {
continue;
}
window->showInNewWindow(separateId, itemId);
const auto shown = Core::App().separateWindowFor(
separateId);
return shown ? shown->sessionController() : window.get();
}
return (Window::SessionController*)nullptr;
};
const auto shownPrimary = tryInExisting(true);
const auto shown = shownPrimary
? shownPrimary
: tryInExisting(false);
if (shown) {
return shown;
}
}
const auto window = separate const auto window = separate
? separate->sessionController() ? separate->sessionController()
: openSeparated : openSeparated
? [&] { ? [&] {
const auto window = Core::App().ensureSeparateWindowFor( const auto window = Core::App().ensureSeparateWindowFor(
topic separateId,
? Window::SeparateId(Window::SeparateType::Forum, history)
: Window::SeparateId(history->peer),
itemId); itemId);
return window ? window->sessionController() : nullptr; return window ? window->sessionController() : nullptr;
}() }()
: history->session().tryResolveWindow(); : history->session().tryResolveWindow();
if (window) { if (window) {
window->widget()->showFromTray();
if (topic) { if (topic) {
window->showSection( window->showSection(
std::make_shared<HistoryView::RepliesMemento>( std::make_shared<HistoryView::RepliesMemento>(
@ -1194,11 +1232,7 @@ void Manager::openNotificationMessage(
itemId); itemId);
} }
} }
if (topic) { return window;
system()->clearFromTopic(topic);
} else {
system()->clearFromHistory(history);
}
} }
void Manager::notificationReplied( void Manager::notificationReplied(

View file

@ -353,7 +353,7 @@ protected:
[[nodiscard]] virtual QString accountNameSeparator(); [[nodiscard]] virtual QString accountNameSeparator();
private: private:
void openNotificationMessage( Window::SessionController *openNotificationMessage(
not_null<History*> history, not_null<History*> history,
MsgId messageId, MsgId messageId,
bool openSeparated); bool openSeparated);

View file

@ -2651,7 +2651,7 @@ void SessionController::showInNewWindow(
const auto active = activeChatCurrent(); const auto active = activeChatCurrent();
// windows check active forum / active archive // windows check active forum / active archive
const auto fromActive = active.thread() const auto fromActive = active.thread()
? (active.thread() == id.thread) ? (active.thread() == id.thread && id.type == SeparateType::Chat)
: false; : false;
const auto toSeparate = [=] { const auto toSeparate = [=] {
Core::App().ensureSeparateWindowFor(id, msgId); Core::App().ensureSeparateWindowFor(id, msgId);