diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index 0c9dfb32..35e740b0 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -10,7 +10,7 @@ env:
jobs:
Build-Linux-Ubuntu:
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-20.04
env:
QT_VERSION: 6.6.2
@@ -20,8 +20,6 @@ jobs:
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
- FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
- PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
steps:
- name: 'Install Qt'
@@ -92,8 +90,6 @@ jobs:
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
- FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
- PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
steps:
- name: 'Get sources'
@@ -160,8 +156,6 @@ jobs:
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
- FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
- PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
steps:
- name: 'Setup xcode'
@@ -196,7 +190,7 @@ jobs:
- name: 'Install go'
uses: actions/setup-go@v5
with:
- go-version: '1.24'
+ go-version: '1.22.1'
cache: false
- name: 'Setup gomobile'
@@ -249,82 +243,18 @@ jobs:
# ------------------------------------------------------
- Build-MacOS-old:
+ Build-MacOS:
runs-on: macos-latest
env:
# Keep compat with MacOS 10.15 aka Catalina by Qt 6.4
QT_VERSION: 6.4.3
+ QIF_VERSION: 4.6
PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }}
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
- FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
- PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
-
- steps:
- - name: 'Setup xcode'
- uses: maxim-lobanov/setup-xcode@v1
- with:
- xcode-version: '15.4.0'
-
- - name: 'Install Qt'
- uses: jurplel/install-qt-action@v3
- with:
- version: ${{ env.QT_VERSION }}
- host: 'mac'
- target: 'desktop'
- arch: 'clang_64'
- modules: 'qtremoteobjects qt5compat qtshadertools'
- dir: ${{ runner.temp }}
- setup-python: 'true'
- set-env: 'true'
- extra: '--external 7z --base ${{ env.QT_MIRROR }}'
-
-
- - name: 'Get sources'
- uses: actions/checkout@v4
- with:
- submodules: 'true'
- fetch-depth: 10
-
- - name: 'Setup ccache'
- uses: hendrikmuhs/ccache-action@v1.2
-
- - name: 'Build project'
- run: |
- export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin"
- bash deploy/build_macos.sh
-
- - name: 'Upload installer artifact'
- uses: actions/upload-artifact@v4
- with:
- name: AmneziaVPN_MacOS_old_installer
- path: deploy/build/pkg/AmneziaVPN.pkg
- retention-days: 7
-
- - name: 'Upload unpacked artifact'
- uses: actions/upload-artifact@v4
- with:
- name: AmneziaVPN_MacOS_old_unpacked
- path: deploy/build/client/AmneziaVPN.app
- retention-days: 7
-
-# ------------------------------------------------------
-
- Build-MacOS:
- runs-on: macos-latest
-
- env:
- QT_VERSION: 6.8.0
- PROD_AGW_PUBLIC_KEY: ${{ secrets.PROD_AGW_PUBLIC_KEY }}
- PROD_S3_ENDPOINT: ${{ secrets.PROD_S3_ENDPOINT }}
- DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
- DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
- DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
- FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
- PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
steps:
- name: 'Setup xcode'
@@ -345,6 +275,11 @@ jobs:
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
@@ -358,13 +293,14 @@ jobs:
- name: 'Build project'
run: |
export QT_BIN_DIR="${{ runner.temp }}/Qt/${{ env.QT_VERSION }}/macos/bin"
+ export QIF_BIN_DIR="${{ runner.temp }}/Qt/Tools/QtInstallerFramework/${{ env.QIF_VERSION }}/bin"
bash deploy/build_macos.sh
- name: 'Upload installer artifact'
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN_MacOS_installer
- path: deploy/build/pkg/AmneziaVPN.pkg
+ path: AmneziaVPN.dmg
retention-days: 7
- name: 'Upload unpacked artifact'
@@ -388,8 +324,6 @@ jobs:
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
- FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
- PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
steps:
- name: 'Install desktop Qt'
diff --git a/.github/workflows/tag-deploy.yml b/.github/workflows/tag-deploy.yml
index 31c334bf..2bcbd8c6 100644
--- a/.github/workflows/tag-deploy.yml
+++ b/.github/workflows/tag-deploy.yml
@@ -20,8 +20,6 @@ jobs:
DEV_AGW_PUBLIC_KEY: ${{ secrets.DEV_AGW_PUBLIC_KEY }}
DEV_AGW_ENDPOINT: ${{ secrets.DEV_AGW_ENDPOINT }}
DEV_S3_ENDPOINT: ${{ secrets.DEV_S3_ENDPOINT }}
- FREE_V2_ENDPOINT: ${{ secrets.FREE_V2_ENDPOINT }}
- PREM_V1_ENDPOINT: ${{ secrets.PREM_V1_ENDPOINT }}
steps:
- name: 'Install desktop Qt'
diff --git a/.github/workflows/tag-upload.yml b/.github/workflows/tag-upload.yml
index 9ac2da58..22629ed3 100644
--- a/.github/workflows/tag-upload.yml
+++ b/.github/workflows/tag-upload.yml
@@ -1,41 +1,64 @@
name: 'Upload a new version'
on:
- workflow_dispatch:
- inputs:
- RELEASE_VERSION:
- description: 'Release version (e.g. 1.2.3.4)'
- required: true
- type: string
+ push:
+ tags:
+ - '[0-9]+.[0-9]+.[0-9]+.[0-9]+'
jobs:
- Upload-S3:
+ upload:
runs-on: ubuntu-latest
+ name: upload
steps:
- - name: Checkout
+ - name: Checkout CMakeLists.txt
uses: actions/checkout@v4
with:
- ref: ${{ inputs.RELEASE_VERSION }}
+ ref: ${{ github.ref_name }}
sparse-checkout: |
CMakeLists.txt
- deploy/deploy_s3.sh
sparse-checkout-cone-mode: false
- name: Verify git tag
run: |
- TAG_NAME=${{ inputs.RELEASE_VERSION }}
+ GIT_TAG=${{ github.ref_name }}
CMAKE_TAG=$(grep 'project.*VERSION' CMakeLists.txt | sed -E 's/.* ([0-9]+.[0-9]+.[0-9]+.[0-9]+)$/\1/')
- if [[ "$TAG_NAME" == "$CMAKE_TAG" ]]; then
- echo "Git tag ($TAG_NAME) matches CMakeLists.txt version ($CMAKE_TAG)."
+
+ if [[ "$GIT_TAG" == "$CMAKE_TAG" ]]; then
+ echo "Git tag ($GIT_TAG) and version in CMakeLists.txt ($CMAKE_TAG) are the same. Continuing..."
else
- echo "::error::Mismatch: Git tag ($TAG_NAME) != CMakeLists.txt version ($CMAKE_TAG). Exiting with error..."
+ echo "Git tag ($GIT_TAG) and version in CMakeLists.txt ($CMAKE_TAG) are not the same! Cancelling..."
exit 1
fi
- - name: Setup Rclone
- uses: AnimMouse/setup-rclone@v1
+ - name: Download artifacts from the "${{ github.ref_name }}" tag
+ uses: robinraju/release-downloader@v1.8
with:
- rclone_config: ${{ secrets.RCLONE_CONFIG }}
+ tag: ${{ github.ref_name }}
+ fileName: "AmneziaVPN_(Linux_|)${{ github.ref_name }}*"
+ out-file-path: ${{ github.ref_name }}
- - name: Send dist to S3
- run: bash deploy/deploy_s3.sh ${{ inputs.RELEASE_VERSION }}
+ - name: Upload beta version
+ uses: jakejarvis/s3-sync-action@master
+ if: contains(github.event.base_ref, 'dev')
+ with:
+ args: --include "AmneziaVPN*" --delete
+ env:
+ AWS_S3_BUCKET: updates
+ AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }}
+ AWS_S3_ENDPOINT: https://${{ vars.CF_ACCOUNT_ID }}.r2.cloudflarestorage.com
+ SOURCE_DIR: ${{ github.ref_name }}
+ DEST_DIR: beta/${{ github.ref_name }}
+
+ - name: Upload stable version
+ uses: jakejarvis/s3-sync-action@master
+ if: contains(github.event.base_ref, 'master')
+ with:
+ args: --include "AmneziaVPN*" --delete
+ env:
+ AWS_S3_BUCKET: updates
+ AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_SECRET_ACCESS_KEY }}
+ AWS_S3_ENDPOINT: https://${{ vars.CF_ACCOUNT_ID }}.r2.cloudflarestorage.com
+ SOURCE_DIR: ${{ github.ref_name }}
+ DEST_DIR: stable/${{ github.ref_name }}
diff --git a/.gitignore b/.gitignore
index 503adc2d..5b90fd55 100644
--- a/.gitignore
+++ b/.gitignore
@@ -133,8 +133,4 @@ client/3rd/ShadowSocks/ss_ios.xcconfig
out/
# CMake files
-CMakeFiles/
-
-ios-ne-build.sh
-macos-ne-build.sh
-macos-signed-build.sh
+CMakeFiles/
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
index 90edb582..3ceaa56e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
+[submodule "client/3rd/OpenVPNAdapter"]
+ path = client/3rd/OpenVPNAdapter
+ url = https://github.com/amnezia-vpn/OpenVPNAdapter.git
[submodule "client/3rd/qtkeychain"]
path = client/3rd/qtkeychain
url = https://github.com/frankosterfeld/qtkeychain.git
@@ -7,7 +10,6 @@
[submodule "client/3rd-prebuilt"]
path = client/3rd-prebuilt
url = https://github.com/amnezia-vpn/3rd-prebuilt
- branch = feature/special-handshake
[submodule "client/3rd/amneziawg-apple"]
path = client/3rd/amneziawg-apple
url = https://github.com/amnezia-vpn/amneziawg-apple
diff --git a/CMakeLists.txt b/CMakeLists.txt
index fec613de..98f3be14 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
-project(${PROJECT} VERSION 4.8.8.1
+project(${PROJECT} VERSION 4.8.3.0
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
-set(APP_ANDROID_VERSION_CODE 2087)
+set(APP_ANDROID_VERSION_CODE 2072)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux")
diff --git a/README.md b/README.md
index 992c3ad0..8f887808 100644
--- a/README.md
+++ b/README.md
@@ -13,13 +13,13 @@
[](https://amnezia.org)
-### [Website](https://amnezia.org) | [Alt website link](https://storage.googleapis.com/amnezia/amnezia.org) | [Documentation](https://docs.amnezia.org) | [Troubleshooting](https://docs.amnezia.org/troubleshooting)
+### [Website](https://amnezia.org) | [Alt website link](https://storage.googleapis.com/kldscp/amnezia.org) | [Documentation](https://docs.amnezia.org) | [Troubleshooting](https://docs.amnezia.org/troubleshooting)
> [!TIP]
-> If the [Amnezia website](https://amnezia.org) is blocked in your region, you can use an [Alternative website link](https://storage.googleapis.com/amnezia/amnezia.org ).
+> If the [Amnezia website](https://amnezia.org) is blocked in your region, you can use an [Alternative website link](https://storage.googleapis.com/kldscp/amnezia.org).
-
+
[All releases](https://github.com/amnezia-vpn/amnezia-client/releases)
@@ -185,7 +185,7 @@ GPL v3.0
Patreon: [https://www.patreon.com/amneziavpn](https://www.patreon.com/amneziavpn)
-Bitcoin: bc1qmhtgcf9637rl3kqyy22r2a8wa8laka4t9rx2mf
+Bitcoin: bc1q26eevjcg9j0wuyywd2e3uc9cs2w58lpkpjxq6p
USDT BEP20: 0x6abD576765a826f87D1D95183438f9408C901bE4
USDT TRC20: TELAitazF1MZGmiNjTcnxDjEiH5oe7LC9d
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
diff --git a/README_RU.md b/README_RU.md
index 44681875..59518f4b 100644
--- a/README_RU.md
+++ b/README_RU.md
@@ -6,16 +6,16 @@
[](https://gitpod.io/#https://github.com/amnezia-vpn/amnezia-client)
### [English](https://github.com/amnezia-vpn/amnezia-client/blob/dev/README.md) | Русский
-[AmneziaVPN](https://amnezia.org) — это open source VPN-клиент, ключевая особенность которого заключается в возможности развернуть собственный VPN на вашем сервере.
+[AmneziaVPN](https://amnezia.org) — это open sourse VPN-клиент, ключевая особенность которого заключается в возможности развернуть собственный VPN на вашем сервере.
[](https://amnezia.org)
-### [Сайт](https://amnezia.org) | [Зеркало сайта](https://storage.googleapis.com/amnezia/amnezia.org) | [Документация](https://docs.amnezia.org) | [Решение проблем](https://docs.amnezia.org/troubleshooting)
+### [Сайт](https://amnezia.org) | [Зеркало на сайт](https://storage.googleapis.com/kldscp/amnezia.org) | [Документация](https://docs.amnezia.org) | [Решение проблем](https://docs.amnezia.org/troubleshooting)
> [!TIP]
-> Если [сайт Amnezia](https://amnezia.org) заблокирован в вашем регионе, вы можете воспользоваться [ссылкой на зеркало](https://storage.googleapis.com/amnezia/amnezia.org).
+> Если [сайт Amnezia](https://amnezia.org) заблокирован в вашем регионе, вы можете воспользоваться [ссылкой на зеркало](https://storage.googleapis.com/kldscp/amnezia.org).
-
+
[Все релизы](https://github.com/amnezia-vpn/amnezia-client/releases)
@@ -30,7 +30,7 @@
- Классические VPN-протоколы: OpenVPN, WireGuard и IKEv2.
- Протоколы с маскировкой трафика (обфускацией): OpenVPN с плагином [Cloak](https://github.com/cbeuw/Cloak), Shadowsocks (OpenVPN over Shadowsocks), [AmneziaWG](https://docs.amnezia.org/documentation/amnezia-wg/) and XRay.
- Поддержка Split Tunneling — добавляйте любые сайты или приложения в список, чтобы включить VPN только для них.
-- Поддерживает платформы: Windows, macOS, Linux, Android, iOS.
+- Поддерживает платформы: Windows, MacOS, Linux, Android, iOS.
- Поддержка конфигурации протокола AmneziaWG на [бета-прошивке Keenetic](https://docs.keenetic.com/ua/air/kn-1611/en/6319-latest-development-release.html#UUID-186c4108-5afd-c10b-f38a-cdff6c17fab3_section-idm33192196168192-improved).
## Ссылки
@@ -38,10 +38,10 @@
- [https://amnezia.org](https://amnezia.org) - Веб-сайт проекта | [Альтернативная ссылка (зеркало)](https://storage.googleapis.com/kldscp/amnezia.org)
- [https://docs.amnezia.org](https://docs.amnezia.org) - Документация
- [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 (Английский)
-- [https://t.me/amnezia_vpn_ir](https://t.me/amnezia_vpn_ir) - Канал поддержки в Telegram (Фарси)
-- [https://t.me/amnezia_vpn_mm](https://t.me/amnezia_vpn_mm) - Канал поддержки в Telegram (Мьянма)
-- [https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Канал поддержки в Telegram (Русский)
+- [https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Канал поддржки в Telegram (Английский)
+- [https://t.me/amnezia_vpn_ir](https://t.me/amnezia_vpn_ir) - Канал поддржки в Telegram (Фарси)
+- [https://t.me/amnezia_vpn_mm](https://t.me/amnezia_vpn_mm) - Канал поддржки в Telegram (Мьянма)
+- [https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Канал поддржки в Telegram (Русский)
- [https://vpnpay.io/en/amnezia-premium/](https://vpnpay.io/en/amnezia-premium/) - Amnezia Premium | [Зеркало](https://storage.googleapis.com/kldscp/vpnpay.io/ru/amnezia-premium\)
## Технологии
@@ -80,8 +80,8 @@ git submodule update --init --recursive
Проверьте папку deploy для скриптов сборки.
### Как собрать iOS-приложение из исходного кода на MacOS
-1. Убедитесь, что у вас установлен Xcode версии 14 или выше.
-2. Для генерации проекта Xcode используется QT. Требуется версия QT 6.6.2. Установите QT для MacOS здесь или через QT Online Installer. Необходимые модули:
+1. Убедитесь, что у вас установлен XCode версии 14 или выше.
+2. Для генерации проекта XCode используется QT. Требуется версия QT 6.6.2. Установите QT для MacOS здесь или через QT Online Installer. Необходимые модули:
- MacOS
- iOS
- Модуль совместимости с Qt 5
@@ -117,7 +117,7 @@ $QT_IOS_BIN/qt-cmake . -B build-ios -GXcode -DQT_HOST_PATH=$QT_MACOS_ROOT_DIR
export PATH=$(PATH):/path/to/GOPATH/bin
```
-6. Откройте проект в Xcode. Теперь вы можете тестировать, архивировать или публиковать приложение.
+6. Откройте проект в XCode. Теперь вы можете тестировать, архивировать или публиковать приложение.
Если сборка завершится с ошибкой:
```
@@ -169,7 +169,7 @@ GPL v3.0
Patreon: [https://www.patreon.com/amneziavpn](https://www.patreon.com/amneziavpn)
-Bitcoin: bc1qmhtgcf9637rl3kqyy22r2a8wa8laka4t9rx2mf
+Bitcoin: bc1q26eevjcg9j0wuyywd2e3uc9cs2w58lpkpjxq6p
USDT BEP20: 0x6abD576765a826f87D1D95183438f9408C901bE4
USDT TRC20: TELAitazF1MZGmiNjTcnxDjEiH5oe7LC9d
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
diff --git a/client/3rd-prebuilt b/client/3rd-prebuilt
index 840b7b07..ba580dc5 160000
--- a/client/3rd-prebuilt
+++ b/client/3rd-prebuilt
@@ -1 +1 @@
-Subproject commit 840b7b070e6ac8b90dda2fac6e98859b23727c0c
+Subproject commit ba580dc5bd7784f7b1e110ff0365f3286e549a61
diff --git a/client/3rd/OpenVPNAdapter b/client/3rd/OpenVPNAdapter
new file mode 160000
index 00000000..7c821a8d
--- /dev/null
+++ b/client/3rd/OpenVPNAdapter
@@ -0,0 +1 @@
+Subproject commit 7c821a8d5c1ad5ad94e0763b4f25a875b5a6fe1b
diff --git a/client/3rd/amneziawg-apple b/client/3rd/amneziawg-apple
index 811af0a8..76e7db55 160000
--- a/client/3rd/amneziawg-apple
+++ b/client/3rd/amneziawg-apple
@@ -1 +1 @@
-Subproject commit 811af0a83b3faeade89a9093a588595666d32066
+Subproject commit 76e7db556a6d7e2582f9481df91db188a46c009c
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index a454142d..3ef92385 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -31,8 +31,9 @@ add_definitions(-DDEV_AGW_PUBLIC_KEY="$ENV{DEV_AGW_PUBLIC_KEY}")
add_definitions(-DDEV_AGW_ENDPOINT="$ENV{DEV_AGW_ENDPOINT}")
add_definitions(-DDEV_S3_ENDPOINT="$ENV{DEV_S3_ENDPOINT}")
-add_definitions(-DFREE_V2_ENDPOINT="$ENV{FREE_V2_ENDPOINT}")
-add_definitions(-DPREM_V1_ENDPOINT="$ENV{PREM_V1_ENDPOINT}")
+if(IOS)
+ set(PACKAGES ${PACKAGES} Multimedia)
+endif()
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
set(PACKAGES ${PACKAGES} Widgets)
@@ -47,6 +48,10 @@ set(LIBS ${LIBS}
Qt6::Core5Compat Qt6::Concurrent
)
+if(IOS)
+ set(LIBS ${LIBS} Qt6::Multimedia)
+endif()
+
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
set(LIBS ${LIBS} Qt6::Widgets)
endif()
@@ -91,6 +96,11 @@ configure_file(${CMAKE_CURRENT_LIST_DIR}/translations/translations.qrc.in ${CMAK
qt6_add_resources(QRC ${I18NQRC} ${CMAKE_CURRENT_BINARY_DIR}/translations.qrc)
# -- i18n end
+if(IOS)
+ execute_process(COMMAND bash ${CMAKE_CURRENT_LIST_DIR}/ios/scripts/openvpn.sh args
+ WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
+endif()
+
set(IS_CI ${CI})
if(IS_CI)
message("Detected CI env")
@@ -100,8 +110,8 @@ if(IS_CI)
endif()
endif()
+
include(${CMAKE_CURRENT_LIST_DIR}/cmake/3rdparty.cmake)
-include(${CMAKE_CURRENT_LIST_DIR}/cmake/sources.cmake)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/../ipc
@@ -110,22 +120,167 @@ include_directories(
${CMAKE_CURRENT_BINARY_DIR}
)
+configure_file(${CMAKE_CURRENT_LIST_DIR}/../version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
+
+set(HEADERS ${HEADERS}
+ ${CMAKE_CURRENT_LIST_DIR}/migrations.h
+ ${CMAKE_CURRENT_LIST_DIR}/../ipc/ipc.h
+ ${CMAKE_CURRENT_LIST_DIR}/amnezia_application.h
+ ${CMAKE_CURRENT_LIST_DIR}/containers/containers_defs.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/defs.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/errorstrings.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/scripts_registry.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/server_defs.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/controllers/apiController.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/controllers/vpnConfigurationController.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/qml_register_protocols.h
+ ${CMAKE_CURRENT_LIST_DIR}/ui/pages.h
+ ${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.h
+ ${CMAKE_CURRENT_BINARY_DIR}/version.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/sshclient.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/networkUtilities.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/serialization.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/transfer.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/enums/apiEnums.h
+ ${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.h
+ ${CMAKE_CURRENT_LIST_DIR}/utils/qmlUtils.h
+)
+
+# Mozilla headres
+set(HEADERS ${HEADERS}
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/models/server.h
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/shared/ipaddress.h
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/shared/leakdetector.h
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/controllerimpl.h
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/localsocketcontroller.h
+)
+
include_directories(mozilla)
include_directories(mozilla/shared)
include_directories(mozilla/models)
-configure_file(${CMAKE_CURRENT_LIST_DIR}/../version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
+if(NOT IOS)
+ set(HEADERS ${HEADERS}
+ ${CMAKE_CURRENT_LIST_DIR}/platforms/ios/QRCodeReaderBase.h
+ )
+endif()
+
+if(NOT ANDROID)
+ set(HEADERS ${HEADERS}
+ ${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.h
+ )
+endif()
+
+set(SOURCES ${SOURCES}
+ ${CMAKE_CURRENT_LIST_DIR}/migrations.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/amnezia_application.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/containers/containers_defs.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/errorstrings.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/scripts_registry.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/server_defs.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/controllers/apiController.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/controllers/serverController.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/controllers/vpnConfigurationController.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/protocols_defs.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/ui/qautostart.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/vpnprotocol.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/sshclient.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/networkUtilities.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/outbound.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/inbound.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/ss.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/ssd.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/vless.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/trojan.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/serialization/vmess_new.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/../common/logger/logger.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/utils/qmlUtils.cpp
+)
+
+# Mozilla sources
+set(SOURCES ${SOURCES}
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/models/server.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/shared/ipaddress.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/shared/leakdetector.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/mozilla/localsocketcontroller.cpp
+)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(${PROJECT} PRIVATE "MZ_DEBUG")
endif()
+if(NOT IOS)
+ set(SOURCES ${SOURCES}
+ ${CMAKE_CURRENT_LIST_DIR}/platforms/ios/QRCodeReaderBase.cpp
+ )
+endif()
+
+if(NOT ANDROID)
+ set(SOURCES ${SOURCES}
+ ${CMAKE_CURRENT_LIST_DIR}/ui/notificationhandler.cpp
+ )
+endif()
+
+file(GLOB COMMON_FILES_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/*.h)
+file(GLOB COMMON_FILES_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/*.cpp)
+
+file(GLOB_RECURSE PAGE_LOGIC_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/pages_logic/*.h)
+file(GLOB_RECURSE PAGE_LOGIC_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/pages_logic/*.cpp)
+
+file(GLOB CONFIGURATORS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.h)
+file(GLOB CONFIGURATORS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/configurators/*.cpp)
+
+file(GLOB UI_MODELS_H CONFIGURE_DEPENDS
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.h
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.h
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/services/*.h
+)
+file(GLOB UI_MODELS_CPP CONFIGURE_DEPENDS
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/*.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/protocols/*.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/ui/models/services/*.cpp
+)
+
+file(GLOB UI_CONTROLLERS_H CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.h)
+file(GLOB UI_CONTROLLERS_CPP CONFIGURE_DEPENDS ${CMAKE_CURRENT_LIST_DIR}/ui/controllers/*.cpp)
+
+set(HEADERS ${HEADERS}
+ ${COMMON_FILES_H}
+ ${PAGE_LOGIC_H}
+ ${CONFIGURATORS_H}
+ ${UI_MODELS_H}
+ ${UI_CONTROLLERS_H}
+)
+set(SOURCES ${SOURCES}
+ ${COMMON_FILES_CPP}
+ ${PAGE_LOGIC_CPP}
+ ${CONFIGURATORS_CPP}
+ ${UI_MODELS_CPP}
+ ${UI_CONTROLLERS_CPP}
+)
+
if(WIN32)
configure_file(
${CMAKE_CURRENT_LIST_DIR}/platforms/windows/amneziavpn.rc.in
${CMAKE_CURRENT_BINARY_DIR}/amneziavpn.rc
)
+ set(HEADERS ${HEADERS}
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_windows.h
+ )
+
+ set(SOURCES ${SOURCES}
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/ikev2_vpn_protocol_windows.cpp
+ )
+
+ set(RESOURCES ${RESOURCES}
+ ${CMAKE_CURRENT_BINARY_DIR}/amneziavpn.rc
+ )
+
set(LIBS ${LIBS}
user32
rasapi32
@@ -169,6 +324,30 @@ endif()
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
message("Client desktop build")
add_compile_definitions(AMNEZIA_DESKTOP)
+
+ set(HEADERS ${HEADERS}
+ ${CMAKE_CURRENT_LIST_DIR}/core/ipcclient.h
+ ${CMAKE_CURRENT_LIST_DIR}/core/privileged_process.h
+ ${CMAKE_CURRENT_LIST_DIR}/ui/systemtray_notificationhandler.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnprotocol.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/xrayprotocol.h
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.h
+ )
+
+ set(SOURCES ${SOURCES}
+ ${CMAKE_CURRENT_LIST_DIR}/core/ipcclient.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/core/privileged_process.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/ui/systemtray_notificationhandler.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnprotocol.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/openvpnovercloakprotocol.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/shadowsocksvpnprotocol.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/wireguardprotocol.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/xrayprotocol.cpp
+ ${CMAKE_CURRENT_LIST_DIR}/protocols/awgprotocol.cpp
+ )
endif()
if(ANDROID)
diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp
index f32d525a..aeed439b 100644
--- a/client/amnezia_application.cpp
+++ b/client/amnezia_application.cpp
@@ -2,8 +2,6 @@
#include
#include
-#include
-#include
#include
#include
#include
@@ -12,16 +10,26 @@
#include
#include
#include
+#include
+#include
#include "logger.h"
-#include "ui/controllers/pageController.h"
#include "ui/models/installedAppsModel.h"
#include "version.h"
#include "platforms/ios/QRCodeReaderBase.h"
+#if defined(Q_OS_ANDROID)
+ #include "core/installedAppsImageProvider.h"
+ #include "platforms/android/android_controller.h"
+#endif
#include "protocols/qml_register_protocols.h"
+#if defined(Q_OS_IOS)
+ #include "platforms/ios/ios_controller.h"
+ #include
+#endif
+
AmneziaApplication::AmneziaApplication(int &argc, char *argv[]) : AMNEZIA_BASE_CLASS(argc, argv)
{
setQuitOnLastWindowClosed(false);
@@ -76,12 +84,79 @@ void AmneziaApplication::init()
m_vpnConnection->moveToThread(&m_vpnConnectionThread);
m_vpnConnectionThread.start();
- m_coreController.reset(new CoreController(m_vpnConnection, m_settings, m_engine));
+ initModels();
+ loadTranslator();
+ initControllers();
+
+#ifdef Q_OS_ANDROID
+ if (!AndroidController::initLogging()) {
+ qFatal("Android logging initialization failed");
+ }
+ AndroidController::instance()->setSaveLogs(m_settings->isSaveLogs());
+ connect(m_settings.get(), &Settings::saveLogsChanged, AndroidController::instance(), &AndroidController::setSaveLogs);
+
+ AndroidController::instance()->setScreenshotsEnabled(m_settings->isScreenshotsEnabled());
+ connect(m_settings.get(), &Settings::screenshotsEnabledChanged, AndroidController::instance(), &AndroidController::setScreenshotsEnabled);
+
+ connect(m_settings.get(), &Settings::serverRemoved, AndroidController::instance(), &AndroidController::resetLastServer);
+
+ connect(m_settings.get(), &Settings::settingsCleared, []() { AndroidController::instance()->resetLastServer(-1); });
+
+ connect(AndroidController::instance(), &AndroidController::initConnectionState, this, [this](Vpn::ConnectionState state) {
+ m_connectionController->onConnectionStateChanged(state);
+ if (m_vpnConnection)
+ m_vpnConnection->restoreConnection();
+ });
+ if (!AndroidController::instance()->initialize()) {
+ qFatal("Android controller initialization failed");
+ }
+
+ connect(AndroidController::instance(), &AndroidController::importConfigFromOutside, this, [this](QString data) {
+ emit m_pageController->goToPageHome();
+ m_importController->extractConfigFromData(data);
+ data.clear();
+ emit m_pageController->goToPageViewConfig();
+ });
+
+ m_engine->addImageProvider(QLatin1String("installedAppImage"), new InstalledAppsImageProvider);
+#endif
+
+#ifdef Q_OS_IOS
+ IosController::Instance()->initialize();
+ connect(IosController::Instance(), &IosController::importConfigFromOutside, this, [this](QString data) {
+ emit m_pageController->goToPageHome();
+ m_importController->extractConfigFromData(data);
+ emit m_pageController->goToPageViewConfig();
+ });
+
+ connect(IosController::Instance(), &IosController::importBackupFromOutside, this, [this](QString filePath) {
+ emit m_pageController->goToPageHome();
+ m_pageController->goToPageSettingsBackup();
+ emit m_settingsController->importBackupFromOutside(filePath);
+ });
+
+ QTimer::singleShot(0, this, [this]() { AmneziaVPN::toggleScreenshots(m_settings->isScreenshotsEnabled()); });
+
+ connect(m_settings.get(), &Settings::screenshotsEnabledChanged, [](bool enabled) { AmneziaVPN::toggleScreenshots(enabled); });
+#endif
+
+#ifndef Q_OS_ANDROID
+ m_notificationHandler.reset(NotificationHandler::create(nullptr));
+
+ connect(m_vpnConnection.get(), &VpnConnection::connectionStateChanged, m_notificationHandler.get(),
+ &NotificationHandler::setConnectionState);
+
+ connect(m_notificationHandler.get(), &NotificationHandler::raiseRequested, m_pageController.get(), &PageController::raiseMainWindow);
+ connect(m_notificationHandler.get(), &NotificationHandler::connectRequested, m_connectionController.get(),
+ static_cast(&ConnectionController::openConnection));
+ connect(m_notificationHandler.get(), &NotificationHandler::disconnectRequested, m_connectionController.get(),
+ &ConnectionController::closeConnection);
+ connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated);
+#endif
m_engine->addImportPath("qrc:/ui/qml/Modules/");
m_engine->load(url);
-
- m_coreController->setQmlRoot();
+ m_systemController->setQmlRoot(m_engine->rootObjects().value(0));
bool enabled = m_settings->isSaveLogs();
#ifndef Q_OS_ANDROID
@@ -93,13 +168,13 @@ void AmneziaApplication::init()
#endif
Logger::setServiceLogsEnabled(enabled);
-#ifdef Q_OS_WIN //TODO
+#ifdef Q_OS_WIN
if (m_parser.isSet("a"))
- m_coreController->pageController()->showOnStartup();
+ m_pageController->showOnStartup();
else
- emit m_coreController->pageController()->raiseMainWindow();
+ emit m_pageController->raiseMainWindow();
#else
- m_coreController->pageController()->showOnStartup();
+ m_pageController->showOnStartup();
#endif
// Android TextArea clipboard workaround
@@ -156,6 +231,33 @@ void AmneziaApplication::loadFonts()
QFontDatabase::addApplicationFont(":/fonts/pt-root-ui_vf.ttf");
}
+void AmneziaApplication::loadTranslator()
+{
+ auto locale = m_settings->getAppLanguage();
+ m_translator.reset(new QTranslator());
+ updateTranslator(locale);
+}
+
+void AmneziaApplication::updateTranslator(const QLocale &locale)
+{
+ if (!m_translator->isEmpty()) {
+ QCoreApplication::removeTranslator(m_translator.get());
+ }
+
+ QString strFileName = QString(":/translations/amneziavpn") + QLatin1String("_") + locale.name() + ".qm";
+ if (m_translator->load(strFileName)) {
+ if (QCoreApplication::installTranslator(m_translator.get())) {
+ m_settings->setAppLanguage(locale);
+ }
+ } else {
+ m_settings->setAppLanguage(QLocale::English);
+ }
+
+ m_engine->retranslate();
+
+ emit translationsUpdated();
+}
+
bool AmneziaApplication::parseCommands()
{
m_parser.setApplicationDescription(APPLICATION_NAME);
@@ -180,20 +282,19 @@ bool AmneziaApplication::parseCommands()
}
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
-void AmneziaApplication::startLocalServer()
-{
+void AmneziaApplication::startLocalServer() {
const QString serverName("AmneziaVPNInstance");
QLocalServer::removeServer(serverName);
- QLocalServer *server = new QLocalServer(this);
+ QLocalServer* server = new QLocalServer(this);
server->listen(serverName);
QObject::connect(server, &QLocalServer::newConnection, this, [server, this]() {
if (server) {
- QLocalSocket *clientConnection = server->nextPendingConnection();
+ QLocalSocket* clientConnection = server->nextPendingConnection();
clientConnection->deleteLater();
}
- emit m_coreController->pageController()->raiseMainWindow(); //TODO
+ emit m_pageController->raiseMainWindow();
});
}
#endif
@@ -203,12 +304,163 @@ QQmlApplicationEngine *AmneziaApplication::qmlEngine() const
return m_engine;
}
-QNetworkAccessManager *AmneziaApplication::networkManager()
+void AmneziaApplication::initModels()
{
- return m_nam;
+ 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());
+ connect(m_languageModel.get(), &LanguageModel::updateTranslations, this, &AmneziaApplication::updateTranslator);
+ connect(this, &AmneziaApplication::translationsUpdated, m_languageModel.get(), &LanguageModel::translationsUpdated);
+
+ m_sitesModel.reset(new SitesModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("SitesModel", m_sitesModel.get());
+
+ m_appSplitTunnelingModel.reset(new AppSplitTunnelingModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("AppSplitTunnelingModel", m_appSplitTunnelingModel.get());
+
+ m_protocolsModel.reset(new ProtocolsModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("ProtocolsModel", m_protocolsModel.get());
+
+ m_openVpnConfigModel.reset(new OpenVpnConfigModel(this));
+ m_engine->rootContext()->setContextProperty("OpenVpnConfigModel", m_openVpnConfigModel.get());
+
+ m_shadowSocksConfigModel.reset(new ShadowSocksConfigModel(this));
+ m_engine->rootContext()->setContextProperty("ShadowSocksConfigModel", m_shadowSocksConfigModel.get());
+
+ m_cloakConfigModel.reset(new CloakConfigModel(this));
+ m_engine->rootContext()->setContextProperty("CloakConfigModel", m_cloakConfigModel.get());
+
+ m_wireGuardConfigModel.reset(new WireGuardConfigModel(this));
+ m_engine->rootContext()->setContextProperty("WireGuardConfigModel", m_wireGuardConfigModel.get());
+
+ m_awgConfigModel.reset(new AwgConfigModel(this));
+ m_engine->rootContext()->setContextProperty("AwgConfigModel", m_awgConfigModel.get());
+
+ m_xrayConfigModel.reset(new XrayConfigModel(this));
+ m_engine->rootContext()->setContextProperty("XrayConfigModel", m_xrayConfigModel.get());
+
+#ifdef Q_OS_WINDOWS
+ m_ikev2ConfigModel.reset(new Ikev2ConfigModel(this));
+ m_engine->rootContext()->setContextProperty("Ikev2ConfigModel", m_ikev2ConfigModel.get());
+#endif
+
+ m_sftpConfigModel.reset(new SftpConfigModel(this));
+ m_engine->rootContext()->setContextProperty("SftpConfigModel", m_sftpConfigModel.get());
+
+ m_socks5ConfigModel.reset(new Socks5ProxyConfigModel(this));
+ m_engine->rootContext()->setContextProperty("Socks5ProxyConfigModel", m_socks5ConfigModel.get());
+
+ m_clientManagementModel.reset(new ClientManagementModel(m_settings, this));
+ m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get());
+ connect(m_clientManagementModel.get(), &ClientManagementModel::adminConfigRevoked, m_serversModel.get(),
+ &ServersModel::clearCachedProfile);
+
+ m_apiServicesModel.reset(new ApiServicesModel(this));
+ m_engine->rootContext()->setContextProperty("ApiServicesModel", m_apiServicesModel.get());
+
+ m_apiCountryModel.reset(new ApiCountryModel(this));
+ m_engine->rootContext()->setContextProperty("ApiCountryModel", m_apiCountryModel.get());
+ connect(m_serversModel.get(), &ServersModel::updateApiLanguageModel, this, [this]() {
+ m_apiCountryModel->updateModel(m_serversModel->getProcessedServerData("apiAvailableCountries").toJsonArray(),
+ m_serversModel->getProcessedServerData("apiServerCountryCode").toString());
+ });
+ connect(m_serversModel.get(), &ServersModel::updateApiServicesModel, this,
+ [this]() { m_apiServicesModel->updateModel(m_serversModel->getProcessedServerData("apiConfig").toJsonObject()); });
}
-QClipboard *AmneziaApplication::getClipboard()
+void AmneziaApplication::initControllers()
{
- return this->clipboard();
+ m_connectionController.reset(
+ new ConnectionController(m_serversModel, m_containersModel, m_clientManagementModel, m_vpnConnection, m_settings));
+ m_engine->rootContext()->setContextProperty("ConnectionController", m_connectionController.get());
+
+ connect(m_connectionController.get(), qOverload(&ConnectionController::connectionErrorOccurred), this,
+ [this](const QString &errorMessage) {
+ emit m_pageController->showErrorMessage(errorMessage);
+ emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
+ });
+
+ connect(m_connectionController.get(), qOverload(&ConnectionController::connectionErrorOccurred), this,
+ [this](ErrorCode errorCode) {
+ emit m_pageController->showErrorMessage(errorCode);
+ emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
+ });
+
+ connect(m_connectionController.get(), &ConnectionController::connectButtonClicked, m_connectionController.get(),
+ &ConnectionController::toggleConnection, Qt::QueuedConnection);
+
+ m_pageController.reset(new PageController(m_serversModel, m_settings));
+ m_engine->rootContext()->setContextProperty("PageController", m_pageController.get());
+
+ m_focusController.reset(new FocusController(m_engine, this));
+ m_engine->rootContext()->setContextProperty("FocusController", m_focusController.get());
+
+ m_installController.reset(new InstallController(m_serversModel, m_containersModel, m_protocolsModel, m_clientManagementModel,
+ m_apiServicesModel, m_settings));
+ m_engine->rootContext()->setContextProperty("InstallController", m_installController.get());
+ connect(m_installController.get(), &InstallController::passphraseRequestStarted, m_pageController.get(),
+ &PageController::showPassphraseRequestDrawer);
+ connect(m_pageController.get(), &PageController::passphraseRequestDrawerClosed, m_installController.get(),
+ &InstallController::setEncryptedPassphrase);
+ connect(m_installController.get(), &InstallController::currentContainerUpdated, m_connectionController.get(),
+ &ConnectionController::onCurrentContainerUpdated);
+
+ connect(m_installController.get(), &InstallController::updateServerFromApiFinished, this, [this]() {
+ disconnect(m_reloadConfigErrorOccurredConnection);
+ emit m_connectionController->configFromApiUpdated();
+ });
+
+ connect(m_connectionController.get(), &ConnectionController::updateApiConfigFromGateway, this, [this]() {
+ m_reloadConfigErrorOccurredConnection = connect(
+ m_installController.get(), qOverload(&InstallController::installationErrorOccurred), this,
+ [this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); },
+ static_cast(Qt::AutoConnection || Qt::SingleShotConnection));
+ m_installController->updateServiceFromApi(m_serversModel->getDefaultServerIndex(), "", "");
+ });
+
+ connect(m_connectionController.get(), &ConnectionController::updateApiConfigFromTelegram, this, [this]() {
+ m_reloadConfigErrorOccurredConnection = connect(
+ m_installController.get(), qOverload(&InstallController::installationErrorOccurred), this,
+ [this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); },
+ static_cast(Qt::AutoConnection || Qt::SingleShotConnection));
+ m_serversModel->removeApiConfig(m_serversModel->getDefaultServerIndex());
+ m_installController->updateServiceFromTelegram(m_serversModel->getDefaultServerIndex());
+ });
+
+ connect(this, &AmneziaApplication::translationsUpdated, m_connectionController.get(), &ConnectionController::onTranslationsUpdated);
+
+ m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings));
+ m_engine->rootContext()->setContextProperty("ImportController", m_importController.get());
+
+ m_exportController.reset(new ExportController(m_serversModel, m_containersModel, m_clientManagementModel, m_settings));
+ m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get());
+
+ m_settingsController.reset(
+ new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_appSplitTunnelingModel, m_settings));
+ m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get());
+ if (m_settingsController->isAutoConnectEnabled() && m_serversModel->getDefaultServerIndex() >= 0) {
+ QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); });
+ }
+ connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled, m_serversModel.get(), &ServersModel::toggleAmneziaDns);
+
+ m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel));
+ m_engine->rootContext()->setContextProperty("SitesController", m_sitesController.get());
+
+ m_appSplitTunnelingController.reset(new AppSplitTunnelingController(m_settings, m_appSplitTunnelingModel));
+ m_engine->rootContext()->setContextProperty("AppSplitTunnelingController", m_appSplitTunnelingController.get());
+
+ m_systemController.reset(new SystemController(m_settings));
+ m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get());
}
diff --git a/client/amnezia_application.h b/client/amnezia_application.h
index ea5f6f52..cfeac0d1 100644
--- a/client/amnezia_application.h
+++ b/client/amnezia_application.h
@@ -11,12 +11,44 @@
#else
#include
#endif
-#include
-#include "core/controllers/coreController.h"
#include "settings.h"
#include "vpnconnection.h"
+#include "ui/controllers/connectionController.h"
+#include "ui/controllers/exportController.h"
+#include "ui/controllers/importController.h"
+#include "ui/controllers/installController.h"
+#include "ui/controllers/focusController.h"
+#include "ui/controllers/pageController.h"
+#include "ui/controllers/settingsController.h"
+#include "ui/controllers/sitesController.h"
+#include "ui/controllers/systemController.h"
+#include "ui/controllers/appSplitTunnelingController.h"
+#include "ui/models/containers_model.h"
+#include "ui/models/languageModel.h"
+#include "ui/models/protocols/cloakConfigModel.h"
+#ifndef Q_OS_ANDROID
+ #include "ui/notificationhandler.h"
+#endif
+#ifdef Q_OS_WINDOWS
+ #include "ui/models/protocols/ikev2ConfigModel.h"
+#endif
+#include "ui/models/protocols/awgConfigModel.h"
+#include "ui/models/protocols/openvpnConfigModel.h"
+#include "ui/models/protocols/shadowsocksConfigModel.h"
+#include "ui/models/protocols/wireguardConfigModel.h"
+#include "ui/models/protocols/xrayConfigModel.h"
+#include "ui/models/protocols_model.h"
+#include "ui/models/servers_model.h"
+#include "ui/models/services/sftpConfigModel.h"
+#include "ui/models/services/socks5ProxyConfigModel.h"
+#include "ui/models/sites_model.h"
+#include "ui/models/clientManagementModel.h"
+#include "ui/models/appSplitTunnelingModel.h"
+#include "ui/models/apiServicesModel.h"
+#include "ui/models/apiCountryModel.h"
+
#define amnApp (static_cast(QCoreApplication::instance()))
#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS)
@@ -35,6 +67,8 @@ public:
void init();
void registerTypes();
void loadFonts();
+ void loadTranslator();
+ void updateTranslator(const QLocale &locale);
bool parseCommands();
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
@@ -42,24 +76,68 @@ public:
#endif
QQmlApplicationEngine *qmlEngine() const;
- QNetworkAccessManager *networkManager();
- QClipboard *getClipboard();
+ QNetworkAccessManager *manager() { return m_nam; }
+
+signals:
+ void translationsUpdated();
private:
+ void initModels();
+ void initControllers();
+
QQmlApplicationEngine *m_engine {};
std::shared_ptr m_settings;
- QScopedPointer m_coreController;
-
QSharedPointer m_containerProps;
QSharedPointer m_protocolProps;
+ QSharedPointer m_translator;
QCommandLineParser m_parser;
+ QSharedPointer m_containersModel;
+ QSharedPointer m_defaultServerContainersModel;
+ QSharedPointer m_serversModel;
+ QSharedPointer m_languageModel;
+ QSharedPointer m_protocolsModel;
+ QSharedPointer m_sitesModel;
+ QSharedPointer m_appSplitTunnelingModel;
+ QSharedPointer m_clientManagementModel;
+ QSharedPointer m_apiServicesModel;
+ QSharedPointer m_apiCountryModel;
+
+ QScopedPointer m_openVpnConfigModel;
+ QScopedPointer m_shadowSocksConfigModel;
+ QScopedPointer m_cloakConfigModel;
+ QScopedPointer m_xrayConfigModel;
+ QScopedPointer m_wireGuardConfigModel;
+ QScopedPointer m_awgConfigModel;
+#ifdef Q_OS_WINDOWS
+ QScopedPointer m_ikev2ConfigModel;
+#endif
+
+ QScopedPointer m_sftpConfigModel;
+ QScopedPointer m_socks5ConfigModel;
+
QSharedPointer m_vpnConnection;
QThread m_vpnConnectionThread;
+#ifndef Q_OS_ANDROID
+ QScopedPointer m_notificationHandler;
+#endif
+
+ QScopedPointer m_connectionController;
+ QScopedPointer m_focusController;
+ QScopedPointer m_pageController;
+ QScopedPointer m_installController;
+ QScopedPointer m_importController;
+ QScopedPointer m_exportController;
+ QScopedPointer m_settingsController;
+ QScopedPointer m_sitesController;
+ QScopedPointer m_systemController;
+ QScopedPointer m_appSplitTunnelingController;
QNetworkAccessManager *m_nam;
+
+ QMetaObject::Connection m_reloadConfigErrorOccurredConnection;
};
#endif // AMNEZIA_APPLICATION_H
diff --git a/client/android/AndroidManifest.xml b/client/android/AndroidManifest.xml
index b28f754b..96f60f53 100644
--- a/client/android/AndroidManifest.xml
+++ b/client/android/AndroidManifest.xml
@@ -11,7 +11,7 @@
-
+