diff --git a/client/settings.cpp b/client/settings.cpp index 3523bcfe..2a083b32 100644 --- a/client/settings.cpp +++ b/client/settings.cpp @@ -256,6 +256,16 @@ Settings::RouteMode Settings::routeMode() const return static_cast(value("Conf/routeMode", 0).toInt()); } +bool Settings::getSitesSplitTunnelingEnabled() const +{ + return value("Conf/sitesSplitTunnelingEnabled", false).toBool(); +} + +void Settings::setSitesSplitTunnelingEnabled(bool enabled) +{ + setValue("Conf/sitesSplitTunnelingEnabled", enabled); +} + bool Settings::addVpnSite(RouteMode mode, const QString &site, const QString &ip) { QVariantMap sites = vpnSites(mode); @@ -403,6 +413,16 @@ void Settings::setVpnApps(AppsRouteMode mode, const QVector &a m_settings.sync(); } +bool Settings::getAppsSplitTunnelingEnabled() const +{ + return value("Conf/appsSplitTunnelingEnabled", false).toBool(); +} + +void Settings::setAppsSplitTunnelingEnabled(bool enabled) +{ + setValue("Conf/appsSplitTunnelingEnabled", enabled); +} + ServerCredentials Settings::defaultServerCredentials() const { return serverCredentials(defaultServerIndex()); diff --git a/client/settings.h b/client/settings.h index 59c6b13c..7eb650db 100644 --- a/client/settings.h +++ b/client/settings.h @@ -115,6 +115,9 @@ public: RouteMode routeMode() const; void setRouteMode(RouteMode mode) { setValue("Conf/routeMode", mode); } + bool getSitesSplitTunnelingEnabled() const; + void setSitesSplitTunnelingEnabled(bool enabled); + QVariantMap vpnSites(RouteMode mode) const { return value("Conf/" + routeModeString(mode)).toMap(); @@ -208,6 +211,9 @@ public: QVector getVpnApps(AppsRouteMode mode) const; void setVpnApps(AppsRouteMode mode, const QVector &apps); + bool getAppsSplitTunnelingEnabled() const; + void setAppsSplitTunnelingEnabled(bool enabled); + signals: void saveLogsChanged(bool enabled); void screenshotsEnabledChanged(bool enabled); diff --git a/client/ui/models/appSplitTunnelingModel.cpp b/client/ui/models/appSplitTunnelingModel.cpp index 6aba5606..84d01f99 100644 --- a/client/ui/models/appSplitTunnelingModel.cpp +++ b/client/ui/models/appSplitTunnelingModel.cpp @@ -5,14 +5,8 @@ AppSplitTunnelingModel::AppSplitTunnelingModel(std::shared_ptr settings, QObject *parent) : QAbstractListModel(parent), m_settings(settings) { - auto routeMode = m_settings->getAppsRouteMode(); - if (routeMode == Settings::AppsRouteMode::VpnAllApps) { - m_isSplitTunnelingEnabled = false; - m_currentRouteMode = Settings::AppsRouteMode::VpnAllExceptApps; - } else { - m_isSplitTunnelingEnabled = true; - m_currentRouteMode = routeMode; - } + m_isSplitTunnelingEnabled = m_settings->getAppsSplitTunnelingEnabled(); + m_currentRouteMode = m_settings->getAppsRouteMode(); m_apps = m_settings->getVpnApps(m_currentRouteMode); } @@ -84,11 +78,7 @@ bool AppSplitTunnelingModel::isSplitTunnelingEnabled() void AppSplitTunnelingModel::toggleSplitTunneling(bool enabled) { - if (enabled) { - setRouteMode(m_currentRouteMode); - } else { - m_settings->setAppsRouteMode(Settings::AppsRouteMode::VpnAllApps); - } + m_settings->setAppsSplitTunnelingEnabled(enabled); m_isSplitTunnelingEnabled = enabled; emit splitTunnelingToggled(); } diff --git a/client/ui/models/installedAppsModel.cpp b/client/ui/models/installedAppsModel.cpp index 7255b4cc..6030c19e 100644 --- a/client/ui/models/installedAppsModel.cpp +++ b/client/ui/models/installedAppsModel.cpp @@ -64,6 +64,7 @@ QVector> InstalledAppsModel::getSelectedAppsInfo() appsInfo.push_back({ appName, packageName }); } + m_selectedAppIndexes.clear(); return appsInfo; } diff --git a/client/ui/models/sites_model.cpp b/client/ui/models/sites_model.cpp index 96b6ca60..e6d12835 100644 --- a/client/ui/models/sites_model.cpp +++ b/client/ui/models/sites_model.cpp @@ -3,14 +3,8 @@ SitesModel::SitesModel(std::shared_ptr settings, QObject *parent) : QAbstractListModel(parent), m_settings(settings) { - auto routeMode = m_settings->routeMode(); - if (routeMode == Settings::RouteMode::VpnAllSites) { - m_isSplitTunnelingEnabled = false; - m_currentRouteMode = Settings::RouteMode::VpnOnlyForwardSites; - } else { - m_isSplitTunnelingEnabled = true; - m_currentRouteMode = routeMode; - } + m_isSplitTunnelingEnabled = m_settings->getSitesSplitTunnelingEnabled(); + m_currentRouteMode = m_settings->routeMode(); fillSites(); } @@ -107,11 +101,7 @@ bool SitesModel::isSplitTunnelingEnabled() void SitesModel::toggleSplitTunneling(bool enabled) { - if (enabled) { - setRouteMode(m_currentRouteMode); - } else { - m_settings->setRouteMode(Settings::RouteMode::VpnAllSites); - } + m_settings->setSitesSplitTunnelingEnabled(enabled); m_isSplitTunnelingEnabled = enabled; emit splitTunnelingToggled(); } diff --git a/client/ui/qml/Components/HomeSplitTunnelingDrawer.qml b/client/ui/qml/Components/HomeSplitTunnelingDrawer.qml index a5da60c7..b5049ffb 100644 --- a/client/ui/qml/Components/HomeSplitTunnelingDrawer.qml +++ b/client/ui/qml/Components/HomeSplitTunnelingDrawer.qml @@ -59,8 +59,6 @@ DrawerType2 { Layout.fillWidth: true Layout.topMargin: 16 - enabled: !ServersModel.isDefaultServerDefaultContainerHasSplitTunneling || !ServersModel.getDefaultServerData("isServerFromApi") - text: qsTr("Site-based split tunneling") descriptionText: enabled && SitesModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled") rightImageSource: "qrc:/images/controls/chevron-right.svg" diff --git a/client/ui/qml/Components/InstalledAppsDrawer.qml b/client/ui/qml/Components/InstalledAppsDrawer.qml index b4e45e1a..915b2f54 100644 --- a/client/ui/qml/Components/InstalledAppsDrawer.qml +++ b/client/ui/qml/Components/InstalledAppsDrawer.qml @@ -5,6 +5,8 @@ import QtQuick.Layouts import "../Controls2" import "../Controls2/TextTypes" +import SortFilterProxyModel 0.2 + import InstalledAppsModel 1.0 DrawerType2 { @@ -34,7 +36,7 @@ DrawerType2 { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - anchors.bottom: addButton.top + anchors.bottom: searchField.top anchors.topMargin: 16 BackButtonType { @@ -66,7 +68,15 @@ DrawerType2 { clip: true interactive: true - model: installedAppsModel + model: SortFilterProxyModel { + id: proxyInstalledAppsModel + sourceModel: installedAppsModel + filters: RegExpFilter { + roleName: "appName" + pattern: ".*" + searchField.textField.text + ".*" + caseSensitivity: Qt.CaseInsensitive + } + } ScrollBar.vertical: ScrollBar { id: scrollBar @@ -93,7 +103,7 @@ DrawerType2 { text: appName onCheckedChanged: { - listView.model.selectedStateChanged(index, checked) + installedAppsModel.selectedStateChanged(proxyInstalledAppsModel.mapToSource(index), checked) } } @@ -113,6 +123,21 @@ DrawerType2 { } } + TextFieldWithHeaderType { + id: searchField + + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: addButton.top + anchors.bottomMargin: 16 + anchors.rightMargin: 16 + anchors.leftMargin: 16 + + backgroundColor: "#2C2D30" + + textFieldPlaceholderText: qsTr("application name") + } + BasicButtonType { id: addButton @@ -127,7 +152,7 @@ DrawerType2 { clickedFunc: function() { PageController.showBusyIndicator(true) - AppSplitTunnelingController.addApps(listView.model.getSelectedAppsInfo()) + AppSplitTunnelingController.addApps(installedAppsModel.getSelectedAppsInfo()) PageController.showBusyIndicator(false) root.close() } diff --git a/client/ui/qml/Pages2/PageSettingsAppSplitTunneling.qml b/client/ui/qml/Pages2/PageSettingsAppSplitTunneling.qml index e787d87c..cb72d5a2 100644 --- a/client/ui/qml/Pages2/PageSettingsAppSplitTunneling.qml +++ b/client/ui/qml/Pages2/PageSettingsAppSplitTunneling.qml @@ -20,6 +20,17 @@ import "../Components" PageType { id: root + property bool pageEnabled + + Component.onCompleted: { + if (ConnectionController.isConnected) { + PageController.showNotificationMessage(qsTr("Cannot change split tunneling settings during active connection")) + root.pageEnabled = false + } else { + root.pageEnabled = true + } + } + QtObject { id: routeMode property int allApps: 0 @@ -70,6 +81,8 @@ PageType { Layout.leftMargin: 16 headerText: qsTr("App split tunneling") + + enabled: root.pageEnabled } SwitcherType { @@ -78,6 +91,8 @@ PageType { Layout.fillWidth: true Layout.rightMargin: 16 + enabled: root.pageEnabled + checked: AppSplitTunnelingModel.isTunnelingEnabled onToggled: { AppSplitTunnelingModel.toggleSplitTunneling(checked) @@ -99,7 +114,7 @@ PageType { headerText: qsTr("Mode") - enabled: Qt.platform.os === "android" + enabled: Qt.platform.os === "android" && root.pageEnabled listView: ListViewWithRadioButtonType { rootWidth: root.width @@ -139,6 +154,8 @@ PageType { anchors.topMargin: 16 contentHeight: col.implicitHeight + addAppButton.implicitHeight + addAppButton.anchors.bottomMargin + addAppButton.anchors.topMargin + enabled: root.pageEnabled + Column { id: col anchors.top: parent.top @@ -213,6 +230,8 @@ PageType { RowLayout { id: addAppButton + enabled: root.pageEnabled + anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right diff --git a/client/ui/qml/Pages2/PageSettingsSplitTunneling.qml b/client/ui/qml/Pages2/PageSettingsSplitTunneling.qml index f50cda1d..a8349f60 100644 --- a/client/ui/qml/Pages2/PageSettingsSplitTunneling.qml +++ b/client/ui/qml/Pages2/PageSettingsSplitTunneling.qml @@ -24,9 +24,7 @@ PageType { defaultActiveFocusItem: searchField.textField - property bool pageEnabled: { - return !ConnectionController.isConnected && !isServerFromApi - } + property bool pageEnabled Component.onCompleted: { if (ConnectionController.isConnected) { diff --git a/client/vpnconnection.cpp b/client/vpnconnection.cpp index a416eacc..512dc229 100644 --- a/client/vpnconnection.cpp +++ b/client/vpnconnection.cpp @@ -301,7 +301,11 @@ void VpnConnection::appendSplitTunnelingConfig() } } - auto routeMode = m_settings->routeMode(); + Settings::RouteMode routeMode = Settings::RouteMode::VpnAllSites; + if (m_settings->getSitesSplitTunnelingEnabled()) { + routeMode = m_settings->routeMode(); + } + auto sites = m_settings->getVpnIps(routeMode); QJsonArray sitesJsonArray; @@ -318,7 +322,11 @@ void VpnConnection::appendSplitTunnelingConfig() m_vpnConfiguration.insert(config_key::splitTunnelType, routeMode); m_vpnConfiguration.insert(config_key::splitTunnelSites, sitesJsonArray); - auto appsRouteMode = m_settings->getAppsRouteMode(); + Settings::AppsRouteMode appsRouteMode = Settings::AppsRouteMode::VpnAllApps; + if (m_settings->getAppsSplitTunnelingEnabled()) { + appsRouteMode = m_settings->getAppsRouteMode(); + } + auto apps = m_settings->getVpnApps(appsRouteMode); QJsonArray appsJsonArray;