Open specific chat only in one window.

This commit is contained in:
John Preston 2022-01-04 19:36:33 +03:00
parent 54247cd11b
commit 18e6e2da9e
16 changed files with 187 additions and 103 deletions

View file

@ -172,11 +172,11 @@ Application::~Application() {
Local::writeSettings();
}
// Depend on activeWindow() for now :(
// Depend on primaryWindow() for now :(
Shortcuts::Finish();
_separateWindows.clear();
_window = nullptr;
_secondaryWindows.clear();
_primaryWindow = nullptr;
_mediaView = nullptr;
_notifications->clearAllFast();
@ -269,13 +269,13 @@ void Application::run() {
// Create mime database, so it won't be slow later.
QMimeDatabase().mimeTypeForName(qsl("text/plain"));
_window = std::make_unique<Window::Controller>();
_lastActiveWindow = _window.get();
_primaryWindow = std::make_unique<Window::Controller>();
_lastActiveWindow = _primaryWindow.get();
_domain->activeChanges(
) | rpl::start_with_next([=](not_null<Main::Account*> account) {
_window->showAccount(account);
}, _window->widget()->lifetime());
_primaryWindow->showAccount(account);
}, _primaryWindow->widget()->lifetime());
QCoreApplication::instance()->installEventFilter(this);
@ -294,20 +294,20 @@ void Application::run() {
startShortcuts();
startDomain();
_window->widget()->show();
_primaryWindow->widget()->show();
const auto currentGeometry = _window->widget()->geometry();
const auto currentGeometry = _primaryWindow->widget()->geometry();
_mediaView = std::make_unique<Media::View::OverlayWidget>();
_window->widget()->Ui::RpWidget::setGeometry(currentGeometry);
_primaryWindow->widget()->Ui::RpWidget::setGeometry(currentGeometry);
DEBUG_LOG(("Application Info: showing."));
_window->finishFirstShow();
_primaryWindow->finishFirstShow();
if (!_window->locked() && cStartToSettings()) {
_window->showSettings();
if (!_primaryWindow->locked() && cStartToSettings()) {
_primaryWindow->showSettings();
}
_window->updateIsActiveFocus();
_primaryWindow->updateIsActiveFocus();
for (const auto &error : Shortcuts::Errors()) {
LOG(("Shortcuts Error: %1").arg(error));
@ -318,12 +318,12 @@ void Application::run() {
showOpenGLCrashNotification();
}
_window->openInMediaViewRequests(
_primaryWindow->openInMediaViewRequests(
) | rpl::start_with_next([=](Media::View::OpenRequest &&request) {
if (_mediaView) {
_mediaView->show(std::move(request));
}
}, _window->lifetime());
}, _primaryWindow->lifetime());
{
const auto countries = std::make_shared<Countries::Manager>(
@ -348,7 +348,7 @@ void Application::showOpenGLCrashNotification() {
Core::App().settings().setDisableOpenGL(true);
Local::writeSettings();
};
_window->show(Box<Ui::ConfirmBox>(
_primaryWindow->show(Box<Ui::ConfirmBox>(
"There may be a problem with your graphics drivers and OpenGL. "
"Try updating your drivers.\n\n"
"OpenGL has been disabled. You can try to enable it again "
@ -469,7 +469,7 @@ bool Application::eventFilter(QObject *object, QEvent *e) {
checkStartUrl();
}
if (StartUrlRequiresActivate(url)) {
_window->activate();
_primaryWindow->activate();
}
}
} break;
@ -669,14 +669,14 @@ void Application::checkLocalTime() {
void Application::handleAppActivated() {
checkLocalTime();
if (_window) {
_window->updateIsActiveFocus();
if (_primaryWindow) {
_primaryWindow->updateIsActiveFocus();
}
}
void Application::handleAppDeactivated() {
if (_window) {
_window->updateIsActiveBlur();
if (_primaryWindow) {
_primaryWindow->updateIsActiveBlur();
}
Ui::Tooltip::Hide();
}
@ -776,7 +776,7 @@ bool Application::canApplyLangPackWithoutRestart() const {
}
void Application::checkStartUrl() {
if (!cStartUrl().isEmpty() && _window && !_window->locked()) {
if (!cStartUrl().isEmpty() && _primaryWindow && !_primaryWindow->locked()) {
const auto url = cStartUrl();
cSetStartUrl(QString());
if (!openLocalUrl(url, {})) {
@ -837,7 +837,9 @@ bool Application::openCustomUrl(
return false;
}
const auto command = base::StringViewMid(urlTrimmed, protocol.size(), 8192);
const auto controller = _window ? _window->sessionController() : nullptr;
const auto controller = _primaryWindow
? _primaryWindow->sessionController()
: nullptr;
using namespace qthelp;
const auto options = RegExOption::CaseInsensitive;
@ -852,22 +854,22 @@ bool Application::openCustomUrl(
}
void Application::preventOrInvoke(Fn<void()> &&callback) {
_window->preventOrInvoke(std::move(callback));
_primaryWindow->preventOrInvoke(std::move(callback));
}
void Application::lockByPasscode() {
preventOrInvoke([=] {
if (_window) {
if (_primaryWindow) {
_passcodeLock = true;
_window->setupPasscodeLock();
_primaryWindow->setupPasscodeLock();
}
});
}
void Application::unlockPasscode() {
clearPasscodeLock();
if (_window) {
_window->clearPasscodeLock();
if (_primaryWindow) {
_primaryWindow->clearPasscodeLock();
}
}
@ -952,13 +954,13 @@ void Application::localPasscodeChanged() {
}
bool Application::hasActiveWindow(not_null<Main::Session*> session) const {
if (App::quitting() || !_window) {
if (App::quitting() || !_primaryWindow) {
return false;
} else if (_calls->hasActivePanel(session)) {
return true;
} else if (const auto controller = _window->sessionController()) {
} else if (const auto controller = _primaryWindow->sessionController()) {
if (&controller->session() == session
&& _window->widget()->isActive()) {
&& _primaryWindow->widget()->isActive()) {
return true;
}
}
@ -966,20 +968,20 @@ bool Application::hasActiveWindow(not_null<Main::Session*> session) const {
}
void Application::saveCurrentDraftsToHistories() {
if (!_window) {
if (!_primaryWindow) {
return;
} else if (const auto controller = _window->sessionController()) {
} else if (const auto controller = _primaryWindow->sessionController()) {
controller->content()->saveFieldToHistoryLocalDraft();
}
}
Window::Controller *Application::mainWindow() const {
return _window.get();
Window::Controller *Application::primaryWindow() const {
return _primaryWindow.get();
}
Window::Controller *Application::separateWindowForPeer(
not_null<PeerData*> peer) const {
for (const auto &[history, window] : _separateWindows) {
for (const auto &[history, window] : _secondaryWindows) {
if (history->peer == peer) {
return window.get();
}
@ -988,18 +990,27 @@ Window::Controller *Application::separateWindowForPeer(
}
Window::Controller *Application::ensureSeparateWindowForPeer(
not_null<PeerData*> peer) {
not_null<PeerData*> peer,
MsgId showAtMsgId) {
const auto activate = [&](not_null<Window::Controller*> window) {
window->activate();
return window;
};
if (const auto existing = separateWindowForPeer(peer)) {
return existing;
existing->sessionController()->showPeerHistory(
peer,
Window::SectionShow::Way::ClearStack,
showAtMsgId);
return activate(existing);
}
const auto result = _separateWindows.emplace(
const auto result = _secondaryWindows.emplace(
peer->owner().history(peer),
std::make_unique<Window::Controller>(peer)).first->second.get();
result->showAccount(&peer->account());
result->sessionController()->showPeerHistory(peer);
std::make_unique<Window::Controller>(peer, showAtMsgId)
).first->second.get();
result->widget()->show();
result->finishFirstShow();
return result;
return activate(result);
}
Window::Controller *Application::activeWindow() const {

View file

@ -140,12 +140,13 @@ public:
// Windows interface.
bool hasActiveWindow(not_null<Main::Session*> session) const;
void saveCurrentDraftsToHistories();
[[nodiscard]] Window::Controller *mainWindow() const;
[[nodiscard]] Window::Controller *primaryWindow() const;
[[nodiscard]] Window::Controller *activeWindow() const;
[[nodiscard]] Window::Controller *separateWindowForPeer(
not_null<PeerData*> peer) const;
Window::Controller *ensureSeparateWindowForPeer(
not_null<PeerData*> peer);
not_null<PeerData*> peer,
MsgId showAtMsgId);
bool closeActiveWindow();
bool minimizeActiveWindow();
[[nodiscard]] QWidget *getFileDialogParent();
@ -346,10 +347,10 @@ private:
const std::unique_ptr<Main::Domain> _domain;
const std::unique_ptr<Export::Manager> _exportManager;
const std::unique_ptr<Calls::Instance> _calls;
std::unique_ptr<Window::Controller> _window;
std::unique_ptr<Window::Controller> _primaryWindow;
base::flat_map<
not_null<History*>,
std::unique_ptr<Window::Controller>> _separateWindows;
std::unique_ptr<Window::Controller>> _secondaryWindows;
Window::Controller *_lastActiveWindow = nullptr;
std::unique_ptr<Media::View::OverlayWidget> _mediaView;

View file

@ -441,7 +441,7 @@ void Manager::set(const QString &keys, Command command, bool replace) {
}
auto shortcut = base::make_unique_q<QShortcut>(
result,
Core::App().activeWindow()->widget().get(),
Core::App().primaryWindow()->widget().get(),
nullptr,
nullptr,
Qt::ApplicationShortcut);

View file

@ -227,15 +227,24 @@ Widget::Widget(
const auto openSearchResult = !controller->selectingPeer()
&& row.filteredRow;
if (const auto history = row.key.history()) {
const auto window = row.newWindow
? Core::App().ensureSeparateWindowForPeer(
history->peer)->sessionController()
: controller.get();
window->content()->choosePeer(
history->peer->id,
(controller->uniqueChatsInSearchResults()
? ShowAtUnreadMsgId
: row.message.fullId.msg));
const auto peer = history->peer;
const auto showAtMsgId = controller->uniqueChatsInSearchResults()
? ShowAtUnreadMsgId
: row.message.fullId.msg;
if (row.newWindow) {
const auto active = controller->activeChatCurrent();
if (const auto history = active.history()) {
if (history->peer == peer) {
controller->content()->ui_showPeerHistory(
0,
Window::SectionShow::Way::ClearStack,
0);
}
}
Core::App().ensureSeparateWindowForPeer(peer, showAtMsgId);
} else {
controller->content()->choosePeer(peer->id, showAtMsgId);
}
} else if (const auto folder = row.key.folder()) {
controller->openFolder(folder);
}

View file

@ -1253,13 +1253,43 @@ void MainWidget::toggleChooseChatTheme(not_null<PeerData*> peer) {
_history->toggleChooseChatTheme(peer);
}
bool MainWidget::showHistoryInDifferentWindow(
PeerId peerId,
const SectionShow &params,
MsgId showAtMsgId) {
const auto peer = session().data().peer(peerId);
if (const auto separate = Core::App().separateWindowForPeer(peer)) {
if (separate == &controller()->window()) {
return false;
}
separate->sessionController()->showPeerHistory(
peerId,
params,
showAtMsgId);
separate->activate();
return true;
} else if (isPrimary() || (singlePeer()->id == peerId)) {
return false;
}
const auto primary = Core::App().primaryWindow();
if (&primary->account() != &session().account()) {
primary->showAccount(&session().account());
}
if (&primary->account() == &session().account()) {
primary->sessionController()->showPeerHistory(
peerId,
params,
showAtMsgId);
}
primary->activate();
return true;
}
void MainWidget::ui_showPeerHistory(
PeerId peerId,
const SectionShow &params,
MsgId showAtMsgId) {
if (!peerId && !isPrimary()) {
return;
} else if (peerId && _controller->window().locked()) {
if (peerId && _controller->window().locked()) {
return;
} else if (auto peer = session().data().peerLoaded(peerId)) {
if (peer->migrateTo()) {
@ -1270,7 +1300,7 @@ void MainWidget::ui_showPeerHistory(
const auto unavailable = peer->computeUnavailableReason();
if (!unavailable.isEmpty()) {
if (params.activation != anim::activation::background) {
Ui::show(Box<Ui::InformBox>(unavailable));
controller()->show(Box<Ui::InformBox>(unavailable));
}
return;
}
@ -1280,6 +1310,8 @@ void MainWidget::ui_showPeerHistory(
&& _mainSection->showMessage(peerId, params, showAtMsgId)) {
session().data().hideShownSpoilers();
return;
} else if (showHistoryInDifferentWindow(peerId, params, showAtMsgId)) {
return;
}
if (!(_history->peer() && _history->peer()->id == peerId)

View file

@ -319,6 +319,10 @@ private:
QImage &&image);
void handleHistoryBack();
bool showHistoryInDifferentWindow(
PeerId peerId,
const SectionShow &params,
MsgId showAtMsgId);
bool isOneColumn() const;
bool isNormalColumn() const;

View file

@ -319,7 +319,7 @@ void MainWindow::setupIntro(Intro::EnterPoint point) {
fixOrder();
}
void MainWindow::setupMain() {
void MainWindow::setupMain(MsgId singlePeerShowAtMsgId) {
Expects(account().sessionExists());
const auto animated = _intro
@ -338,7 +338,10 @@ void MainWindow::setupMain() {
clearWidgets();
_main = std::move(created);
if (const auto peer = singlePeer()) {
_main->controller()->showPeerHistory(peer);
_main->controller()->showPeerHistory(
peer,
Window::SectionShow::Way::ClearStack,
singlePeerShowAtMsgId);
}
if (_passcodeLock) {
_main->hide();
@ -859,8 +862,8 @@ MainWindow::~MainWindow() {
namespace App {
MainWindow *wnd() {
return (Core::IsAppLaunched() && Core::App().activeWindow())
? Core::App().activeWindow()->widget().get()
return (Core::IsAppLaunched() && Core::App().primaryWindow())
? Core::App().primaryWindow()->widget().get()
: nullptr;
}

View file

@ -54,7 +54,7 @@ public:
void setupPasscodeLock();
void clearPasscodeLock();
void setupIntro(Intro::EnterPoint point);
void setupMain();
void setupMain(MsgId singlePeerShowAtMsgId);
void showSettings();

View file

@ -172,7 +172,7 @@ ApplicationDelegate *_sharedDelegate = nil;
Core::Sandbox::Instance().customEnterFromEventLoop([&] {
if (Core::IsAppLaunched() && !_ignoreActivation) {
Core::App().handleAppActivated();
if (auto window = Core::App().activeWindow()) {
if (const auto window = Core::App().activeWindow()) {
if (window->widget()->isHidden()) {
window->widget()->showFromTray();
}

View file

@ -21,7 +21,7 @@ namespace Platform {
// account, with 100% scale and without "px" dimensions, because thats
// how it will look in real launched macOS app.
int PreviewTitleHeight() {
if (auto window = Core::App().activeWindow()) {
if (auto window = Core::App().primaryWindow()) {
if (auto height = window->widget()->getCustomTitleHeight()) {
return height;
}

View file

@ -730,7 +730,10 @@ void MainWindow::initGeometry() {
if (initGeometryFromSystem()) {
return;
}
const auto geometry = countInitialGeometry(positionFromSettings());
// #TODO windows
const auto geometry = countInitialGeometry(isPrimary()
? positionFromSettings()
: Core::WindowPosition());
DEBUG_LOG(("Window Pos: Setting first %1, %2, %3, %4"
).arg(geometry.x()
).arg(geometry.y()
@ -813,6 +816,7 @@ void MainWindow::savePosition(Qt::WindowState state) {
if (state == Qt::WindowMinimized
|| !isVisible()
|| !isPrimary() // #TODO windows
|| !positionInited()) {
return;
}

View file

@ -414,7 +414,7 @@ void System::showNext() {
const auto &settings = Core::App().settings();
if (alert) {
if (settings.flashBounceNotify() && !_manager->skipFlashBounce()) {
if (const auto window = Core::App().activeWindow()) {
if (const auto window = Core::App().primaryWindow()) {
if (const auto handle = window->widget()->windowHandle()) {
handle->alert(kSystemAlertDuration);
// (handle, SLOT(_q_clearAlert())); in the future.

View file

@ -43,7 +43,7 @@ namespace {
QPoint notificationStartPosition() {
const auto corner = Core::App().settings().notificationsCorner();
const auto window = Core::App().activeWindow();
const auto window = Core::App().primaryWindow();
const auto r = window
? window->widget()->desktopRect()
: QGuiApplication::primaryScreen()->availableGeometry();

View file

@ -44,8 +44,11 @@ namespace Window {
Controller::Controller() : Controller(CreateArgs{}) {
}
Controller::Controller(not_null<PeerData*> singlePeer)
Controller::Controller(
not_null<PeerData*> singlePeer,
MsgId showAtMsgId)
: Controller(CreateArgs{ singlePeer.get() }) {
showAccount(&singlePeer->account(), showAtMsgId);
}
Controller::Controller(CreateArgs &&args)
@ -63,6 +66,12 @@ Controller::~Controller() {
}
void Controller::showAccount(not_null<Main::Account*> account) {
showAccount(account, ShowAtUnreadMsgId);
}
void Controller::showAccount(
not_null<Main::Account*> account,
MsgId singlePeerShowAtMsgId) {
Expects(isPrimary() || &_singlePeer->account() == account);
const auto prevSessionUniqueId = (_account && _account->sessionExists())
@ -91,20 +100,10 @@ void Controller::showAccount(not_null<Main::Account*> account) {
_sessionController = session
? std::make_unique<SessionController>(session, this)
: nullptr;
if (_sessionController) {
_sessionController->filtersMenuChanged(
) | rpl::start_with_next([=] {
sideBarChanged();
}, _sessionController->lifetime());
}
if (session && session->settings().dialogsFiltersEnabled()) {
_sessionController->toggleFiltersMenu(true);
} else {
sideBarChanged();
}
setupSideBar();
_widget.updateWindowIcon();
if (session) {
setupMain();
setupMain(singlePeerShowAtMsgId);
session->updates().isIdleValue(
) | rpl::filter([=](bool idle) {
@ -120,6 +119,9 @@ void Controller::showAccount(not_null<Main::Account*> account) {
}, _sessionController->lifetime());
widget()->setInnerFocus();
} else if (!isPrimary()) {
// #TODO windows test
close();
} else {
setupIntro();
_widget.updateGlobalMenu();
@ -133,6 +135,26 @@ PeerData *Controller::singlePeer() const {
return _singlePeer;
}
void Controller::setupSideBar() {
if (!isPrimary()) {
return;
}
if (!_sessionController) {
sideBarChanged();
return;
}
_sessionController->filtersMenuChanged(
) | rpl::start_with_next([=] {
sideBarChanged();
}, _sessionController->lifetime());
if (_sessionController->session().settings().dialogsFiltersEnabled()) {
_sessionController->toggleFiltersMenu(true);
} else {
sideBarChanged();
}
}
void Controller::checkLockByTerms() {
const auto data = account().sessionExists()
? account().session().termsLocked()
@ -260,10 +282,10 @@ void Controller::setupIntro() {
: Intro::EnterPoint::Start);
}
void Controller::setupMain() {
void Controller::setupMain(MsgId singlePeerShowAtMsgId) {
Expects(_sessionController != nullptr);
_widget.setupMain();
_widget.setupMain(singlePeerShowAtMsgId);
if (const auto id = Ui::Emoji::NeedToSwitchBackToId()) {
Ui::Emoji::LoadAndSwitchTo(&_sessionController->session(), id);

View file

@ -24,7 +24,9 @@ namespace Window {
class Controller final : public base::has_weak_ptr {
public:
Controller();
explicit Controller(not_null<PeerData*> singlePeer);
Controller(
not_null<PeerData*> singlePeer,
MsgId showAtMsgId);
~Controller();
Controller(const Controller &other) = delete;
@ -56,7 +58,7 @@ public:
void setupPasscodeLock();
void clearPasscodeLock();
void setupIntro();
void setupMain();
void setupMain(MsgId singlePeerShowAtMsgId);
void showLogoutConfirmation();
@ -80,7 +82,6 @@ public:
anim::type animated = anim::type::normal);
void showRightColumn(object_ptr<TWidget> widget);
void sideBarChanged();
void activate();
void reActivate();
@ -110,6 +111,12 @@ private:
};
explicit Controller(CreateArgs &&args);
void showAccount(
not_null<Main::Account*> account,
MsgId singlePeerShowAtMsgId);
void setupSideBar();
void sideBarChanged();
void showBox(
object_ptr<Ui::BoxContent> content,
Ui::LayerOptions options,

View file

@ -478,20 +478,14 @@ void SessionNavigation::showPeerHistory(
not_null<PeerData*> peer,
const SectionShow &params,
MsgId msgId) {
showPeerHistory(
peer->id,
params,
msgId);
showPeerHistory(peer->id, params, msgId);
}
void SessionNavigation::showPeerHistory(
not_null<History*> history,
const SectionShow &params,
MsgId msgId) {
showPeerHistory(
history->peer->id,
params,
msgId);
showPeerHistory(history->peer->id, params, msgId);
}
void SessionNavigation::showSettings(
@ -680,7 +674,7 @@ void SessionController::initSupportMode() {
}
void SessionController::toggleFiltersMenu(bool enabled) {
if (!enabled == !_filters) {
if (!isPrimary() || (!enabled == !_filters)) {
return;
} else if (enabled) {
_filters = std::make_unique<FiltersMenu>(
@ -1316,10 +1310,7 @@ void SessionController::showPeerHistory(
PeerId peerId,
const SectionShow &params,
MsgId msgId) {
content()->ui_showPeerHistory(
peerId,
params,
msgId);
content()->ui_showPeerHistory(peerId, params, msgId);
}
void SessionController::showPeerHistoryAtItem(