Merge branch 'dev' of github.com:amnezia-vpn/amnezia-client into feature/new-awg-docker-container
This commit is contained in:
commit
cd9cdd24ec
18 changed files with 229 additions and 28 deletions
|
@ -15,6 +15,15 @@ set(PACKAGES
|
|||
Core5Compat Concurrent LinguistTools
|
||||
)
|
||||
|
||||
execute_process(
|
||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||
COMMAND git rev-parse --short HEAD
|
||||
OUTPUT_VARIABLE GIT_COMMIT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
|
||||
add_definitions(-DGIT_COMMIT_HASH="${GIT_COMMIT_HASH}")
|
||||
|
||||
if(IOS)
|
||||
set(PACKAGES ${PACKAGES} Multimedia)
|
||||
endif()
|
||||
|
|
6
client/images/controls/split-tunneling.svg
Normal file
6
client/images/controls/split-tunneling.svg
Normal file
|
@ -0,0 +1,6 @@
|
|||
<svg width="19" height="18" viewBox="0 0 19 18" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="0.5" width="18" height="18" rx="5" fill="white"/>
|
||||
<path d="M8.49219 13.5L8.49219 9.44141L14.0191 4.99484" stroke="#0E0E11" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M4.47363 5.49805L6.98828 8.0127" stroke="#0E0E11" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.4727 9.5L14.4727 4.5033L9.50195 4.5033" stroke="#0E0E11" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 511 B |
|
@ -224,6 +224,8 @@
|
|||
<file>ui/qml/Pages2/PageShareFullAccess.qml</file>
|
||||
<file>images/controls/close.svg</file>
|
||||
<file>images/controls/search.svg</file>
|
||||
<file>ui/qml/Components/HomeSplitTunnelingDrawer.qml</file>
|
||||
<file>images/controls/split-tunneling.svg</file>
|
||||
<file>ui/qml/Controls2/DrawerType2.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -997,6 +997,11 @@ And if you don't like the app, all the more support it - the donation will
|
|||
<source>https://amnezia.org</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="176"/>
|
||||
<source>Software version: %1</source>
|
||||
<translation>%1 :إصدار البرنامج</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="192"/>
|
||||
<source>Check for updates</source>
|
||||
|
@ -2999,11 +3004,6 @@ While it offers a blend of security, stability, and speed, it's essential t
|
|||
</context>
|
||||
<context>
|
||||
<name>SettingsController</name>
|
||||
<message>
|
||||
<location filename="../ui/controllers/settingsController.cpp" line="31"/>
|
||||
<source>Software version</source>
|
||||
<translation>إصدار البرنامج</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/controllers/settingsController.cpp" line="139"/>
|
||||
<source>Backup file is corrupted</source>
|
||||
|
|
|
@ -1022,6 +1022,11 @@ Already installed containers were found on the server. All installed containers
|
|||
<source>https://amnezia.org</source>
|
||||
<translation>https://amnezia.org</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="176"/>
|
||||
<source>Software version: %1</source>
|
||||
<translation>%1 :نسخه نرمافزار</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="192"/>
|
||||
<source>Check for updates</source>
|
||||
|
@ -3107,11 +3112,6 @@ This means that AmneziaWG keeps the fast performance of the original while addin
|
|||
</context>
|
||||
<context>
|
||||
<name>SettingsController</name>
|
||||
<message>
|
||||
<location filename="../ui/controllers/settingsController.cpp" line="27"/>
|
||||
<source>Software version</source>
|
||||
<translation>نسخه نرمافزار</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/controllers/settingsController.cpp" line="148"/>
|
||||
<source>All settings have been reset to default values</source>
|
||||
|
|
|
@ -1020,6 +1020,11 @@ Already installed containers were found on the server. All installed containers
|
|||
<source>https://amnezia.org</source>
|
||||
<translation>https://amnezia.org</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="176"/>
|
||||
<source>Software version: %1</source>
|
||||
<translation>Версия ПО: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="192"/>
|
||||
<source>Check for updates</source>
|
||||
|
@ -3058,11 +3063,6 @@ This means that AmneziaWG keeps the fast performance of the original while addin
|
|||
</context>
|
||||
<context>
|
||||
<name>SettingsController</name>
|
||||
<message>
|
||||
<location filename="../ui/controllers/settingsController.cpp" line="27"/>
|
||||
<source>Software version</source>
|
||||
<translation>Версия ПО</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/controllers/settingsController.cpp" line="148"/>
|
||||
<source>All settings have been reset to default values</source>
|
||||
|
|
|
@ -1067,6 +1067,11 @@ And if you don't like the app, all the more support it - the donation will
|
|||
<source>https://amnezia.org</source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="176"/>
|
||||
<source>Software version: %1</source>
|
||||
<translation>软件版本: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="192"/>
|
||||
<source>Check for updates</source>
|
||||
|
@ -3206,11 +3211,6 @@ While it offers a blend of security, stability, and speed, it's essential t
|
|||
</context>
|
||||
<context>
|
||||
<name>SettingsController</name>
|
||||
<message>
|
||||
<location filename="../ui/controllers/settingsController.cpp" line="27"/>
|
||||
<source>Software version</source>
|
||||
<translation>软件版本</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/controllers/settingsController.cpp" line="132"/>
|
||||
<source>Backup file is corrupted</source>
|
||||
|
|
|
@ -28,7 +28,7 @@ SettingsController::SettingsController(const QSharedPointer<ServersModel> &serve
|
|||
m_sitesModel(sitesModel),
|
||||
m_settings(settings)
|
||||
{
|
||||
m_appVersion = QString("%1: %2 (%3)").arg(tr("Software version"), QString(APP_VERSION), __DATE__);
|
||||
m_appVersion = QString("%1 (%2, %3)").arg(QString(APP_VERSION), __DATE__, GIT_COMMIT_HASH);
|
||||
|
||||
#ifdef Q_OS_ANDROID
|
||||
if (!m_settings->isScreenshotsEnabled()) {
|
||||
|
|
|
@ -220,6 +220,11 @@ bool ServersModel::isDefaultServerCurrentlyProcessed()
|
|||
return m_defaultServerIndex == m_processedServerIndex;
|
||||
}
|
||||
|
||||
bool ServersModel::isDefaultServerFromApi()
|
||||
{
|
||||
return qvariant_cast<bool>(data(m_defaultServerIndex, IsServerFromApiRole));
|
||||
}
|
||||
|
||||
bool ServersModel::isProcessedServerHasWriteAccess()
|
||||
{
|
||||
return qvariant_cast<bool>(data(m_processedServerIndex, HasWriteAccessRole));
|
||||
|
@ -249,7 +254,7 @@ void ServersModel::editServer(const QJsonObject &server, const int serverIndex)
|
|||
}
|
||||
updateContainersModel();
|
||||
|
||||
if (isDefaultServerCurrentlyProcessed()) {
|
||||
if (serverIndex == m_defaultServerIndex) {
|
||||
auto defaultContainer = qvariant_cast<DockerContainer>(getDefaultServerData("defaultContainer"));
|
||||
emit defaultServerDefaultContainerChanged(defaultContainer);
|
||||
}
|
||||
|
@ -577,3 +582,18 @@ void ServersModel::setProcessedServerData(const QString roleString, const QVaria
|
|||
|
||||
}
|
||||
|
||||
bool ServersModel::isDefaultServerDefaultContainerHasSplitTunneling()
|
||||
{
|
||||
auto server = m_servers.at(m_defaultServerIndex).toObject();
|
||||
auto defaultContainer = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
||||
auto containerConfig = server.value(config_key::containers).toArray().at(defaultContainer).toObject();
|
||||
auto protocolConfig = containerConfig.value(ContainerProps::containerTypeToString(defaultContainer)).toObject();
|
||||
|
||||
if (defaultContainer == DockerContainer::Awg || defaultContainer == DockerContainer::WireGuard) {
|
||||
return !(protocolConfig.value(config_key::last_config).toString().contains("AllowedIPs = 0.0.0.0/0, ::/0"));
|
||||
} else if (defaultContainer == DockerContainer::Cloak || defaultContainer == DockerContainer::OpenVpn || defaultContainer == DockerContainer::ShadowSocks) {
|
||||
return !(protocolConfig.value(config_key::last_config).toString().contains("redirect-gateway"));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
Q_PROPERTY(QString defaultServerDefaultContainerName READ getDefaultServerDefaultContainerName NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(bool isDefaultServerDefaultContainerHasSplitTunneling READ isDefaultServerDefaultContainerHasSplitTunneling NOTIFY defaultServerDefaultContainerChanged)
|
||||
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIndexChanged)
|
||||
|
||||
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
|
||||
|
||||
|
@ -59,6 +61,7 @@ public slots:
|
|||
const QString getDefaultServerDescriptionExpanded();
|
||||
const QString getDefaultServerDefaultContainerName();
|
||||
bool isDefaultServerCurrentlyProcessed();
|
||||
bool isDefaultServerFromApi();
|
||||
|
||||
bool isProcessedServerHasWriteAccess();
|
||||
bool isDefaultServerHasWriteAccess();
|
||||
|
@ -103,6 +106,8 @@ public slots:
|
|||
QVariant getProcessedServerData(const QString roleString);
|
||||
void setProcessedServerData(const QString roleString, const QVariant &value);
|
||||
|
||||
bool isDefaultServerDefaultContainerHasSplitTunneling();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
||||
|
|
|
@ -113,6 +113,7 @@ void SitesModel::toggleSplitTunneling(bool enabled)
|
|||
m_settings->setRouteMode(Settings::RouteMode::VpnAllSites);
|
||||
}
|
||||
m_isSplitTunnelingEnabled = enabled;
|
||||
emit splitTunnelingToggled();
|
||||
}
|
||||
|
||||
QVector<QPair<QString, QString> > SitesModel::getCurrentSites()
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
|
||||
Q_PROPERTY(int routeMode READ getRouteMode WRITE setRouteMode NOTIFY routeModeChanged)
|
||||
Q_PROPERTY(bool isTunnelingEnabled READ isSplitTunnelingEnabled NOTIFY splitTunnelingToggled)
|
||||
|
||||
public slots:
|
||||
bool addSite(const QString &hostname, const QString &ip);
|
||||
|
@ -38,6 +39,7 @@ public slots:
|
|||
|
||||
signals:
|
||||
void routeModeChanged();
|
||||
void splitTunnelingToggled();
|
||||
|
||||
protected:
|
||||
QHash<int, QByteArray> roleNames() const override;
|
||||
|
|
92
client/ui/qml/Components/HomeSplitTunnelingDrawer.qml
Normal file
92
client/ui/qml/Components/HomeSplitTunnelingDrawer.qml
Normal file
|
@ -0,0 +1,92 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
|
||||
DrawerType2 {
|
||||
id: root
|
||||
|
||||
anchors.fill: parent
|
||||
expandedHeight: parent.height * 0.7
|
||||
|
||||
expandedContent: ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
spacing: 0
|
||||
|
||||
Header2Type {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 24
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
Layout.bottomMargin: 16
|
||||
|
||||
headerText: qsTr("Split tunneling")
|
||||
descriptionText: qsTr("Allows you to connect to some sites or applications through a VPN connection and bypass others")
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi")
|
||||
|
||||
text: qsTr("Split tunneling on the server")
|
||||
descriptionText: qsTr("Enabled \nCan't be disabled for current server")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
// PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
|
||||
// root.close()
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi")
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
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"
|
||||
|
||||
clickedFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
}
|
||||
|
||||
LabelWithButtonType {
|
||||
Layout.fillWidth: true
|
||||
visible: false
|
||||
|
||||
text: qsTr("App-based split tunneling")
|
||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
// PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
||||
root.close()
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
visible: false
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,6 +21,8 @@ Button {
|
|||
property int borderFocusedWidth: 1
|
||||
|
||||
property string imageSource
|
||||
property string rightImageSource
|
||||
property string leftImageColor: textColor
|
||||
|
||||
property bool squareLeftSide: false
|
||||
|
||||
|
@ -118,7 +120,7 @@ Button {
|
|||
layer {
|
||||
enabled: true
|
||||
effect: ColorOverlay {
|
||||
color: textColor
|
||||
color: leftImageColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +133,21 @@ Button {
|
|||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
|
||||
Image {
|
||||
Layout.preferredHeight: 20
|
||||
Layout.preferredWidth: 20
|
||||
|
||||
source: root.rightImageSource
|
||||
visible: root.rightImageSource === "" ? false : true
|
||||
|
||||
layer {
|
||||
enabled: true
|
||||
effect: ColorOverlay {
|
||||
color: textColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,45 @@ PageType {
|
|||
anchors.bottomMargin: drawer.collapsedHeight
|
||||
|
||||
ConnectButton {
|
||||
id: connectButton
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 34
|
||||
leftPadding: 16
|
||||
rightPadding: 16
|
||||
|
||||
implicitHeight: 36
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#878B91"
|
||||
leftImageColor: "transparent"
|
||||
borderWidth: 0
|
||||
|
||||
property bool isSplitTunnelingEnabled: SitesModel.isTunnelingEnabled ||
|
||||
(ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi"))
|
||||
|
||||
text: isSplitTunnelingEnabled ? qsTr("Split tunneling enabled") : qsTr("Split tunneling disabled")
|
||||
|
||||
imageSource: isSplitTunnelingEnabled ? "qrc:/images/controls/split-tunneling.svg" : ""
|
||||
rightImageSource: "qrc:/images/controls/chevron-down.svg"
|
||||
|
||||
onClicked: {
|
||||
homeSplitTunnelingDrawer.open()
|
||||
}
|
||||
|
||||
HomeSplitTunnelingDrawer {
|
||||
id: homeSplitTunnelingDrawer
|
||||
|
||||
parent: root
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -156,7 +193,7 @@ PageType {
|
|||
|
||||
LabelTextType {
|
||||
id: expandedServersMenuDescription
|
||||
Layout.bottomMargin: 24
|
||||
Layout.bottomMargin: ServersModel.isDefaultServerFromApi ? 69 : 24
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Qt.AlignHCenter
|
||||
verticalAlignment: Qt.AlignVCenter
|
||||
|
@ -167,6 +204,9 @@ PageType {
|
|||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
spacing: 8
|
||||
|
||||
visible: !ServersModel.isDefaultServerFromApi
|
||||
onVisibleChanged: expandedServersMenuDescription.Layout
|
||||
|
||||
DropDownType {
|
||||
id: containersDropDown
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ PageType {
|
|||
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
|
||||
text: SettingsController.getAppVersion()
|
||||
text: qsTr("Software version: %1").arg(SettingsController.getAppVersion())
|
||||
color: "#878B91"
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,14 @@ PageType {
|
|||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (isServerFromApi) {
|
||||
if (ConnectionController.isConnected) {
|
||||
PageController.showNotificationMessage(qsTr("Cannot change split tunneling settings during active connection"))
|
||||
root.pageEnabled = false
|
||||
} else if (ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && isServerFromApi) {
|
||||
PageController.showNotificationMessage(qsTr("Default server does not support split tunneling function"))
|
||||
root.pageEnabled = false
|
||||
} else {
|
||||
root.pageEnabled = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +114,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
Layout.rightMargin: 16
|
||||
|
||||
checked: SitesModel.isSplitTunnelingEnabled()
|
||||
checked: SitesModel.isTunnelingEnabled
|
||||
onToggled: {
|
||||
SitesModel.toggleSplitTunneling(checked)
|
||||
selector.text = root.routeModesModel[getRouteModesModelIndex()].name
|
||||
|
|
|
@ -44,6 +44,7 @@ PageType {
|
|||
|
||||
function onClosePage() {
|
||||
tabBar.isServerInfoShow = tabBarStackView.currentItem.objectName !== PageController.getPagePath(PageEnum.PageSettingsServerInfo)
|
||||
&& tabBarStackView.currentItem.objectName !== PageController.getPagePath(PageEnum.PageSettingsSplitTunneling)
|
||||
|
||||
if (tabBarStackView.depth <= 1) {
|
||||
return
|
||||
|
@ -60,7 +61,7 @@ PageType {
|
|||
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
||||
}
|
||||
|
||||
tabBar.isServerInfoShow = page === PageEnum.PageSettingsServerInfo || tabBar.isServerInfoShow
|
||||
tabBar.isServerInfoShow = page === PageEnum.PageSettingsServerInfo || PageEnum.PageSettingsSplitTunneling || tabBar.isServerInfoShow
|
||||
}
|
||||
|
||||
function onGoToStartPage() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue