feat(daemon): Friendly message on daemon connection error

This commit is contained in:
Nick Bolton
2025-04-15 21:52:36 +01:00
committed by Chris Rizzitello
parent c62b4ec068
commit 901dacf593
8 changed files with 86 additions and 28 deletions

View File

@ -289,6 +289,7 @@ void MainWindow::connectSlots()
connect(&m_coreProcess, &CoreProcess::processStateChanged, this, &MainWindow::coreProcessStateChanged);
connect(&m_coreProcess, &CoreProcess::connectionStateChanged, this, &MainWindow::coreConnectionStateChanged);
connect(&m_coreProcess, &CoreProcess::secureSocket, this, &MainWindow::secureSocket);
connect(&m_coreProcess, &CoreProcess::daemonIpcClientConnectFailed, this, &MainWindow::daemonIpcClientConnectFailed);
connect(m_actionAbout, &QAction::triggered, this, &MainWindow::openAboutDialog);
connect(m_actionClearSettings, &QAction::triggered, this, &MainWindow::clearSettings);
@ -365,6 +366,21 @@ void MainWindow::firstShown()
// hacky and fragile, so maybe there's a better approach.
const auto kCriticalDialogDelay = 100;
QTimer::singleShot(kCriticalDialogDelay, this, &messages::raiseCriticalDialog);
if (!Settings::value(Settings::Gui::AutoUpdateCheck).isValid()) {
showAndActivate();
Settings::setValue(Settings::Gui::AutoUpdateCheck, messages::showUpdateCheckOption(this));
}
if (Settings::value(Settings::Gui::AutoUpdateCheck).toBool()) {
m_versionChecker.checkLatest();
} else {
qDebug() << "update check disabled";
}
if (Settings::value(Settings::Core::StartedBefore).toBool()) {
m_coreProcess.start();
}
}
void MainWindow::settingsChanged(const QString &key)
@ -603,24 +619,6 @@ void MainWindow::serverConnectionConfigureClient(const QString &clientName)
void MainWindow::open()
{
if (!Settings::value(Settings::Gui::AutoUpdateCheck).isValid()) {
showAndActivate();
Settings::setValue(Settings::Gui::AutoUpdateCheck, messages::showUpdateCheckOption(this));
}
if (Settings::value(Settings::Gui::AutoUpdateCheck).toBool()) {
m_versionChecker.checkLatest();
} else {
qDebug() << "update check disabled";
}
m_coreProcess.applyLogLevel();
if (Settings::value(Settings::Core::StartedBefore).toBool()) {
m_coreProcess.start();
}
Settings::value(Settings::Gui::Autohide).toBool() ? hide() : showAndActivate();
}
@ -1137,3 +1135,10 @@ bool MainWindow::regenerateLocalFingerprints()
updateLocalFingerprint();
return true;
}
void MainWindow::daemonIpcClientConnectFailed()
{
if (deskflow::gui::messages::showDaemonOffline(this)) {
m_coreProcess.retryDaemon();
}
}

View File

@ -158,6 +158,7 @@ private:
void showAndActivate();
void showHostNameEditor();
void setHostName();
void daemonIpcClientConnectFailed();
/**
* @brief trustedFingerprintDb get the fingerprintDb for the trusted clients or trusted servers.

View File

@ -309,4 +309,35 @@ bool showUpdateCheckOption(QWidget *parent)
return message.clickedButton() == checkButton;
}
bool showDaemonOffline(QWidget *parent)
{
QMessageBox message(parent);
message.setIcon(QMessageBox::Warning);
message.setWindowTitle(QObject::tr("Background service offline"));
message.addButton(QObject::tr("Retry"), QMessageBox::AcceptRole);
const auto ignore = message.addButton(QObject::tr("Ignore"), QMessageBox::RejectRole);
const auto disable = message.addButton(QObject::tr("Disable"), QMessageBox::NoRole);
message.setText(QString(
"<p>There was a problem finding the %1 background service (daemon).</p>"
"<p>The background service makes %1 work with UAC prompts and the login screen.</p>"
"<p>If don't want to use the background service and intentionally stopped it, "
"you can prevent it's use by disabling this feature.</p>"
"<p>If you did not stop the background service intentionally, there may be a problem with it. "
"Please retry or try restarting the %1 service from the Windows services program.</p>"
)
.arg(kAppName));
message.exec();
if (message.clickedButton() == ignore) {
return false;
} else if (message.clickedButton() == disable) {
Settings::setValue(Settings::Core::ProcessMode, Settings::ProcessMode::Desktop);
return false;
}
return true;
}
} // namespace deskflow::gui::messages

View File

@ -49,4 +49,6 @@ void showWaylandLibraryError(QWidget *parent);
bool showUpdateCheckOption(QWidget *parent);
bool showDaemonOffline(QWidget *parent);
} // namespace deskflow::gui::messages

View File

@ -140,6 +140,7 @@ CoreProcess::CoreProcess(const IServerConfig &serverConfig, std::shared_ptr<Deps
m_daemonIpcClient{new ipc::DaemonIpcClient(this)}
{
connect(m_daemonIpcClient, &ipc::DaemonIpcClient::connected, this, &CoreProcess::daemonIpcClientConnected);
connect(m_daemonIpcClient, &ipc::DaemonIpcClient::connectFailed, this, &CoreProcess::daemonIpcClientConnectFailed);
connect(&m_pDeps->process(), &QProcessProxy::finished, this, &CoreProcess::onProcessFinished);
@ -224,7 +225,7 @@ void CoreProcess::applyLogLevel()
if (processMode == ProcessMode::Service) {
qDebug() << "setting daemon log level:" << Settings::logLevelText();
if (!m_daemonIpcClient->sendLogLevel(Settings::logLevelText())) {
qCritical() << "failed to set daemon ipc log level";
qWarning() << "failed to set daemon ipc log level";
}
}
}
@ -263,7 +264,7 @@ void CoreProcess::startProcessFromDaemon(const QString &app, const QStringList &
qInfo("running command: %s", qPrintable(commandQuoted));
if (!m_daemonIpcClient->sendStartProcess(commandQuoted, Settings::value(Settings::Daemon::Elevate).toBool())) {
qCritical("cannot start process, ipc command failed");
qWarning("cannot start process, ipc command failed");
return;
}
@ -297,7 +298,7 @@ void CoreProcess::stopProcessFromDaemon()
}
if (!m_daemonIpcClient->sendStopProcess()) {
qCritical("cannot stop process, ipc command failed");
qWarning("cannot stop process, ipc command failed");
return;
}
@ -736,4 +737,11 @@ void CoreProcess::clearSettings()
m_daemonIpcClient->sendClearSettings();
}
void CoreProcess::retryDaemon()
{
if (m_daemonIpcClient->connectToServer()) {
qInfo("successfully reconnected to daemon");
}
}
} // namespace deskflow::gui

View File

@ -79,6 +79,7 @@ public:
void cleanup();
void applyLogLevel();
void clearSettings();
void retryDaemon();
// getters
Settings::CoreMode mode() const
@ -119,6 +120,7 @@ signals:
void connectionStateChanged(ConnectionState state);
void processStateChanged(ProcessState state);
void secureSocket(bool enabled);
void daemonIpcClientConnectFailed();
private slots:
void onProcessFinished(int exitCode, QProcess::ExitStatus);

View File

@ -27,20 +27,32 @@ DaemonIpcClient::DaemonIpcClient(QObject *parent)
bool DaemonIpcClient::connectToServer()
{
qDebug() << "daemon ipc client connecting to server:" << kDaemonIpcName;
if (m_connecting) {
qDebug() << "daemon ipc client already connecting to server";
return false;
}
qDebug() << "daemon ipc client connecting to server:" << kDaemonIpcName;
m_connecting = true;
m_socket->connectToServer(kDaemonIpcName);
if (!m_socket->waitForConnected(kTimeout)) {
qWarning() << "daemon ipc client failed to connect";
m_connecting = false;
Q_EMIT connectFailed();
return false;
}
if (!sendMessage("hello", "hello", false)) {
qWarning() << "daemon ipc client failed to send hello";
m_connecting = false;
Q_EMIT connectFailed();
return false;
}
m_connecting = false;
m_connected = true;
qDebug() << "daemon ipc client connected";
Q_EMIT connected();
@ -51,10 +63,7 @@ void DaemonIpcClient::handleDisconnected()
{
qWarning() << "daemon ipc client disconnected from server";
m_connected = false;
if (!connectToServer()) {
qWarning() << "daemon ipc client failed to reconnect to server";
}
Q_EMIT connectFailed();
}
void DaemonIpcClient::handleErrorOccurred()

View File

@ -8,8 +8,6 @@
#include <QObject>
#include "common/Settings.h"
class QLocalSocket;
namespace deskflow::gui::ipc {
@ -34,6 +32,7 @@ public:
signals:
void connected();
void connectFailed();
private slots:
void handleDisconnected();
@ -46,6 +45,7 @@ private:
private:
QLocalSocket *m_socket;
bool m_connected{false};
bool m_connecting{false};
};
} // namespace deskflow::gui::ipc