Compare commits

...

55 Commits

Author SHA1 Message Date
vladimir.kuznetsov
a0011305ad fixed allowed_ips parsing for api configs 2024-02-29 18:49:33 +05:00
sa6ta6ni6c
e648054c7a Misc update README (#652)
Update README.md
2024-02-29 00:14:09 +00:00
pokamest
fe558163cc Merge pull request #651 from amnezia-vpn/bugfix/on-escape-pressed
fixed initial value of m_drawerDepth
2024-02-28 06:35:38 -08:00
vladimir.kuznetsov
3883b8ff34 fixed initial value of m_drawerDepth 2024-02-28 17:31:46 +03:00
pokamest
d286664763 Merge pull request #649 from sa6ta6ni6c/patch-1
Ru translation update
2024-02-28 05:31:14 -08:00
Nethius
b05ad2392b added escape key handler (#461)
Added escape key handler for drawer2type
2024-02-28 12:39:28 +00:00
Nethius
6dbdb85aaf fixed "file does not exist" error when opening a file for saving (#636) 2024-02-28 12:32:25 +00:00
sa6ta6ni6c
26b48cfe4f Обновил перевод 2024-02-27 20:47:41 +00:00
Andrey Zaharow
2f39136143 Fix translations (#646)
Fix awg texts
2024-02-26 21:17:57 +00:00
pokamest
8d0d3c5ce9 Merge pull request #641 from amnezia-vpn/feature/linux-ipv6
Remove ipv6 address for Linux WG/AWG interface
2024-02-26 12:07:50 -08:00
lunardunno
256081e4ed Improved server cleaning (#639)
Deleting the amnezia directory in opt when cleaning the server.
2024-02-26 12:35:31 +00:00
pokamest
1dd7b0a221 Merge pull request #647 from amnezia-vpn/bugfix/ru-translations
fixed ru translations file
2024-02-26 04:17:42 -08:00
vladimir.kuznetsov
82c0b28906 fixed ru translations file 2024-02-26 17:12:46 +05:00
KsZnak
985fe083f0 split-tunneling translate (#640)
Update amneziavpn_ru.ts
2024-02-26 11:53:22 +00:00
pokamest
6a0000dc4b Merge pull request #642 from amnezia-vpn/translations/update_zh_CN
Update amneziavpn_zh_CN.ts
2024-02-26 03:47:31 -08:00
pokamest
1dd2f38066 Merge pull request #643 from amnezia-vpn/translations/update_fa_IR.ts
Update amneziavpn_fa_IR.ts
2024-02-26 03:45:04 -08:00
pokamest
004e1e3ca5 MacOS GH actions QIF fix (#645)
Install Qt Installer Framework 4.6 from R2 to keep compatibility for old MacOS. In addition, update Qt version in build scripts.
2024-02-26 10:44:28 +00:00
KsZnak
7c560d709b Update amneziavpn_fa_IR.ts 2024-02-24 22:16:18 +02:00
KsZnak
d3743ad62f Update amneziavpn_zh_CN.ts 2024-02-24 22:06:05 +02:00
pokamest
ac234b77e2 Merge pull request #638 from amnezia-vpn/update/update_ts
Update all translations
2024-02-24 06:59:50 -08:00
Mykola Baibuz
9886987e68 Remove ipv6 address for Linux WG/AWG interface 2024-02-24 16:07:59 +02:00
pokamest
d34cb8898f Update all translations 2024-02-24 11:51:22 +00:00
pokamest
13aadbda64 Merge pull request #637 from amnezia-vpn/bugfix/connection-drawer-close-button
fixed connection drawer close button
2024-02-23 09:56:52 -08:00
agalehaga
c7c7c8eb01 added export awg native format (#635)
add export awg native format
2024-02-23 17:55:59 +00:00
vladimir.kuznetsov
b1e5bba33f fixed connection drawer close button 2024-02-23 22:51:46 +05:00
pokamest
474e7c6d62 Merge pull request #634 from amnezia-vpn/update/gh_actions_qt_update
Update Qt in deploy.yml
2024-02-22 06:02:04 -08:00
pokamest
794ec921b8 Update Qt in deploy.yml 2024-02-22 13:28:37 +00:00
pokamest
b674240362 Merge pull request #632 from amnezia-vpn/refactoring/changing-settings-item-location
moving settings item to other settings page
2024-02-22 05:02:13 -08:00
pokamest
a768c7c451 Merge pull request #633 from rodionos/patch-1
MacOS build: increase image size to 256Mb
2024-02-22 04:58:21 -08:00
Sergei Rodionov
28d2a4ec2c MacOS build: increase image size to 256Mb
In my case, using Qt 6.6.2, the size of the AmneziaVPN.dmg file is 226Mb so a higher image size is needed for the hdiutil command.
2024-02-22 13:57:58 +03:00
Shehab Ahmed
9f1210d18f changed the location of Auto connect item from settings connections page to settings application page 2024-02-22 02:31:51 +02:00
pokamest
3012559627 Merge pull request #630 from amnezia-vpn/feature/api-containers-listview
for api servers, removed the ability to select a container
2024-02-21 11:03:18 -08:00
vladimir.kuznetsov
b3ed57aee7 for api servers, removed the ability to select a container 2024-02-21 23:41:47 +05:00
pokamest
89d0a8107d Merge pull request #620 from amnezia-vpn/translations/fix-for-pr618
Fix translation for #618
2024-02-21 06:03:12 -08:00
Andrey Zaharow
6c0b71bd1b Fix translation on About Page (#618)
Fix About Page
2024-02-21 14:01:53 +00:00
Nethius
61abf74b2d feature/page-home-split-tunneling (#540)
Added split tunneling button on home page
2024-02-21 11:27:27 +00:00
pokamest
21fdf02921 Merge pull request #625 from amnezia-vpn/bugfix/default-server-default-container-update
fixed the use of defaultServerDefaultContainerChanged
2024-02-21 03:22:09 -08:00
vladimir.kuznetsov
7a245d80ee fixed the use of defaultServerDefaultContainerChanged 2024-02-21 13:06:39 +05:00
KsZnak
da85922f23 Update amneziavpn_zh_CN.ts (#617)
Update amneziavpn_zh_CN.ts
2024-02-20 20:49:26 +00:00
pokamest
a5356b6319 Merge pull request #623 from amnezia-vpn/update/Arabic-translation
updated the Arabic translation for fixing some sentences
2024-02-20 12:47:41 -08:00
KsZnak
3828891b9b Update amneziavpn_fa_IR.ts (#622)
Update amneziavpn_fa_IR.ts
2024-02-20 20:46:23 +00:00
pokamest
15d866ce04 WG/AWG ipv6 fix (#621)
WG/AWG ipv6 fix
2024-02-20 19:05:36 +00:00
Shehab Ahmed
560eb3d620 updated the Arabic translation for fixing some sentences 2024-02-20 20:37:19 +02:00
Andrey Zaharow
ac894254cc Fix translation for #618 2024-02-20 00:23:20 +01:00
pokamest
17e3fbde25 Merge pull request #616 from amnezia-vpn/bugfix/cursor-changing-fix
Fix cursor change when hover over elements
2024-02-19 12:20:46 -08:00
Andrey Zaharow
ee11a8410c Fix cursor change when hover over elements 2024-02-19 18:28:29 +01:00
pokamest
ff5c51cfd9 Merge pull request #615 from amnezia-vpn/KsZnak-patch-1
Update amneziavpn_ru.ts
2024-02-19 07:10:49 -08:00
Nethius
b3943ae5e3 serversModel cleanup (#599) 2024-02-19 14:54:15 +00:00
pokamest
a32952fde6 Qt.ImhNoAutoUppercase | Qt.ImhSensitiveData | Qt.ImhNoPredictiveText for
all TextFields
2024-02-19 14:06:18 +00:00
isamnezia
9c4ee4014d Fix for Codacy: variable name should be between 3 and 40 characters long (#608)
Tiny fixes for iOS
2024-02-19 13:13:10 +00:00
KsZnak
dc9069f1f4 Update_2_amneziavpn_ru.ts
Add new change
2024-02-19 13:37:40 +02:00
pokamest
e402cacc05 Merge pull request #614 from amnezia-vpn/bugfix/translations
returned translation files to commit fab167bb34a9f7199359e3d8589a1cd1…
2024-02-19 02:23:39 -08:00
vladimir.kuznetsov
a98cd248d6 returned translation files to commit fab167bb34 2024-02-19 09:31:31 +05:00
pokamest
00fbfb6a01 Merge pull request #611 from amnezia-vpn/refactoring/show-installed-containers-first
show installed protocols first
2024-02-18 11:10:37 -08:00
vladimir.kuznetsov
86c31c3766 show installed protocols first in services tab and page home containers listview 2024-02-18 13:24:21 +05:00
68 changed files with 4794 additions and 3340 deletions

View File

@@ -14,8 +14,8 @@ jobs:
runs-on: ubuntu-20.04
env:
QT_VERSION: 6.5.1
QIF_VERSION: 4.6
QT_VERSION: 6.6.2
QIF_VERSION: 4.7
steps:
- name: 'Install Qt'
@@ -72,8 +72,8 @@ jobs:
runs-on: windows-latest
env:
QT_VERSION: 6.5.1
QIF_VERSION: 4.6
QT_VERSION: 6.6.2
QIF_VERSION: 4.7
BUILD_ARCH: 64
steps:
@@ -134,7 +134,7 @@ jobs:
runs-on: macos-13
env:
QT_VERSION: 6.5.2
QT_VERSION: 6.6.2
CC: cc
CXX: c++
@@ -245,10 +245,15 @@ jobs:
modules: 'qtremoteobjects qt5compat qtshadertools'
dir: ${{ runner.temp }}
setup-python: 'true'
tools: 'tools_ifw'
set-env: 'true'
extra: '--external 7z --base ${{ env.QT_MIRROR }}'
- name: 'Install Qt Installer Framework ${{ env.QIF_VERSION }}'
run: |
mkdir -pv ${{ runner.temp }}/Qt/Tools/QtInstallerFramework
wget https://qt.amzsvc.com/tools/ifw/${{ env.QIF_VERSION }}.zip
unzip ${{ env.QIF_VERSION }}.zip -d ${{ runner.temp }}/Qt/Tools/QtInstallerFramework/
- name: 'Get sources'
uses: actions/checkout@v4
with:
@@ -286,7 +291,7 @@ jobs:
env:
ANDROID_BUILD_PLATFORM: android-34
QT_VERSION: 6.6.1
QT_VERSION: 6.6.2
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
steps:

3
.gitignore vendored
View File

@@ -131,3 +131,6 @@ client/3rd/ShadowSocks/ss_ios.xcconfig
# UML generated pics
out/
# CMake files
CMakeFiles/

View File

@@ -7,13 +7,15 @@
Amnezia is an open-source VPN client, with a key feature that enables you to deploy your own VPN server on your server.
## Features
- Very easy to use - enter your ip address, ssh login and password, and Amnezia will automatically install VPN docker containers to your server and connect to VPN.
- OpenVPN, ShadowSocks, WireGuard, IKEv2 protocols support.
- Very easy to use - enter your IP address, SSH login, and password, and Amnezia will automatically install VPN docker containers to your server and connect to the VPN.
- OpenVPN, ShadowSocks, WireGuard, and IKEv2 protocols support.
- Masking VPN with OpenVPN over Cloak plugin
- Split tunneling support - add any sites to client to enable VPN only for them (only for desktops)
- Split tunneling support - add any sites to the client to enable VPN only for them (only for desktops)
- Windows, MacOS, Linux, Android, iOS releases.
## Links
[https://amnezia.org](https://amnezia.org) - project website
[https://www.reddit.com/r/AmneziaVPN](https://www.reddit.com/r/AmneziaVPN) - Reddit
[https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Telegram support channel (English)
@@ -21,13 +23,13 @@ Amnezia is an open-source VPN client, with a key feature that enables you to dep
## Tech
AmneziaVPN uses a number of open source projects to work:
AmneziaVPN uses several open-source projects to work:
- [OpenSSL](https://www.openssl.org/)
- [OpenVPN](https://openvpn.net/)
- [ShadowSocks](https://shadowsocks.org/)
- [Qt](https://www.qt.io/)
- [LibSsh](https://libssh.org) - forked form Qt Creator
- [LibSsh](https://libssh.org) - forked from Qt Creator
- and more...
## Checking out the source code
@@ -43,14 +45,15 @@ git submodule update --init --recursive
Want to contribute? Welcome!
### Building sources and deployment
Look deploy folder for build scripts.
### How to build iOS app from source code on MacOS
Check deploy folder for build scripts.
### How to build an iOS app from source code on MacOS
1. First, make sure you have [XCode](https://developer.apple.com/xcode/) installed, at least version 14 or higher.
2. We use QT to generate the XCode project. we need QT version 6.6.1. Install QT for macos in [here](https://doc.qt.io/qt-6/macos.html) or [QT Online Installer](https://www.qt.io/download-open-source). Required modules:
- macOS
2. We use QT to generate the XCode project. We need QT version 6.6.1. Install QT for MacOS [here](https://doc.qt.io/qt-6/macos.html) or [QT Online Installer](https://www.qt.io/download-open-source). Required modules:
- MacOS
- iOS
- Qt 5 Compatibility Module
- Qt Shader Tools
@@ -59,18 +62,18 @@ Look deploy folder for build scripts.
- Qt Multimedia
- Qt Remote Objects
3. Install cmake is require. We recommend cmake version 3.25. You can install cmake in [here](https://cmake.org/download/)
3. Install CMake if required. We recommend CMake version 3.25. You can install CMake [here](https://cmake.org/download/)
4. You also need to install go >= v1.16. If you don't have it done already,
4. You also need to install go >= v1.16. If you don't have it installed already,
download go from the [official website](https://golang.org/dl/) or use Homebrew.
Latest version is recommended. Install gomobile
The latest version is recommended. Install gomobile
```bash
export PATH=$PATH:~/go/bin
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
```
5. Build project
5. Build the project
```bash
export QT_BIN_DIR="<PATH-TO-QT-FOLDER>/Qt/<QT-VERSION>/ios/bin"
export QT_MACOS_ROOT_DIR="<PATH-TO-QT-FOLDER>/Qt/<QT-VERSION>/macos"
@@ -88,62 +91,63 @@ of the bin folder where gomobile was installed. Usually, it's in `GOPATH`.
export PATH=$(PATH):/path/to/GOPATH/bin
```
5. Open XCode project. You can then run/test/archive/ship the app.
6. Open the XCode project. You can then run /test/archive/ship the app.
If build fails with the following error
If the build fails with the following error
```
make: ***
[$(PROJECTDIR)/client/build/AmneziaVPN.build/Debug-iphoneos/wireguard-go-bridge/goroot/.prepared]
Error 1
```
Add a user defined variable to both AmneziaVPN and WireGuardNetworkExtension targets' build settings with
Add a user-defined variable to both AmneziaVPN and WireGuardNetworkExtension targets' build settings with
key `PATH` and value `${PATH}/path/to/bin/folder/with/go/executable`, e.g. `${PATH}:/usr/local/go/bin`.
if above error still persists on you M1 Mac, then most probably you need to install arch based cmake
if the above error persists on your M1 Mac, then most probably you need to install arch based CMake
```
arch -arm64 brew install cmake
```
Build might fail with "source files not found" error the first time you try it, because modern XCode build system compiles
dependencies in parallel, and some dependencies end up being built after the ones that
require them. In this case simply restart the build.
Build might fail with the "source files not found" error the first time you try it, because the modern XCode build system compiles dependencies in parallel, and some dependencies end up being built after the ones that
require them. In this case, simply restart the build.
## How to build the Android app
_tested on Mac OS_
_Tested on Mac OS_
The Android app has the following requirements:
* JDK 11
* Android platform SDK 33
* cmake 3.25.0
* CMake 3.25.0
After you have installed QT, QT Creator and Android Studio installed, you need to configure QT Creator correctly. Click in the top menu bar on `QT Creator` -> `Preferences` -> `Devices` and select the tab `Android`.
* set path to jdk 11
After you have installed QT, QT Creator, and Android Studio, you need to configure QT Creator correctly. Click in the top menu bar on `QT Creator` -> `Preferences` -> `Devices` and select the tab `Android`.
* set path to JDK 11
* set path to Android SDK ($ANDROID_HOME)
In case you get errors regarding missing SDK or 'sdkmanager not running', you cannot fix them by correcting the paths and you have some spare GBs on your disk, you can let QT Creator install all requirements by choosing an empty folder for `Android SDK location` and click on `Set Up SDK`. Be aware: This will install a second Android SDK and NDK on your machine!
In case you get errors regarding missing SDK or 'SDK manager not running', you cannot fix them by correcting the paths. If you have some spare GBs on your disk, you can let QT Creator install all requirements by choosing an empty folder for `Android SDK location` and clicking on `Set Up SDK`. Be aware: This will install a second Android SDK and NDK on your machine! 
Double-check that the right CMake version is configured:  Click on `QT Creator` -> `Preferences` and click on the side menu on `Kits`. Under the center content view's `Kits` tab, you'll find an entry for `CMake Tool`. If the default selected CMake version is lower than 3.25.0, install on your system CMake >= 3.25.0 and choose `System CMake at <path>` from the drop-down list. If this entry is missing, you either have not installed CMake yet or QT Creator hasn't found the path to it. In that case, click in the preferences window on the side menu item `CMake`, then on the tab `Tools` in the center content view, and finally on the button `Add` to set the path to your installed CMake. 
Please make sure that you have selected Android Platform SDK 33 for your project: click in the main view's side menu on `Projects`, and on the left, you'll see a section `Build & Run` showing different Android build targets. You can select any of them, Amnezia VPN's project setup is designed in a way that all Android targets will be built. Click on the targets submenu item `Build` and scroll in the center content view to `Build Steps`. Click on `Details` at the end of the headline `Build Android APK` (the `Details` button might be hidden in case the QT Creator Window is not running in full screen!). Here we are: Choose `android-33` as `Android Build Platform SDK`.
Double check that the right cmake version is configured: Click on `QT Creator` -> `Preferences` and click on the side menu on `Kits`. Under the center content view's `Kits` tab you'll find an entry `CMake Tool`. If the default selected CMake version is lower than 3.25.0, install on your system CMake >= 3.25.0 and choose `System CMake at <path>` from the drop down list. If this entry is missing, you either have not installed CMake yet or QT Creator hasn't found the path to it. In that case click in the preferences window on the side menu item `CMake`, then on the tab `Tools`in the center content view and finally on the Button `Add` to set the path to your installed CMake.
Please make sure that you have selected Android Platform SDK 33 for your project: click in the main view's side menu on on `Projects`, on the left you'll see a section `Build & Run` showing different Android build targets. You can select any of them, Amnezia VPN's project setup is designed in a way that always all Android targets will be build. Click on the targets submenu item `Build` and scroll in the center content view to `Build Steps`. Click on `Details` at the end of the headline `Build Android APK` (The `Details` button might be hidden in case QT Creator Window is not running in full screen!). Here we are: choose `android-33` as `Android Build platform SDK`.
That's it you should be ready to compile the project from QT Creator!
That's it! You should be ready to compile the project from QT Creator!
### Development flow
After you've hit the build button, QT-Creator copies the whole project to a folder in the repositories parent directory. The folder should look something like `build-amnezia-client-Android_Qt_<version>_Clang_<architecture>-<BuildType>`.
If you want to develop Amnezia VPNs Android components written in Kotlin, such as components using system APIs, you need to import the generated project in Android Studio with `build-amnezia-client-Android_Qt_<version>_Clang_<architecture>-<BuildType>/client/android-build` as the projects root directory. While you should be able to compile the generated project from Android Studio, you cannot work directly in the repository's Android project. So whenever you are confident with your work in the generated project, you'll need to copy and paste the affected files to the corresponding path in the repositories Android project so that you can add and commit your changes!
You may face compiling issues in QT Creator after you've worked in Android Studio on the generated project. Just do a `./gradlew clean` in the generated project's root directory (`<path>/client/android-build/.`) and you should be good to continue.
After you've hit the build button, QT-Creator copies the whole project to a folder in the repository parent directory. The folder should look something like `build-amnezia-client-Android_Qt_<version>_Clang_<architecture>-<BuildType>`.
If you want to develop Amnezia VPNs Android components written in Kotlin, such as components using system APIs, you need to import the generated project in Android Studio with `build-amnezia-client-Android_Qt_<version>_Clang_<architecture>-<BuildType>/client/android-build` as the projects root directory. While you should be able to compile the generated project from Android Studio, you cannot work directly in the repository's Android project. So whenever you are confident with your work in the generated project, you'll need to copy and paste the affected files to the corresponding path in the repository's Android project so that you can add and commit your changes!
You may face compiling issues in QT Creator after you've worked in Android Studio on the generated project. Just do a `./gradlew clean` in the generated project's root directory (`<path>/client/android-build/.`) and you should be good to go.
## License
GPL v.3
GPL v3.0
## Donate
Bitcoin: bc1qn9rhsffuxwnhcuuu4qzrwp4upkrq94xnh8r26u
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
payeer.com: P2561305
ko-fi.com: [https://ko-fi.com/amnezia_vpn](https://ko-fi.com/amnezia_vpn)
## Acknowledgments
## etc
This project is tested with BrowserStack.
We express our gratitude to [BrowserStack](https://www.browserstack.com) for supporting our project.

View File

@@ -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()

View File

@@ -286,10 +286,16 @@ void AmneziaApplication::initModels()
m_containersModel.reset(new ContainersModel(this));
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
m_defaultServerContainersModel.reset(new ContainersModel(this));
m_engine->rootContext()->setContextProperty("DefaultServerContainersModel", m_defaultServerContainersModel.get());
m_serversModel.reset(new ServersModel(m_settings, this));
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(),
&ContainersModel::updateModel);
connect(m_serversModel.get(), &ServersModel::defaultServerContainersUpdated, m_defaultServerContainersModel.get(),
&ContainersModel::updateModel);
m_serversModel->resetModel();
m_languageModel.reset(new LanguageModel(m_settings, this));
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
@@ -333,7 +339,7 @@ void AmneziaApplication::initModels()
connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this,
[this](const QString &clientId, const QString &clientName, const DockerContainer container,
ServerCredentials credentials) {
m_serversModel->reloadContainerConfig();
m_serversModel->reloadDefaultServerContainerConfig();
m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
emit m_configurator->clientModelUpdated();
});

View File

@@ -92,6 +92,7 @@ private:
QCommandLineParser m_parser;
QSharedPointer<ContainersModel> m_containersModel;
QSharedPointer<ContainersModel> m_defaultServerContainersModel;
QSharedPointer<ServersModel> m_serversModel;
QSharedPointer<LanguageModel> m_languageModel;
QSharedPointer<ProtocolsModel> m_protocolsModel;

View 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

View File

@@ -124,7 +124,10 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
json.insert("privateKey", wgConfig.value(amnezia::config_key::client_priv_key));
json.insert("deviceIpv4Address", wgConfig.value(amnezia::config_key::client_ip));
// todo review wg ipv6
#ifdef Q_OS_MACOS
json.insert("deviceIpv6Address", "dead::1");
#endif
json.insert("serverPublicKey", wgConfig.value(amnezia::config_key::server_pub_key));
json.insert("serverPskKey", wgConfig.value(amnezia::config_key::psk_key));
json.insert("serverIpv4AddrIn", wgConfig.value(amnezia::config_key::hostName));

View File

@@ -175,7 +175,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
return
}
guard let wgConfigStr = try? JSONDecoder().decode(WGConfig.self, from: wgConfig).wg,
guard let wgConfigStr = try? JSONDecoder().decode(WGConfig.self, from: wgConfig).str,
let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr)
else {
wg_log(.error, message: "Can't parse WireGuard config")

View File

@@ -1,22 +1,23 @@
import Foundation
struct WGConfigData: Decodable {
let h1, h2, h3, h4: String?
let jc, jmax, jmin: String?
let s1, s2: String?
let initPacketMagicHeader, responsePacketMagicHeader: String?
let underloadPacketMagicHeader, transportPacketMagicHeader: String?
let junkPacketCount, junkPacketMinSize, junkPacketMaxSize: String?
let initPacketJunkSize, responsePacketJunkSize: String?
var settings: String {
jc == nil ? "" :
junkPacketCount == nil ? "" :
"""
Jc = \(jc!)
Jmin = \(jmin!)
Jmax = \(jmax!)
S1 = \(s1!)
S2 = \(s2!)
H1 = \(h1!)
H2 = \(h2!)
H3 = \(h3!)
H4 = \(h4!)
Jc = \(junkPacketCount!)
Jmin = \(junkPacketMinSize!)
Jmax = \(junkPacketMaxSize!)
S1 = \(initPacketJunkSize!)
S2 = \(responsePacketJunkSize!)
H1 = \(initPacketMagicHeader!)
H2 = \(responsePacketMagicHeader!)
H3 = \(underloadPacketMagicHeader!)
H4 = \(transportPacketMagicHeader!)
"""
}
@@ -33,9 +34,10 @@ struct WGConfigData: Decodable {
var persistentKeepAlive: String
enum CodingKeys: String, CodingKey {
case h1 = "H1", h2 = "H2", h3 = "H3", h4 = "H4"
case jc = "Jc", jmax = "Jmax", jmin = "Jmin"
case s1 = "S1", s2 = "S2"
case initPacketMagicHeader = "H1", responsePacketMagicHeader = "H2"
case underloadPacketMagicHeader = "H3", transportPacketMagicHeader = "H4"
case junkPacketCount = "Jc", junkPacketMinSize = "Jmin", junkPacketMaxSize = "Jmax"
case initPacketJunkSize = "S1", responsePacketJunkSize = "S2"
case clientIP = "client_ip" // "10.8.1.16"
case clientPrivateKey = "client_priv_key"
@@ -51,15 +53,15 @@ struct WGConfigData: Decodable {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.h1 = try container.decodeIfPresent(String.self, forKey: .h1)
self.h2 = try container.decodeIfPresent(String.self, forKey: .h2)
self.h3 = try container.decodeIfPresent(String.self, forKey: .h3)
self.h4 = try container.decodeIfPresent(String.self, forKey: .h4)
self.jc = try container.decodeIfPresent(String.self, forKey: .jc)
self.jmax = try container.decodeIfPresent(String.self, forKey: .jmax)
self.jmin = try container.decodeIfPresent(String.self, forKey: .jmin)
self.s1 = try container.decodeIfPresent(String.self, forKey: .s1)
self.s2 = try container.decodeIfPresent(String.self, forKey: .s2)
self.initPacketMagicHeader = try container.decodeIfPresent(String.self, forKey: .initPacketMagicHeader)
self.responsePacketMagicHeader = try container.decodeIfPresent(String.self, forKey: .responsePacketMagicHeader)
self.underloadPacketMagicHeader = try container.decodeIfPresent(String.self, forKey: .underloadPacketMagicHeader)
self.transportPacketMagicHeader = try container.decodeIfPresent(String.self, forKey: .transportPacketMagicHeader)
self.junkPacketCount = try container.decodeIfPresent(String.self, forKey: .junkPacketCount)
self.junkPacketMinSize = try container.decodeIfPresent(String.self, forKey: .junkPacketMinSize)
self.junkPacketMaxSize = try container.decodeIfPresent(String.self, forKey: .junkPacketMaxSize)
self.initPacketJunkSize = try container.decodeIfPresent(String.self, forKey: .initPacketJunkSize)
self.responsePacketJunkSize = try container.decodeIfPresent(String.self, forKey: .responsePacketJunkSize)
self.clientIP = try container.decode(String.self, forKey: .clientIP)
self.clientPrivateKey = try container.decode(String.self, forKey: .clientPrivateKey)
self.clientPublicKey = try container.decode(String.self, forKey: .clientPublicKey)
@@ -115,7 +117,7 @@ struct WGConfig: Decodable {
self.splitTunnelType = try container.decode(Int.self, forKey: .splitTunnelType)
}
var wg: String {
var str: String {
"""
[Interface]
Address = \(data.clientIP)/32

View File

@@ -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>

View File

@@ -1,4 +1,5 @@
sudo docker ps -a | grep amnezia | awk '{print $1}' | xargs sudo docker stop
sudo docker ps -a | grep amnezia | awk '{print $1}' | xargs sudo docker rm -fv
sudo docker images -a | grep amnezia | awk '{print $3}' | xargs sudo docker rmi
sudo docker network ls | grep amnezia-dns-net | awk '{print $1}' | xargs sudo docker network rm
sudo docker ps -a | grep amnezia | awk '{print $1}' | xargs sudo docker stop;\
sudo docker ps -a | grep amnezia | awk '{print $1}' | xargs sudo docker rm -fv;\
sudo docker images -a | grep amnezia | awk '{print $3}' | xargs sudo docker rmi;\
sudo docker network ls | grep amnezia-dns-net | awk '{print $1}' | xargs sudo docker network rm;\
sudo rm -frd /opt/amnezia

View File

@@ -1,3 +1,3 @@
sudo docker stop $CONTAINER_NAME
sudo docker rm -fv $CONTAINER_NAME
sudo docker stop $CONTAINER_NAME;\
sudo docker rm -fv $CONTAINER_NAME;\
sudo docker rmi $CONTAINER_NAME

View File

@@ -92,7 +92,7 @@
<context>
<name>ExportController</name>
<message>
<location filename="../ui/controllers/exportController.cpp" line="38"/>
<location filename="../ui/controllers/exportController.cpp" line="39"/>
<source>Access error!</source>
<translation>خطأ في الوصول!</translation>
</message>
@@ -100,16 +100,60 @@
<context>
<name>HomeContainersListView</name>
<message>
<location filename="../ui/qml/Components/HomeContainersListView.qml" line="58"/>
<location filename="../ui/qml/Components/HomeContainersListView.qml" line="59"/>
<source>Unable change protocol while there is an active connection</source>
<translation>قم بتغيير البروتوكول عند تواجد اتصال</translation>
</message>
<message>
<location filename="../ui/qml/Components/HomeContainersListView.qml" line="67"/>
<location filename="../ui/qml/Components/HomeContainersListView.qml" line="68"/>
<source>The selected protocol is not supported on the current platform</source>
<translation>البروتوكول المحدد غير مدعوم علي المنصة الحالية</translation>
</message>
</context>
<context>
<name>HomeSplitTunnelingDrawer</name>
<message>
<location filename="../ui/qml/Components/HomeSplitTunnelingDrawer.qml" line="32"/>
<source>Split tunneling</source>
<translation type="unfinished">تقسيم الانفاق</translation>
</message>
<message>
<location filename="../ui/qml/Components/HomeSplitTunnelingDrawer.qml" line="33"/>
<source>Allows you to connect to some sites or applications through a VPN connection and bypass others</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Components/HomeSplitTunnelingDrawer.qml" line="42"/>
<source>Split tunneling on the server</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Components/HomeSplitTunnelingDrawer.qml" line="43"/>
<source>Enabled
Can&apos;t be disabled for current server</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Components/HomeSplitTunnelingDrawer.qml" line="62"/>
<source>Site-based split tunneling</source>
<translation type="unfinished">انقسام الانفاق القائم علي الموقع</translation>
</message>
<message>
<location filename="../ui/qml/Components/HomeSplitTunnelingDrawer.qml" line="63"/>
<source>Enabled</source>
<translation type="unfinished">مٌفعل</translation>
</message>
<message>
<location filename="../ui/qml/Components/HomeSplitTunnelingDrawer.qml" line="63"/>
<source>Disabled</source>
<translation type="unfinished">مٌعطل</translation>
</message>
<message>
<location filename="../ui/qml/Components/HomeSplitTunnelingDrawer.qml" line="79"/>
<source>App-based split tunneling</source>
<translation type="unfinished">انقسام الانفاق القائم علي التطبيق</translation>
</message>
</context>
<context>
<name>ImportController</name>
<message>
@@ -270,17 +314,27 @@ Already installed containers were found on the server. All installed containers
<context>
<name>PageHome</name>
<message>
<location filename="../ui/qml/Pages2/PageHome.qml" line="184"/>
<location filename="../ui/qml/Pages2/PageHome.qml" line="61"/>
<source>Split tunneling enabled</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageHome.qml" line="61"/>
<source>Split tunneling disabled</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageHome.qml" line="224"/>
<source>VPN protocol</source>
<translation>بروتوكول VPN</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageHome.qml" line="229"/>
<location filename="../ui/qml/Pages2/PageHome.qml" line="272"/>
<source>Servers</source>
<translation>الخوادم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageHome.qml" line="331"/>
<location filename="../ui/qml/Pages2/PageHome.qml" line="360"/>
<source>Unable change server while there is an active connection</source>
<translation>لا يمكن تغير الخادم بينما هناك اتصال مفعل</translation>
</message>
@@ -297,51 +351,6 @@ Already installed containers were found on the server. All installed containers
<source>Port</source>
<translation>منفذ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="114"/>
<source>Junk packet count</source>
<translation>عدد الحزم الغير مرغوب فيها</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="139"/>
<source>Junk packet minimum size</source>
<translation>الحد الادني لحجم الحزمة الغير مرغوب فيها</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="159"/>
<source>Junk packet maximum size</source>
<translation>الحجم الاقصي للحزمة الغير مرغوب فيها</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="179"/>
<source>Init packet junk size</source>
<translation>Init packet junk size</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="199"/>
<source>Response packet junk size</source>
<translation>حجم حزمة الاستجابة الغير مرغوب فيها</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="219"/>
<source>Init packet magic header</source>
<translation>إطلاق حزمة magic header</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="239"/>
<source>Response packet magic header</source>
<translation>حزمة الرد magic header</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="259"/>
<source>Transport packet magic header</source>
<translation>نقل حزمة magic header</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="279"/>
<source>Underload packet magic header</source>
<translation>تحميل حزمة magic header</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageProtocolAwgSettings.qml" line="304"/>
<source>Remove AmneziaWG</source>
@@ -997,6 +1006,11 @@ And if you don&apos;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="178"/>
<source>Software version: %1</source>
<translation>%1 :إصدار البرنامج</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsAbout.qml" line="194"/>
<source>Check for updates</source>
@@ -1035,56 +1049,66 @@ And if you don&apos;t like the app, all the more support it - the donation will
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="93"/>
<source>Auto connect</source>
<translation type="unfinished">الاتصال التلقائي</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="94"/>
<source>Connect to VPN on app start</source>
<translation type="unfinished">اتصل ب ال VPN عند تشغيل التطبيق</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="114"/>
<source>Start minimized</source>
<translation>ابدأ ب الحجم الادني</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="94"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="115"/>
<source>Launch application minimized</source>
<translation>تشغيل التطبيق في الحد الادني</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="111"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="132"/>
<source>Language</source>
<translation>اللغة</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="126"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="147"/>
<source>Logging</source>
<translation>تسجيل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="127"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="148"/>
<source>Enabled</source>
<translation>مٌفعل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="127"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="148"/>
<source>Disabled</source>
<translation>مٌعطل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="140"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="161"/>
<source>Reset settings and remove all data from the application</source>
<translation>إعادة ضبط الاعدادات ومسح جميع البيانات من التطبيق</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="144"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="166"/>
<source>Reset settings and remove all data from the application?</source>
<translation>إعادة ضبط الاعدادات ومسح جميع البيانات من التطبيق؟</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="145"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="167"/>
<source>All settings will be reset to default. All installed AmneziaVPN services will still remain on the server.</source>
<translation>سيتم ضبط الاعدادات الافتراضية. جميع خدمات AmneziaVPN المٌثبتة ستبقي علي الخادم.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="146"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="168"/>
<source>Continue</source>
<translation>واصل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="147"/>
<location filename="../ui/qml/Pages2/PageSettingsApplication.qml" line="169"/>
<source>Cancel</source>
<translation>إلغاء</translation>
</message>
@@ -1139,7 +1163,7 @@ And if you don&apos;t like the app, all the more support it - the donation will
<message>
<location filename="../ui/qml/Pages2/PageSettingsBackup.qml" line="122"/>
<source>Restore from backup</source>
<translation>استرجاع من ملف احتياطي</translation>
<translation>استرجاع من ملف يحتوي علي نسخة احتياطية</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsBackup.qml" line="125"/>
@@ -1175,22 +1199,20 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation>الاتصال</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="50"/>
<source>Auto connect</source>
<translation>الاتصال التلقائي</translation>
<translation type="vanished">الاتصال التلقائي</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="51"/>
<source>Connect to VPN on app start</source>
<translation>اتصل ب ال VPN عند تشغيل التطبيق</translation>
<translation type="vanished">اتصل ب ال VPN عند تشغيل التطبيق</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="86"/>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="65"/>
<source>When AmneziaDNS is not used or installed</source>
<translation>عندما يكون AmneziaDNS غير مٌثبت او غير مستخدم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="120"/>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="99"/>
<source>Allows you to use the VPN only for certain Apps</source>
<translation>يسمح لك بأستخدام ال VPN علي تطبيقات معينة</translation>
</message>
@@ -1199,32 +1221,32 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation type="obsolete">استخدم AmneziaDNS إذا كان مٌثبت علي الخادم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="69"/>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="48"/>
<source>Use AmneziaDNS</source>
<translation>استخدم AmneziaDNS</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="70"/>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="49"/>
<source>If AmneziaDNS is installed on the server</source>
<translation>في حالة كان AmneziaDNS مٌثبت علي الخادم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="85"/>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="64"/>
<source>DNS servers</source>
<translation>خوادم DNS</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="101"/>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="80"/>
<source>Site-based split tunneling</source>
<translation>انقسام الانفاق القائم علي الموقع</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="102"/>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="81"/>
<source>Allows you to select which sites you want to access through the VPN</source>
<translation>يسمح لك بتحديد اي موقع تريد الوصول له عن طريق ال VPN</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="119"/>
<location filename="../ui/qml/Pages2/PageSettingsConnection.qml" line="98"/>
<source>App-based split tunneling</source>
<translation>انقسام الانفاق القائم علي التطبيق</translation>
</message>
@@ -1244,62 +1266,62 @@ And if you don&apos;t like the app, all the more support it - the donation will
<context>
<name>PageSettingsDns</name>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="37"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="39"/>
<source>Default server does not support custom dns</source>
<translation>الخادم الافتراضي لا يدعم DNS مخصص</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="55"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="57"/>
<source>DNS servers</source>
<translation>خوادم ال DNS</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="60"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="62"/>
<source>If AmneziaDNS is not used or installed</source>
<translation>AmneziaVPN ليس مٌستخدم او مٌثبت</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="67"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="69"/>
<source>Primary DNS</source>
<translation>الرئيسي DNS</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="81"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="83"/>
<source>Secondary DNS</source>
<translation>الثانوي DNS</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="101"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="103"/>
<source>Restore default</source>
<translation>استعادة الافتراضي</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="104"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="106"/>
<source>Restore default DNS settings?</source>
<translation>قم بأعادة ضبط إعدادات ال DNS الافتراضية؟</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="105"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="107"/>
<source>Continue</source>
<translation>واصل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="106"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="108"/>
<source>Cancel</source>
<translation>إلغاء</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="113"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="115"/>
<source>Settings have been reset</source>
<translation>لم يتم إعادة ضبط الإعدادات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="127"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="129"/>
<source>Save</source>
<translation>احفظ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="136"/>
<location filename="../ui/qml/Pages2/PageSettingsDns.qml" line="138"/>
<source>Settings saved</source>
<translation>تم حفظ الإعدادات</translation>
</message>
@@ -1339,7 +1361,7 @@ And if you don&apos;t like the app, all the more support it - the donation will
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="128"/>
<source>Save logs to file</source>
<translation>احفظ السجلات لملف</translation>
<translation>احفظ السجلات في ملف</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsLogging.qml" line="146"/>
@@ -1486,27 +1508,27 @@ And if you don&apos;t like the app, all the more support it - the donation will
<context>
<name>PageSettingsServerInfo</name>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="109"/>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="105"/>
<source>Server name</source>
<translation>اسم الخادم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="122"/>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="118"/>
<source>Save</source>
<translation>احفظ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="153"/>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="155"/>
<source>Protocols</source>
<translation>البروتوكولات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="159"/>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="161"/>
<source>Services</source>
<translation>الخدمات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="163"/>
<location filename="../ui/qml/Pages2/PageSettingsServerInfo.qml" line="165"/>
<source>Data</source>
<translation>البيانات</translation>
</message>
@@ -1575,95 +1597,100 @@ And if you don&apos;t like the app, all the more support it - the donation will
<translation type="obsolete">قسم نفق الموقع</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="31"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="36"/>
<source>Default server does not support split tunneling function</source>
<translation>السرفر الافتراضي لا يدعم ميزة تقسيم الانفاق</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="66"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="74"/>
<source>Addresses from the list should not be accessed via VPN</source>
<translation>لا يجب الولوج للعنواين المذكورة هنا من خلال ال VPN</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="98"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="106"/>
<source>Split tunneling</source>
<translation>تقسيم الانفاق</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="130"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="138"/>
<source>Mode</source>
<translation>وضع</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="208"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="216"/>
<source>Remove </source>
<translation>احذف </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="209"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="217"/>
<source>Continue</source>
<translation>واصل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="210"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="218"/>
<source>Cancel</source>
<translation>إلغاء</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="61"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="69"/>
<source>Only the sites listed here will be accessed through the VPN</source>
<translation>سيتم الولوج للمواقع المذكورة هنا فقط عن طريق ال VPN</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="254"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="33"/>
<source>Cannot change split tunneling settings during active connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="262"/>
<source>website or IP</source>
<translation>موقع او IP</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="295"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="303"/>
<source>Import / Export Sites</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="301"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="309"/>
<source>Import</source>
<translation>استرد</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="313"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="321"/>
<source>Save site list</source>
<translation>احفظ قائمة المواقع</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="320"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="328"/>
<source>Save sites</source>
<translation>احفظ المواقع</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="321"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="390"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="405"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="329"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="398"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="413"/>
<source>Sites files (*.json)</source>
<translation></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="380"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="388"/>
<source>Import a list of sites</source>
<translation>استرد قائمة من المواقع</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="386"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="394"/>
<source>Replace site list</source>
<translation>تبديل قائمة المواقع</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="389"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="404"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="397"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="412"/>
<source>Open sites file</source>
<translation>افتح ملف المواقع</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="401"/>
<location filename="../ui/qml/Pages2/PageSettingsSplitTunneling.qml" line="409"/>
<source>Add imported sites to existing ones</source>
<translation>إضافة المواقع المستردة للمواقع الموجودة</translation>
</message>
@@ -1937,7 +1964,8 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardTextKey.qml" line="42"/>
<source>A line that starts with vpn://...</source>
<translation>سطر يبدأ ب vpn://...</translation>
<translatorcomment>يجب ان تٌكتب بهذه الطريقة حتي بوجود الخطأ كي تظهر بشكل صحيح داخل التطبيق</translatorcomment>
<translation>سطر يبدأ ب ...//:vpn</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageSetupWizardTextKey.qml" line="53"/>
@@ -1986,128 +2014,138 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<context>
<name>PageShare</name>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="54"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="58"/>
<source>Save OpenVPN config</source>
<translation>احفظ تكوين OpenVPN</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="61"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="65"/>
<source>Save WireGuard config</source>
<translation>احفظ تكوين WireGuard</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="68"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="72"/>
<source>Save AmneziaWG config</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="79"/>
<source>Save ShadowSocks config</source>
<translation>احفظ تكوين ShadowSocks</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="75"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="86"/>
<source>Save Cloak config</source>
<translation>احفظ تكوين Cloak</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="100"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="111"/>
<source>For the AmneziaVPN app</source>
<translation>AmneziaVPN من اجل تطبيق</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="105"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="116"/>
<source>OpenVpn native format</source>
<translation>تنسيق OpenVpn الاصلي</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="110"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="121"/>
<source>WireGuard native format</source>
<translation>تنسيق WireGuard الاصلي</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="115"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="126"/>
<source>AmneziaWG native format</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="131"/>
<source>ShadowSocks native format</source>
<translation>تنسيق ShadowSocks الاصلي</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="120"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="136"/>
<source>Cloak native format</source>
<translation>تنسيق Cloak الاصلي</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="145"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="161"/>
<source>Share VPN Access</source>
<translation>شارك اتصال VPN</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="174"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="190"/>
<source>Share full access to the server and VPN</source>
<translation>شارك ولوج كامل للخادم و ال VPN</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="175"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="191"/>
<source>Use for your own devices, or share with those you trust to manage the server.</source>
<translation>استخدمه للأجهزة الخاصة بك، أو شاركه مع من تثق بهم لإدارة الخادم.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="227"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="486"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="243"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="504"/>
<source>Users</source>
<translation>المستخدمين</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="247"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="263"/>
<source>Share VPN access without the ability to manage the server</source>
<translation>شارك اتصال VPN بدون القدرة علي إدارة الخادم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="502"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="520"/>
<source>Search</source>
<translation>ابحث</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="586"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="604"/>
<source>Creation date: </source>
<translation>تاريخ الإنشاء: </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="600"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="618"/>
<source>Rename</source>
<translation>إعادة التسمية</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="632"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="650"/>
<source>Client name</source>
<translation>اسم العميل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="645"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="663"/>
<source>Save</source>
<translation>احفظ</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="677"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="695"/>
<source>Revoke</source>
<translation>سحب وإبطال</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="680"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="698"/>
<source>Revoke the config for a user - %1?</source>
<translation>سحب وإبطال للمستخدم - %1?</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="681"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="699"/>
<source>The user will no longer be able to connect to your server.</source>
<translation>المستخدم لن يكون قادر علي الاتصال بعد الان.</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="682"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="700"/>
<source>Continue</source>
<translation>واصل</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="683"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="701"/>
<source>Cancel</source>
<translation>إلغاء</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="216"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="232"/>
<source>Connection</source>
<translation>الاتصال</translation>
</message>
@@ -2120,13 +2158,13 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation type="obsolete">الخوادم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="279"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="280"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="295"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="296"/>
<source>Server</source>
<translation>خادم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="44"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="45"/>
<source>File with connection settings to </source>
<translation>ملف بإعدادات إلي </translation>
</message>
@@ -2135,35 +2173,35 @@ It&apos;s okay as long as it&apos;s from someone you trust.</source>
<translation type="obsolete">البروتوكولات</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="332"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="333"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="348"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="349"/>
<source>Protocol</source>
<translation>بروتوكول</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="43"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="44"/>
<source>Connection to </source>
<translation>اتصال إلي </translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="36"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="37"/>
<source>Config revoked</source>
<translation>تم سحب وإبطال التكوين</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="258"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="274"/>
<source>User name</source>
<translation>اسم المستخدم</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="431"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="432"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="449"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="450"/>
<source>Connection format</source>
<translation>تنسيق الاتصال</translation>
</message>
<message>
<location filename="../ui/qml/Pages2/PageShare.qml" line="182"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="469"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="198"/>
<location filename="../ui/qml/Pages2/PageShare.qml" line="487"/>
<source>Share</source>
<translation>شارك</translation>
</message>
@@ -2993,11 +3031,6 @@ While it offers a blend of security, stability, and speed, it&apos;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>
@@ -3033,20 +3066,18 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<translation>انسخ</translation>
</message>
<message>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="115"/>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="140"/>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="181"/>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="191"/>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="167"/>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="177"/>
<source>Copied</source>
<translation>تم النسخ</translation>
</message>
<message>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="133"/>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="126"/>
<source>Copy config string</source>
<translation>انسخ نص التكوين</translation>
</message>
<message>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="155"/>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="141"/>
<source>Show connection settings</source>
<translation>اظهر إعدادات الاتصال</translation>
</message>
@@ -3055,7 +3086,7 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<translation type="obsolete"></translation>
</message>
<message>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="319"/>
<location filename="../ui/qml/Components/ShareConnectionDrawer.qml" line="305"/>
<source>To read the QR code in the Amnezia app, select &quot;Add server&quot; &quot;I have data to connect&quot; &quot;QR code, key or settings file&quot;</source>
<translation>حتي تقرأ رمز ال QR في تطبيق Amnezia, اختار &quot;إضافة خادم&quot; - &quot;لدي بيانات الاتصال&quot; - &quot;رمز Qr, او مفتاح تعريف او ملف إعدادات&quot;</translation>
</message>
@@ -3139,7 +3170,7 @@ While it offers a blend of security, stability, and speed, it&apos;s essential t
<context>
<name>TextFieldWithHeaderType</name>
<message>
<location filename="../ui/qml/Controls2/TextFieldWithHeaderType.qml" line="106"/>
<location filename="../ui/qml/Controls2/TextFieldWithHeaderType.qml" line="108"/>
<source>The field can&apos;t be empty</source>
<translation>الحقل لا يمكن ان يكون فارغ</translation>
</message>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -136,8 +136,7 @@ void ApiController::updateServerConfigFromApi()
auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString();
serverConfig.insert(config_key::defaultContainer, defaultContainer);
m_serversModel->editServer(serverConfig);
emit m_serversModel->defaultContainerChanged(ContainerProps::containerFromString(defaultContainer));
m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex());
} else {
qDebug() << reply->error();
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
@@ -164,5 +163,5 @@ void ApiController::clearApiConfig()
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
m_serversModel->editServer(serverConfig);
m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex());
}

View File

@@ -33,7 +33,7 @@ void ConnectionController::openConnection()
int serverIndex = m_serversModel->getDefaultServerIndex();
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
DockerContainer container = m_serversModel->getDefaultContainer(serverIndex);
DockerContainer container = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
const QJsonObject &containerConfig = m_containersModel->getContainerConfig(container);
if (container == DockerContainer::None) {

View File

@@ -8,6 +8,7 @@
#include <QImage>
#include <QStandardPaths>
#include "configurators/awg_configurator.h"
#include "configurators/cloak_configurator.h"
#include "configurators/openvpn_configurator.h"
#include "configurators/shadowsocks_configurator.h"
@@ -45,7 +46,7 @@ void ExportController::generateFullAccessConfig()
{
clearPreviousConfig();
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
QJsonObject config = m_settings->server(serverIndex);
QJsonArray containers = config.value(config_key::containers).toArray();
@@ -99,7 +100,7 @@ void ExportController::generateConnectionConfig(const QString &clientName)
{
clearPreviousConfig();
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
@@ -155,7 +156,7 @@ void ExportController::generateOpenVpnConfig(const QString &clientName)
{
clearPreviousConfig();
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
@@ -193,7 +194,7 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
{
clearPreviousConfig();
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
@@ -228,11 +229,50 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
emit exportConfigChanged();
}
void ExportController::generateAwgConfig(const QString &clientName)
{
clearPreviousConfig();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
QJsonObject containerConfig = m_containersModel->getContainerConfig(container);
containerConfig.insert(config_key::container, ContainerProps::containerToString(container));
QString clientId;
ErrorCode errorCode = ErrorCode::NoError;
QString config = m_configurator->awgConfigurator->genAwgConfig(credentials, container, containerConfig,
clientId, &errorCode);
if (errorCode) {
emit exportErrorOccurred(errorString(errorCode));
return;
}
config = m_configurator->processConfigWithExportSettings(serverIndex, container, Proto::Awg, config);
auto configJson = QJsonDocument::fromJson(config.toUtf8()).object();
QStringList lines = configJson.value(config_key::config).toString().replace("\r", "").split("\n");
for (const QString &line : lines) {
m_config.append(line + "\n");
}
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(m_config.toUtf8(), qrcodegen::QrCode::Ecc::LOW);
m_qrCodes << svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
errorCode = m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
if (errorCode) {
emit exportErrorOccurred(errorString(errorCode));
return;
}
emit exportConfigChanged();
}
void ExportController::generateShadowSocksConfig()
{
clearPreviousConfig();
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
@@ -268,7 +308,7 @@ void ExportController::generateCloakConfig()
{
clearPreviousConfig();
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
@@ -328,7 +368,7 @@ void ExportController::updateClientManagementModel(const DockerContainer contain
void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials)
{
ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials,
m_serversModel->getCurrentlyProcessedServerIndex());
m_serversModel->getProcessedServerIndex());
if (errorCode != ErrorCode::NoError) {
emit exportErrorOccurred(errorString(errorCode));
}

View File

@@ -34,6 +34,7 @@ public slots:
void generateConnectionConfig(const QString &clientName);
void generateOpenVpnConfig(const QString &clientName);
void generateWireGuardConfig(const QString &clientName);
void generateAwgConfig(const QString &clientName);
void generateShadowSocksConfig();
void generateCloakConfig();

View File

@@ -259,7 +259,7 @@ QJsonObject ImportController::extractWireGuardConfig(const QString &data)
// return QJsonObject();
// }
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(","));
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configMap.value("AllowedIPs").split(", "));
lastConfig[config_key::allowed_ips] = allowedIpsJsonArray;

View File

@@ -176,7 +176,7 @@ void InstallController::installServer(DockerContainer container, QJsonObject &co
void InstallController::installContainer(DockerContainer container, QJsonObject &config)
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials serverCredentials =
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
@@ -238,7 +238,7 @@ bool InstallController::isServerAlreadyExists()
void InstallController::scanServerForInstalledContainers()
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials serverCredentials =
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
@@ -267,7 +267,7 @@ void InstallController::scanServerForInstalledContainers()
void InstallController::updateContainer(QJsonObject config)
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials serverCredentials =
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
@@ -283,8 +283,8 @@ void InstallController::updateContainer(QJsonObject config)
m_serversModel->updateContainerConfig(container, config);
m_protocolModel->updateModel(config);
if ((serverIndex == m_serversModel->getDefaultServerIndex())
&& (container == m_serversModel->getDefaultContainer(serverIndex))) {
auto defaultContainer = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
if ((serverIndex == m_serversModel->getDefaultServerIndex()) && (container == defaultContainer)) {
emit currentContainerUpdated();
} else {
emit updateContainerFinished(tr("Settings updated successfully"));
@@ -296,27 +296,27 @@ void InstallController::updateContainer(QJsonObject config)
emit installationErrorOccurred(errorString(errorCode));
}
void InstallController::rebootCurrentlyProcessedServer()
void InstallController::rebootProcessedServer()
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
m_serversModel->rebootServer();
emit rebootCurrentlyProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName));
emit rebootProcessedServerFinished(tr("Server '%1' was rebooted").arg(serverName));
}
void InstallController::removeCurrentlyProcessedServer()
void InstallController::removeProcessedServer()
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
m_serversModel->removeServer();
emit removeCurrentlyProcessedServerFinished(tr("Server '%1' was removed").arg(serverName));
emit removeProcessedServerFinished(tr("Server '%1' was removed").arg(serverName));
}
void InstallController::removeAllContainers()
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
ErrorCode errorCode = m_serversModel->removeAllContainers();
@@ -329,7 +329,7 @@ void InstallController::removeAllContainers()
void InstallController::removeCurrentlyProcessedContainer()
{
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
int container = m_containersModel->getCurrentlyProcessedContainerIndex();
@@ -377,7 +377,7 @@ void InstallController::mountSftpDrive(const QString &port, const QString &passw
QString mountPath;
QString cmd;
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
int serverIndex = m_serversModel->getProcessedServerIndex();
ServerCredentials serverCredentials =
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
QString hostname = serverCredentials.hostName;

View File

@@ -30,8 +30,8 @@ public slots:
void updateContainer(QJsonObject config);
void removeCurrentlyProcessedServer();
void rebootCurrentlyProcessedServer();
void removeProcessedServer();
void rebootProcessedServer();
void removeAllContainers();
void removeCurrentlyProcessedContainer();
@@ -54,8 +54,8 @@ signals:
void scanServerFinished(bool isInstalledContainerFound);
void rebootCurrentlyProcessedServerFinished(const QString &finishedMessage);
void removeCurrentlyProcessedServerFinished(const QString &finishedMessage);
void rebootProcessedServerFinished(const QString &finishedMessage);
void removeProcessedServerFinished(const QString &finishedMessage);
void removeAllContainersFinished(const QString &finishedMessage);
void removeCurrentlyProcessedContainerFinished(const QString &finishedMessage);

View File

@@ -77,7 +77,16 @@ void PageController::closeWindow()
void PageController::keyPressEvent(Qt::Key key)
{
switch (key) {
case Qt::Key_Back: emit closePage();
case Qt::Key_Back:
case Qt::Key_Escape: {
if (m_drawerDepth) {
emit closeTopDrawer();
setDrawerDepth(getDrawerDepth() - 1);
} else {
emit escapePressed();
}
break;
}
default: return;
}
}
@@ -132,3 +141,15 @@ void PageController::closeApplication()
{
qApp->quit();
}
void PageController::setDrawerDepth(const int depth)
{
if (depth >= 0) {
m_drawerDepth = depth;
}
}
int PageController::getDrawerDepth()
{
return m_drawerDepth;
}

View File

@@ -87,6 +87,9 @@ public slots:
void closeApplication();
void setDrawerDepth(const int depth);
int getDrawerDepth();
signals:
void goToPage(PageLoader::PageEnum page, bool slide = true);
void goToStartPage();
@@ -105,7 +108,7 @@ signals:
void showNotificationMessage(const QString &message);
void showBusyIndicator(bool visible);
void enableTabBar(bool enabled);
void disableControls(bool disabled);
void hideMainWindow();
void raiseMainWindow();
@@ -113,12 +116,17 @@ signals:
void showPassphraseRequestDrawer();
void passphraseRequestDrawerClosed(QString passphrase);
void escapePressed();
void closeTopDrawer();
private:
QSharedPointer<ServersModel> m_serversModel;
std::shared_ptr<Settings> m_settings;
bool m_isTriggeredByConnectButton;
int m_drawerDepth = 0;
};
#endif // PAGECONTROLLER_H

View File

@@ -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()) {

View File

@@ -92,11 +92,11 @@ QString SystemController::getFileName(const QString &acceptLabel, const QString
mainFileDialog->setProperty("acceptLabel", QVariant::fromValue(acceptLabel));
mainFileDialog->setProperty("nameFilters", QVariant::fromValue(QStringList(nameFilter)));
if (!selectedFile.isEmpty()) {
mainFileDialog->setProperty("selectedFile", QVariant::fromValue(selectedFile));
}
mainFileDialog->setProperty("isSaveMode", QVariant::fromValue(isSaveMode));
mainFileDialog->setProperty("defaultSuffix", QVariant::fromValue(defaultSuffix));
mainFileDialog->setProperty("isSaveMode", QVariant::fromValue(isSaveMode));
if (!selectedFile.isEmpty()) {
mainFileDialog->setProperty("selectedFile", QVariant::fromValue(QUrl(selectedFile)));
}
QMetaObject::invokeMethod(mainFileDialog, "open");
bool isFileDialogAccepted = false;

View File

@@ -5,19 +5,13 @@
ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
: m_settings(settings), QAbstractListModel(parent)
{
m_servers = m_settings->serversArray();
m_defaultServerIndex = m_settings->defaultServerIndex();
m_currentlyProcessedServerIndex = m_defaultServerIndex;
connect(this, &ServersModel::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged);
connect(this, &ServersModel::defaultContainerChanged, this, &ServersModel::defaultServerDescriptionChanged);
connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) {
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
emit ServersModel::defaultContainerChanged(defaultContainer);
});
connect(this, &ServersModel::currentlyProcessedServerIndexChanged, this, [this](const int serverIndex) {
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
emit ServersModel::defaultContainerChanged(defaultContainer);
emit ServersModel::defaultServerDefaultContainerChanged(defaultContainer);
emit ServersModel::defaultServerNameChanged();
updateDefaultServerContainersModel();
});
}
@@ -74,16 +68,14 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
return name;
}
case ServerDescriptionRole: {
if (configVersion) {
return server.value(config_key::description).toString();
}
return server.value(config_key::hostName).toString();
auto description = getServerDescription(server, index.row());
return configVersion ? description : description + server.value(config_key::hostName).toString();
}
case HostNameRole: return server.value(config_key::hostName).toString();
case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row()));
case CredentialsLoginRole: return serverCredentials(index.row()).userName;
case IsDefaultRole: return index.row() == m_defaultServerIndex;
case IsCurrentlyProcessedRole: return index.row() == m_currentlyProcessedServerIndex;
case IsCurrentlyProcessedRole: return index.row() == m_processedServerIndex;
case HasWriteAccessRole: {
auto credentials = serverCredentials(index.row());
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
@@ -95,6 +87,13 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
case DefaultContainerRole: {
return ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
}
case IsServerFromApiRole: {
return server.value(config_key::configVersion).toInt();
}
case HasAmneziaDns: {
QString primaryDns = server.value(config_key::dns1).toString();
return primaryDns == protocols::dns::amneziaDnsIp;
}
}
return QVariant();
@@ -111,8 +110,9 @@ void ServersModel::resetModel()
beginResetModel();
m_servers = m_settings->serversArray();
m_defaultServerIndex = m_settings->defaultServerIndex();
m_currentlyProcessedServerIndex = m_defaultServerIndex;
m_processedServerIndex = m_defaultServerIndex;
endResetModel();
emit defaultServerIndexChanged(m_defaultServerIndex);
}
void ServersModel::setDefaultServerIndex(const int index)
@@ -132,12 +132,7 @@ const QString ServersModel::getDefaultServerName()
return qvariant_cast<QString>(data(m_defaultServerIndex, NameRole));
}
const QString ServersModel::getDefaultServerHostName()
{
return qvariant_cast<QString>(data(m_defaultServerIndex, HostNameRole));
}
QString ServersModel::getDefaultServerDescription(const QJsonObject &server)
QString ServersModel::getServerDescription(const QJsonObject &server, const int index) const
{
const auto configVersion = server.value(config_key::configVersion).toInt();
@@ -145,13 +140,12 @@ QString ServersModel::getDefaultServerDescription(const QJsonObject &server)
if (configVersion) {
return server.value(config_key::description).toString();
} else if (isDefaultServerHasWriteAccess()) {
if (m_isAmneziaDnsEnabled
&& isAmneziaDnsContainerInstalled(m_defaultServerIndex)) {
} else if (data(index, HasWriteAccessRole).toBool()) {
if (m_isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) {
description += "Amnezia DNS | ";
}
} else {
if (isDefaultServerConfigContainsAmneziaDns()) {
if (data(index, HasAmneziaDns).toBool()) {
description += "Amnezia DNS | ";
}
}
@@ -162,7 +156,7 @@ const QString ServersModel::getDefaultServerDescriptionCollapsed()
{
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
const auto configVersion = server.value(config_key::configVersion).toInt();
auto description = getDefaultServerDescription(server);
auto description = getServerDescription(server, m_defaultServerIndex);
if (configVersion) {
return description;
}
@@ -176,7 +170,7 @@ const QString ServersModel::getDefaultServerDescriptionExpanded()
{
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
const auto configVersion = server.value(config_key::configVersion).toInt();
auto description = getDefaultServerDescription(server);
auto description = getServerDescription(server, m_defaultServerIndex);
if (configVersion) {
return description;
}
@@ -199,26 +193,21 @@ bool ServersModel::hasServerWithWriteAccess()
return false;
}
void ServersModel::setCurrentlyProcessedServerIndex(const int index)
void ServersModel::setProcessedServerIndex(const int index)
{
m_currentlyProcessedServerIndex = index;
m_processedServerIndex = index;
updateContainersModel();
emit currentlyProcessedServerIndexChanged(m_currentlyProcessedServerIndex);
emit processedServerIndexChanged(m_processedServerIndex);
}
int ServersModel::getCurrentlyProcessedServerIndex()
int ServersModel::getProcessedServerIndex()
{
return m_currentlyProcessedServerIndex;
return m_processedServerIndex;
}
QString ServersModel::getCurrentlyProcessedServerHostName()
const ServerCredentials ServersModel::getProcessedServerCredentials()
{
return qvariant_cast<QString>(data(m_currentlyProcessedServerIndex, HostNameRole));
}
const ServerCredentials ServersModel::getCurrentlyProcessedServerCredentials()
{
return serverCredentials(m_currentlyProcessedServerIndex);
return serverCredentials(m_processedServerIndex);
}
const ServerCredentials ServersModel::getServerCredentials(const int index)
@@ -228,12 +217,17 @@ const ServerCredentials ServersModel::getServerCredentials(const int index)
bool ServersModel::isDefaultServerCurrentlyProcessed()
{
return m_defaultServerIndex == m_currentlyProcessedServerIndex;
return m_defaultServerIndex == m_processedServerIndex;
}
bool ServersModel::isCurrentlyProcessedServerHasWriteAccess()
bool ServersModel::isDefaultServerFromApi()
{
return qvariant_cast<bool>(data(m_currentlyProcessedServerIndex, HasWriteAccessRole));
return qvariant_cast<bool>(data(m_defaultServerIndex, IsServerFromApiRole));
}
bool ServersModel::isProcessedServerHasWriteAccess()
{
return qvariant_cast<bool>(data(m_processedServerIndex, HasWriteAccessRole));
}
bool ServersModel::isDefaultServerHasWriteAccess()
@@ -249,40 +243,42 @@ void ServersModel::addServer(const QJsonObject &server)
endResetModel();
}
void ServersModel::editServer(const QJsonObject &server)
void ServersModel::editServer(const QJsonObject &server, const int serverIndex)
{
m_settings->editServer(m_currentlyProcessedServerIndex, server);
m_servers.replace(m_currentlyProcessedServerIndex, m_settings->serversArray().at(m_currentlyProcessedServerIndex));
emit dataChanged(index(m_currentlyProcessedServerIndex, 0), index(m_currentlyProcessedServerIndex, 0));
m_settings->editServer(serverIndex, server);
m_servers.replace(serverIndex, m_settings->serversArray().at(serverIndex));
emit dataChanged(index(serverIndex, 0), index(serverIndex, 0));
if (serverIndex == m_defaultServerIndex) {
updateDefaultServerContainersModel();
}
updateContainersModel();
if (serverIndex == m_defaultServerIndex) {
auto defaultContainer = qvariant_cast<DockerContainer>(getDefaultServerData("defaultContainer"));
emit defaultServerDefaultContainerChanged(defaultContainer);
}
}
void ServersModel::removeServer()
{
beginResetModel();
m_settings->removeServer(m_currentlyProcessedServerIndex);
m_settings->removeServer(m_processedServerIndex);
m_servers = m_settings->serversArray();
if (m_settings->defaultServerIndex() == m_currentlyProcessedServerIndex) {
if (m_settings->defaultServerIndex() == m_processedServerIndex) {
setDefaultServerIndex(0);
} else if (m_settings->defaultServerIndex() > m_currentlyProcessedServerIndex) {
} else if (m_settings->defaultServerIndex() > m_processedServerIndex) {
setDefaultServerIndex(m_settings->defaultServerIndex() - 1);
}
if (m_settings->serversCount() == 0) {
setDefaultServerIndex(-1);
}
setCurrentlyProcessedServerIndex(m_defaultServerIndex);
setProcessedServerIndex(m_defaultServerIndex);
endResetModel();
}
bool ServersModel::isDefaultServerConfigContainsAmneziaDns()
{
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
QString primaryDns = server.value(config_key::dns1).toString();
return primaryDns == protocols::dns::amneziaDnsIp;
}
QHash<int, QByteArray> ServersModel::roleNames() const
{
QHash<int, QByteArray> roles;
@@ -290,6 +286,8 @@ QHash<int, QByteArray> ServersModel::roleNames() const
roles[NameRole] = "serverName";
roles[NameRole] = "name";
roles[ServerDescriptionRole] = "serverDescription";
roles[CollapsedServerDescriptionRole] = "collapsedServerDescription";
roles[ExpandedServerDescriptionRole] = "expandedServerDescription";
roles[HostNameRole] = "hostName";
@@ -304,6 +302,8 @@ QHash<int, QByteArray> ServersModel::roleNames() const
roles[ContainsAmneziaDnsRole] = "containsAmneziaDns";
roles[DefaultContainerRole] = "defaultContainer";
roles[IsServerFromApiRole] = "isServerFromApi";
return roles;
}
@@ -322,28 +322,29 @@ ServerCredentials ServersModel::serverCredentials(int index) const
void ServersModel::updateContainersModel()
{
auto containers = m_servers.at(m_currentlyProcessedServerIndex).toObject().value(config_key::containers).toArray();
auto containers = m_servers.at(m_processedServerIndex).toObject().value(config_key::containers).toArray();
emit containersUpdated(containers);
}
void ServersModel::updateDefaultServerContainersModel()
{
auto containers = m_servers.at(m_defaultServerIndex).toObject().value(config_key::containers).toArray();
emit defaultServerContainersUpdated(containers);
}
QJsonObject ServersModel::getDefaultServerConfig()
{
return m_servers.at(m_defaultServerIndex).toObject();
}
QJsonObject ServersModel::getCurrentlyProcessedServerConfig()
void ServersModel::reloadDefaultServerContainerConfig()
{
return m_servers.at(m_currentlyProcessedServerIndex).toObject();
}
void ServersModel::reloadContainerConfig()
{
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
auto containers = server.value(config_key::containers).toArray();
auto config = m_settings->containerConfig(m_currentlyProcessedServerIndex, container);
auto config = m_settings->containerConfig(m_defaultServerIndex, container);
for (auto i = 0; i < containers.size(); i++) {
auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString());
if (c == container) {
@@ -353,13 +354,13 @@ void ServersModel::reloadContainerConfig()
}
server.insert(config_key::containers, containers);
editServer(server);
editServer(server, m_defaultServerIndex);
}
void ServersModel::updateContainerConfig(const int containerIndex, const QJsonObject config)
{
auto container = static_cast<DockerContainer>(containerIndex);
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
QJsonObject server = m_servers.at(m_processedServerIndex).toObject();
auto containers = server.value(config_key::containers).toArray();
for (auto i = 0; i < containers.size(); i++) {
@@ -377,30 +378,25 @@ void ServersModel::updateContainerConfig(const int containerIndex, const QJsonOb
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
}
editServer(server);
editServer(server, m_processedServerIndex);
}
void ServersModel::addContainerConfig(const int containerIndex, const QJsonObject config)
{
auto container = static_cast<DockerContainer>(containerIndex);
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
QJsonObject server = m_servers.at(m_processedServerIndex).toObject();
auto containers = server.value(config_key::containers).toArray();
containers.push_back(config);
server.insert(config_key::containers, containers);
bool isDefaultContainerChanged = false;
auto defaultContainer = server.value(config_key::defaultContainer).toString();
if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None || ContainerProps::containerService(container) != ServiceType::Other)) {
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
isDefaultContainerChanged = true;
}
editServer(server);
if (isDefaultContainerChanged) {
emit defaultContainerChanged(container);
}
editServer(server, m_processedServerIndex);
}
void ServersModel::setDefaultContainer(const int serverIndex, const int containerIndex)
@@ -408,18 +404,12 @@ void ServersModel::setDefaultContainer(const int serverIndex, const int containe
auto container = static_cast<DockerContainer>(containerIndex);
QJsonObject s = m_servers.at(serverIndex).toObject();
s.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
editServer(s); //check
emit defaultContainerChanged(container);
editServer(s, serverIndex); //check
}
DockerContainer ServersModel::getDefaultContainer(const int serverIndex)
const QString ServersModel::getDefaultServerDefaultContainerName()
{
return qvariant_cast<DockerContainer>(data(serverIndex, DefaultContainerRole));
}
const QString ServersModel::getDefaultContainerName()
{
auto defaultContainer = getDefaultContainer(m_defaultServerIndex);
auto defaultContainer = qvariant_cast<DockerContainer>(getDefaultServerData("defaultContainer"));
return ContainerProps::containerHumanNames().value(defaultContainer);
}
@@ -427,15 +417,14 @@ ErrorCode ServersModel::removeAllContainers()
{
ServerController serverController(m_settings);
ErrorCode errorCode =
serverController.removeAllContainers(m_settings->serverCredentials(m_currentlyProcessedServerIndex));
serverController.removeAllContainers(m_settings->serverCredentials(m_processedServerIndex));
if (errorCode == ErrorCode::NoError) {
QJsonObject s = m_servers.at(m_currentlyProcessedServerIndex).toObject();
QJsonObject s = m_servers.at(m_processedServerIndex).toObject();
s.insert(config_key::containers, {});
s.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
editServer(s);
emit defaultContainerChanged(DockerContainer::None);
editServer(s, m_processedServerIndex);
}
return errorCode;
}
@@ -443,7 +432,7 @@ ErrorCode ServersModel::removeAllContainers()
ErrorCode ServersModel::rebootServer()
{
ServerController serverController(m_settings);
auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex);
auto credentials = m_settings->serverCredentials(m_processedServerIndex);
ErrorCode errorCode = serverController.rebootServer(credentials);
return errorCode;
@@ -452,13 +441,13 @@ ErrorCode ServersModel::rebootServer()
ErrorCode ServersModel::removeContainer(const int containerIndex)
{
ServerController serverController(m_settings);
auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex);
auto credentials = m_settings->serverCredentials(m_processedServerIndex);
auto dockerContainer = static_cast<DockerContainer>(containerIndex);
ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer);
if (errorCode == ErrorCode::NoError) {
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
QJsonObject server = m_servers.at(m_processedServerIndex).toObject();
auto containers = server.value(config_key::containers).toArray();
for (auto it = containers.begin(); it != containers.end(); it++) {
@@ -480,32 +469,37 @@ ErrorCode ServersModel::removeContainer(const int containerIndex)
server.insert(config_key::defaultContainer, ContainerProps::containerToString(defaultContainer));
}
editServer(server);
emit defaultContainerChanged(defaultContainer);
editServer(server, m_processedServerIndex);
}
return errorCode;
}
void ServersModel::clearCachedProfiles()
{
const auto &containers = m_settings->containers(m_currentlyProcessedServerIndex);
const auto &containers = m_settings->containers(m_processedServerIndex);
for (DockerContainer container : containers.keys()) {
m_settings->clearLastConnectionConfig(m_currentlyProcessedServerIndex, container);
m_settings->clearLastConnectionConfig(m_processedServerIndex, container);
}
m_servers.replace(m_currentlyProcessedServerIndex, m_settings->server(m_currentlyProcessedServerIndex));
m_servers.replace(m_processedServerIndex, m_settings->server(m_processedServerIndex));
if (m_processedServerIndex == m_defaultServerIndex) {
updateDefaultServerContainersModel();
}
updateContainersModel();
}
void ServersModel::clearCachedProfile(const DockerContainer container)
{
m_settings->clearLastConnectionConfig(m_currentlyProcessedServerIndex, container);
m_settings->clearLastConnectionConfig(m_processedServerIndex, container);
m_servers.replace(m_currentlyProcessedServerIndex, m_settings->server(m_currentlyProcessedServerIndex));
m_servers.replace(m_processedServerIndex, m_settings->server(m_processedServerIndex));
if (m_processedServerIndex == m_defaultServerIndex) {
updateDefaultServerContainersModel();
}
updateContainersModel();
}
bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex)
bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex) const
{
QJsonObject server = m_servers.at(serverIndex).toObject();
auto containers = server.value(config_key::containers).toArray();
@@ -544,16 +538,6 @@ void ServersModel::toggleAmneziaDns(bool enabled)
emit defaultServerDescriptionChanged();
}
bool ServersModel::isDefaultServerFromApi()
{
return m_settings->server(m_defaultServerIndex).value(config_key::configVersion).toInt();
}
bool ServersModel::isCurrentlyProcessedServerFromApi()
{
return m_settings->server(m_currentlyProcessedServerIndex).value(config_key::configVersion).toInt();
}
bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
{
for (const auto &server : qAsConst(m_servers)) {
@@ -564,3 +548,52 @@ bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
return false;
}
QVariant ServersModel::getDefaultServerData(const QString roleString)
{
auto roles = roleNames();
for (auto it = roles.begin(); it != roles.end(); it++) {
if (QString(it.value()) == roleString) {
return data(m_defaultServerIndex, it.key());
}
}
return {};
}
void ServersModel::setDefaultServerData(const QString roleString, const QVariant &value)
{
}
QVariant ServersModel::getProcessedServerData(const QString roleString)
{
auto roles = roleNames();
for (auto it = roles.begin(); it != roles.end(); it++) {
if (QString(it.value()) == roleString) {
return data(m_processedServerIndex, it.key());
}
}
return {};
}
void ServersModel::setProcessedServerData(const QString roleString, const QVariant &value)
{
}
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;
}

View File

@@ -12,7 +12,8 @@ public:
enum Roles {
NameRole = Qt::UserRole + 1,
ServerDescriptionRole,
CollapsedServerDescriptionRole,
ExpandedServerDescriptionRole,
HostNameRole,
CredentialsRole,
@@ -25,7 +26,11 @@ public:
ContainsAmneziaDnsRole,
DefaultContainerRole
DefaultContainerRole,
IsServerFromApiRole,
HasAmneziaDns
};
ServersModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
@@ -40,47 +45,43 @@ public:
Q_PROPERTY(int defaultIndex READ getDefaultServerIndex WRITE setDefaultServerIndex NOTIFY defaultServerIndexChanged)
Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerNameChanged)
Q_PROPERTY(QString defaultServerHostName READ getDefaultServerHostName NOTIFY defaultServerIndexChanged)
Q_PROPERTY(QString defaultContainerName READ getDefaultContainerName NOTIFY defaultContainerChanged)
Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerDescriptionChanged)
Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerDescriptionChanged)
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 currentlyProcessedIndex READ getCurrentlyProcessedServerIndex WRITE setCurrentlyProcessedServerIndex
NOTIFY currentlyProcessedServerIndexChanged)
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
public slots:
void setDefaultServerIndex(const int index);
const int getDefaultServerIndex();
const QString getDefaultServerName();
const QString getDefaultServerHostName();
const QString getDefaultServerDescriptionCollapsed();
const QString getDefaultServerDescriptionExpanded();
const QString getDefaultServerDefaultContainerName();
bool isDefaultServerCurrentlyProcessed();
bool isDefaultServerFromApi();
bool isCurrentlyProcessedServerHasWriteAccess();
bool isProcessedServerHasWriteAccess();
bool isDefaultServerHasWriteAccess();
bool hasServerWithWriteAccess();
const int getServersCount();
void setCurrentlyProcessedServerIndex(const int index);
int getCurrentlyProcessedServerIndex();
void setProcessedServerIndex(const int index);
int getProcessedServerIndex();
QString getCurrentlyProcessedServerHostName();
const ServerCredentials getCurrentlyProcessedServerCredentials();
const ServerCredentials getProcessedServerCredentials();
const ServerCredentials getServerCredentials(const int index);
void addServer(const QJsonObject &server);
void editServer(const QJsonObject &server);
void editServer(const QJsonObject &server, const int serverIndex);
void removeServer();
bool isDefaultServerConfigContainsAmneziaDns();
bool isAmneziaDnsContainerInstalled(const int serverIndex);
QJsonObject getDefaultServerConfig();
QJsonObject getCurrentlyProcessedServerConfig();
void reloadContainerConfig();
void reloadDefaultServerContainerConfig();
void updateContainerConfig(const int containerIndex, const QJsonObject config);
void addContainerConfig(const int containerIndex, const QJsonObject config);
@@ -92,42 +93,49 @@ public slots:
ErrorCode rebootServer();
void setDefaultContainer(const int serverIndex, const int containerIndex);
DockerContainer getDefaultContainer(const int serverIndex);
const QString getDefaultContainerName();
QStringList getAllInstalledServicesName(const int serverIndex);
void toggleAmneziaDns(bool enabled);
bool isDefaultServerFromApi();
bool isCurrentlyProcessedServerFromApi();
bool isServerFromApiAlreadyExists(const quint16 crc);
QVariant getDefaultServerData(const QString roleString);
void setDefaultServerData(const QString roleString, const QVariant &value);
QVariant getProcessedServerData(const QString roleString);
void setProcessedServerData(const QString roleString, const QVariant &value);
bool isDefaultServerDefaultContainerHasSplitTunneling();
protected:
QHash<int, QByteArray> roleNames() const override;
signals:
void currentlyProcessedServerIndexChanged(const int index);
void processedServerIndexChanged(const int index);
void defaultServerIndexChanged(const int index);
void defaultServerNameChanged();
void defaultServerDescriptionChanged();
void containersUpdated(const QJsonArray &containers);
void defaultContainerChanged(const int containerIndex);
void defaultServerContainersUpdated(const QJsonArray &containers);
void defaultServerDefaultContainerChanged(const int containerIndex);
private:
ServerCredentials serverCredentials(int index) const;
void updateContainersModel();
void updateDefaultServerContainersModel();
QString getDefaultServerDescription(const QJsonObject &server);
QString getServerDescription(const QJsonObject &server, const int index) const;
bool isAmneziaDnsContainerInstalled(const int serverIndex) const;
QJsonArray m_servers;
std::shared_ptr<Settings> m_settings;
int m_defaultServerIndex;
int m_currentlyProcessedServerIndex;
int m_processedServerIndex;
bool m_isAmneziaDnsEnabled = m_settings->useAmneziaDns();
};

View File

@@ -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()

View File

@@ -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;

View File

@@ -138,7 +138,7 @@ Button {
}
onClicked: {
ServersModel.setCurrentlyProcessedServerIndex(ServersModel.defaultIndex)
ServersModel.setProcessedServerIndex(ServersModel.defaultIndex)
ApiController.updateServerConfigFromApi()
}
}

View File

@@ -15,6 +15,7 @@ ListView {
id: menuContent
property var rootWidth
property var selectedText
width: rootWidth
height: menuContent.contentItem.height
@@ -51,7 +52,7 @@ ListView {
showImage: !isInstalled
checkable: isInstalled && !ConnectionController.isConnected && isSupported
checked: proxyContainersModel.mapToSource(index) === ServersModel.getDefaultContainer(ServersModel.defaultIndex)
checked: proxyDefaultServerContainersModel.mapToSource(index) === ServersModel.getDefaultServerData("defaultContainer")
onClicked: {
if (ConnectionController.isConnected && isInstalled) {
@@ -61,14 +62,14 @@ ListView {
if (checked) {
containersDropDown.close()
ServersModel.setDefaultContainer(ServersModel.defaultIndex, proxyContainersModel.mapToSource(index))
ServersModel.setDefaultContainer(ServersModel.defaultIndex, proxyDefaultServerContainersModel.mapToSource(index))
} else {
if (!isSupported && isInstalled) {
PageController.showErrorMessage(qsTr("The selected protocol is not supported on the current platform"))
return
}
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(index))
ContainersModel.setCurrentlyProcessedContainerIndex(proxyDefaultServerContainersModel.mapToSource(index))
InstallController.setShouldCreateServer(false)
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
containersDropDown.close()

View 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
}
}
}

View File

@@ -107,13 +107,6 @@ DrawerType2 {
text: qsTr("Copy")
imageSource: "qrc:/images/controls/copy.svg"
clickedFunc: function() {
configText.selectAll()
configText.copy()
configText.select(0, 0)
PageController.showNotificationMessage(qsTr("Copied"))
}
}
BasicButtonType {
@@ -132,13 +125,6 @@ DrawerType2 {
text: qsTr("Copy config string")
imageSource: "qrc:/images/controls/copy.svg"
clickedFunc: function() {
nativeConfigString.selectAll()
nativeConfigString.copy()
nativeConfigString.select(0, 0)
PageController.showNotificationMessage(qsTr("Copied"))
}
}
BasicButtonType {
@@ -201,7 +187,7 @@ DrawerType2 {
anchors.topMargin: 16
backButtonFunction: function() {
configContentDrawer.open()
configContentDrawer.close()
}
}

View File

@@ -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
}
}
}
}
}

View File

@@ -25,6 +25,8 @@ Item {
property real expandedHeight
property real collapsedHeight: 0
property int depthIndex: 0
signal entered
signal exited
signal pressed(bool pressed, bool entered)
@@ -36,6 +38,24 @@ Item {
signal closed
signal opened
Connections {
target: PageController
function onCloseTopDrawer() {
if (depthIndex === PageController.getDrawerDepth()) {
if (isCollapsed) {
return
}
aboutToHide()
drawerContent.state = root.drawerCollapsed
depthIndex = 0
closed()
}
}
}
Connections {
target: root
@@ -47,6 +67,8 @@ Item {
aboutToHide()
drawerContent.state = root.drawerCollapsed
depthIndex = 0
PageController.setDrawerDepth(PageController.getDrawerDepth() - 1)
closed()
}
@@ -58,6 +80,8 @@ Item {
aboutToShow()
drawerContent.state = root.drawerExpanded
depthIndex = PageController.getDrawerDepth() + 1
PageController.setDrawerDepth(depthIndex)
opened()
}
}
@@ -84,6 +108,7 @@ Item {
id: emptyArea
anchors.fill: parent
enabled: root.isExpanded
visible: enabled
onClicked: {
root.close()
}

View File

@@ -74,6 +74,8 @@ Item {
enabled: root.textFieldEditable
color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhSensitiveData | Qt.ImhNoPredictiveText
placeholderText: root.textFieldPlaceholderText
placeholderTextColor: "#494B50"

View File

@@ -14,8 +14,8 @@ import "../Config"
PageType {
id: root
Component.onCompleted: PageController.enableTabBar(false)
Component.onDestruction: PageController.enableTabBar(true)
Component.onCompleted: PageController.disableControls(true)
Component.onDestruction: PageController.disableControls(false)
SortFilterProxyModel {
id: proxyServersModel

View File

@@ -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
@@ -179,13 +219,12 @@ PageType {
rootButtonTextTopMargin: 8
rootButtonTextBottomMargin: 8
text: ServersModel.defaultContainerName
text: ServersModel.defaultServerDefaultContainerName
textColor: "#0E0E11"
headerText: qsTr("VPN protocol")
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
rootButtonClickedFunction: function() {
ServersModel.currentlyProcessedIndex = serversMenuContent.currentIndex
containersDropDown.open()
}
@@ -197,22 +236,26 @@ PageType {
Connections {
target: ServersModel
function onCurrentlyProcessedServerIndexChanged() {
function onDefaultServerIndexChanged() {
updateContainersModelFilters()
}
}
function updateContainersModelFilters() {
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
if (ServersModel.isDefaultServerHasWriteAccess()) {
proxyDefaultServerContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
} else {
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
proxyDefaultServerContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
}
}
model: SortFilterProxyModel {
id: proxyContainersModel
sourceModel: ContainersModel
id: proxyDefaultServerContainersModel
sourceModel: DefaultServerContainersModel
sorters: [
RoleSorter { roleName: "isInstalled"; sortOrder: Qt.DescendingOrder }
]
}
Component.onCompleted: updateContainersModelFilters()
@@ -305,21 +348,7 @@ PageType {
Layout.fillWidth: true
text: name
descriptionText: {
var fullDescription = ""
if (hasWriteAccess) {
if (SettingsController.isAmneziaDnsEnabled()
&& ServersModel.isAmneziaDnsContainerInstalled(index)) {
fullDescription += "Amnezia DNS | "
}
} else {
if (containsAmneziaDns) {
fullDescription += "Amnezia DNS | "
}
}
return fullDescription += serverDescription
}
descriptionText: serverDescription
checked: index === serversMenuContent.currentIndex
checkable: !ConnectionController.isConnected
@@ -334,7 +363,6 @@ PageType {
serversMenuContent.currentIndex = index
ServersModel.currentlyProcessedIndex = index
ServersModel.defaultIndex = index
}
@@ -355,7 +383,7 @@ PageType {
z: 1
onClicked: function() {
ServersModel.currentlyProcessedIndex = index
ServersModel.processedIndex = index
PageController.goToPage(PageEnum.PageSettingsServerInfo)
drawer.close()
}

View File

@@ -44,7 +44,7 @@ PageType {
anchors.left: parent.left
anchors.right: parent.right
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
enabled: ServersModel.isProcessedServerHasWriteAccess()
ListView {
@@ -111,7 +111,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Junk packet count")
headerText: "Jc - Junk packet count"
textFieldText: junkPacketCount
textField.validator: IntValidator { bottom: 0 }
@@ -136,7 +136,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Junk packet minimum size")
headerText: "Jmin - Junk packet minimum size"
textFieldText: junkPacketMinSize
textField.validator: IntValidator { bottom: 0 }
@@ -156,7 +156,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Junk packet maximum size")
headerText: "Jmax - Junk packet maximum size"
textFieldText: junkPacketMaxSize
textField.validator: IntValidator { bottom: 0 }
@@ -176,7 +176,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Init packet junk size")
headerText: "S1 - Init packet junk size"
textFieldText: initPacketJunkSize
textField.validator: IntValidator { bottom: 0 }
@@ -196,7 +196,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Response packet junk size")
headerText: "S2 - Response packet junk size"
textFieldText: responsePacketJunkSize
textField.validator: IntValidator { bottom: 0 }
@@ -216,7 +216,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Init packet magic header")
headerText: "H1 - Init packet magic header"
textFieldText: initPacketMagicHeader
textField.validator: IntValidator { bottom: 0 }
@@ -236,7 +236,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Response packet magic header")
headerText: "H2 - Response packet magic header"
textFieldText: responsePacketMagicHeader
textField.validator: IntValidator { bottom: 0 }
@@ -256,7 +256,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Transport packet magic header")
headerText: "H4 - Transport packet magic header"
textFieldText: transportPacketMagicHeader
textField.validator: IntValidator { bottom: 0 }
@@ -276,7 +276,7 @@ PageType {
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Underload packet magic header")
headerText: "H3 - Underload packet magic header"
textFieldText: underloadPacketMagicHeader
textField.validator: IntValidator { bottom: 0 }

View File

@@ -43,7 +43,7 @@ PageType {
anchors.left: parent.left
anchors.right: parent.right
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
enabled: ServersModel.isProcessedServerHasWriteAccess()
ListView {
id: listview

View File

@@ -44,7 +44,7 @@ PageType {
anchors.left: parent.left
anchors.right: parent.right
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
enabled: ServersModel.isProcessedServerHasWriteAccess()
ListView {
id: listview

View File

@@ -175,7 +175,7 @@ PageType {
width: parent.width
visible: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
visible: ServersModel.isProcessedServerHasWriteAccess()
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
textColor: "#EB5757"

View File

@@ -43,7 +43,7 @@ PageType {
anchors.left: parent.left
anchors.right: parent.right
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
enabled: ServersModel.isProcessedServerHasWriteAccess()
ListView {
id: listview

View File

@@ -49,7 +49,7 @@ PageType {
anchors.left: parent.left
anchors.right: parent.right
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
enabled: ServersModel.isProcessedServerHasWriteAccess()
ListView {
id: listview
@@ -88,7 +88,7 @@ PageType {
Layout.topMargin: 32
text: qsTr("Host")
descriptionText: ServersModel.getCurrentlyProcessedServerHostName()
descriptionText: ServersModel.getProcessedServerData("HostName")
descriptionOnTop: true

View File

@@ -175,7 +175,7 @@ PageType {
horizontalAlignment: Text.AlignHCenter
text: SettingsController.getAppVersion()
text: qsTr("Software version: %1").arg(SettingsController.getAppVersion())
color: "#878B91"
}

View File

@@ -84,6 +84,27 @@ PageType {
visible: !GC.isMobile()
}
SwitcherType {
visible: !GC.isMobile()
Layout.fillWidth: true
Layout.margins: 16
text: qsTr("Auto connect")
descriptionText: qsTr("Connect to VPN on app start")
checked: SettingsController.isAutoConnectEnabled()
onCheckedChanged: {
if (checked !== SettingsController.isAutoConnectEnabled()) {
SettingsController.toggleAutoConnect(checked)
}
}
}
DividerType {
visible: !GC.isMobile()
}
SwitcherType {
visible: !GC.isMobile()

View File

@@ -41,27 +41,6 @@ PageType {
headerText: qsTr("Connection")
}
SwitcherType {
visible: !GC.isMobile()
Layout.fillWidth: true
Layout.margins: 16
text: qsTr("Auto connect")
descriptionText: qsTr("Connect to VPN on app start")
checked: SettingsController.isAutoConnectEnabled()
onCheckedChanged: {
if (checked !== SettingsController.isAutoConnectEnabled()) {
SettingsController.toggleAutoConnect(checked)
}
}
}
DividerType {
visible: !GC.isMobile()
}
SwitcherType {
Layout.fillWidth: true
Layout.margins: 16

View File

@@ -30,10 +30,12 @@ PageType {
anchors.bottom: parent.bottom
contentHeight: content.height
enabled: !ServersModel.isDefaultServerFromApi()
property var isServerFromApi: ServersModel.getDefaultServerData("isServerFromApi")
enabled: !isServerFromApi
Component.onCompleted: {
if (ServersModel.isDefaultServerFromApi()) {
if (isServerFromApi) {
PageController.showNotificationMessage(qsTr("Default server does not support custom dns"))
}
}

View File

@@ -28,7 +28,7 @@ PageType {
PageController.showErrorMessage(message)
}
function onRemoveCurrentlyProcessedServerFinished(finishedMessage) {
function onRemoveProcessedServerFinished(finishedMessage) {
if (!ServersModel.getServersCount()) {
PageController.replaceStartPage()
} else {
@@ -38,7 +38,7 @@ PageType {
PageController.showNotificationMessage(finishedMessage)
}
function onRebootCurrentlyProcessedServerFinished(finishedMessage) {
function onRebootProcessedServerFinished(finishedMessage) {
PageController.showNotificationMessage(finishedMessage)
}
@@ -64,8 +64,8 @@ PageType {
Connections {
target: ServersModel
function onCurrentlyProcessedServerIndexChanged() {
content.isServerWithWriteAccess = ServersModel.isCurrentlyProcessedServerHasWriteAccess()
function onProcessedServerIndexChanged() {
content.isServerWithWriteAccess = ServersModel.isProcessedServerHasWriteAccess()
}
}
@@ -82,7 +82,7 @@ PageType {
anchors.left: parent.left
anchors.right: parent.right
property bool isServerWithWriteAccess: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
property bool isServerWithWriteAccess: ServersModel.isProcessedServerHasWriteAccess()
LabelWithButtonType {
visible: content.isServerWithWriteAccess
@@ -149,7 +149,7 @@ PageType {
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
ConnectionController.closeConnection()
}
InstallController.rebootCurrentlyProcessedServer()
InstallController.rebootProcessedServer()
PageController.showBusyIndicator(false)
}
var noButtonFunction = function() {
@@ -180,7 +180,7 @@ PageType {
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
ConnectionController.closeConnection()
}
InstallController.removeCurrentlyProcessedServer()
InstallController.removeProcessedServer()
PageController.showBusyIndicator(false)
}
var noButtonFunction = function() {
@@ -224,7 +224,7 @@ PageType {
}
LabelWithButtonType {
visible: ServersModel.isCurrentlyProcessedServerFromApi()
visible: ServersModel.getProcessedServerData("isServerFromApi")
Layout.fillWidth: true
text: qsTr("Reset API config")
@@ -249,7 +249,7 @@ PageType {
}
DividerType {
visible: ServersModel.isCurrentlyProcessedServerFromApi()
visible: ServersModel.getProcessedServerData("isServerFromApi")
}
}
}

View File

@@ -63,7 +63,7 @@ PageType {
headerText: name
descriptionText: {
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
if (ServersModel.isProcessedServerHasWriteAccess()) {
return credentialsLogin + " · " + hostName
} else {
return hostName

View File

@@ -107,7 +107,7 @@ PageType {
width: parent.width
visible: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
visible: ServersModel.isProcessedServerHasWriteAccess()
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
textColor: "#EB5757"

View File

@@ -38,13 +38,13 @@ PageType {
Connections {
target: ServersModel
function onCurrentlyProcessedServerIndexChanged() {
function onProcessedServerIndexChanged() {
settingsContainersListView.updateContainersModelFilters()
}
}
function updateContainersModelFilters() {
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
if (ServersModel.isProcessedServerHasWriteAccess()) {
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
} else {
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()

View File

@@ -38,13 +38,13 @@ PageType {
Connections {
target: ServersModel
function onCurrentlyProcessedServerIndexChanged() {
function onProcessedServerIndexChanged() {
settingsContainersListView.updateContainersModelFilters()
}
}
function updateContainersModelFilters() {
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
if (ServersModel.isProcessedServerHasWriteAccess()) {
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessServicesListFilters()
} else {
proxyContainersModel.filters = ContainersModelFilters.getReadAccessServicesListFilters()
@@ -55,6 +55,9 @@ PageType {
model: SortFilterProxyModel {
id: proxyContainersModel
sourceModel: ContainersModel
sorters: [
RoleSorter { roleName: "isInstalled"; sortOrder: Qt.DescendingOrder }
]
}
Component.onCompleted: updateContainersModelFilters()

View File

@@ -87,7 +87,7 @@ PageType {
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
ServersModel.currentlyProcessedIndex = index
ServersModel.processedIndex = index
PageController.goToPage(PageEnum.PageSettingsServerInfo)
}
}

View File

@@ -20,15 +20,23 @@ import "../Components"
PageType {
id: root
property var isServerFromApi: ServersModel.getDefaultServerData("isServerFromApi")
defaultActiveFocusItem: website_ip_field.textField
property bool pageEnabled: {
return !ConnectionController.isConnected && !ServersModel.isDefaultServerFromApi()
return !ConnectionController.isConnected && !isServerFromApi
}
Component.onCompleted: {
if (ServersModel.isDefaultServerFromApi()) {
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
}
}
@@ -106,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

View File

@@ -14,8 +14,8 @@ import "../Config"
PageType {
id: root
Component.onCompleted: PageController.enableTabBar(false)
Component.onDestruction: PageController.enableTabBar(true)
Component.onCompleted: PageController.disableControls(true)
Component.onDestruction: PageController.disableControls(false)
property bool isTimerRunning: true
property string progressBarText: qsTr("Usually it takes no more than 5 minutes")
@@ -26,7 +26,7 @@ PageType {
function onInstallContainerFinished(finishedMessage, isServiceInstall) {
if (!ConnectionController.isConnected && !isServiceInstall) {
ServersModel.setDefaultContainer(ServersModel.currentlyProcessedIndex, ContainersModel.getCurrentlyProcessedContainerIndex())
ServersModel.setDefaultContainer(ServersModel.processedIndex, ContainersModel.getCurrentlyProcessedContainerIndex())
}
PageController.closePage() // close installing page
@@ -42,7 +42,7 @@ PageType {
function onInstallServerFinished(finishedMessage) {
if (!ConnectionController.isConnected) {
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
ServersModel.processedIndex = ServersModel.defaultIndex
}
PageController.goToStartPage()
@@ -55,7 +55,7 @@ PageType {
function onServerAlreadyExists(serverIndex) {
PageController.goToStartPage()
ServersModel.currentlyProcessedIndex = serverIndex
ServersModel.processedIndex = serverIndex
PageController.goToPage(PageEnum.PageSettingsServerInfo, false)
PageController.showErrorMessage(qsTr("The server has already been added to the application"))

View File

@@ -13,6 +13,8 @@ import "../Components"
PageType {
id: root
property bool isControlsDisabled: false
Connections {
target: PageController
@@ -45,6 +47,18 @@ PageType {
stackView.pop()
}
}
function onDisableControls(disabled) {
isControlsDisabled = disabled
}
function onEscapePressed() {
if (isControlsDisabled || busyIndicator.visible) {
return
}
PageController.closePage()
}
}
Connections {

View File

@@ -30,7 +30,7 @@ PageType {
function onImportFinished() {
if (!ConnectionController.isConnected) {
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
ServersModel.processedIndex = ServersModel.defaultIndex
}
PageController.goToStartPage()

View File

@@ -22,6 +22,7 @@ PageType {
AmneziaConnection,
OpenVpn,
WireGuard,
Awg,
ShadowSocks,
Cloak
}
@@ -31,7 +32,7 @@ PageType {
PageController.showBusyIndicator(true)
ExportController.revokeConfig(index,
ContainersModel.getCurrentlyProcessedContainerIndex(),
ServersModel.getCurrentlyProcessedServerCredentials())
ServersModel.getProcessedServerCredentials())
PageController.showBusyIndicator(false)
PageController.showNotificationMessage(qsTr("Config revoked"))
}
@@ -48,7 +49,10 @@ PageType {
PageController.showBusyIndicator(true)
switch (type) {
case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(clientNameTextField.textFieldText); break;
case PageShare.ConfigType.AmneziaConnection: {
ExportController.generateConnectionConfig(clientNameTextField.textFieldText);
break;
}
case PageShare.ConfigType.OpenVpn: {
ExportController.generateOpenVpnConfig(clientNameTextField.textFieldText)
shareConnectionDrawer.configCaption = qsTr("Save OpenVPN config")
@@ -63,6 +67,13 @@ PageType {
shareConnectionDrawer.configFileName = "amnezia_for_wireguard"
break
}
case PageShare.ConfigType.Awg: {
ExportController.generateAwgConfig(clientNameTextField.textFieldText)
shareConnectionDrawer.configCaption = qsTr("Save AmneziaWG config")
shareConnectionDrawer.configExtension = ".conf"
shareConnectionDrawer.configFileName = "amnezia_for_awg"
break
}
case PageShare.ConfigType.ShadowSocks: {
ExportController.generateShadowSocksConfig()
shareConnectionDrawer.configCaption = qsTr("Save ShadowSocks config")
@@ -110,6 +121,11 @@ PageType {
property string name: qsTr("WireGuard native format")
property var type: PageShare.ConfigType.WireGuard
}
QtObject {
id: awgConnectionFormat
property string name: qsTr("AmneziaWG native format")
property var type: PageShare.ConfigType.Awg
}
QtObject {
id: shadowSocksConnectionFormat
property string name: qsTr("ShadowSocks native format")
@@ -230,7 +246,7 @@ PageType {
accessTypeSelector.currentIndex = 1
PageController.showBusyIndicator(true)
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
ServersModel.getCurrentlyProcessedServerCredentials())
ServersModel.getProcessedServerCredentials())
PageController.showBusyIndicator(false)
}
}
@@ -315,7 +331,7 @@ PageType {
function handler() {
serverSelector.text = selectedText
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
ServersModel.processedIndex = proxyServersModel.mapToSource(currentIndex)
}
}
}
@@ -365,7 +381,7 @@ PageType {
target: serverSelector
function onSeverSelectorIndexChanged() {
var defaultContainer = proxyContainersModel.mapFromSource(ServersModel.getDefaultContainer(ServersModel.currentlyProcessedIndex))
var defaultContainer = proxyContainersModel.mapFromSource(ServersModel.getProcessedServerData("defaultContainer"))
protocolSelectorListView.currentIndex = defaultContainer
protocolSelectorListView.triggerCurrentItem()
}
@@ -388,7 +404,7 @@ PageType {
if (accessTypeSelector.currentIndex === 1) {
PageController.showBusyIndicator(true)
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
ServersModel.getCurrentlyProcessedServerCredentials())
ServersModel.getProcessedServerCredentials())
PageController.showBusyIndicator(false)
}
}
@@ -402,6 +418,8 @@ PageType {
root.connectionTypesModel.push(openVpnConnectionFormat)
} else if (index === ContainerProps.containerFromString("amnezia-wireguard")) {
root.connectionTypesModel.push(wireGuardConnectionFormat)
} else if (index === ContainerProps.containerFromString("amnezia-awg")) {
root.connectionTypesModel.push(awgConnectionFormat)
} else if (index === ContainerProps.containerFromString("amnezia-shadowsocks")) {
root.connectionTypesModel.push(openVpnConnectionFormat)
root.connectionTypesModel.push(shadowSocksConnectionFormat)
@@ -654,7 +672,7 @@ PageType {
ExportController.renameClient(index,
clientNameEditor.textFieldText,
ContainersModel.getCurrentlyProcessedContainerIndex(),
ServersModel.getCurrentlyProcessedServerCredentials())
ServersModel.getProcessedServerCredentials())
PageController.showBusyIndicator(false)
clientNameEditDrawer.close()
}

View File

@@ -111,7 +111,7 @@ PageType {
function handler() {
serverSelector.text = selectedText
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
ServersModel.processedIndex = proxyServersModel.mapToSource(currentIndex)
}
}
}

View File

@@ -38,12 +38,13 @@ PageType {
tabBar.enabled = !visible
}
function onEnableTabBar(enabled) {
tabBar.enabled = enabled
function onDisableControls(disabled) {
tabBar.enabled = !disabled
}
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() {
@@ -69,6 +70,21 @@ PageType {
tabBarStackView.pop()
}
}
function onEscapePressed() {
if (!tabBar.enabled || busyIndicator.visible) {
return
}
var pageName = tabBarStackView.currentItem.objectName
if ((pageName === PageController.getPagePath(PageEnum.PageShare)) ||
(pageName === PageController.getPagePath(PageEnum.PageSettings))) {
PageController.goToPageHome()
tabBar.previousIndex = 0
} else {
PageController.closePage()
}
}
}
Connections {
@@ -108,7 +124,7 @@ PageType {
function onNoInstalledContainers() {
PageController.setTriggeredBtConnectButton(true)
ServersModel.currentlyProcessedIndex = ServersModel.getDefaultServerIndex()
ServersModel.processedIndex = ServersModel.getDefaultServerIndex()
InstallController.setShouldCreateServer(false)
PageController.goToPage(PageEnum.PageSetupWizardEasy)
}
@@ -136,7 +152,7 @@ PageType {
Component.onCompleted: {
var pagePath = PageController.getPagePath(PageEnum.PageHome)
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
ServersModel.processedIndex = ServersModel.defaultIndex
tabBarStackView.push(pagePath, { "objectName" : pagePath })
}
}
@@ -180,7 +196,7 @@ PageType {
image: "qrc:/images/controls/home.svg"
onClicked: {
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
ServersModel.processedIndex = ServersModel.defaultIndex
tabBar.previousIndex = 0
}
}

View File

@@ -392,18 +392,11 @@ void VpnConnection::appendSplitTunnelingConfig()
auto protocolName = m_vpnConfiguration.value(config_key::vpnproto).toString();
if (protocolName == ProtocolProps::protoToString(Proto::Awg)) {
auto configData = m_vpnConfiguration.value(protocolName + "_config_data").toObject();
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configData.value("allowed_ips").toString().split(","));
QJsonArray defaultAllowedIP = QJsonArray::fromStringList(QString("0.0.0.0/0, ::/0").split(","));
QJsonArray allowedIpsJsonArray = QJsonArray::fromStringList(configData.value("allowed_ips").toString().split(", "));
if (allowedIpsJsonArray != defaultAllowedIP) {
allowedIpsJsonArray.append(m_vpnConfiguration.value(config_key::dns1).toString());
allowedIpsJsonArray.append(m_vpnConfiguration.value(config_key::dns2).toString());
m_vpnConfiguration.insert(config_key::splitTunnelType, Settings::RouteMode::VpnOnlyForwardSites);
m_vpnConfiguration.insert(config_key::splitTunnelSites, allowedIpsJsonArray);
return;
}
configData[config_key::allowed_ips] = allowedIpsJsonArray;
m_vpnConfiguration.insert(protocolName + "_config_data", configData);
return;
}
}

View File

@@ -20,7 +20,7 @@ PLIST_NAME=$APP_NAME.plist
# Search Qt
if [ -z "${QT_VERSION+x}" ]; then
QT_VERSION=6.5.2;
QT_VERSION=6.6.2;
QT_BIN_DIR=$HOME/Qt/$QT_VERSION/ios/bin
fi

View File

@@ -36,7 +36,7 @@ QMAKE_STASH_FILE=$PROJECT_DIR/.qmake_stash
# Search Qt
if [ -z "${QT_VERSION+x}" ]; then
QT_VERSION=5.15.2
QT_VERSION=6.6.2
if [ -f /opt/Qt/$QT_VERSION/gcc_64/bin/qmake ]; then
QT_BIN_DIR=/opt/Qt/$QT_VERSION/gcc_64/bin
elif [ -f $HOME/Qt/$QT_VERSION/gcc_64/bin/qmake ]; then

View File

@@ -37,7 +37,7 @@ DMG_FILENAME=$PROJECT_DIR/${APP_NAME}.dmg
# Search Qt
if [ -z "${QT_VERSION+x}" ]; then
QT_VERSION=6.5.1;
QT_VERSION=6.4.3;
QIF_VERSION=4.6
QT_BIN_DIR=$HOME/Qt/$QT_VERSION/macos/bin
QIF_BIN_DIR=$QT_BIN_DIR/../../../Tools/QtInstallerFramework/$QIF_VERSION/bin
@@ -146,7 +146,8 @@ if [ "${MAC_CERT_PW+x}" ]; then
fi
echo "Building DMG installer..."
hdiutil create -size 120mb -volname AmneziaVPN -srcfolder $BUILD_DIR/installer/$APP_NAME.app -ov -format UDZO $DMG_FILENAME
# Allow Terminal to make changes in Privacy & Security > App Management
hdiutil create -size 256mb -volname AmneziaVPN -srcfolder $BUILD_DIR/installer/$APP_NAME.app -ov -format UDZO $DMG_FILENAME
if [ "${MAC_CERT_PW+x}" ]; then
echo "Signing DMG installer..."