feat: implement custom close behavior for Amnezia application on different platforms

This commit is contained in:
Yaroslav Yashin 2025-06-02 17:30:42 +03:00
parent 4f2d9b4fa9
commit 7aacd15a4c
5 changed files with 30 additions and 26 deletions

View file

@ -12,6 +12,7 @@
#include <QTextDocument> #include <QTextDocument>
#include <QTimer> #include <QTimer>
#include <QTranslator> #include <QTranslator>
#include <QEvent>
#include "logger.h" #include "logger.h"
#include "ui/controllers/pageController.h" #include "ui/controllers/pageController.h"
@ -206,6 +207,22 @@ void AmneziaApplication::startLocalServer() {
} }
#endif #endif
bool AmneziaApplication::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::Close) {
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
quit();
#else
if (m_coreController && m_coreController->pageController()) {
m_coreController->pageController()->hideMainWindow();
}
#endif
return true; // eat the close
}
// call base QObject::eventFilter
return QObject::eventFilter(watched, event);
}
QQmlApplicationEngine *AmneziaApplication::qmlEngine() const QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
{ {
return m_engine; return m_engine;

View file

@ -60,6 +60,8 @@ private:
QThread m_vpnConnectionThread; QThread m_vpnConnectionThread;
QNetworkAccessManager *m_nam; QNetworkAccessManager *m_nam;
protected:
bool eventFilter(QObject *watched, QEvent *event) override;
}; };
#endif // AMNEZIA_APPLICATION_H #endif // AMNEZIA_APPLICATION_H

View file

@ -59,29 +59,11 @@ QString PageController::getPagePath(PageLoader::PageEnum page)
void PageController::closeWindow() void PageController::closeWindow()
{ {
#ifdef Q_OS_ANDROID // On mobile platforms, quit app on close; on desktop, just hide window
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
qApp->quit(); qApp->quit();
#elif defined(MACOS_NE)
// macOS App Store build with Network Extension: hide UI, then gracefully disconnect NE and quit
emit hideMainWindow();
{
auto ctrl = IosController::Instance();
// when NE state changes to Disconnected, quit app
connect(ctrl, &IosController::connectionStateChanged, this, [=](Vpn::ConnectionState s) {
if (s == Vpn::ConnectionState::Disconnected) {
qApp->quit();
}
});
ctrl->disconnectVpn();
}
#else #else
if (m_serversModel->getServersCount() == 0) { emit hideMainWindow();
qApp->quit();
} else {
emit hideMainWindow();
}
#endif #endif
} }
@ -132,7 +114,7 @@ void PageController::showOnStartup()
} else { } else {
#if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) #if defined(Q_OS_WIN) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
emit hideMainWindow(); emit hideMainWindow();
#elif defined(Q_OS_MACX) and defined(MACOS_NE) #elif defined(Q_OS_MACX) && !defined(MACOS_NE)
setDockIconVisible(false); setDockIconVisible(false);
#endif #endif
} }

View file

@ -26,7 +26,8 @@ Window {
color: AmneziaStyle.color.midnightBlack color: AmneziaStyle.color.midnightBlack
onClosing: function() { onClosing: function(close) {
close.accepted = false
PageController.closeWindow() PageController.closeWindow()
} }

View file

@ -41,9 +41,11 @@ SystemTrayNotificationHandler::SystemTrayNotificationHandler(QObject* parent) :
QDesktopServices::openUrl(QUrl("https://amnezia.org")); QDesktopServices::openUrl(QUrl("https://amnezia.org"));
}); });
m_trayActionQuit = m_menu.addAction(QIcon(":/images/tray/cancel.png"), tr("Quit") + " " + APPLICATION_NAME, this, [&](){ // Quit action: disconnect VPN first on macOS NE, else quit directly
qApp->quit(); m_trayActionQuit = m_menu.addAction(QIcon(":/images/tray/cancel.png"),
}); tr("Quit") + " " + APPLICATION_NAME,
this,
[&](){ qApp->quit(); });
m_systemTrayIcon.setContextMenu(&m_menu); m_systemTrayIcon.setContextMenu(&m_menu);
setTrayState(Vpn::ConnectionState::Disconnected); setTrayState(Vpn::ConnectionState::Disconnected);