mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-23 02:00:20 +07:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7c560d709b | |||
| ac234b77e2 | |||
| d34cb8898f | |||
| 13aadbda64 | |||
| c7c7c8eb01 | |||
| b1e5bba33f | |||
| 474e7c6d62 | |||
| 794ec921b8 | |||
| b674240362 | |||
| a768c7c451 | |||
| 28d2a4ec2c | |||
| 9f1210d18f | |||
| 3012559627 | |||
| b3ed57aee7 | |||
| 89d0a8107d | |||
| 6c0b71bd1b | |||
| 61abf74b2d | |||
| 21fdf02921 | |||
| 7a245d80ee | |||
| da85922f23 | |||
| a5356b6319 | |||
| 3828891b9b | |||
| 15d866ce04 | |||
| 560eb3d620 | |||
| ac894254cc | |||
| 17e3fbde25 | |||
| ee11a8410c | |||
| ff5c51cfd9 | |||
| b3943ae5e3 | |||
| a32952fde6 | |||
| 9c4ee4014d | |||
| dc9069f1f4 | |||
| e402cacc05 | |||
| a98cd248d6 | |||
| 00fbfb6a01 | |||
| 86c31c3766 | |||
| 698cfe910c | |||
| 16db23c159 | |||
| b05a5ee1c6 | |||
| 8cb298937f | |||
| 68fe20ddf6 | |||
| fab167bb34 | |||
| f640d4b5f5 | |||
| 074562b141 | |||
| fd030a5fd4 | |||
| 82fa6b13c6 | |||
| bf16298c40 | |||
| bcebb0a2b5 | |||
| b27442cf74 | |||
| 92fbbd4812 | |||
| 321ed810e3 | |||
| 17ff530683 | |||
| 2b413736a4 | |||
| 0b8f3c9d9d |
@@ -14,8 +14,8 @@ jobs:
|
|||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 6.5.1
|
QT_VERSION: 6.6.2
|
||||||
QIF_VERSION: 4.6
|
QIF_VERSION: 4.7
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Install Qt'
|
- name: 'Install Qt'
|
||||||
@@ -72,8 +72,8 @@ jobs:
|
|||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 6.5.1
|
QT_VERSION: 6.6.2
|
||||||
QIF_VERSION: 4.6
|
QIF_VERSION: 4.7
|
||||||
BUILD_ARCH: 64
|
BUILD_ARCH: 64
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
@@ -134,7 +134,7 @@ jobs:
|
|||||||
runs-on: macos-13
|
runs-on: macos-13
|
||||||
|
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 6.5.2
|
QT_VERSION: 6.6.2
|
||||||
CC: cc
|
CC: cc
|
||||||
CXX: c++
|
CXX: c++
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
# Keep compat with MacOS 10.15 aka Catalina by Qt 6.4
|
# Keep compat with MacOS 10.15 aka Catalina by Qt 6.4
|
||||||
QT_VERSION: 6.4.3
|
QT_VERSION: 6.4.3
|
||||||
QIF_VERSION: 4.6
|
QIF_VERSION: 4.7
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: 'Setup xcode'
|
- name: 'Setup xcode'
|
||||||
@@ -286,7 +286,7 @@ jobs:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
ANDROID_BUILD_PLATFORM: android-34
|
ANDROID_BUILD_PLATFORM: android-34
|
||||||
QT_VERSION: 6.6.1
|
QT_VERSION: 6.6.2
|
||||||
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
|
QT_MODULES: 'qtremoteobjects qt5compat qtimageformats qtshadertools'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -131,3 +131,6 @@ client/3rd/ShadowSocks/ss_ios.xcconfig
|
|||||||
|
|
||||||
# UML generated pics
|
# UML generated pics
|
||||||
out/
|
out/
|
||||||
|
|
||||||
|
# CMake files
|
||||||
|
CMakeFiles/
|
||||||
+2
-2
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
|||||||
|
|
||||||
set(PROJECT AmneziaVPN)
|
set(PROJECT AmneziaVPN)
|
||||||
|
|
||||||
project(${PROJECT} VERSION 4.3.0.0
|
project(${PROJECT} VERSION 4.4.0.0
|
||||||
DESCRIPTION "AmneziaVPN"
|
DESCRIPTION "AmneziaVPN"
|
||||||
HOMEPAGE_URL "https://amnezia.org/"
|
HOMEPAGE_URL "https://amnezia.org/"
|
||||||
)
|
)
|
||||||
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
|
|||||||
set(RELEASE_DATE "${CURRENT_DATE}")
|
set(RELEASE_DATE "${CURRENT_DATE}")
|
||||||
|
|
||||||
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
|
||||||
set(APP_ANDROID_VERSION_CODE 44)
|
set(APP_ANDROID_VERSION_CODE 46)
|
||||||
|
|
||||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
set(MZ_PLATFORM_NAME "linux")
|
set(MZ_PLATFORM_NAME "linux")
|
||||||
|
|||||||
+1
-1
Submodule client/3rd-prebuilt updated: e568e7d0e8...2fa21880b9
Vendored
+1
-1
Submodule client/3rd/OpenVPNAdapter updated: f95f0b2b56...6f71d0743d
@@ -15,6 +15,15 @@ set(PACKAGES
|
|||||||
Core5Compat Concurrent LinguistTools
|
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)
|
if(IOS)
|
||||||
set(PACKAGES ${PACKAGES} Multimedia)
|
set(PACKAGES ${PACKAGES} Multimedia)
|
||||||
endif()
|
endif()
|
||||||
@@ -57,6 +66,7 @@ set(AMNEZIAVPN_TS_FILES
|
|||||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts
|
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ru.ts
|
||||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_zh_CN.ts
|
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_zh_CN.ts
|
||||||
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_fa_IR.ts
|
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_fa_IR.ts
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/translations/amneziavpn_ar.ts
|
||||||
)
|
)
|
||||||
|
|
||||||
file(GLOB_RECURSE AMNEZIAVPN_TS_SOURCES *.qrc *.cpp *.h *.ui)
|
file(GLOB_RECURSE AMNEZIAVPN_TS_SOURCES *.qrc *.cpp *.h *.ui)
|
||||||
|
|||||||
@@ -286,13 +286,16 @@ void AmneziaApplication::initModels()
|
|||||||
m_containersModel.reset(new ContainersModel(this));
|
m_containersModel.reset(new ContainersModel(this));
|
||||||
m_engine->rootContext()->setContextProperty("ContainersModel", m_containersModel.get());
|
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_serversModel.reset(new ServersModel(m_settings, this));
|
||||||
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
|
m_engine->rootContext()->setContextProperty("ServersModel", m_serversModel.get());
|
||||||
connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(),
|
connect(m_serversModel.get(), &ServersModel::containersUpdated, m_containersModel.get(),
|
||||||
&ContainersModel::updateModel);
|
&ContainersModel::updateModel);
|
||||||
connect(m_serversModel.get(), &ServersModel::defaultContainerChanged, m_containersModel.get(),
|
connect(m_serversModel.get(), &ServersModel::defaultServerContainersUpdated, m_defaultServerContainersModel.get(),
|
||||||
&ContainersModel::setDefaultContainer);
|
&ContainersModel::updateModel);
|
||||||
m_containersModel->setDefaultContainer(m_serversModel->getDefaultContainer()); // make better?
|
m_serversModel->resetModel();
|
||||||
|
|
||||||
m_languageModel.reset(new LanguageModel(m_settings, this));
|
m_languageModel.reset(new LanguageModel(m_settings, this));
|
||||||
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
|
m_engine->rootContext()->setContextProperty("LanguageModel", m_languageModel.get());
|
||||||
@@ -336,7 +339,7 @@ void AmneziaApplication::initModels()
|
|||||||
connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this,
|
connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this,
|
||||||
[this](const QString &clientId, const QString &clientName, const DockerContainer container,
|
[this](const QString &clientId, const QString &clientName, const DockerContainer container,
|
||||||
ServerCredentials credentials) {
|
ServerCredentials credentials) {
|
||||||
m_serversModel->reloadContainerConfig();
|
m_serversModel->reloadDefaultServerContainerConfig();
|
||||||
m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
|
m_clientManagementModel->appendClient(clientId, clientName, container, credentials);
|
||||||
emit m_configurator->clientModelUpdated();
|
emit m_configurator->clientModelUpdated();
|
||||||
});
|
});
|
||||||
@@ -388,7 +391,13 @@ void AmneziaApplication::initControllers()
|
|||||||
m_engine->rootContext()->setContextProperty("ApiController", m_apiController.get());
|
m_engine->rootContext()->setContextProperty("ApiController", m_apiController.get());
|
||||||
connect(m_apiController.get(), &ApiController::updateStarted, this,
|
connect(m_apiController.get(), &ApiController::updateStarted, this,
|
||||||
[this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Connecting); });
|
[this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Connecting); });
|
||||||
connect(m_apiController.get(), &ApiController::errorOccurred, this,
|
connect(m_apiController.get(), &ApiController::errorOccurred, this, [this](const QString &errorMessage) {
|
||||||
[this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); });
|
if (m_connectionController->isConnectionInProgress()) {
|
||||||
connect(m_apiController.get(), &ApiController::updateFinished, m_connectionController.get(), &ConnectionController::toggleConnection);
|
emit m_pageController->showErrorMessage(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected);
|
||||||
|
});
|
||||||
|
connect(m_apiController.get(), &ApiController::updateFinished, m_connectionController.get(),
|
||||||
|
&ConnectionController::toggleConnection);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ private:
|
|||||||
QCommandLineParser m_parser;
|
QCommandLineParser m_parser;
|
||||||
|
|
||||||
QSharedPointer<ContainersModel> m_containersModel;
|
QSharedPointer<ContainersModel> m_containersModel;
|
||||||
|
QSharedPointer<ContainersModel> m_defaultServerContainersModel;
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
QSharedPointer<LanguageModel> m_languageModel;
|
QSharedPointer<LanguageModel> m_languageModel;
|
||||||
QSharedPointer<ProtocolsModel> m_protocolsModel;
|
QSharedPointer<ProtocolsModel> m_protocolsModel;
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
|
||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
|
|
||||||
<!-- Enable when VPN-per-app mode will be implemented -->
|
<!-- Enable when VPN-per-app mode will be implemented -->
|
||||||
@@ -137,14 +137,13 @@
|
|||||||
android:name=".AmneziaVpnService"
|
android:name=".AmneziaVpnService"
|
||||||
android:process=":amneziaVpnService"
|
android:process=":amneziaVpnService"
|
||||||
android:permission="android.permission.BIND_VPN_SERVICE"
|
android:permission="android.permission.BIND_VPN_SERVICE"
|
||||||
android:foregroundServiceType="specialUse"
|
android:foregroundServiceType="systemExempted"
|
||||||
android:exported="false">
|
android:exported="false"
|
||||||
|
tools:ignore="ForegroundServicePermission">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.net.VpnService" />
|
<action android:name="android.net.VpnService" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<property android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE" android:value="vpn" />
|
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import android.app.Notification
|
|||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST
|
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MANIFEST
|
||||||
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
import android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED
|
||||||
import android.net.VpnService
|
import android.net.VpnService
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
@@ -156,7 +156,7 @@ class AmneziaVpnService : VpnService() {
|
|||||||
*/
|
*/
|
||||||
private val foregroundServiceTypeCompat
|
private val foregroundServiceTypeCompat
|
||||||
get() = when {
|
get() = when {
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> FOREGROUND_SERVICE_TYPE_SPECIAL_USE
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE -> FOREGROUND_SERVICE_TYPE_SYSTEM_EXEMPTED
|
||||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> FOREGROUND_SERVICE_TYPE_MANIFEST
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> FOREGROUND_SERVICE_TYPE_MANIFEST
|
||||||
else -> 0
|
else -> 0
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -1,7 +1,5 @@
|
|||||||
package com.wireguard.android.backend
|
package org.amnezia.vpn.protocol.wireguard
|
||||||
|
|
||||||
// TODO: Refactor Amnezia wireguard project by changing the JNI method names
|
|
||||||
// to move this object to 'org.amnezia.vpn.protocol.wireguard.backend' package
|
|
||||||
object GoBackend {
|
object GoBackend {
|
||||||
external fun wgGetConfig(handle: Int): String?
|
external fun wgGetConfig(handle: Int): String?
|
||||||
external fun wgGetSocketV4(handle: Int): Int
|
external fun wgGetSocketV4(handle: Int): Int
|
||||||
-1
@@ -3,7 +3,6 @@ package org.amnezia.vpn.protocol.wireguard
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.VpnService.Builder
|
import android.net.VpnService.Builder
|
||||||
import java.util.TreeMap
|
import java.util.TreeMap
|
||||||
import com.wireguard.android.backend.GoBackend
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import org.amnezia.vpn.protocol.Protocol
|
import org.amnezia.vpn.protocol.Protocol
|
||||||
import org.amnezia.vpn.protocol.ProtocolState
|
import org.amnezia.vpn.protocol.ProtocolState
|
||||||
@@ -42,9 +42,9 @@ set(SOURCES ${SOURCES}
|
|||||||
|
|
||||||
foreach(abi IN ITEMS ${QT_ANDROID_ABIS})
|
foreach(abi IN ITEMS ${QT_ANDROID_ABIS})
|
||||||
set_property(TARGET ${PROJECT} PROPERTY QT_ANDROID_EXTRA_LIBS
|
set_property(TARGET ${PROJECT} PROPERTY QT_ANDROID_EXTRA_LIBS
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/android/${abi}/libwg.so
|
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/amneziawg/android/${abi}/libwg.so
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/android/${abi}/libwg-go.so
|
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/amneziawg/android/${abi}/libwg-go.so
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/android/${abi}/libwg-quick.so
|
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/amneziawg/android/${abi}/libwg-quick.so
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/shadowsocks/android/${abi}/libredsocks.so
|
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/shadowsocks/android/${abi}/libredsocks.so
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/shadowsocks/android/${abi}/libsslocal.so
|
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/shadowsocks/android/${abi}/libsslocal.so
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/shadowsocks/android/${abi}/libtun2socks.so
|
${CMAKE_CURRENT_SOURCE_DIR}/3rd-prebuilt/3rd-prebuilt/shadowsocks/android/${abi}/libtun2socks.so
|
||||||
|
|||||||
@@ -211,13 +211,7 @@ ErrorCode ServerController::uploadFileToHost(const ServerCredentials &credential
|
|||||||
localFile.write(data);
|
localFile.write(data);
|
||||||
localFile.close();
|
localFile.close();
|
||||||
|
|
||||||
#ifdef Q_OS_WINDOWS
|
error = m_sshClient.sftpFileCopy(overwriteMode, localFile.fileName(), remotePath, "non_desc");
|
||||||
error = m_sshClient.sftpFileCopy(overwriteMode, localFile.fileName().toLocal8Bit().toStdString(), remotePath.toStdString(),
|
|
||||||
"non_desc");
|
|
||||||
#else
|
|
||||||
error = m_sshClient.sftpFileCopy(overwriteMode, localFile.fileName().toStdString(), remotePath.toStdString(),
|
|
||||||
"non_desc");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (error != ErrorCode::NoError) {
|
if (error != ErrorCode::NoError) {
|
||||||
return error;
|
return error;
|
||||||
|
|||||||
+13
-15
@@ -222,7 +222,7 @@ namespace libssh {
|
|||||||
return fromLibsshErrorCode();
|
return fromLibsshErrorCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorCode Client::sftpFileCopy(const SftpOverwriteMode overwriteMode, const std::string& localPath, const std::string& remotePath, const std::string& fileDesc)
|
ErrorCode Client::sftpFileCopy(const SftpOverwriteMode overwriteMode, const QString& localPath, const QString& remotePath, const QString &fileDesc)
|
||||||
{
|
{
|
||||||
m_sftpSession = sftp_new(m_session);
|
m_sftpSession = sftp_new(m_session);
|
||||||
|
|
||||||
@@ -245,40 +245,38 @@ namespace libssh {
|
|||||||
const size_t bufferSize = 16384;
|
const size_t bufferSize = 16384;
|
||||||
char buffer[bufferSize];
|
char buffer[bufferSize];
|
||||||
|
|
||||||
file = sftp_open(m_sftpSession, remotePath.c_str(), accessType, S_IRWXU);
|
file = sftp_open(m_sftpSession, remotePath.toStdString().c_str(), accessType, S_IRWXU);
|
||||||
|
|
||||||
if (file == nullptr) {
|
if (file == nullptr) {
|
||||||
return closeSftpSession();
|
return closeSftpSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
int localFileSize = std::filesystem::file_size(localPath);
|
int localFileSize = QFileInfo(localPath).size();
|
||||||
int chunksCount = localFileSize / (bufferSize);
|
int chunksCount = localFileSize / (bufferSize);
|
||||||
|
|
||||||
std::ifstream fin(localPath, std::ios::binary | std::ios::in);
|
QFile fin(localPath);
|
||||||
|
|
||||||
if (fin.is_open()) {
|
if (fin.open(QIODevice::ReadOnly)) {
|
||||||
for (int currentChunkId = 0; currentChunkId < chunksCount; currentChunkId++) {
|
for (int currentChunkId = 0; currentChunkId < chunksCount; currentChunkId++) {
|
||||||
fin.read(buffer, bufferSize);
|
QByteArray chunk = fin.read(bufferSize);
|
||||||
|
if (chunk.size() != bufferSize) return ErrorCode::SshSftpEofError;
|
||||||
|
|
||||||
int bytesWritten = sftp_write(file, buffer, bufferSize);
|
int bytesWritten = sftp_write(file, chunk.data(), chunk.size());
|
||||||
|
|
||||||
std::string chunk(buffer, bufferSize);
|
if (bytesWritten != chunk.size()) {
|
||||||
|
|
||||||
if (bytesWritten != bufferSize) {
|
|
||||||
fin.close();
|
fin.close();
|
||||||
sftp_close(file);
|
sftp_close(file);
|
||||||
return closeSftpSession();
|
return closeSftpSession();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int lastChunkSize = localFileSize % (bufferSize);
|
int lastChunkSize = localFileSize % bufferSize;
|
||||||
|
|
||||||
if (lastChunkSize != 0) {
|
if (lastChunkSize != 0) {
|
||||||
fin.read(buffer, lastChunkSize);
|
QByteArray lastChunk = fin.read(lastChunkSize);
|
||||||
|
if (lastChunk.size() != lastChunkSize) return ErrorCode::SshSftpEofError;
|
||||||
|
|
||||||
std::string chunk(buffer, lastChunkSize);
|
int bytesWritten = sftp_write(file, lastChunk.data(), lastChunkSize);
|
||||||
|
|
||||||
int bytesWritten = sftp_write(file, buffer, lastChunkSize);
|
|
||||||
|
|
||||||
if (bytesWritten != lastChunkSize) {
|
if (bytesWritten != lastChunkSize) {
|
||||||
fin.close();
|
fin.close();
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ namespace libssh {
|
|||||||
const std::function<ErrorCode (const QString &, Client &)> &cbReadStdErr);
|
const std::function<ErrorCode (const QString &, Client &)> &cbReadStdErr);
|
||||||
ErrorCode writeResponse(const QString &data);
|
ErrorCode writeResponse(const QString &data);
|
||||||
ErrorCode sftpFileCopy(const SftpOverwriteMode overwriteMode,
|
ErrorCode sftpFileCopy(const SftpOverwriteMode overwriteMode,
|
||||||
const std::string& localPath,
|
const QString &localPath,
|
||||||
const std::string& remotePath,
|
const QString &remotePath,
|
||||||
const std::string& fileDesc);
|
const QString& fileDesc);
|
||||||
ErrorCode getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey, const std::function<QString()> &passphraseCallback);
|
ErrorCode getDecryptedPrivateKey(const ServerCredentials &credentials, QString &decryptedPrivateKey, const std::function<QString()> &passphraseCallback);
|
||||||
private:
|
private:
|
||||||
ErrorCode closeChannel();
|
ErrorCode closeChannel();
|
||||||
|
|||||||
@@ -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 |
@@ -85,6 +85,7 @@ target_sources(networkextension PRIVATE
|
|||||||
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift
|
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPNAdapterDelegate.swift
|
||||||
|
${CLIENT_ROOT_DIR}/platforms/ios/WGConfig.swift
|
||||||
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
|
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -124,7 +124,10 @@ void LocalSocketController::activate(const QJsonObject &rawConfig) {
|
|||||||
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
|
// json.insert("hopindex", QJsonValue((double)hop.m_hopindex));
|
||||||
json.insert("privateKey", wgConfig.value(amnezia::config_key::client_priv_key));
|
json.insert("privateKey", wgConfig.value(amnezia::config_key::client_priv_key));
|
||||||
json.insert("deviceIpv4Address", wgConfig.value(amnezia::config_key::client_ip));
|
json.insert("deviceIpv4Address", wgConfig.value(amnezia::config_key::client_ip));
|
||||||
|
// todo review wg ipv6
|
||||||
|
#ifndef Q_OS_WINDOWS
|
||||||
json.insert("deviceIpv6Address", "dead::1");
|
json.insert("deviceIpv6Address", "dead::1");
|
||||||
|
#endif
|
||||||
json.insert("serverPublicKey", wgConfig.value(amnezia::config_key::server_pub_key));
|
json.insert("serverPublicKey", wgConfig.value(amnezia::config_key::server_pub_key));
|
||||||
json.insert("serverPskKey", wgConfig.value(amnezia::config_key::psk_key));
|
json.insert("serverPskKey", wgConfig.value(amnezia::config_key::psk_key));
|
||||||
json.insert("serverIpv4AddrIn", wgConfig.value(amnezia::config_key::hostName));
|
json.insert("serverIpv4AddrIn", wgConfig.value(amnezia::config_key::hostName));
|
||||||
|
|||||||
@@ -59,10 +59,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
var stopHandler: (() -> Void)?
|
var stopHandler: (() -> Void)?
|
||||||
var protoType: TunnelProtoType = .none
|
var protoType: TunnelProtoType = .none
|
||||||
|
|
||||||
override init() {
|
|
||||||
super.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
|
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)? = nil) {
|
||||||
let tmpStr = String(data: messageData, encoding: .utf8)!
|
let tmpStr = String(data: messageData, encoding: .utf8)!
|
||||||
wg_log(.error, message: tmpStr)
|
wg_log(.error, message: tmpStr)
|
||||||
@@ -71,7 +67,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let completionHandler = completionHandler else {
|
guard let completionHandler else {
|
||||||
log(.error, message: "Missing message completion handler")
|
log(.error, message: "Missing message completion handler")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -179,14 +175,16 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let wgConfigStr = String(data: wgConfig, encoding: .utf8)!
|
guard let wgConfigStr = try? JSONDecoder().decode(WGConfig.self, from: wgConfig).str,
|
||||||
|
let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr)
|
||||||
guard let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: wgConfigStr) else {
|
else {
|
||||||
wg_log(.error, message: "Can't parse WireGuard config")
|
wg_log(.error, message: "Can't parse WireGuard config")
|
||||||
completionHandler(nil)
|
completionHandler(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log(.info, message: "wgConfig: \(wgConfigStr.replacingOccurrences(of: "\n", with: " "))")
|
||||||
|
|
||||||
if tunnelConfiguration.peers.first!.allowedIPs
|
if tunnelConfiguration.peers.first!.allowedIPs
|
||||||
.map({ $0.stringRepresentation })
|
.map({ $0.stringRepresentation })
|
||||||
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
.joined(separator: ", ") == "0.0.0.0/0, ::/0" {
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
struct WGConfigData: Decodable {
|
||||||
|
let initPacketMagicHeader, responsePacketMagicHeader: String?
|
||||||
|
let underloadPacketMagicHeader, transportPacketMagicHeader: String?
|
||||||
|
let junkPacketCount, junkPacketMinSize, junkPacketMaxSize: String?
|
||||||
|
let initPacketJunkSize, responsePacketJunkSize: String?
|
||||||
|
|
||||||
|
var settings: String {
|
||||||
|
junkPacketCount == nil ? "" :
|
||||||
|
"""
|
||||||
|
Jc = \(junkPacketCount!)
|
||||||
|
Jmin = \(junkPacketMinSize!)
|
||||||
|
Jmax = \(junkPacketMaxSize!)
|
||||||
|
S1 = \(initPacketJunkSize!)
|
||||||
|
S2 = \(responsePacketJunkSize!)
|
||||||
|
H1 = \(initPacketMagicHeader!)
|
||||||
|
H2 = \(responsePacketMagicHeader!)
|
||||||
|
H3 = \(underloadPacketMagicHeader!)
|
||||||
|
H4 = \(transportPacketMagicHeader!)
|
||||||
|
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
|
||||||
|
let clientIP: String
|
||||||
|
let clientPrivateKey: String
|
||||||
|
let clientPublicKey: String
|
||||||
|
let serverPublicKey: String
|
||||||
|
let presharedKey: String
|
||||||
|
let hostName: String
|
||||||
|
let port: Int
|
||||||
|
|
||||||
|
var allowedIPs: [String]
|
||||||
|
var persistentKeepAlive: String
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
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"
|
||||||
|
case clientPublicKey = "client_pub_key"
|
||||||
|
case serverPublicKey = "server_pub_key"
|
||||||
|
case presharedKey = "psk_key"
|
||||||
|
|
||||||
|
case allowedIPs = "allowed_ips"
|
||||||
|
case persistentKeepAlive = "persistent_keep_alive"
|
||||||
|
case hostName
|
||||||
|
case port
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
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)
|
||||||
|
self.serverPublicKey = try container.decode(String.self, forKey: .serverPublicKey)
|
||||||
|
self.presharedKey = try container.decode(String.self, forKey: .presharedKey)
|
||||||
|
self.allowedIPs = try container.decodeIfPresent([String].self, forKey: .allowedIPs) ?? ["0.0.0.0/0", "::/0"]
|
||||||
|
self.persistentKeepAlive = try container.decodeIfPresent(String.self, forKey: .persistentKeepAlive) ?? "25"
|
||||||
|
self.hostName = try container.decode(String.self, forKey: .hostName)
|
||||||
|
self.port = try container.decode(Int.self, forKey: .port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WGConfig: Decodable {
|
||||||
|
let data: WGConfigData
|
||||||
|
let configVersion: Int
|
||||||
|
let description: String
|
||||||
|
let dns1: String
|
||||||
|
let dns2: String
|
||||||
|
let hostName: String
|
||||||
|
let `protocol`: String
|
||||||
|
let splitTunnelSites: [String]
|
||||||
|
let splitTunnelType: Int
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case awgConfigData = "awg_config_data", wgConfigData = "wireguard_config_data"
|
||||||
|
case configData
|
||||||
|
case configVersion = "config_version"
|
||||||
|
case description
|
||||||
|
case dns1
|
||||||
|
case dns2
|
||||||
|
case hostName
|
||||||
|
case `protocol`
|
||||||
|
case splitTunnelSites
|
||||||
|
case splitTunnelType
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
|
||||||
|
if container.contains(.awgConfigData) {
|
||||||
|
self.data = try container.decode(WGConfigData.self, forKey: .awgConfigData)
|
||||||
|
} else {
|
||||||
|
self.data = try container.decode(WGConfigData.self, forKey: .wgConfigData)
|
||||||
|
}
|
||||||
|
|
||||||
|
self.configVersion = try container.decode(Int.self, forKey: .configVersion)
|
||||||
|
self.description = try container.decode(String.self, forKey: .description)
|
||||||
|
self.dns1 = try container.decode(String.self, forKey: .dns1)
|
||||||
|
self.dns2 = try container.decode(String.self, forKey: .dns2)
|
||||||
|
self.hostName = try container.decode(String.self, forKey: .hostName)
|
||||||
|
self.protocol = try container.decode(String.self, forKey: .protocol)
|
||||||
|
self.splitTunnelSites = try container.decode([String].self, forKey: .splitTunnelSites)
|
||||||
|
self.splitTunnelType = try container.decode(Int.self, forKey: .splitTunnelType)
|
||||||
|
}
|
||||||
|
|
||||||
|
var str: String {
|
||||||
|
"""
|
||||||
|
[Interface]
|
||||||
|
Address = \(data.clientIP)/32
|
||||||
|
DNS = \(dns1), \(dns2)
|
||||||
|
PrivateKey = \(data.clientPrivateKey)
|
||||||
|
\(data.settings)
|
||||||
|
[Peer]
|
||||||
|
PublicKey = \(data.serverPublicKey)
|
||||||
|
PresharedKey = \(data.presharedKey)
|
||||||
|
AllowedIPs = \(data.allowedIPs.joined(separator: ", "))
|
||||||
|
Endpoint = \(data.hostName):\(data.port)
|
||||||
|
PersistentKeepalive = \(data.persistentKeepAlive)
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -400,9 +400,10 @@ bool IosController::setupCloak()
|
|||||||
bool IosController::setupWireGuard()
|
bool IosController::setupWireGuard()
|
||||||
{
|
{
|
||||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::WireGuard)].toObject();
|
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::WireGuard)].toObject();
|
||||||
|
|
||||||
QString wgConfig = config[config_key::config].toString();
|
|
||||||
|
|
||||||
|
QJsonDocument doc(m_rawConfig);
|
||||||
|
QString wgConfig(doc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
return startWireGuard(wgConfig);
|
return startWireGuard(wgConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,8 +411,9 @@ bool IosController::setupAwg()
|
|||||||
{
|
{
|
||||||
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
|
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
|
||||||
|
|
||||||
QString wgConfig = config[config_key::config].toString();
|
QJsonDocument doc(m_rawConfig);
|
||||||
|
QString wgConfig(doc.toJson(QJsonDocument::Compact));
|
||||||
|
|
||||||
return startWireGuard(wgConfig);
|
return startWireGuard(wgConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,7 +160,6 @@
|
|||||||
<file>ui/qml/Components/SettingsContainersListView.qml</file>
|
<file>ui/qml/Components/SettingsContainersListView.qml</file>
|
||||||
<file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file>
|
<file>ui/qml/Controls2/TextTypes/ListItemTitleType.qml</file>
|
||||||
<file>ui/qml/Controls2/DividerType.qml</file>
|
<file>ui/qml/Controls2/DividerType.qml</file>
|
||||||
<file>ui/qml/Controls2/DrawerType.qml</file>
|
|
||||||
<file>ui/qml/Controls2/StackViewType.qml</file>
|
<file>ui/qml/Controls2/StackViewType.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSettings.qml</file>
|
<file>ui/qml/Pages2/PageSettings.qml</file>
|
||||||
<file>images/controls/amnezia.svg</file>
|
<file>images/controls/amnezia.svg</file>
|
||||||
@@ -225,5 +224,8 @@
|
|||||||
<file>ui/qml/Pages2/PageShareFullAccess.qml</file>
|
<file>ui/qml/Pages2/PageShareFullAccess.qml</file>
|
||||||
<file>images/controls/close.svg</file>
|
<file>images/controls/close.svg</file>
|
||||||
<file>images/controls/search.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>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
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
File diff suppressed because it is too large
Load Diff
@@ -70,14 +70,17 @@ QJsonObject ApiController::fillApiPayload(const QString &protocol, const ApiCont
|
|||||||
void ApiController::updateServerConfigFromApi()
|
void ApiController::updateServerConfigFromApi()
|
||||||
{
|
{
|
||||||
QtConcurrent::run([this]() {
|
QtConcurrent::run([this]() {
|
||||||
|
if (m_isConfigUpdateStarted) {
|
||||||
|
emit updateFinished(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto serverConfig = m_serversModel->getDefaultServerConfig();
|
auto serverConfig = m_serversModel->getDefaultServerConfig();
|
||||||
auto containerConfig = serverConfig.value(config_key::containers).toArray();
|
auto containerConfig = serverConfig.value(config_key::containers).toArray();
|
||||||
|
|
||||||
bool isConfigUpdateStarted = false;
|
|
||||||
|
|
||||||
if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) {
|
if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) {
|
||||||
emit updateStarted();
|
emit updateStarted();
|
||||||
isConfigUpdateStarted = true;
|
m_isConfigUpdateStarted = true;
|
||||||
|
|
||||||
QNetworkAccessManager manager;
|
QNetworkAccessManager manager;
|
||||||
|
|
||||||
@@ -110,6 +113,12 @@ void ApiController::updateServerConfigFromApi()
|
|||||||
QByteArray ba = QByteArray::fromBase64(data.toUtf8(),
|
QByteArray ba = QByteArray::fromBase64(data.toUtf8(),
|
||||||
QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||||
|
|
||||||
|
if (ba.isEmpty()) {
|
||||||
|
emit errorOccurred(errorString(ApiConfigDownloadError));
|
||||||
|
m_isConfigUpdateStarted = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray ba_uncompressed = qUncompress(ba);
|
QByteArray ba_uncompressed = qUncompress(ba);
|
||||||
if (!ba_uncompressed.isEmpty()) {
|
if (!ba_uncompressed.isEmpty()) {
|
||||||
ba = ba_uncompressed;
|
ba = ba_uncompressed;
|
||||||
@@ -127,17 +136,18 @@ void ApiController::updateServerConfigFromApi()
|
|||||||
|
|
||||||
auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString();
|
auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString();
|
||||||
serverConfig.insert(config_key::defaultContainer, defaultContainer);
|
serverConfig.insert(config_key::defaultContainer, defaultContainer);
|
||||||
m_serversModel->editServer(serverConfig);
|
m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex());
|
||||||
emit m_serversModel->defaultContainerChanged(ContainerProps::containerFromString(defaultContainer));
|
|
||||||
} else {
|
} else {
|
||||||
qDebug() << reply->error();
|
qDebug() << reply->error();
|
||||||
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
|
||||||
emit errorOccurred(errorString(ApiConfigDownloadError));
|
emit errorOccurred(errorString(ApiConfigDownloadError));
|
||||||
|
m_isConfigUpdateStarted = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit updateFinished(isConfigUpdateStarted);
|
emit updateFinished(m_isConfigUpdateStarted);
|
||||||
|
m_isConfigUpdateStarted = false;
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -153,5 +163,5 @@ void ApiController::clearApiConfig()
|
|||||||
|
|
||||||
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
||||||
|
|
||||||
m_serversModel->editServer(serverConfig);
|
m_serversModel->editServer(serverConfig, m_serversModel->getDefaultServerIndex());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ private:
|
|||||||
|
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
QSharedPointer<ContainersModel> m_containersModel;
|
QSharedPointer<ContainersModel> m_containersModel;
|
||||||
|
|
||||||
|
bool m_isConfigUpdateStarted = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // APICONTROLLER_H
|
#endif // APICONTROLLER_H
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ void ConnectionController::openConnection()
|
|||||||
int serverIndex = m_serversModel->getDefaultServerIndex();
|
int serverIndex = m_serversModel->getDefaultServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = m_containersModel->getDefaultContainer();
|
DockerContainer container = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
|
||||||
const QJsonObject &containerConfig = m_containersModel->getContainerConfig(container);
|
const QJsonObject &containerConfig = m_containersModel->getContainerConfig(container);
|
||||||
|
|
||||||
if (container == DockerContainer::None) {
|
if (container == DockerContainer::None) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include "configurators/awg_configurator.h"
|
||||||
#include "configurators/cloak_configurator.h"
|
#include "configurators/cloak_configurator.h"
|
||||||
#include "configurators/openvpn_configurator.h"
|
#include "configurators/openvpn_configurator.h"
|
||||||
#include "configurators/shadowsocks_configurator.h"
|
#include "configurators/shadowsocks_configurator.h"
|
||||||
@@ -45,7 +46,7 @@ void ExportController::generateFullAccessConfig()
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
QJsonObject config = m_settings->server(serverIndex);
|
QJsonObject config = m_settings->server(serverIndex);
|
||||||
|
|
||||||
QJsonArray containers = config.value(config_key::containers).toArray();
|
QJsonArray containers = config.value(config_key::containers).toArray();
|
||||||
@@ -99,7 +100,7 @@ void ExportController::generateConnectionConfig(const QString &clientName)
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -155,7 +156,7 @@ void ExportController::generateOpenVpnConfig(const QString &clientName)
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -193,7 +194,7 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -228,11 +229,50 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
|
|||||||
emit exportConfigChanged();
|
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()
|
void ExportController::generateShadowSocksConfig()
|
||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
||||||
@@ -268,7 +308,7 @@ void ExportController::generateCloakConfig()
|
|||||||
{
|
{
|
||||||
clearPreviousConfig();
|
clearPreviousConfig();
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex);
|
||||||
|
|
||||||
DockerContainer container = static_cast<DockerContainer>(m_containersModel->getCurrentlyProcessedContainerIndex());
|
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)
|
void ExportController::revokeConfig(const int row, const DockerContainer container, ServerCredentials credentials)
|
||||||
{
|
{
|
||||||
ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials,
|
ErrorCode errorCode = m_clientManagementModel->revokeClient(row, container, credentials,
|
||||||
m_serversModel->getCurrentlyProcessedServerIndex());
|
m_serversModel->getProcessedServerIndex());
|
||||||
if (errorCode != ErrorCode::NoError) {
|
if (errorCode != ErrorCode::NoError) {
|
||||||
emit exportErrorOccurred(errorString(errorCode));
|
emit exportErrorOccurred(errorString(errorCode));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public slots:
|
|||||||
void generateConnectionConfig(const QString &clientName);
|
void generateConnectionConfig(const QString &clientName);
|
||||||
void generateOpenVpnConfig(const QString &clientName);
|
void generateOpenVpnConfig(const QString &clientName);
|
||||||
void generateWireGuardConfig(const QString &clientName);
|
void generateWireGuardConfig(const QString &clientName);
|
||||||
|
void generateAwgConfig(const QString &clientName);
|
||||||
void generateShadowSocksConfig();
|
void generateShadowSocksConfig();
|
||||||
void generateCloakConfig();
|
void generateCloakConfig();
|
||||||
|
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ void InstallController::installServer(DockerContainer container, QJsonObject &co
|
|||||||
|
|
||||||
void InstallController::installContainer(DockerContainer container, QJsonObject &config)
|
void InstallController::installContainer(DockerContainer container, QJsonObject &config)
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials serverCredentials =
|
ServerCredentials serverCredentials =
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ bool InstallController::isServerAlreadyExists()
|
|||||||
|
|
||||||
void InstallController::scanServerForInstalledContainers()
|
void InstallController::scanServerForInstalledContainers()
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials serverCredentials =
|
ServerCredentials serverCredentials =
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||||
|
|
||||||
@@ -267,7 +267,7 @@ void InstallController::scanServerForInstalledContainers()
|
|||||||
|
|
||||||
void InstallController::updateContainer(QJsonObject config)
|
void InstallController::updateContainer(QJsonObject config)
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials serverCredentials =
|
ServerCredentials serverCredentials =
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
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_serversModel->updateContainerConfig(container, config);
|
||||||
m_protocolModel->updateModel(config);
|
m_protocolModel->updateModel(config);
|
||||||
|
|
||||||
if ((serverIndex == m_serversModel->getDefaultServerIndex())
|
auto defaultContainer = qvariant_cast<DockerContainer>(m_serversModel->data(serverIndex, ServersModel::Roles::DefaultContainerRole));
|
||||||
&& (container == m_containersModel->getDefaultContainer())) {
|
if ((serverIndex == m_serversModel->getDefaultServerIndex()) && (container == defaultContainer)) {
|
||||||
emit currentContainerUpdated();
|
emit currentContainerUpdated();
|
||||||
} else {
|
} else {
|
||||||
emit updateContainerFinished(tr("Settings updated successfully"));
|
emit updateContainerFinished(tr("Settings updated successfully"));
|
||||||
@@ -296,27 +296,27 @@ void InstallController::updateContainer(QJsonObject config)
|
|||||||
emit installationErrorOccurred(errorString(errorCode));
|
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();
|
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
||||||
|
|
||||||
m_serversModel->rebootServer();
|
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();
|
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
||||||
|
|
||||||
m_serversModel->removeServer();
|
m_serversModel->removeServer();
|
||||||
emit removeCurrentlyProcessedServerFinished(tr("Server '%1' was removed").arg(serverName));
|
emit removeProcessedServerFinished(tr("Server '%1' was removed").arg(serverName));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallController::removeAllContainers()
|
void InstallController::removeAllContainers()
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
||||||
|
|
||||||
ErrorCode errorCode = m_serversModel->removeAllContainers();
|
ErrorCode errorCode = m_serversModel->removeAllContainers();
|
||||||
@@ -329,7 +329,7 @@ void InstallController::removeAllContainers()
|
|||||||
|
|
||||||
void InstallController::removeCurrentlyProcessedContainer()
|
void InstallController::removeCurrentlyProcessedContainer()
|
||||||
{
|
{
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
QString serverName = m_serversModel->data(serverIndex, ServersModel::Roles::NameRole).toString();
|
||||||
|
|
||||||
int container = m_containersModel->getCurrentlyProcessedContainerIndex();
|
int container = m_containersModel->getCurrentlyProcessedContainerIndex();
|
||||||
@@ -377,7 +377,7 @@ void InstallController::mountSftpDrive(const QString &port, const QString &passw
|
|||||||
QString mountPath;
|
QString mountPath;
|
||||||
QString cmd;
|
QString cmd;
|
||||||
|
|
||||||
int serverIndex = m_serversModel->getCurrentlyProcessedServerIndex();
|
int serverIndex = m_serversModel->getProcessedServerIndex();
|
||||||
ServerCredentials serverCredentials =
|
ServerCredentials serverCredentials =
|
||||||
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
qvariant_cast<ServerCredentials>(m_serversModel->data(serverIndex, ServersModel::Roles::CredentialsRole));
|
||||||
QString hostname = serverCredentials.hostName;
|
QString hostname = serverCredentials.hostName;
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ public slots:
|
|||||||
|
|
||||||
void updateContainer(QJsonObject config);
|
void updateContainer(QJsonObject config);
|
||||||
|
|
||||||
void removeCurrentlyProcessedServer();
|
void removeProcessedServer();
|
||||||
void rebootCurrentlyProcessedServer();
|
void rebootProcessedServer();
|
||||||
void removeAllContainers();
|
void removeAllContainers();
|
||||||
void removeCurrentlyProcessedContainer();
|
void removeCurrentlyProcessedContainer();
|
||||||
|
|
||||||
@@ -54,8 +54,8 @@ signals:
|
|||||||
|
|
||||||
void scanServerFinished(bool isInstalledContainerFound);
|
void scanServerFinished(bool isInstalledContainerFound);
|
||||||
|
|
||||||
void rebootCurrentlyProcessedServerFinished(const QString &finishedMessage);
|
void rebootProcessedServerFinished(const QString &finishedMessage);
|
||||||
void removeCurrentlyProcessedServerFinished(const QString &finishedMessage);
|
void removeProcessedServerFinished(const QString &finishedMessage);
|
||||||
void removeAllContainersFinished(const QString &finishedMessage);
|
void removeAllContainersFinished(const QString &finishedMessage);
|
||||||
void removeCurrentlyProcessedContainerFinished(const QString &finishedMessage);
|
void removeCurrentlyProcessedContainerFinished(const QString &finishedMessage);
|
||||||
|
|
||||||
|
|||||||
@@ -118,36 +118,6 @@ void PageController::showOnStartup()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PageController::updateDrawerRootPage(PageLoader::PageEnum page)
|
|
||||||
{
|
|
||||||
m_drawerLayer = 0;
|
|
||||||
m_currentRootPage = page;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageController::goToDrawerRootPage()
|
|
||||||
{
|
|
||||||
|
|
||||||
m_drawerLayer = 0;
|
|
||||||
|
|
||||||
emit showTopCloseButton(false);
|
|
||||||
emit forceCloseDrawer();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageController::drawerOpen()
|
|
||||||
{
|
|
||||||
m_drawerLayer = m_drawerLayer + 1;
|
|
||||||
emit showTopCloseButton(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PageController::drawerClose()
|
|
||||||
{
|
|
||||||
m_drawerLayer = m_drawerLayer -1;
|
|
||||||
if (m_drawerLayer <= 0) {
|
|
||||||
emit showTopCloseButton(false);
|
|
||||||
m_drawerLayer = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PageController::isTriggeredByConnectButton()
|
bool PageController::isTriggeredByConnectButton()
|
||||||
{
|
{
|
||||||
return m_isTriggeredByConnectButton;
|
return m_isTriggeredByConnectButton;
|
||||||
|
|||||||
@@ -82,11 +82,6 @@ public slots:
|
|||||||
|
|
||||||
void showOnStartup();
|
void showOnStartup();
|
||||||
|
|
||||||
void updateDrawerRootPage(PageLoader::PageEnum page);
|
|
||||||
void goToDrawerRootPage();
|
|
||||||
void drawerOpen();
|
|
||||||
void drawerClose();
|
|
||||||
|
|
||||||
bool isTriggeredByConnectButton();
|
bool isTriggeredByConnectButton();
|
||||||
void setTriggeredBtConnectButton(bool trigger);
|
void setTriggeredBtConnectButton(bool trigger);
|
||||||
|
|
||||||
@@ -118,17 +113,11 @@ signals:
|
|||||||
void showPassphraseRequestDrawer();
|
void showPassphraseRequestDrawer();
|
||||||
void passphraseRequestDrawerClosed(QString passphrase);
|
void passphraseRequestDrawerClosed(QString passphrase);
|
||||||
|
|
||||||
void showTopCloseButton(bool visible);
|
|
||||||
void forceCloseDrawer();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
|
|
||||||
std::shared_ptr<Settings> m_settings;
|
std::shared_ptr<Settings> m_settings;
|
||||||
|
|
||||||
PageLoader::PageEnum m_currentRootPage;
|
|
||||||
int m_drawerLayer;
|
|
||||||
|
|
||||||
bool m_isTriggeredByConnectButton;
|
bool m_isTriggeredByConnectButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ SettingsController::SettingsController(const QSharedPointer<ServersModel> &serve
|
|||||||
m_sitesModel(sitesModel),
|
m_sitesModel(sitesModel),
|
||||||
m_settings(settings)
|
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
|
#ifdef Q_OS_ANDROID
|
||||||
if (!m_settings->isScreenshotsEnabled()) {
|
if (!m_settings->isScreenshotsEnabled()) {
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const
|
|||||||
case EasySetupOrderRole: return ContainerProps::easySetupOrder(container);
|
case EasySetupOrderRole: return ContainerProps::easySetupOrder(container);
|
||||||
case IsInstalledRole: return m_containers.contains(container);
|
case IsInstalledRole: return m_containers.contains(container);
|
||||||
case IsCurrentlyProcessedRole: return container == static_cast<DockerContainer>(m_currentlyProcessedContainerIndex);
|
case IsCurrentlyProcessedRole: return container == static_cast<DockerContainer>(m_currentlyProcessedContainerIndex);
|
||||||
case IsDefaultRole: return container == m_defaultContainerIndex;
|
|
||||||
case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container);
|
case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container);
|
||||||
case IsShareableRole: return ContainerProps::isShareable(container);
|
case IsShareableRole: return ContainerProps::isShareable(container);
|
||||||
}
|
}
|
||||||
@@ -64,18 +63,6 @@ void ContainersModel::updateModel(const QJsonArray &containers)
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContainersModel::setDefaultContainer(const int containerIndex)
|
|
||||||
{
|
|
||||||
m_defaultContainerIndex = static_cast<DockerContainer>(containerIndex);
|
|
||||||
emit dataChanged(index(containerIndex, 0), index(containerIndex, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DockerContainer ContainersModel::getDefaultContainer()
|
|
||||||
{
|
|
||||||
return m_defaultContainerIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ContainersModel::setCurrentlyProcessedContainerIndex(int index)
|
void ContainersModel::setCurrentlyProcessedContainerIndex(int index)
|
||||||
{
|
{
|
||||||
m_currentlyProcessedContainerIndex = index;
|
m_currentlyProcessedContainerIndex = index;
|
||||||
@@ -127,7 +114,6 @@ QHash<int, QByteArray> ContainersModel::roleNames() const
|
|||||||
|
|
||||||
roles[IsInstalledRole] = "isInstalled";
|
roles[IsInstalledRole] = "isInstalled";
|
||||||
roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed";
|
roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed";
|
||||||
roles[IsDefaultRole] = "isDefault";
|
|
||||||
roles[IsSupportedRole] = "isSupported";
|
roles[IsSupportedRole] = "isSupported";
|
||||||
roles[IsShareableRole] = "isShareable";
|
roles[IsShareableRole] = "isShareable";
|
||||||
return roles;
|
return roles;
|
||||||
|
|||||||
@@ -42,9 +42,6 @@ public:
|
|||||||
public slots:
|
public slots:
|
||||||
void updateModel(const QJsonArray &containers);
|
void updateModel(const QJsonArray &containers);
|
||||||
|
|
||||||
DockerContainer getDefaultContainer();
|
|
||||||
void setDefaultContainer(const int containerIndex);
|
|
||||||
|
|
||||||
void setCurrentlyProcessedContainerIndex(int containerIndex);
|
void setCurrentlyProcessedContainerIndex(int containerIndex);
|
||||||
int getCurrentlyProcessedContainerIndex();
|
int getCurrentlyProcessedContainerIndex();
|
||||||
|
|
||||||
@@ -58,14 +55,12 @@ protected:
|
|||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void defaultContainerChanged();
|
|
||||||
void containersModelUpdated();
|
void containersModelUpdated();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<DockerContainer, QJsonObject> m_containers;
|
QMap<DockerContainer, QJsonObject> m_containers;
|
||||||
|
|
||||||
int m_currentlyProcessedContainerIndex;
|
int m_currentlyProcessedContainerIndex;
|
||||||
DockerContainer m_defaultContainerIndex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CONTAINERS_MODEL_H
|
#endif // CONTAINERS_MODEL_H
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ QString LanguageModel::getLocalLanguageName(const LanguageSettings::AvailableLan
|
|||||||
case LanguageSettings::AvailableLanguageEnum::Russian: strLanguage = "Русский"; break;
|
case LanguageSettings::AvailableLanguageEnum::Russian: strLanguage = "Русский"; break;
|
||||||
case LanguageSettings::AvailableLanguageEnum::China_cn: strLanguage = "\347\256\200\344\275\223\344\270\255\346\226\207"; break;
|
case LanguageSettings::AvailableLanguageEnum::China_cn: strLanguage = "\347\256\200\344\275\223\344\270\255\346\226\207"; break;
|
||||||
case LanguageSettings::AvailableLanguageEnum::Persian: strLanguage = "فارسی"; break;
|
case LanguageSettings::AvailableLanguageEnum::Persian: strLanguage = "فارسی"; break;
|
||||||
|
case LanguageSettings::AvailableLanguageEnum::Arabic: strLanguage = "العربية"; break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -59,6 +60,7 @@ void LanguageModel::changeLanguage(const LanguageSettings::AvailableLanguageEnum
|
|||||||
case LanguageSettings::AvailableLanguageEnum::Russian: emit updateTranslations(QLocale::Russian); break;
|
case LanguageSettings::AvailableLanguageEnum::Russian: emit updateTranslations(QLocale::Russian); break;
|
||||||
case LanguageSettings::AvailableLanguageEnum::China_cn: emit updateTranslations(QLocale::Chinese); break;
|
case LanguageSettings::AvailableLanguageEnum::China_cn: emit updateTranslations(QLocale::Chinese); break;
|
||||||
case LanguageSettings::AvailableLanguageEnum::Persian: emit updateTranslations(QLocale::Persian); break;
|
case LanguageSettings::AvailableLanguageEnum::Persian: emit updateTranslations(QLocale::Persian); break;
|
||||||
|
case LanguageSettings::AvailableLanguageEnum::Arabic: emit updateTranslations(QLocale::Arabic); break;
|
||||||
default: emit updateTranslations(QLocale::English); break;
|
default: emit updateTranslations(QLocale::English); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,6 +73,7 @@ int LanguageModel::getCurrentLanguageIndex()
|
|||||||
case QLocale::Russian: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Russian); break;
|
case QLocale::Russian: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Russian); break;
|
||||||
case QLocale::Chinese: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::China_cn); break;
|
case QLocale::Chinese: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::China_cn); break;
|
||||||
case QLocale::Persian: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Persian); break;
|
case QLocale::Persian: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Persian); break;
|
||||||
|
case QLocale::Arabic: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::Arabic); break;
|
||||||
default: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::English); break;
|
default: return static_cast<int>(LanguageSettings::AvailableLanguageEnum::English); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ namespace LanguageSettings
|
|||||||
English,
|
English,
|
||||||
Russian,
|
Russian,
|
||||||
China_cn,
|
China_cn,
|
||||||
Persian
|
Persian,
|
||||||
|
Arabic
|
||||||
};
|
};
|
||||||
Q_ENUM_NS(AvailableLanguageEnum)
|
Q_ENUM_NS(AvailableLanguageEnum)
|
||||||
|
|
||||||
|
|||||||
+146
-113
@@ -5,19 +5,13 @@
|
|||||||
ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
|
ServersModel::ServersModel(std::shared_ptr<Settings> settings, QObject *parent)
|
||||||
: m_settings(settings), QAbstractListModel(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::defaultServerIndexChanged, this, &ServersModel::defaultServerNameChanged);
|
||||||
connect(this, &ServersModel::defaultContainerChanged, this, &ServersModel::defaultServerDescriptionChanged);
|
|
||||||
connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) {
|
connect(this, &ServersModel::defaultServerIndexChanged, this, [this](const int serverIndex) {
|
||||||
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
|
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();
|
||||||
connect(this, &ServersModel::currentlyProcessedServerIndexChanged, this, [this](const int serverIndex) {
|
updateDefaultServerContainersModel();
|
||||||
auto defaultContainer = ContainerProps::containerFromString(m_servers.at(serverIndex).toObject().value(config_key::defaultContainer).toString());
|
|
||||||
emit ServersModel::defaultContainerChanged(defaultContainer);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,16 +68,14 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
case ServerDescriptionRole: {
|
case ServerDescriptionRole: {
|
||||||
if (configVersion) {
|
auto description = getServerDescription(server, index.row());
|
||||||
return server.value(config_key::description).toString();
|
return configVersion ? description : description + server.value(config_key::hostName).toString();
|
||||||
}
|
|
||||||
return server.value(config_key::hostName).toString();
|
|
||||||
}
|
}
|
||||||
case HostNameRole: return server.value(config_key::hostName).toString();
|
case HostNameRole: return server.value(config_key::hostName).toString();
|
||||||
case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row()));
|
case CredentialsRole: return QVariant::fromValue(serverCredentials(index.row()));
|
||||||
case CredentialsLoginRole: return serverCredentials(index.row()).userName;
|
case CredentialsLoginRole: return serverCredentials(index.row()).userName;
|
||||||
case IsDefaultRole: return index.row() == m_defaultServerIndex;
|
case IsDefaultRole: return index.row() == m_defaultServerIndex;
|
||||||
case IsCurrentlyProcessedRole: return index.row() == m_currentlyProcessedServerIndex;
|
case IsCurrentlyProcessedRole: return index.row() == m_processedServerIndex;
|
||||||
case HasWriteAccessRole: {
|
case HasWriteAccessRole: {
|
||||||
auto credentials = serverCredentials(index.row());
|
auto credentials = serverCredentials(index.row());
|
||||||
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
|
return (!credentials.userName.isEmpty() && !credentials.secretData.isEmpty());
|
||||||
@@ -95,6 +87,13 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
|||||||
case DefaultContainerRole: {
|
case DefaultContainerRole: {
|
||||||
return ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
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();
|
return QVariant();
|
||||||
@@ -111,8 +110,9 @@ void ServersModel::resetModel()
|
|||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_servers = m_settings->serversArray();
|
m_servers = m_settings->serversArray();
|
||||||
m_defaultServerIndex = m_settings->defaultServerIndex();
|
m_defaultServerIndex = m_settings->defaultServerIndex();
|
||||||
m_currentlyProcessedServerIndex = m_defaultServerIndex;
|
m_processedServerIndex = m_defaultServerIndex;
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
emit defaultServerIndexChanged(m_defaultServerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::setDefaultServerIndex(const int index)
|
void ServersModel::setDefaultServerIndex(const int index)
|
||||||
@@ -132,12 +132,7 @@ const QString ServersModel::getDefaultServerName()
|
|||||||
return qvariant_cast<QString>(data(m_defaultServerIndex, NameRole));
|
return qvariant_cast<QString>(data(m_defaultServerIndex, NameRole));
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString ServersModel::getDefaultServerHostName()
|
QString ServersModel::getServerDescription(const QJsonObject &server, const int index) const
|
||||||
{
|
|
||||||
return qvariant_cast<QString>(data(m_defaultServerIndex, HostNameRole));
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ServersModel::getDefaultServerDescription(const QJsonObject &server)
|
|
||||||
{
|
{
|
||||||
const auto configVersion = server.value(config_key::configVersion).toInt();
|
const auto configVersion = server.value(config_key::configVersion).toInt();
|
||||||
|
|
||||||
@@ -145,13 +140,12 @@ QString ServersModel::getDefaultServerDescription(const QJsonObject &server)
|
|||||||
|
|
||||||
if (configVersion) {
|
if (configVersion) {
|
||||||
return server.value(config_key::description).toString();
|
return server.value(config_key::description).toString();
|
||||||
} else if (isDefaultServerHasWriteAccess()) {
|
} else if (data(index, HasWriteAccessRole).toBool()) {
|
||||||
if (m_isAmneziaDnsEnabled
|
if (m_isAmneziaDnsEnabled && isAmneziaDnsContainerInstalled(index)) {
|
||||||
&& isAmneziaDnsContainerInstalled(m_defaultServerIndex)) {
|
|
||||||
description += "Amnezia DNS | ";
|
description += "Amnezia DNS | ";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isDefaultServerConfigContainsAmneziaDns()) {
|
if (data(index, HasAmneziaDns).toBool()) {
|
||||||
description += "Amnezia DNS | ";
|
description += "Amnezia DNS | ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -162,7 +156,7 @@ const QString ServersModel::getDefaultServerDescriptionCollapsed()
|
|||||||
{
|
{
|
||||||
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
||||||
const auto configVersion = server.value(config_key::configVersion).toInt();
|
const auto configVersion = server.value(config_key::configVersion).toInt();
|
||||||
auto description = getDefaultServerDescription(server);
|
auto description = getServerDescription(server, m_defaultServerIndex);
|
||||||
if (configVersion) {
|
if (configVersion) {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
@@ -176,7 +170,7 @@ const QString ServersModel::getDefaultServerDescriptionExpanded()
|
|||||||
{
|
{
|
||||||
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
const QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
||||||
const auto configVersion = server.value(config_key::configVersion).toInt();
|
const auto configVersion = server.value(config_key::configVersion).toInt();
|
||||||
auto description = getDefaultServerDescription(server);
|
auto description = getServerDescription(server, m_defaultServerIndex);
|
||||||
if (configVersion) {
|
if (configVersion) {
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
@@ -199,26 +193,21 @@ bool ServersModel::hasServerWithWriteAccess()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::setCurrentlyProcessedServerIndex(const int index)
|
void ServersModel::setProcessedServerIndex(const int index)
|
||||||
{
|
{
|
||||||
m_currentlyProcessedServerIndex = index;
|
m_processedServerIndex = index;
|
||||||
updateContainersModel();
|
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));
|
return serverCredentials(m_processedServerIndex);
|
||||||
}
|
|
||||||
|
|
||||||
const ServerCredentials ServersModel::getCurrentlyProcessedServerCredentials()
|
|
||||||
{
|
|
||||||
return serverCredentials(m_currentlyProcessedServerIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ServerCredentials ServersModel::getServerCredentials(const int index)
|
const ServerCredentials ServersModel::getServerCredentials(const int index)
|
||||||
@@ -228,12 +217,17 @@ const ServerCredentials ServersModel::getServerCredentials(const int index)
|
|||||||
|
|
||||||
bool ServersModel::isDefaultServerCurrentlyProcessed()
|
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()
|
bool ServersModel::isDefaultServerHasWriteAccess()
|
||||||
@@ -249,40 +243,42 @@ void ServersModel::addServer(const QJsonObject &server)
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::editServer(const QJsonObject &server)
|
void ServersModel::editServer(const QJsonObject &server, const int serverIndex)
|
||||||
{
|
{
|
||||||
m_settings->editServer(m_currentlyProcessedServerIndex, server);
|
m_settings->editServer(serverIndex, server);
|
||||||
m_servers.replace(m_currentlyProcessedServerIndex, m_settings->serversArray().at(m_currentlyProcessedServerIndex));
|
m_servers.replace(serverIndex, m_settings->serversArray().at(serverIndex));
|
||||||
emit dataChanged(index(m_currentlyProcessedServerIndex, 0), index(m_currentlyProcessedServerIndex, 0));
|
emit dataChanged(index(serverIndex, 0), index(serverIndex, 0));
|
||||||
|
|
||||||
|
if (serverIndex == m_defaultServerIndex) {
|
||||||
|
updateDefaultServerContainersModel();
|
||||||
|
}
|
||||||
updateContainersModel();
|
updateContainersModel();
|
||||||
|
|
||||||
|
if (serverIndex == m_defaultServerIndex) {
|
||||||
|
auto defaultContainer = qvariant_cast<DockerContainer>(getDefaultServerData("defaultContainer"));
|
||||||
|
emit defaultServerDefaultContainerChanged(defaultContainer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::removeServer()
|
void ServersModel::removeServer()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
m_settings->removeServer(m_currentlyProcessedServerIndex);
|
m_settings->removeServer(m_processedServerIndex);
|
||||||
m_servers = m_settings->serversArray();
|
m_servers = m_settings->serversArray();
|
||||||
|
|
||||||
if (m_settings->defaultServerIndex() == m_currentlyProcessedServerIndex) {
|
if (m_settings->defaultServerIndex() == m_processedServerIndex) {
|
||||||
setDefaultServerIndex(0);
|
setDefaultServerIndex(0);
|
||||||
} else if (m_settings->defaultServerIndex() > m_currentlyProcessedServerIndex) {
|
} else if (m_settings->defaultServerIndex() > m_processedServerIndex) {
|
||||||
setDefaultServerIndex(m_settings->defaultServerIndex() - 1);
|
setDefaultServerIndex(m_settings->defaultServerIndex() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_settings->serversCount() == 0) {
|
if (m_settings->serversCount() == 0) {
|
||||||
setDefaultServerIndex(-1);
|
setDefaultServerIndex(-1);
|
||||||
}
|
}
|
||||||
setCurrentlyProcessedServerIndex(m_defaultServerIndex);
|
setProcessedServerIndex(m_defaultServerIndex);
|
||||||
endResetModel();
|
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> ServersModel::roleNames() const
|
||||||
{
|
{
|
||||||
QHash<int, QByteArray> roles;
|
QHash<int, QByteArray> roles;
|
||||||
@@ -290,6 +286,8 @@ QHash<int, QByteArray> ServersModel::roleNames() const
|
|||||||
roles[NameRole] = "serverName";
|
roles[NameRole] = "serverName";
|
||||||
roles[NameRole] = "name";
|
roles[NameRole] = "name";
|
||||||
roles[ServerDescriptionRole] = "serverDescription";
|
roles[ServerDescriptionRole] = "serverDescription";
|
||||||
|
roles[CollapsedServerDescriptionRole] = "collapsedServerDescription";
|
||||||
|
roles[ExpandedServerDescriptionRole] = "expandedServerDescription";
|
||||||
|
|
||||||
roles[HostNameRole] = "hostName";
|
roles[HostNameRole] = "hostName";
|
||||||
|
|
||||||
@@ -304,6 +302,8 @@ QHash<int, QByteArray> ServersModel::roleNames() const
|
|||||||
roles[ContainsAmneziaDnsRole] = "containsAmneziaDns";
|
roles[ContainsAmneziaDnsRole] = "containsAmneziaDns";
|
||||||
|
|
||||||
roles[DefaultContainerRole] = "defaultContainer";
|
roles[DefaultContainerRole] = "defaultContainer";
|
||||||
|
|
||||||
|
roles[IsServerFromApiRole] = "isServerFromApi";
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,28 +322,29 @@ ServerCredentials ServersModel::serverCredentials(int index) const
|
|||||||
|
|
||||||
void ServersModel::updateContainersModel()
|
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);
|
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()
|
QJsonObject ServersModel::getDefaultServerConfig()
|
||||||
{
|
{
|
||||||
return m_servers.at(m_defaultServerIndex).toObject();
|
return m_servers.at(m_defaultServerIndex).toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject ServersModel::getCurrentlyProcessedServerConfig()
|
void ServersModel::reloadDefaultServerContainerConfig()
|
||||||
{
|
{
|
||||||
return m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
QJsonObject server = m_servers.at(m_defaultServerIndex).toObject();
|
||||||
}
|
|
||||||
|
|
||||||
void ServersModel::reloadContainerConfig()
|
|
||||||
{
|
|
||||||
QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
|
||||||
auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
auto container = ContainerProps::containerFromString(server.value(config_key::defaultContainer).toString());
|
||||||
|
|
||||||
auto containers = server.value(config_key::containers).toArray();
|
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++) {
|
for (auto i = 0; i < containers.size(); i++) {
|
||||||
auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString());
|
auto c = ContainerProps::containerFromString(containers.at(i).toObject().value(config_key::container).toString());
|
||||||
if (c == container) {
|
if (c == container) {
|
||||||
@@ -353,13 +354,13 @@ void ServersModel::reloadContainerConfig()
|
|||||||
}
|
}
|
||||||
|
|
||||||
server.insert(config_key::containers, containers);
|
server.insert(config_key::containers, containers);
|
||||||
editServer(server);
|
editServer(server, m_defaultServerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::updateContainerConfig(const int containerIndex, const QJsonObject config)
|
void ServersModel::updateContainerConfig(const int containerIndex, const QJsonObject config)
|
||||||
{
|
{
|
||||||
auto container = static_cast<DockerContainer>(containerIndex);
|
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();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
for (auto i = 0; i < containers.size(); i++) {
|
for (auto i = 0; i < containers.size(); i++) {
|
||||||
@@ -377,49 +378,38 @@ void ServersModel::updateContainerConfig(const int containerIndex, const QJsonOb
|
|||||||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||||
}
|
}
|
||||||
|
|
||||||
editServer(server);
|
editServer(server, m_processedServerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::addContainerConfig(const int containerIndex, const QJsonObject config)
|
void ServersModel::addContainerConfig(const int containerIndex, const QJsonObject config)
|
||||||
{
|
{
|
||||||
auto container = static_cast<DockerContainer>(containerIndex);
|
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();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
containers.push_back(config);
|
containers.push_back(config);
|
||||||
|
|
||||||
server.insert(config_key::containers, containers);
|
server.insert(config_key::containers, containers);
|
||||||
|
|
||||||
bool isDefaultContainerChanged = false;
|
|
||||||
auto defaultContainer = server.value(config_key::defaultContainer).toString();
|
auto defaultContainer = server.value(config_key::defaultContainer).toString();
|
||||||
if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None || ContainerProps::containerService(container) != ServiceType::Other)) {
|
if ((ContainerProps::containerFromString(defaultContainer) == DockerContainer::None || ContainerProps::containerService(container) != ServiceType::Other)) {
|
||||||
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
server.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||||
isDefaultContainerChanged = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
editServer(server);
|
editServer(server, m_processedServerIndex);
|
||||||
if (isDefaultContainerChanged) {
|
|
||||||
emit defaultContainerChanged(container);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::setDefaultContainer(const int containerIndex)
|
void ServersModel::setDefaultContainer(const int serverIndex, const int containerIndex)
|
||||||
{
|
{
|
||||||
auto container = static_cast<DockerContainer>(containerIndex);
|
auto container = static_cast<DockerContainer>(containerIndex);
|
||||||
QJsonObject s = m_servers.at(m_currentlyProcessedServerIndex).toObject();
|
QJsonObject s = m_servers.at(serverIndex).toObject();
|
||||||
s.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
s.insert(config_key::defaultContainer, ContainerProps::containerToString(container));
|
||||||
editServer(s); //check
|
editServer(s, serverIndex); //check
|
||||||
emit defaultContainerChanged(container);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DockerContainer ServersModel::getDefaultContainer()
|
const QString ServersModel::getDefaultServerDefaultContainerName()
|
||||||
{
|
{
|
||||||
return qvariant_cast<DockerContainer>(data(m_currentlyProcessedServerIndex, DefaultContainerRole));
|
auto defaultContainer = qvariant_cast<DockerContainer>(getDefaultServerData("defaultContainer"));
|
||||||
}
|
|
||||||
|
|
||||||
const QString ServersModel::getDefaultContainerName()
|
|
||||||
{
|
|
||||||
auto defaultContainer = getDefaultContainer();
|
|
||||||
return ContainerProps::containerHumanNames().value(defaultContainer);
|
return ContainerProps::containerHumanNames().value(defaultContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,15 +417,14 @@ ErrorCode ServersModel::removeAllContainers()
|
|||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
ErrorCode errorCode =
|
ErrorCode errorCode =
|
||||||
serverController.removeAllContainers(m_settings->serverCredentials(m_currentlyProcessedServerIndex));
|
serverController.removeAllContainers(m_settings->serverCredentials(m_processedServerIndex));
|
||||||
|
|
||||||
if (errorCode == ErrorCode::NoError) {
|
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::containers, {});
|
||||||
s.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
s.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None));
|
||||||
|
|
||||||
editServer(s);
|
editServer(s, m_processedServerIndex);
|
||||||
emit defaultContainerChanged(DockerContainer::None);
|
|
||||||
}
|
}
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
@@ -443,7 +432,7 @@ ErrorCode ServersModel::removeAllContainers()
|
|||||||
ErrorCode ServersModel::rebootServer()
|
ErrorCode ServersModel::rebootServer()
|
||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex);
|
auto credentials = m_settings->serverCredentials(m_processedServerIndex);
|
||||||
|
|
||||||
ErrorCode errorCode = serverController.rebootServer(credentials);
|
ErrorCode errorCode = serverController.rebootServer(credentials);
|
||||||
return errorCode;
|
return errorCode;
|
||||||
@@ -452,13 +441,13 @@ ErrorCode ServersModel::rebootServer()
|
|||||||
ErrorCode ServersModel::removeContainer(const int containerIndex)
|
ErrorCode ServersModel::removeContainer(const int containerIndex)
|
||||||
{
|
{
|
||||||
ServerController serverController(m_settings);
|
ServerController serverController(m_settings);
|
||||||
auto credentials = m_settings->serverCredentials(m_currentlyProcessedServerIndex);
|
auto credentials = m_settings->serverCredentials(m_processedServerIndex);
|
||||||
auto dockerContainer = static_cast<DockerContainer>(containerIndex);
|
auto dockerContainer = static_cast<DockerContainer>(containerIndex);
|
||||||
|
|
||||||
ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer);
|
ErrorCode errorCode = serverController.removeContainer(credentials, dockerContainer);
|
||||||
|
|
||||||
if (errorCode == ErrorCode::NoError) {
|
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();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
for (auto it = containers.begin(); it != containers.end(); it++) {
|
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));
|
server.insert(config_key::defaultContainer, ContainerProps::containerToString(defaultContainer));
|
||||||
}
|
}
|
||||||
|
|
||||||
editServer(server);
|
editServer(server, m_processedServerIndex);
|
||||||
emit defaultContainerChanged(defaultContainer);
|
|
||||||
}
|
}
|
||||||
return errorCode;
|
return errorCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::clearCachedProfiles()
|
void ServersModel::clearCachedProfiles()
|
||||||
{
|
{
|
||||||
const auto &containers = m_settings->containers(m_currentlyProcessedServerIndex);
|
const auto &containers = m_settings->containers(m_processedServerIndex);
|
||||||
for (DockerContainer container : containers.keys()) {
|
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();
|
updateContainersModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServersModel::clearCachedProfile(const DockerContainer container)
|
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();
|
updateContainersModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex)
|
bool ServersModel::isAmneziaDnsContainerInstalled(const int serverIndex) const
|
||||||
{
|
{
|
||||||
QJsonObject server = m_servers.at(serverIndex).toObject();
|
QJsonObject server = m_servers.at(serverIndex).toObject();
|
||||||
auto containers = server.value(config_key::containers).toArray();
|
auto containers = server.value(config_key::containers).toArray();
|
||||||
@@ -544,16 +538,6 @@ void ServersModel::toggleAmneziaDns(bool enabled)
|
|||||||
emit defaultServerDescriptionChanged();
|
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)
|
bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
|
||||||
{
|
{
|
||||||
for (const auto &server : qAsConst(m_servers)) {
|
for (const auto &server : qAsConst(m_servers)) {
|
||||||
@@ -564,3 +548,52 @@ bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc)
|
|||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ public:
|
|||||||
enum Roles {
|
enum Roles {
|
||||||
NameRole = Qt::UserRole + 1,
|
NameRole = Qt::UserRole + 1,
|
||||||
ServerDescriptionRole,
|
ServerDescriptionRole,
|
||||||
|
CollapsedServerDescriptionRole,
|
||||||
|
ExpandedServerDescriptionRole,
|
||||||
HostNameRole,
|
HostNameRole,
|
||||||
|
|
||||||
CredentialsRole,
|
CredentialsRole,
|
||||||
@@ -25,7 +26,11 @@ public:
|
|||||||
|
|
||||||
ContainsAmneziaDnsRole,
|
ContainsAmneziaDnsRole,
|
||||||
|
|
||||||
DefaultContainerRole
|
DefaultContainerRole,
|
||||||
|
|
||||||
|
IsServerFromApiRole,
|
||||||
|
|
||||||
|
HasAmneziaDns
|
||||||
};
|
};
|
||||||
|
|
||||||
ServersModel(std::shared_ptr<Settings> settings, QObject *parent = nullptr);
|
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(int defaultIndex READ getDefaultServerIndex WRITE setDefaultServerIndex NOTIFY defaultServerIndexChanged)
|
||||||
Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerNameChanged)
|
Q_PROPERTY(QString defaultServerName READ getDefaultServerName NOTIFY defaultServerNameChanged)
|
||||||
Q_PROPERTY(QString defaultServerHostName READ getDefaultServerHostName NOTIFY defaultServerIndexChanged)
|
Q_PROPERTY(QString defaultServerDefaultContainerName READ getDefaultServerDefaultContainerName NOTIFY defaultServerDefaultContainerChanged)
|
||||||
Q_PROPERTY(QString defaultContainerName READ getDefaultContainerName NOTIFY defaultContainerChanged)
|
Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerDefaultContainerChanged)
|
||||||
Q_PROPERTY(QString defaultServerDescriptionCollapsed READ getDefaultServerDescriptionCollapsed NOTIFY defaultServerDescriptionChanged)
|
Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerDefaultContainerChanged)
|
||||||
Q_PROPERTY(QString defaultServerDescriptionExpanded READ getDefaultServerDescriptionExpanded NOTIFY defaultServerDescriptionChanged)
|
Q_PROPERTY(bool isDefaultServerDefaultContainerHasSplitTunneling READ isDefaultServerDefaultContainerHasSplitTunneling NOTIFY defaultServerDefaultContainerChanged)
|
||||||
|
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIndexChanged)
|
||||||
|
|
||||||
Q_PROPERTY(int currentlyProcessedIndex READ getCurrentlyProcessedServerIndex WRITE setCurrentlyProcessedServerIndex
|
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
|
||||||
NOTIFY currentlyProcessedServerIndexChanged)
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setDefaultServerIndex(const int index);
|
void setDefaultServerIndex(const int index);
|
||||||
const int getDefaultServerIndex();
|
const int getDefaultServerIndex();
|
||||||
const QString getDefaultServerName();
|
const QString getDefaultServerName();
|
||||||
const QString getDefaultServerHostName();
|
|
||||||
const QString getDefaultServerDescriptionCollapsed();
|
const QString getDefaultServerDescriptionCollapsed();
|
||||||
const QString getDefaultServerDescriptionExpanded();
|
const QString getDefaultServerDescriptionExpanded();
|
||||||
|
const QString getDefaultServerDefaultContainerName();
|
||||||
bool isDefaultServerCurrentlyProcessed();
|
bool isDefaultServerCurrentlyProcessed();
|
||||||
|
bool isDefaultServerFromApi();
|
||||||
|
|
||||||
bool isCurrentlyProcessedServerHasWriteAccess();
|
bool isProcessedServerHasWriteAccess();
|
||||||
bool isDefaultServerHasWriteAccess();
|
bool isDefaultServerHasWriteAccess();
|
||||||
bool hasServerWithWriteAccess();
|
bool hasServerWithWriteAccess();
|
||||||
|
|
||||||
const int getServersCount();
|
const int getServersCount();
|
||||||
|
|
||||||
void setCurrentlyProcessedServerIndex(const int index);
|
void setProcessedServerIndex(const int index);
|
||||||
int getCurrentlyProcessedServerIndex();
|
int getProcessedServerIndex();
|
||||||
|
|
||||||
QString getCurrentlyProcessedServerHostName();
|
const ServerCredentials getProcessedServerCredentials();
|
||||||
const ServerCredentials getCurrentlyProcessedServerCredentials();
|
|
||||||
const ServerCredentials getServerCredentials(const int index);
|
const ServerCredentials getServerCredentials(const int index);
|
||||||
|
|
||||||
void addServer(const QJsonObject &server);
|
void addServer(const QJsonObject &server);
|
||||||
void editServer(const QJsonObject &server);
|
void editServer(const QJsonObject &server, const int serverIndex);
|
||||||
void removeServer();
|
void removeServer();
|
||||||
|
|
||||||
bool isDefaultServerConfigContainsAmneziaDns();
|
|
||||||
bool isAmneziaDnsContainerInstalled(const int serverIndex);
|
|
||||||
|
|
||||||
QJsonObject getDefaultServerConfig();
|
QJsonObject getDefaultServerConfig();
|
||||||
QJsonObject getCurrentlyProcessedServerConfig();
|
|
||||||
|
|
||||||
void reloadContainerConfig();
|
void reloadDefaultServerContainerConfig();
|
||||||
void updateContainerConfig(const int containerIndex, const QJsonObject config);
|
void updateContainerConfig(const int containerIndex, const QJsonObject config);
|
||||||
void addContainerConfig(const int containerIndex, const QJsonObject config);
|
void addContainerConfig(const int containerIndex, const QJsonObject config);
|
||||||
|
|
||||||
@@ -91,43 +92,50 @@ public slots:
|
|||||||
ErrorCode removeAllContainers();
|
ErrorCode removeAllContainers();
|
||||||
ErrorCode rebootServer();
|
ErrorCode rebootServer();
|
||||||
|
|
||||||
void setDefaultContainer(const int containerIndex);
|
void setDefaultContainer(const int serverIndex, const int containerIndex);
|
||||||
DockerContainer getDefaultContainer();
|
|
||||||
const QString getDefaultContainerName();
|
|
||||||
|
|
||||||
QStringList getAllInstalledServicesName(const int serverIndex);
|
QStringList getAllInstalledServicesName(const int serverIndex);
|
||||||
|
|
||||||
void toggleAmneziaDns(bool enabled);
|
void toggleAmneziaDns(bool enabled);
|
||||||
|
|
||||||
bool isDefaultServerFromApi();
|
|
||||||
bool isCurrentlyProcessedServerFromApi();
|
|
||||||
|
|
||||||
bool isServerFromApiAlreadyExists(const quint16 crc);
|
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:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentlyProcessedServerIndexChanged(const int index);
|
void processedServerIndexChanged(const int index);
|
||||||
void defaultServerIndexChanged(const int index);
|
void defaultServerIndexChanged(const int index);
|
||||||
void defaultServerNameChanged();
|
void defaultServerNameChanged();
|
||||||
void defaultServerDescriptionChanged();
|
void defaultServerDescriptionChanged();
|
||||||
|
|
||||||
void containersUpdated(const QJsonArray &containers);
|
void containersUpdated(const QJsonArray &containers);
|
||||||
void defaultContainerChanged(const int containerIndex);
|
void defaultServerContainersUpdated(const QJsonArray &containers);
|
||||||
|
void defaultServerDefaultContainerChanged(const int containerIndex);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ServerCredentials serverCredentials(int index) const;
|
ServerCredentials serverCredentials(int index) const;
|
||||||
void updateContainersModel();
|
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;
|
QJsonArray m_servers;
|
||||||
|
|
||||||
std::shared_ptr<Settings> m_settings;
|
std::shared_ptr<Settings> m_settings;
|
||||||
|
|
||||||
int m_defaultServerIndex;
|
int m_defaultServerIndex;
|
||||||
int m_currentlyProcessedServerIndex;
|
int m_processedServerIndex;
|
||||||
|
|
||||||
bool m_isAmneziaDnsEnabled = m_settings->useAmneziaDns();
|
bool m_isAmneziaDnsEnabled = m_settings->useAmneziaDns();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ void SitesModel::toggleSplitTunneling(bool enabled)
|
|||||||
m_settings->setRouteMode(Settings::RouteMode::VpnAllSites);
|
m_settings->setRouteMode(Settings::RouteMode::VpnAllSites);
|
||||||
}
|
}
|
||||||
m_isSplitTunnelingEnabled = enabled;
|
m_isSplitTunnelingEnabled = enabled;
|
||||||
|
emit splitTunnelingToggled();
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QPair<QString, QString> > SitesModel::getCurrentSites()
|
QVector<QPair<QString, QString> > SitesModel::getCurrentSites()
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public:
|
|||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
Q_PROPERTY(int routeMode READ getRouteMode WRITE setRouteMode NOTIFY routeModeChanged)
|
Q_PROPERTY(int routeMode READ getRouteMode WRITE setRouteMode NOTIFY routeModeChanged)
|
||||||
|
Q_PROPERTY(bool isTunnelingEnabled READ isSplitTunnelingEnabled NOTIFY splitTunnelingToggled)
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool addSite(const QString &hostname, const QString &ip);
|
bool addSite(const QString &hostname, const QString &ip);
|
||||||
@@ -38,6 +39,7 @@ public slots:
|
|||||||
|
|
||||||
signals:
|
signals:
|
||||||
void routeModeChanged();
|
void routeModeChanged();
|
||||||
|
void splitTunnelingToggled();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QHash<int, QByteArray> roleNames() const override;
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|||||||
@@ -138,8 +138,7 @@ Button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!ConnectionController.isConnectionInProgress) {
|
ServersModel.setProcessedServerIndex(ServersModel.defaultIndex)
|
||||||
ApiController.updateServerConfigFromApi()
|
ApiController.updateServerConfigFromApi()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,18 +8,24 @@ import "../Controls2"
|
|||||||
import "../Controls2/TextTypes"
|
import "../Controls2/TextTypes"
|
||||||
import "../Config"
|
import "../Config"
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
height: parent.height * 0.4375
|
height: parent.height
|
||||||
|
|
||||||
|
expandedContent: ColumnLayout {
|
||||||
|
id: content
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
spacing: 0
|
spacing: 0
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.expandedHeight = content.implicitHeight + 32
|
||||||
|
}
|
||||||
|
|
||||||
Header2Type {
|
Header2Type {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
@@ -40,7 +46,7 @@ DrawerType {
|
|||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardCredentials)
|
PageController.goToPage(PageEnum.PageSetupWizardCredentials)
|
||||||
root.visible = false
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,7 +60,7 @@ DrawerType {
|
|||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
|
||||||
root.visible = false
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ ListView {
|
|||||||
id: menuContent
|
id: menuContent
|
||||||
|
|
||||||
property var rootWidth
|
property var rootWidth
|
||||||
|
property var selectedText
|
||||||
|
|
||||||
width: rootWidth
|
width: rootWidth
|
||||||
height: menuContent.contentItem.height
|
height: menuContent.contentItem.height
|
||||||
@@ -26,24 +27,6 @@ ListView {
|
|||||||
id: containersRadioButtonGroup
|
id: containersRadioButtonGroup
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: ServersModel
|
|
||||||
|
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
|
||||||
if (ContainersModel.getDefaultContainer()) {
|
|
||||||
menuContent.checkCurrentItem()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkCurrentItem() {
|
|
||||||
var item = menuContent.itemAtIndex(currentIndex)
|
|
||||||
if (item !== null) {
|
|
||||||
var radioButton = item.children[0].children[0]
|
|
||||||
radioButton.checked = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
implicitWidth: rootWidth
|
implicitWidth: rootWidth
|
||||||
implicitHeight: content.implicitHeight
|
implicitHeight: content.implicitHeight
|
||||||
@@ -69,7 +52,7 @@ ListView {
|
|||||||
showImage: !isInstalled
|
showImage: !isInstalled
|
||||||
|
|
||||||
checkable: isInstalled && !ConnectionController.isConnected && isSupported
|
checkable: isInstalled && !ConnectionController.isConnected && isSupported
|
||||||
checked: isDefault
|
checked: proxyDefaultServerContainersModel.mapToSource(index) === ServersModel.getDefaultServerData("defaultContainer")
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (ConnectionController.isConnected && isInstalled) {
|
if (ConnectionController.isConnected && isInstalled) {
|
||||||
@@ -78,18 +61,18 @@ ListView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
containersDropDown.menuVisible = false
|
containersDropDown.close()
|
||||||
ServersModel.setDefaultContainer(proxyContainersModel.mapToSource(index))
|
ServersModel.setDefaultContainer(ServersModel.defaultIndex, proxyDefaultServerContainersModel.mapToSource(index))
|
||||||
} else {
|
} else {
|
||||||
if (!isSupported && isInstalled) {
|
if (!isSupported && isInstalled) {
|
||||||
PageController.showErrorMessage(qsTr("The selected protocol is not supported on the current platform"))
|
PageController.showErrorMessage(qsTr("The selected protocol is not supported on the current platform"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ContainersModel.setCurrentlyProcessedContainerIndex(proxyContainersModel.mapToSource(index))
|
ContainersModel.setCurrentlyProcessedContainerIndex(proxyDefaultServerContainersModel.mapToSource(index))
|
||||||
InstallController.setShouldCreateServer(false)
|
InstallController.setShouldCreateServer(false)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
|
PageController.goToPage(PageEnum.PageSetupWizardProtocolSettings)
|
||||||
containersDropDown.menuVisible = false
|
containersDropDown.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import QtQuick.Layouts
|
|||||||
import "../Controls2"
|
import "../Controls2"
|
||||||
import "../Controls2/TextTypes"
|
import "../Controls2/TextTypes"
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string headerText
|
property string headerText
|
||||||
@@ -16,23 +16,24 @@ DrawerType {
|
|||||||
property var yesButtonFunction
|
property var yesButtonFunction
|
||||||
property var noButtonFunction
|
property var noButtonFunction
|
||||||
|
|
||||||
width: parent.width
|
expandedContent: ColumnLayout {
|
||||||
height: content.implicitHeight + 32
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: content
|
id: content
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
spacing: 8
|
spacing: 8
|
||||||
|
|
||||||
|
onImplicitHeightChanged: {
|
||||||
|
root.expandedHeight = content.implicitHeight + 32
|
||||||
|
}
|
||||||
|
|
||||||
Header2TextType {
|
Header2TextType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: headerText
|
text: headerText
|
||||||
}
|
}
|
||||||
@@ -40,6 +41,8 @@ DrawerType {
|
|||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
Layout.topMargin: 8
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: descriptionText
|
text: descriptionText
|
||||||
}
|
}
|
||||||
@@ -47,10 +50,12 @@ DrawerType {
|
|||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
text: yesButtonText
|
text: yesButtonText
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
||||||
yesButtonFunction()
|
yesButtonFunction()
|
||||||
}
|
}
|
||||||
@@ -59,6 +64,8 @@ DrawerType {
|
|||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
defaultColor: "transparent"
|
defaultColor: "transparent"
|
||||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||||
@@ -69,7 +76,7 @@ DrawerType {
|
|||||||
|
|
||||||
text: noButtonText
|
text: noButtonText
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (noButtonFunction && typeof noButtonFunction === "function") {
|
if (noButtonFunction && typeof noButtonFunction === "function") {
|
||||||
noButtonFunction()
|
noButtonFunction()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,129 +5,136 @@ import QtQuick.Layouts
|
|||||||
import "../Controls2"
|
import "../Controls2"
|
||||||
import "../Controls2/TextTypes"
|
import "../Controls2/TextTypes"
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
width: parent.width
|
expandedContent: Item {
|
||||||
height: parent.height * 0.9
|
id: container
|
||||||
|
|
||||||
ColumnLayout {
|
implicitHeight: root.height * 0.9
|
||||||
id: backButton
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
Component.onCompleted: {
|
||||||
anchors.left: parent.left
|
root.expandedHeight = container.implicitHeight
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
BackButtonType {
|
|
||||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
|
||||||
backButtonFunction: function() {
|
|
||||||
root.close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
|
||||||
anchors.top: backButton.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
contentHeight: content.implicitHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: content
|
id: backButton
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
Header2Type {
|
BackButtonType {
|
||||||
id: header
|
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||||
Layout.fillWidth: true
|
backButtonFunction: function() {
|
||||||
Layout.topMargin: 16
|
root.close()
|
||||||
Layout.rightMargin: 16
|
}
|
||||||
Layout.leftMargin: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Choose language")
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ListView {
|
FlickableType {
|
||||||
id: listView
|
anchors.top: backButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
contentHeight: content.implicitHeight
|
||||||
|
|
||||||
Layout.fillWidth: true
|
ColumnLayout {
|
||||||
height: listView.contentItem.height
|
id: content
|
||||||
|
|
||||||
clip: true
|
anchors.fill: parent
|
||||||
interactive: false
|
|
||||||
|
|
||||||
model: LanguageModel
|
Header2Type {
|
||||||
currentIndex: LanguageModel.currentLanguageIndex
|
id: header
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
|
||||||
ButtonGroup {
|
headerText: qsTr("Choose language")
|
||||||
id: buttonGroup
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate: Item {
|
ListView {
|
||||||
implicitWidth: root.width
|
id: listView
|
||||||
implicitHeight: delegateContent.implicitHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
Layout.fillWidth: true
|
||||||
id: delegateContent
|
height: listView.contentItem.height
|
||||||
|
|
||||||
anchors.fill: parent
|
clip: true
|
||||||
|
interactive: false
|
||||||
|
|
||||||
RadioButton {
|
model: LanguageModel
|
||||||
id: radioButton
|
currentIndex: LanguageModel.currentLanguageIndex
|
||||||
|
|
||||||
implicitWidth: parent.width
|
ButtonGroup {
|
||||||
implicitHeight: radioButtonContent.implicitHeight
|
id: buttonGroup
|
||||||
|
}
|
||||||
|
|
||||||
hoverEnabled: true
|
delegate: Item {
|
||||||
|
implicitWidth: root.width
|
||||||
|
implicitHeight: delegateContent.implicitHeight
|
||||||
|
|
||||||
indicator: Rectangle {
|
ColumnLayout {
|
||||||
anchors.fill: parent
|
id: delegateContent
|
||||||
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
|
|
||||||
|
|
||||||
Behavior on color {
|
anchors.fill: parent
|
||||||
PropertyAnimation { duration: 200 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
RadioButton {
|
||||||
id: radioButtonContent
|
id: radioButton
|
||||||
anchors.fill: parent
|
|
||||||
|
|
||||||
anchors.rightMargin: 16
|
implicitWidth: parent.width
|
||||||
anchors.leftMargin: 16
|
implicitHeight: radioButtonContent.implicitHeight
|
||||||
|
|
||||||
spacing: 0
|
hoverEnabled: true
|
||||||
|
|
||||||
z: 1
|
indicator: Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
|
||||||
|
|
||||||
ParagraphTextType {
|
Behavior on color {
|
||||||
Layout.fillWidth: true
|
PropertyAnimation { duration: 200 }
|
||||||
Layout.topMargin: 20
|
}
|
||||||
Layout.bottomMargin: 20
|
|
||||||
|
|
||||||
text: languageName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
RowLayout {
|
||||||
source: "qrc:/images/controls/check.svg"
|
id: radioButtonContent
|
||||||
visible: radioButton.checked
|
anchors.fill: parent
|
||||||
|
|
||||||
width: 24
|
anchors.rightMargin: 16
|
||||||
height: 24
|
anchors.leftMargin: 16
|
||||||
|
|
||||||
Layout.rightMargin: 8
|
spacing: 0
|
||||||
|
|
||||||
|
z: 1
|
||||||
|
|
||||||
|
ParagraphTextType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 20
|
||||||
|
Layout.bottomMargin: 20
|
||||||
|
|
||||||
|
text: languageName
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
source: "qrc:/images/controls/check.svg"
|
||||||
|
visible: radioButton.checked
|
||||||
|
|
||||||
|
width: 24
|
||||||
|
height: 24
|
||||||
|
|
||||||
|
Layout.rightMargin: 8
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ButtonGroup.group: buttonGroup
|
ButtonGroup.group: buttonGroup
|
||||||
checked: listView.currentIndex === index
|
checked: listView.currentIndex === index
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
listView.currentIndex = index
|
listView.currentIndex = index
|
||||||
LanguageModel.changeLanguage(languageIndex)
|
LanguageModel.changeLanguage(languageIndex)
|
||||||
root.close()
|
root.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,19 +16,18 @@ import "../Controls2/TextTypes"
|
|||||||
import "../Config"
|
import "../Config"
|
||||||
import "../Components"
|
import "../Components"
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property alias headerText: header.headerText
|
property string headerText
|
||||||
property alias configContentHeaderText: configContentHeader.headerText
|
property string configContentHeaderText
|
||||||
property alias contentVisible: content.visible
|
property string contentVisible
|
||||||
|
|
||||||
property string configExtension: ".vpn"
|
property string configExtension: ".vpn"
|
||||||
property string configCaption: qsTr("Save AmneziaVPN config")
|
property string configCaption: qsTr("Save AmneziaVPN config")
|
||||||
property string configFileName: "amnezia_config"
|
property string configFileName: "amnezia_config"
|
||||||
|
|
||||||
width: parent.width
|
expandedHeight: parent.height * 0.9
|
||||||
height: parent.height * 0.9
|
|
||||||
|
|
||||||
onClosed: {
|
onClosed: {
|
||||||
configExtension = ".vpn"
|
configExtension = ".vpn"
|
||||||
@@ -36,8 +35,8 @@ DrawerType {
|
|||||||
configFileName = "amnezia_config"
|
configFileName = "amnezia_config"
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
expandedContent: Item {
|
||||||
anchors.fill: parent
|
implicitHeight: root.expandedHeight
|
||||||
|
|
||||||
Header2Type {
|
Header2Type {
|
||||||
id: header
|
id: header
|
||||||
@@ -47,6 +46,8 @@ DrawerType {
|
|||||||
anchors.topMargin: 20
|
anchors.topMargin: 20
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
headerText: root.headerText
|
||||||
}
|
}
|
||||||
|
|
||||||
FlickableType {
|
FlickableType {
|
||||||
@@ -64,6 +65,8 @@ DrawerType {
|
|||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
visible: root.contentVisible
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
@@ -71,7 +74,7 @@ DrawerType {
|
|||||||
text: qsTr("Share")
|
text: qsTr("Share")
|
||||||
imageSource: "qrc:/images/controls/share-2.svg"
|
imageSource: "qrc:/images/controls/share-2.svg"
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
var fileName = ""
|
var fileName = ""
|
||||||
if (GC.isMobile()) {
|
if (GC.isMobile()) {
|
||||||
fileName = configFileName + configExtension
|
fileName = configFileName + configExtension
|
||||||
@@ -91,6 +94,7 @@ DrawerType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: copyConfigTextButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
Layout.topMargin: 8
|
||||||
|
|
||||||
@@ -103,20 +107,14 @@ DrawerType {
|
|||||||
|
|
||||||
text: qsTr("Copy")
|
text: qsTr("Copy")
|
||||||
imageSource: "qrc:/images/controls/copy.svg"
|
imageSource: "qrc:/images/controls/copy.svg"
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
configText.selectAll()
|
|
||||||
configText.copy()
|
|
||||||
configText.select(0, 0)
|
|
||||||
PageController.showNotificationMessage(qsTr("Copied"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: copyNativeConfigStringButton
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 8
|
Layout.topMargin: 8
|
||||||
|
|
||||||
visible: nativeConfigString.text !== ""
|
visible: false
|
||||||
|
|
||||||
defaultColor: "transparent"
|
defaultColor: "transparent"
|
||||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||||
@@ -127,13 +125,6 @@ DrawerType {
|
|||||||
|
|
||||||
text: qsTr("Copy config string")
|
text: qsTr("Copy config string")
|
||||||
imageSource: "qrc:/images/controls/copy.svg"
|
imageSource: "qrc:/images/controls/copy.svg"
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
nativeConfigString.selectAll()
|
|
||||||
nativeConfigString.copy()
|
|
||||||
nativeConfigString.select(0, 0)
|
|
||||||
PageController.showNotificationMessage(qsTr("Copied"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
@@ -149,83 +140,117 @@ DrawerType {
|
|||||||
|
|
||||||
text: qsTr("Show connection settings")
|
text: qsTr("Show connection settings")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
configContentDrawer.visible = true
|
configContentDrawer.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: configContentDrawer
|
id: configContentDrawer
|
||||||
|
|
||||||
width: parent.width
|
parent: root.parent
|
||||||
height: parent.height * 0.9
|
|
||||||
|
|
||||||
BackButtonType {
|
anchors.fill: parent
|
||||||
id: backButton
|
expandedHeight: parent.height * 0.9
|
||||||
|
|
||||||
anchors.top: parent.top
|
expandedContent: Item {
|
||||||
anchors.left: parent.left
|
id: configContentContainer
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
backButtonFunction: function() {
|
implicitHeight: configContentDrawer.expandedHeight
|
||||||
configContentDrawer.visible = false
|
|
||||||
|
Connections {
|
||||||
|
target: copyNativeConfigStringButton
|
||||||
|
function onClicked() {
|
||||||
|
nativeConfigString.selectAll()
|
||||||
|
nativeConfigString.copy()
|
||||||
|
nativeConfigString.select(0, 0)
|
||||||
|
PageController.showNotificationMessage(qsTr("Copied"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
Connections {
|
||||||
anchors.top: backButton.bottom
|
target: copyConfigTextButton
|
||||||
anchors.left: parent.left
|
function onClicked() {
|
||||||
anchors.right: parent.right
|
configText.selectAll()
|
||||||
anchors.bottom: parent.bottom
|
configText.copy()
|
||||||
contentHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
|
configText.select(0, 0)
|
||||||
|
PageController.showNotificationMessage(qsTr("Copied"))
|
||||||
ColumnLayout {
|
|
||||||
id: configContent
|
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
id: configContentHeader
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextField {
|
BackButtonType {
|
||||||
id: nativeConfigString
|
id: backButton
|
||||||
visible: false
|
|
||||||
text: ExportController.nativeConfigString
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
|
backButtonFunction: function() {
|
||||||
|
configContentDrawer.close()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextArea {
|
FlickableType {
|
||||||
id: configText
|
anchors.top: backButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
contentHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
|
||||||
|
|
||||||
Layout.fillWidth: true
|
ColumnLayout {
|
||||||
Layout.topMargin: 16
|
id: configContent
|
||||||
Layout.bottomMargin: 16
|
|
||||||
|
|
||||||
padding: 0
|
anchors.fill: parent
|
||||||
leftPadding: 0
|
anchors.rightMargin: 16
|
||||||
height: 24
|
anchors.leftMargin: 16
|
||||||
|
|
||||||
readOnly: true
|
Header2Type {
|
||||||
|
id: configContentHeader
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
color: "#D7D8DB"
|
headerText: root.configContentHeaderText
|
||||||
selectionColor: "#633303"
|
}
|
||||||
selectedTextColor: "#D7D8DB"
|
|
||||||
|
|
||||||
font.pixelSize: 16
|
TextField {
|
||||||
font.weight: Font.Medium
|
id: nativeConfigString
|
||||||
font.family: "PT Root UI VF"
|
visible: false
|
||||||
|
text: ExportController.nativeConfigString
|
||||||
|
|
||||||
text: ExportController.config
|
onTextChanged: {
|
||||||
|
copyNativeConfigStringButton.visible = nativeConfigString.text !== ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wrapMode: Text.Wrap
|
TextArea {
|
||||||
|
id: configText
|
||||||
|
|
||||||
background: Rectangle {
|
Layout.fillWidth: true
|
||||||
color: "transparent"
|
Layout.topMargin: 16
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
|
||||||
|
padding: 0
|
||||||
|
leftPadding: 0
|
||||||
|
height: 24
|
||||||
|
|
||||||
|
readOnly: true
|
||||||
|
|
||||||
|
color: "#D7D8DB"
|
||||||
|
selectionColor: "#633303"
|
||||||
|
selectedTextColor: "#D7D8DB"
|
||||||
|
|
||||||
|
font.pixelSize: 16
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.family: "PT Root UI VF"
|
||||||
|
|
||||||
|
text: ExportController.config
|
||||||
|
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,47 +16,39 @@ Button {
|
|||||||
property string textColor: "#0E0E11"
|
property string textColor: "#0E0E11"
|
||||||
|
|
||||||
property string borderColor: "#D7D8DB"
|
property string borderColor: "#D7D8DB"
|
||||||
|
property string borderFocusedColor: "#D7D8DB"
|
||||||
property int borderWidth: 0
|
property int borderWidth: 0
|
||||||
|
property int borderFocusedWidth: 1
|
||||||
|
|
||||||
property string imageSource
|
property string imageSource
|
||||||
|
property string rightImageSource
|
||||||
|
property string leftImageColor: textColor
|
||||||
|
|
||||||
property bool squareLeftSide: false
|
property bool squareLeftSide: false
|
||||||
|
|
||||||
|
property var clickedFunc
|
||||||
|
|
||||||
implicitHeight: 56
|
implicitHeight: 56
|
||||||
|
|
||||||
hoverEnabled: true
|
hoverEnabled: true
|
||||||
|
|
||||||
background: Rectangle {
|
background: Rectangle {
|
||||||
id: background
|
id: background_border
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
|
||||||
|
border.width: root.activeFocus ? root.borderFocusedWidth : "transparent"
|
||||||
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
radius: 16
|
radius: 16
|
||||||
color: {
|
|
||||||
if (root.enabled) {
|
|
||||||
if (root.pressed) {
|
|
||||||
return pressedColor
|
|
||||||
}
|
|
||||||
return root.hovered ? hoveredColor : defaultColor
|
|
||||||
} else {
|
|
||||||
return disabledColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
border.color: borderColor
|
|
||||||
border.width: borderWidth
|
|
||||||
|
|
||||||
Behavior on color {
|
|
||||||
PropertyAnimation { duration: 200 }
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
visible: root.squareLeftSide
|
id: background
|
||||||
|
|
||||||
z: 1
|
anchors.fill: background_border
|
||||||
|
anchors.margins: root.activeFocus ? 2: 0
|
||||||
|
|
||||||
width: parent.radius
|
radius: 16
|
||||||
height: parent.radius
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
color: {
|
color: {
|
||||||
if (root.enabled) {
|
if (root.enabled) {
|
||||||
if (root.pressed) {
|
if (root.pressed) {
|
||||||
@@ -67,24 +59,53 @@ Button {
|
|||||||
return disabledColor
|
return disabledColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
border.color: root.activeFocus ? "transparent" : borderColor
|
||||||
|
border.width: root.activeFocus ? 0 : borderWidth
|
||||||
|
|
||||||
Behavior on color {
|
Behavior on color {
|
||||||
PropertyAnimation { duration: 200 }
|
PropertyAnimation { duration: 200 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
visible: root.squareLeftSide
|
||||||
|
|
||||||
|
z: 1
|
||||||
|
|
||||||
|
width: parent.radius
|
||||||
|
height: parent.radius
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
color: {
|
||||||
|
if (root.enabled) {
|
||||||
|
if (root.pressed) {
|
||||||
|
return pressedColor
|
||||||
|
}
|
||||||
|
return root.hovered ? hoveredColor : defaultColor
|
||||||
|
} else {
|
||||||
|
return disabledColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
PropertyAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: background
|
anchors.fill: background_border
|
||||||
enabled: false
|
enabled: false
|
||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
contentItem: Item {
|
contentItem: Item {
|
||||||
anchors.fill: background
|
anchors.fill: background_border
|
||||||
|
|
||||||
implicitWidth: content.implicitWidth
|
implicitWidth: content.implicitWidth
|
||||||
implicitHeight: content.implicitHeight
|
implicitHeight: content.implicitHeight
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: content
|
id: content
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
@@ -99,7 +120,7 @@ Button {
|
|||||||
layer {
|
layer {
|
||||||
enabled: true
|
enabled: true
|
||||||
effect: ColorOverlay {
|
effect: ColorOverlay {
|
||||||
color: textColor
|
color: leftImageColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -112,6 +133,39 @@ Button {
|
|||||||
horizontalAlignment: Text.AlignLeft
|
horizontalAlignment: Text.AlignLeft
|
||||||
verticalAlignment: Text.AlignVCenter
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onEnterPressed: {
|
||||||
|
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||||
|
root.clickedFunc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||||
|
root.clickedFunc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||||
|
root.clickedFunc()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
import QtQuick
|
|
||||||
import QtQuick.Controls
|
|
||||||
|
|
||||||
import "../Config"
|
|
||||||
|
|
||||||
Drawer {
|
|
||||||
id: drawer
|
|
||||||
property bool needCloseButton: true
|
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: PageController
|
|
||||||
|
|
||||||
function onForceCloseDrawer() {
|
|
||||||
visible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
edge: Qt.BottomEdge
|
|
||||||
|
|
||||||
clip: true
|
|
||||||
modal: true
|
|
||||||
dragMargin: -10
|
|
||||||
|
|
||||||
enter: Transition {
|
|
||||||
SmoothedAnimation {
|
|
||||||
velocity: 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
exit: Transition {
|
|
||||||
SmoothedAnimation {
|
|
||||||
velocity: 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
background: Rectangle {
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.bottomMargin: -radius
|
|
||||||
radius: 16
|
|
||||||
color: "#1C1D21"
|
|
||||||
|
|
||||||
border.color: "#2C2D30"
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
visible: GC.isMobile()
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
|
||||||
anchors.topMargin: 10
|
|
||||||
|
|
||||||
width: 20
|
|
||||||
height: 2
|
|
||||||
color: "#2C2D30"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Overlay.modal: Rectangle {
|
|
||||||
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
|
||||||
}
|
|
||||||
|
|
||||||
onAboutToShow: {
|
|
||||||
if (PageController.getInitialPageNavigationBarColor() !== 0xFF1C1D21) {
|
|
||||||
PageController.updateNavigationBarColor(0xFF1C1D21)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onOpened: {
|
|
||||||
if (needCloseButton) {
|
|
||||||
PageController.drawerOpen()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onClosed: {
|
|
||||||
if (needCloseButton) {
|
|
||||||
PageController.drawerClose()
|
|
||||||
}
|
|
||||||
|
|
||||||
var initialPageNavigationBarColor = PageController.getInitialPageNavigationBarColor()
|
|
||||||
if (initialPageNavigationBarColor !== 0xFF1C1D21) {
|
|
||||||
PageController.updateNavigationBarColor(initialPageNavigationBarColor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
import QtQuick
|
||||||
|
import QtQuick.Controls
|
||||||
|
import QtQuick.Layouts
|
||||||
|
|
||||||
|
import "TextTypes"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
readonly property string drawerExpanded: "expanded"
|
||||||
|
readonly property string drawerCollapsed: "collapsed"
|
||||||
|
|
||||||
|
readonly property bool isOpened: drawerContent.state === root.drawerExpanded || (drawerContent.state === root.drawerCollapsed && dragArea.drag.active === true)
|
||||||
|
readonly property bool isClosed: drawerContent.state === root.drawerCollapsed && dragArea.drag.active === false
|
||||||
|
|
||||||
|
readonly property bool isExpanded: drawerContent.state === root.drawerExpanded
|
||||||
|
readonly property bool isCollapsed: drawerContent.state === root.drawerCollapsed
|
||||||
|
|
||||||
|
property Component collapsedContent
|
||||||
|
property Component expandedContent
|
||||||
|
|
||||||
|
property string defaultColor: "#1C1D21"
|
||||||
|
property string borderColor: "#2C2D30"
|
||||||
|
|
||||||
|
property real expandedHeight
|
||||||
|
property real collapsedHeight: 0
|
||||||
|
|
||||||
|
signal entered
|
||||||
|
signal exited
|
||||||
|
signal pressed(bool pressed, bool entered)
|
||||||
|
|
||||||
|
signal aboutToHide
|
||||||
|
signal aboutToShow
|
||||||
|
signal close
|
||||||
|
signal open
|
||||||
|
signal closed
|
||||||
|
signal opened
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: root
|
||||||
|
|
||||||
|
function onClose() {
|
||||||
|
if (isCollapsed) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToHide()
|
||||||
|
|
||||||
|
drawerContent.state = root.drawerCollapsed
|
||||||
|
closed()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOpen() {
|
||||||
|
if (isExpanded) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToShow()
|
||||||
|
|
||||||
|
drawerContent.state = root.drawerExpanded
|
||||||
|
opened()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set once based on first implicit height change once all children are layed out */
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (root.isCollapsed && root.collapsedHeight == 0) {
|
||||||
|
root.collapsedHeight = drawerContent.implicitHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: background
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
color: root.isCollapsed ? "transparent" : Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
PropertyAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: emptyArea
|
||||||
|
anchors.fill: parent
|
||||||
|
enabled: root.isExpanded
|
||||||
|
visible: enabled
|
||||||
|
onClicked: {
|
||||||
|
root.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: dragArea
|
||||||
|
|
||||||
|
anchors.fill: drawerContentBackground
|
||||||
|
cursorShape: root.isCollapsed ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||||
|
hoverEnabled: true
|
||||||
|
|
||||||
|
enabled: drawerContent.implicitHeight > 0
|
||||||
|
|
||||||
|
drag.target: drawerContent
|
||||||
|
drag.axis: Drag.YAxis
|
||||||
|
drag.maximumY: root.height - root.collapsedHeight
|
||||||
|
drag.minimumY: root.height - root.expandedHeight
|
||||||
|
|
||||||
|
/** If drag area is released at any point other than min or max y, transition to the other state */
|
||||||
|
onReleased: {
|
||||||
|
if (root.isCollapsed && drawerContent.y < dragArea.drag.maximumY) {
|
||||||
|
root.open()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (root.isExpanded && drawerContent.y > dragArea.drag.minimumY) {
|
||||||
|
root.close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onEntered: {
|
||||||
|
root.entered()
|
||||||
|
}
|
||||||
|
onExited: {
|
||||||
|
root.exited()
|
||||||
|
}
|
||||||
|
onPressedChanged: {
|
||||||
|
root.pressed(pressed, entered)
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.isCollapsed) {
|
||||||
|
root.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: drawerContentBackground
|
||||||
|
|
||||||
|
anchors { left: drawerContent.left; right: drawerContent.right; top: drawerContent.top }
|
||||||
|
height: root.height
|
||||||
|
radius: 16
|
||||||
|
color: root.defaultColor
|
||||||
|
border.color: root.borderColor
|
||||||
|
border.width: 1
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
width: parent.radius
|
||||||
|
height: parent.radius
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
color: parent.color
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: drawerContent
|
||||||
|
|
||||||
|
Drag.active: dragArea.drag.active
|
||||||
|
anchors.right: root.right
|
||||||
|
anchors.left: root.left
|
||||||
|
y: root.height - drawerContent.height
|
||||||
|
state: root.drawerCollapsed
|
||||||
|
|
||||||
|
implicitHeight: root.isCollapsed ? collapsedLoader.implicitHeight : expandedLoader.implicitHeight
|
||||||
|
|
||||||
|
onStateChanged: {
|
||||||
|
if (root.isCollapsed) {
|
||||||
|
var initialPageNavigationBarColor = PageController.getInitialPageNavigationBarColor()
|
||||||
|
if (initialPageNavigationBarColor !== 0xFF1C1D21) {
|
||||||
|
PageController.updateNavigationBarColor(initialPageNavigationBarColor)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (root.isExpanded) {
|
||||||
|
if (PageController.getInitialPageNavigationBarColor() !== 0xFF1C1D21) {
|
||||||
|
PageController.updateNavigationBarColor(0xFF1C1D21)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: root.drawerCollapsed
|
||||||
|
PropertyChanges {
|
||||||
|
target: drawerContent
|
||||||
|
y: root.height - root.collapsedHeight
|
||||||
|
}
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: root.drawerExpanded
|
||||||
|
PropertyChanges {
|
||||||
|
target: drawerContent
|
||||||
|
y: dragArea.drag.minimumY
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
transitions: [
|
||||||
|
Transition {
|
||||||
|
from: root.drawerCollapsed
|
||||||
|
to: root.drawerExpanded
|
||||||
|
PropertyAnimation {
|
||||||
|
target: drawerContent
|
||||||
|
properties: "y"
|
||||||
|
duration: 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Transition {
|
||||||
|
from: root.drawerExpanded
|
||||||
|
to: root.drawerCollapsed
|
||||||
|
PropertyAnimation {
|
||||||
|
target: drawerContent
|
||||||
|
properties: "y"
|
||||||
|
duration: 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: collapsedLoader
|
||||||
|
|
||||||
|
visible: root.isCollapsed
|
||||||
|
sourceComponent: root.collapsedContent
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: expandedLoader
|
||||||
|
|
||||||
|
visible: root.isExpanded
|
||||||
|
sourceComponent: root.expandedContent
|
||||||
|
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -36,19 +36,23 @@ Item {
|
|||||||
property int rootButtonTextBottomMargin: 16
|
property int rootButtonTextBottomMargin: 16
|
||||||
|
|
||||||
property real drawerHeight: 0.9
|
property real drawerHeight: 0.9
|
||||||
|
property Item drawerParent
|
||||||
property Component listView
|
property Component listView
|
||||||
|
|
||||||
property alias menuVisible: menu.visible
|
signal open
|
||||||
|
signal close
|
||||||
|
|
||||||
implicitWidth: rootButtonContent.implicitWidth
|
implicitWidth: rootButtonContent.implicitWidth
|
||||||
implicitHeight: rootButtonContent.implicitHeight
|
implicitHeight: rootButtonContent.implicitHeight
|
||||||
|
|
||||||
onMenuVisibleChanged: {
|
onOpen: {
|
||||||
if (menuVisible) {
|
menu.open()
|
||||||
rootButtonBackground.border.color = rootButtonPressedBorderColor
|
rootButtonBackground.border.color = rootButtonPressedBorderColor
|
||||||
} else {
|
}
|
||||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
|
||||||
}
|
onClose: {
|
||||||
|
menu.close()
|
||||||
|
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||||
}
|
}
|
||||||
|
|
||||||
onEnabledChanged: {
|
onEnabledChanged: {
|
||||||
@@ -133,21 +137,21 @@ Item {
|
|||||||
hoverEnabled: root.enabled ? true : false
|
hoverEnabled: root.enabled ? true : false
|
||||||
|
|
||||||
onEntered: {
|
onEntered: {
|
||||||
if (menu.visible === false) {
|
if (menu.isClosed) {
|
||||||
rootButtonBackground.border.color = rootButtonHoveredBorderColor
|
rootButtonBackground.border.color = rootButtonHoveredBorderColor
|
||||||
rootButtonBackground.color = rootButtonBackgroundHoveredColor
|
rootButtonBackground.color = rootButtonBackgroundHoveredColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onExited: {
|
onExited: {
|
||||||
if (menu.visible === false) {
|
if (menu.isClosed) {
|
||||||
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
rootButtonBackground.border.color = rootButtonDefaultBorderColor
|
||||||
rootButtonBackground.color = rootButtonBackgroundColor
|
rootButtonBackground.color = rootButtonBackgroundColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onPressed: {
|
onPressed: {
|
||||||
if (menu.visible === false) {
|
if (menu.isClosed) {
|
||||||
rootButtonBackground.color = pressed ? rootButtonBackgroundPressedColor : entered ? rootButtonHoveredBorderColor : rootButtonDefaultBorderColor
|
rootButtonBackground.color = pressed ? rootButtonBackgroundPressedColor : entered ? rootButtonHoveredBorderColor : rootButtonDefaultBorderColor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,60 +160,68 @@ Item {
|
|||||||
if (rootButtonClickedFunction && typeof rootButtonClickedFunction === "function") {
|
if (rootButtonClickedFunction && typeof rootButtonClickedFunction === "function") {
|
||||||
rootButtonClickedFunction()
|
rootButtonClickedFunction()
|
||||||
} else {
|
} else {
|
||||||
menu.visible = true
|
menu.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: menu
|
id: menu
|
||||||
|
|
||||||
width: parent.width
|
parent: drawerParent
|
||||||
height: parent.height * drawerHeight
|
|
||||||
|
|
||||||
ColumnLayout {
|
anchors.fill: parent
|
||||||
id: header
|
expandedHeight: drawerParent.height * drawerHeight
|
||||||
|
|
||||||
anchors.top: parent.top
|
expandedContent: Item {
|
||||||
anchors.left: parent.left
|
id: container
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
BackButtonType {
|
implicitHeight: menu.expandedHeight
|
||||||
backButtonImage: root.headerBackButtonImage
|
|
||||||
backButtonFunction: function() {
|
|
||||||
root.menuVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
ColumnLayout {
|
||||||
anchors.top: header.bottom
|
id: header
|
||||||
anchors.topMargin: 16
|
|
||||||
contentHeight: col.implicitHeight
|
|
||||||
|
|
||||||
Column {
|
|
||||||
id: col
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
spacing: 16
|
BackButtonType {
|
||||||
|
backButtonImage: root.headerBackButtonImage
|
||||||
|
backButtonFunction: function() {
|
||||||
|
menu.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Header2Type {
|
FlickableType {
|
||||||
|
anchors.top: header.bottom
|
||||||
|
anchors.topMargin: 16
|
||||||
|
contentHeight: col.implicitHeight
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: col
|
||||||
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.leftMargin: 16
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
|
|
||||||
headerText: root.headerText
|
spacing: 16
|
||||||
|
|
||||||
width: parent.width
|
Header2Type {
|
||||||
}
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
Loader {
|
headerText: root.headerText
|
||||||
id: listViewLoader
|
|
||||||
sourceComponent: root.listView
|
width: parent.width
|
||||||
|
}
|
||||||
|
|
||||||
|
Loader {
|
||||||
|
id: listViewLoader
|
||||||
|
sourceComponent: root.listView
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ Item {
|
|||||||
|
|
||||||
property StackView stackView: StackView.view
|
property StackView stackView: StackView.view
|
||||||
|
|
||||||
|
property var defaultActiveFocusItem: null
|
||||||
|
|
||||||
// MouseArea {
|
// MouseArea {
|
||||||
// id: globalMouseArea
|
// id: globalMouseArea
|
||||||
// z: 99
|
// z: 99
|
||||||
@@ -19,4 +21,17 @@ Item {
|
|||||||
// mouse.accepted = false
|
// mouse.accepted = false
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// Set a timer to set focus after a short delay
|
||||||
|
Timer {
|
||||||
|
id: timer
|
||||||
|
interval: 100 // Milliseconds
|
||||||
|
onTriggered: {
|
||||||
|
if (defaultActiveFocusItem) {
|
||||||
|
defaultActiveFocusItem.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repeat: false // Stop the timer after one trigger
|
||||||
|
running: true // Start the timer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ Popup {
|
|||||||
borderWidth: 0
|
borderWidth: 0
|
||||||
|
|
||||||
text: qsTr("Close")
|
text: qsTr("Close")
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
root.close()
|
root.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,10 +69,13 @@ Item {
|
|||||||
|
|
||||||
TextField {
|
TextField {
|
||||||
id: textField
|
id: textField
|
||||||
|
activeFocusOnTab: false
|
||||||
|
|
||||||
enabled: root.textFieldEditable
|
enabled: root.textFieldEditable
|
||||||
color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor
|
color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor
|
||||||
|
|
||||||
|
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhSensitiveData | Qt.ImhNoPredictiveText
|
||||||
|
|
||||||
placeholderText: root.textFieldPlaceholderText
|
placeholderText: root.textFieldPlaceholderText
|
||||||
placeholderTextColor: "#494B50"
|
placeholderTextColor: "#494B50"
|
||||||
|
|
||||||
@@ -142,7 +145,7 @@ Item {
|
|||||||
Layout.preferredWidth: content.implicitHeight
|
Layout.preferredWidth: content.implicitHeight
|
||||||
squareLeftSide: true
|
squareLeftSide: true
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
if (root.clickedFunc && typeof root.clickedFunc === "function") {
|
||||||
root.clickedFunc()
|
root.clickedFunc()
|
||||||
}
|
}
|
||||||
@@ -186,4 +189,12 @@ Item {
|
|||||||
function getBackgroundBorderColor(noneFocusedColor) {
|
function getBackgroundBorderColor(noneFocusedColor) {
|
||||||
return textField.focus ? root.borderFocusedColor : noneFocusedColor
|
return textField.focus ? root.borderFocusedColor : noneFocusedColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Keys.onEnterPressed: {
|
||||||
|
KeyNavigation.tab.forceActiveFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReturnPressed: {
|
||||||
|
KeyNavigation.tab.forceActiveFocus();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+318
-419
@@ -18,484 +18,383 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property string defaultColor: "#1C1D21"
|
|
||||||
|
|
||||||
property string borderColor: "#2C2D30"
|
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: PageController
|
target: PageController
|
||||||
|
|
||||||
function onRestorePageHomeState(isContainerInstalled) {
|
function onRestorePageHomeState(isContainerInstalled) {
|
||||||
buttonContent.state = "expanded"
|
drawer.open()
|
||||||
if (isContainerInstalled) {
|
if (isContainerInstalled) {
|
||||||
containersDropDown.rootButtonClickedFunction()
|
containersDropDown.rootButtonClickedFunction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onForceCloseDrawer() {
|
|
||||||
buttonContent.state = "collapsed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
enabled: buttonContent.state === "expanded"
|
|
||||||
onClicked: {
|
|
||||||
buttonContent.state = "collapsed"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.bottomMargin: buttonContent.collapsedHeight
|
anchors.bottomMargin: drawer.collapsedHeight
|
||||||
|
|
||||||
ConnectButton {
|
ConnectButton {
|
||||||
|
id: connectButton
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
BasicButtonType {
|
||||||
id: dragArea
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
|
||||||
anchors.fill: buttonBackground
|
|
||||||
cursorShape: buttonContent.state === "collapsed" ? Qt.PointingHandCursor : Qt.ArrowCursor
|
|
||||||
hoverEnabled: true
|
|
||||||
|
|
||||||
drag.target: buttonContent
|
|
||||||
drag.axis: Drag.YAxis
|
|
||||||
drag.maximumY: root.height - buttonContent.collapsedHeight
|
|
||||||
drag.minimumY: root.height - root.height * 0.9
|
|
||||||
|
|
||||||
/** If drag area is released at any point other than min or max y, transition to the other state */
|
|
||||||
onReleased: {
|
|
||||||
if (buttonContent.state === "collapsed" && buttonContent.y < dragArea.drag.maximumY) {
|
|
||||||
buttonContent.state = "expanded"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (buttonContent.state === "expanded" && buttonContent.y > dragArea.drag.minimumY) {
|
|
||||||
buttonContent.state = "collapsed"
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onEntered: {
|
|
||||||
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.hoveredColor
|
|
||||||
collapsedButtonHeader.opacity = 0.8
|
|
||||||
}
|
|
||||||
onExited: {
|
|
||||||
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.defaultColor
|
|
||||||
collapsedButtonHeader.opacity = 1
|
|
||||||
}
|
|
||||||
onPressedChanged: {
|
|
||||||
collapsedButtonChevron.backgroundColor = pressed ? collapsedButtonChevron.pressedColor : entered ? collapsedButtonChevron.hoveredColor : collapsedButtonChevron.defaultColor
|
|
||||||
collapsedButtonHeader.opacity = 0.7
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (buttonContent.state === "collapsed") {
|
|
||||||
buttonContent.state = "expanded"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
id: buttonBackground
|
|
||||||
|
|
||||||
anchors { left: buttonContent.left; right: buttonContent.right; top: buttonContent.top }
|
|
||||||
height: root.height
|
|
||||||
radius: 16
|
|
||||||
color: root.defaultColor
|
|
||||||
border.color: root.borderColor
|
|
||||||
border.width: 1
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
width: parent.radius
|
|
||||||
height: parent.radius
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.right: parent.right
|
anchors.bottomMargin: 34
|
||||||
anchors.left: parent.left
|
leftPadding: 16
|
||||||
color: parent.color
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: buttonContent
|
|
||||||
|
|
||||||
/** Initial height of button content */
|
DrawerType2 {
|
||||||
property int collapsedHeight: 0
|
id: drawer
|
||||||
/** True when expanded objects should be visible */
|
anchors.fill: parent
|
||||||
property bool expandedVisibility: buttonContent.state === "expanded" || (buttonContent.state === "collapsed" && dragArea.drag.active === true)
|
|
||||||
/** True when collapsed objects should be visible */
|
|
||||||
property bool collapsedVisibility: buttonContent.state === "collapsed" && dragArea.drag.active === false
|
|
||||||
|
|
||||||
Drag.active: dragArea.drag.active
|
collapsedContent: ColumnLayout {
|
||||||
anchors.right: root.right
|
DividerType {
|
||||||
anchors.left: root.left
|
Layout.topMargin: 10
|
||||||
y: root.height - buttonContent.height
|
Layout.fillWidth: false
|
||||||
|
Layout.preferredWidth: 20
|
||||||
Component.onCompleted: {
|
Layout.preferredHeight: 2
|
||||||
buttonContent.state = "collapsed"
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
}
|
|
||||||
|
|
||||||
/** Set once based on first implicit height change once all children are layed out */
|
|
||||||
onImplicitHeightChanged: {
|
|
||||||
if (buttonContent.state === "collapsed" && collapsedHeight == 0) {
|
|
||||||
collapsedHeight = implicitHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onStateChanged: {
|
|
||||||
if (buttonContent.state === "collapsed") {
|
|
||||||
var initialPageNavigationBarColor = PageController.getInitialPageNavigationBarColor()
|
|
||||||
if (initialPageNavigationBarColor !== 0xFF1C1D21) {
|
|
||||||
PageController.updateNavigationBarColor(initialPageNavigationBarColor)
|
|
||||||
}
|
|
||||||
PageController.drawerClose()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (buttonContent.state === "expanded") {
|
|
||||||
if (PageController.getInitialPageNavigationBarColor() !== 0xFF1C1D21) {
|
|
||||||
PageController.updateNavigationBarColor(0xFF1C1D21)
|
|
||||||
}
|
|
||||||
PageController.drawerOpen()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Two states of buttonContent, great place to add any future animations for the drawer */
|
|
||||||
states: [
|
|
||||||
State {
|
|
||||||
name: "collapsed"
|
|
||||||
PropertyChanges {
|
|
||||||
target: buttonContent
|
|
||||||
y: root.height - collapsedHeight
|
|
||||||
}
|
|
||||||
},
|
|
||||||
State {
|
|
||||||
name: "expanded"
|
|
||||||
PropertyChanges {
|
|
||||||
target: buttonContent
|
|
||||||
y: dragArea.drag.minimumY
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
transitions: [
|
|
||||||
Transition {
|
|
||||||
from: "collapsed"
|
|
||||||
to: "expanded"
|
|
||||||
PropertyAnimation {
|
|
||||||
target: buttonContent
|
|
||||||
properties: "y"
|
|
||||||
duration: 200
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Transition {
|
|
||||||
from: "expanded"
|
|
||||||
to: "collapsed"
|
|
||||||
PropertyAnimation {
|
|
||||||
target: buttonContent
|
|
||||||
properties: "y"
|
|
||||||
duration: 200
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
Layout.topMargin: 10
|
|
||||||
Layout.fillWidth: false
|
|
||||||
Layout.preferredWidth: 20
|
|
||||||
Layout.preferredHeight: 2
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
|
||||||
|
|
||||||
visible: (buttonContent.collapsedVisibility || buttonContent.expandedVisibility)
|
|
||||||
}
|
|
||||||
|
|
||||||
RowLayout {
|
|
||||||
Layout.topMargin: 14
|
|
||||||
Layout.leftMargin: 24
|
|
||||||
Layout.rightMargin: 24
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
|
||||||
visible: buttonContent.collapsedVisibility
|
|
||||||
|
|
||||||
spacing: 0
|
|
||||||
|
|
||||||
Header1TextType {
|
|
||||||
id: collapsedButtonHeader
|
|
||||||
Layout.maximumWidth: buttonContent.width - 48 - 18 - 12 // todo
|
|
||||||
|
|
||||||
maximumLineCount: 2
|
|
||||||
elide: Qt.ElideRight
|
|
||||||
|
|
||||||
text: ServersModel.defaultServerName
|
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
|
||||||
|
|
||||||
Behavior on opacity {
|
|
||||||
PropertyAnimation { duration: 200 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageButtonType {
|
|
||||||
id: collapsedButtonChevron
|
|
||||||
|
|
||||||
Layout.leftMargin: 8
|
|
||||||
|
|
||||||
hoverEnabled: false
|
|
||||||
image: "qrc:/images/controls/chevron-down.svg"
|
|
||||||
imageColor: "#d7d8db"
|
|
||||||
|
|
||||||
icon.width: 18
|
|
||||||
icon.height: 18
|
|
||||||
backgroundRadius: 16
|
|
||||||
horizontalPadding: 4
|
|
||||||
topPadding: 4
|
|
||||||
bottomPadding: 3
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (buttonContent.state === "collapsed") {
|
|
||||||
buttonContent.state = "expanded"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelTextType {
|
|
||||||
id: collapsedServerMenuDescription
|
|
||||||
Layout.bottomMargin: 44
|
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
|
||||||
visible: buttonContent.collapsedVisibility
|
|
||||||
text: ServersModel.defaultServerDescriptionCollapsed
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: serversMenuHeader
|
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
|
||||||
Layout.fillWidth: true
|
|
||||||
visible: buttonContent.expandedVisibility
|
|
||||||
|
|
||||||
Header1TextType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 14
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
|
|
||||||
text: ServersModel.defaultServerName
|
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
|
||||||
maximumLineCount: 2
|
|
||||||
elide: Qt.ElideRight
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelTextType {
|
|
||||||
id: expandedServersMenuDescription
|
|
||||||
Layout.bottomMargin: 24
|
|
||||||
Layout.fillWidth: true
|
|
||||||
horizontalAlignment: Qt.AlignHCenter
|
|
||||||
verticalAlignment: Qt.AlignVCenter
|
|
||||||
text: ServersModel.defaultServerDescriptionExpanded
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
|
Layout.topMargin: 14
|
||||||
|
Layout.leftMargin: 24
|
||||||
|
Layout.rightMargin: 24
|
||||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
spacing: 8
|
|
||||||
|
|
||||||
DropDownType {
|
spacing: 0
|
||||||
id: containersDropDown
|
|
||||||
|
|
||||||
rootButtonImageColor: "#0E0E11"
|
Connections {
|
||||||
rootButtonBackgroundColor: "#D7D8DB"
|
target: drawer
|
||||||
rootButtonBackgroundHoveredColor: Qt.rgba(215, 216, 219, 0.8)
|
function onEntered() {
|
||||||
rootButtonBackgroundPressedColor: Qt.rgba(215, 216, 219, 0.65)
|
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.hoveredColor
|
||||||
rootButtonHoveredBorderColor: "transparent"
|
collapsedButtonHeader.opacity = 0.8
|
||||||
rootButtonDefaultBorderColor: "transparent"
|
|
||||||
rootButtonTextTopMargin: 8
|
|
||||||
rootButtonTextBottomMargin: 8
|
|
||||||
|
|
||||||
text: ServersModel.defaultContainerName
|
|
||||||
textColor: "#0E0E11"
|
|
||||||
headerText: qsTr("VPN protocol")
|
|
||||||
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
|
|
||||||
|
|
||||||
rootButtonClickedFunction: function() {
|
|
||||||
ServersModel.currentlyProcessedIndex = serversMenuContent.currentIndex
|
|
||||||
containersDropDown.menuVisible = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listView: HomeContainersListView {
|
function onExited() {
|
||||||
rootWidth: root.width
|
collapsedButtonChevron.backgroundColor = collapsedButtonChevron.defaultColor
|
||||||
|
collapsedButtonHeader.opacity = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function onPressed(pressed, entered) {
|
||||||
|
collapsedButtonChevron.backgroundColor = pressed ? collapsedButtonChevron.pressedColor : entered ? collapsedButtonChevron.hoveredColor : collapsedButtonChevron.defaultColor
|
||||||
|
collapsedButtonHeader.opacity = 0.7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Header1TextType {
|
||||||
|
id: collapsedButtonHeader
|
||||||
|
Layout.maximumWidth: drawer.width - 48 - 18 - 12 // todo
|
||||||
|
|
||||||
|
maximumLineCount: 2
|
||||||
|
elide: Qt.ElideRight
|
||||||
|
|
||||||
|
text: ServersModel.defaultServerName
|
||||||
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
Behavior on opacity {
|
||||||
|
PropertyAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageButtonType {
|
||||||
|
id: collapsedButtonChevron
|
||||||
|
|
||||||
|
Layout.leftMargin: 8
|
||||||
|
|
||||||
|
hoverEnabled: false
|
||||||
|
image: "qrc:/images/controls/chevron-down.svg"
|
||||||
|
imageColor: "#d7d8db"
|
||||||
|
|
||||||
|
icon.width: 18
|
||||||
|
icon.height: 18
|
||||||
|
backgroundRadius: 16
|
||||||
|
horizontalPadding: 4
|
||||||
|
topPadding: 4
|
||||||
|
bottomPadding: 3
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (drawer.isCollapsed) {
|
||||||
|
drawer.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelTextType {
|
||||||
|
id: collapsedServerMenuDescription
|
||||||
|
Layout.bottomMargin: 44
|
||||||
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
text: ServersModel.defaultServerDescriptionCollapsed
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
expandedContent: Item {
|
||||||
|
id: serverMenuContainer
|
||||||
|
|
||||||
|
implicitHeight: root.height * 0.9
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
drawer.expandedHeight = serverMenuContainer.implicitHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: serversMenuHeader
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
|
||||||
|
|
||||||
|
Header1TextType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 14
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
|
text: ServersModel.defaultServerName
|
||||||
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
|
maximumLineCount: 2
|
||||||
|
elide: Qt.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelTextType {
|
||||||
|
id: expandedServersMenuDescription
|
||||||
|
Layout.bottomMargin: ServersModel.isDefaultServerFromApi ? 69 : 24
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Qt.AlignHCenter
|
||||||
|
verticalAlignment: Qt.AlignVCenter
|
||||||
|
text: ServersModel.defaultServerDescriptionExpanded
|
||||||
|
}
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
visible: !ServersModel.isDefaultServerFromApi
|
||||||
|
onVisibleChanged: expandedServersMenuDescription.Layout
|
||||||
|
|
||||||
|
DropDownType {
|
||||||
|
id: containersDropDown
|
||||||
|
|
||||||
|
rootButtonImageColor: "#0E0E11"
|
||||||
|
rootButtonBackgroundColor: "#D7D8DB"
|
||||||
|
rootButtonBackgroundHoveredColor: Qt.rgba(215, 216, 219, 0.8)
|
||||||
|
rootButtonBackgroundPressedColor: Qt.rgba(215, 216, 219, 0.65)
|
||||||
|
rootButtonHoveredBorderColor: "transparent"
|
||||||
|
rootButtonDefaultBorderColor: "transparent"
|
||||||
|
rootButtonTextTopMargin: 8
|
||||||
|
rootButtonTextBottomMargin: 8
|
||||||
|
|
||||||
|
text: ServersModel.defaultServerDefaultContainerName
|
||||||
|
textColor: "#0E0E11"
|
||||||
|
headerText: qsTr("VPN protocol")
|
||||||
|
headerBackButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||||
|
|
||||||
|
rootButtonClickedFunction: function() {
|
||||||
|
containersDropDown.open()
|
||||||
|
}
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
|
listView: HomeContainersListView {
|
||||||
|
rootWidth: root.width
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: ServersModel
|
||||||
|
|
||||||
|
function onDefaultServerIndexChanged() {
|
||||||
|
updateContainersModelFilters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateContainersModelFilters() {
|
||||||
|
if (ServersModel.isDefaultServerHasWriteAccess()) {
|
||||||
|
proxyDefaultServerContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
||||||
|
} else {
|
||||||
|
proxyDefaultServerContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model: SortFilterProxyModel {
|
||||||
|
id: proxyDefaultServerContainersModel
|
||||||
|
sourceModel: DefaultServerContainersModel
|
||||||
|
|
||||||
|
sorters: [
|
||||||
|
RoleSorter { roleName: "isInstalled"; sortOrder: Qt.DescendingOrder }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: updateContainersModelFilters()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Header2Type {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 48
|
||||||
|
Layout.leftMargin: 16
|
||||||
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
|
headerText: qsTr("Servers")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Flickable {
|
||||||
|
id: serversContainer
|
||||||
|
|
||||||
|
anchors.top: serversMenuHeader.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
|
contentHeight: col.height + col.anchors.bottomMargin
|
||||||
|
implicitHeight: parent.height - serversMenuHeader.implicitHeight
|
||||||
|
clip: true
|
||||||
|
|
||||||
|
ScrollBar.vertical: ScrollBar {
|
||||||
|
id: scrollBar
|
||||||
|
policy: serversContainer.height >= serversContainer.contentHeight ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onUpPressed: scrollBar.decrease()
|
||||||
|
Keys.onDownPressed: scrollBar.increase()
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: col
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottomMargin: 32
|
||||||
|
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
ButtonGroup {
|
||||||
|
id: serversRadioButtonGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: serversMenuContent
|
||||||
|
width: parent.width
|
||||||
|
height: serversMenuContent.contentItem.height
|
||||||
|
|
||||||
|
model: ServersModel
|
||||||
|
currentIndex: ServersModel.defaultIndex
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: ServersModel
|
target: ServersModel
|
||||||
|
function onDefaultServerIndexChanged(serverIndex) {
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
serversMenuContent.currentIndex = serverIndex
|
||||||
updateContainersModelFilters()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateContainersModelFilters() {
|
clip: true
|
||||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
interactive: false
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
|
||||||
} else {
|
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
model: SortFilterProxyModel {
|
delegate: Item {
|
||||||
id: proxyContainersModel
|
id: menuContentDelegate
|
||||||
sourceModel: ContainersModel
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: updateContainersModelFilters()
|
property variant delegateData: model
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Header2Type {
|
implicitWidth: serversMenuContent.width
|
||||||
Layout.fillWidth: true
|
implicitHeight: serverRadioButtonContent.implicitHeight
|
||||||
Layout.topMargin: 48
|
|
||||||
Layout.leftMargin: 16
|
|
||||||
Layout.rightMargin: 16
|
|
||||||
visible: buttonContent.expandedVisibility
|
|
||||||
|
|
||||||
headerText: qsTr("Servers")
|
ColumnLayout {
|
||||||
}
|
id: serverRadioButtonContent
|
||||||
}
|
|
||||||
|
|
||||||
Flickable {
|
anchors.fill: parent
|
||||||
id: serversContainer
|
anchors.rightMargin: 16
|
||||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
anchors.leftMargin: 16
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
contentHeight: col.implicitHeight
|
|
||||||
implicitHeight: root.height - (root.height * 0.1) - serversMenuHeader.implicitHeight - 52 //todo 52 is tabbar height
|
|
||||||
visible: buttonContent.expandedVisibility
|
|
||||||
clip: true
|
|
||||||
|
|
||||||
ScrollBar.vertical: ScrollBar {
|
spacing: 0
|
||||||
id: scrollBar
|
|
||||||
policy: serversContainer.height >= serversContainer.contentHeight ? ScrollBar.AlwaysOff : ScrollBar.AlwaysOn
|
|
||||||
}
|
|
||||||
|
|
||||||
Keys.onUpPressed: scrollBar.decrease()
|
RowLayout {
|
||||||
Keys.onDownPressed: scrollBar.increase()
|
VerticalRadioButton {
|
||||||
|
id: serverRadioButton
|
||||||
|
|
||||||
Column {
|
Layout.fillWidth: true
|
||||||
id: col
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
spacing: 16
|
text: name
|
||||||
|
descriptionText: serverDescription
|
||||||
|
|
||||||
ButtonGroup {
|
checked: index === serversMenuContent.currentIndex
|
||||||
id: serversRadioButtonGroup
|
checkable: !ConnectionController.isConnected
|
||||||
}
|
|
||||||
|
|
||||||
ListView {
|
ButtonGroup.group: serversRadioButtonGroup
|
||||||
id: serversMenuContent
|
|
||||||
width: parent.width
|
|
||||||
height: serversMenuContent.contentItem.height
|
|
||||||
|
|
||||||
model: ServersModel
|
onClicked: {
|
||||||
currentIndex: ServersModel.defaultIndex
|
if (ConnectionController.isConnected) {
|
||||||
|
PageController.showNotificationMessage(qsTr("Unable change server while there is an active connection"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
Connections {
|
serversMenuContent.currentIndex = index
|
||||||
target: ServersModel
|
|
||||||
function onDefaultServerIndexChanged(serverIndex) {
|
|
||||||
serversMenuContent.currentIndex = serverIndex
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clip: true
|
ServersModel.defaultIndex = index
|
||||||
interactive: false
|
}
|
||||||
|
|
||||||
delegate: Item {
|
MouseArea {
|
||||||
id: menuContentDelegate
|
anchors.fill: serverRadioButton
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
enabled: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
property variant delegateData: model
|
ImageButtonType {
|
||||||
|
image: "qrc:/images/controls/settings.svg"
|
||||||
|
imageColor: "#D7D8DB"
|
||||||
|
|
||||||
implicitWidth: serversMenuContent.width
|
implicitWidth: 56
|
||||||
implicitHeight: serverRadioButtonContent.implicitHeight
|
implicitHeight: 56
|
||||||
|
|
||||||
ColumnLayout {
|
z: 1
|
||||||
id: serverRadioButtonContent
|
|
||||||
|
|
||||||
anchors.fill: parent
|
onClicked: function() {
|
||||||
anchors.rightMargin: 16
|
ServersModel.processedIndex = index
|
||||||
anchors.leftMargin: 16
|
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||||
|
drawer.close()
|
||||||
spacing: 0
|
}
|
||||||
|
}
|
||||||
RowLayout {
|
}
|
||||||
VerticalRadioButton {
|
|
||||||
id: serverRadioButton
|
|
||||||
|
|
||||||
|
DividerType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
Layout.leftMargin: 0
|
||||||
text: name
|
Layout.rightMargin: 0
|
||||||
descriptionText: {
|
|
||||||
var fullDescription = ""
|
|
||||||
if (hasWriteAccess) {
|
|
||||||
if (SettingsController.isAmneziaDnsEnabled()
|
|
||||||
&& ServersModel.isAmneziaDnsContainerInstalled(index)) {
|
|
||||||
fullDescription += "Amnezia DNS | "
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (containsAmneziaDns) {
|
|
||||||
fullDescription += "Amnezia DNS | "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fullDescription += serverDescription
|
|
||||||
}
|
|
||||||
|
|
||||||
checked: index === serversMenuContent.currentIndex
|
|
||||||
checkable: !ConnectionController.isConnected
|
|
||||||
|
|
||||||
ButtonGroup.group: serversRadioButtonGroup
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (ConnectionController.isConnected) {
|
|
||||||
PageController.showNotificationMessage(qsTr("Unable change server while there is an active connection"))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
serversMenuContent.currentIndex = index
|
|
||||||
|
|
||||||
ServersModel.currentlyProcessedIndex = index
|
|
||||||
ServersModel.defaultIndex = index
|
|
||||||
}
|
|
||||||
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: serverRadioButton
|
|
||||||
cursorShape: Qt.PointingHandCursor
|
|
||||||
enabled: false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageButtonType {
|
|
||||||
image: "qrc:/images/controls/settings.svg"
|
|
||||||
imageColor: "#D7D8DB"
|
|
||||||
|
|
||||||
implicitWidth: 56
|
|
||||||
implicitHeight: 56
|
|
||||||
|
|
||||||
z: 1
|
|
||||||
|
|
||||||
onClicked: function() {
|
|
||||||
ServersModel.currentlyProcessedIndex = index
|
|
||||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
|
||||||
buttonContent.state = "collapsed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.leftMargin: 0
|
|
||||||
Layout.rightMargin: 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ import "../Controls2/TextTypes"
|
|||||||
import "../Config"
|
import "../Config"
|
||||||
import "../Components"
|
import "../Components"
|
||||||
|
|
||||||
|
|
||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: listview.currentItem.portTextField.textField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -41,9 +44,11 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
|
|
||||||
|
|
||||||
id: listview
|
id: listview
|
||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
@@ -55,9 +60,13 @@ PageType {
|
|||||||
model: AwgConfigModel
|
model: AwgConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
|
id: _delegate
|
||||||
|
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias portTextField:portTextField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
@@ -93,6 +102,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: junkPacketCountTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -116,6 +127,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: junkPacketMinSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -134,6 +147,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: junkPacketMaxSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -152,6 +167,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: initPacketJunkSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -170,6 +187,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: responsePacketJunkSizeTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -188,6 +207,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: initPacketMagicHeaderTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -206,6 +227,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: responsePacketMagicHeaderTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -224,6 +247,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: transportPacketMagicHeaderTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -242,6 +267,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: underloadPacketMagicHeaderTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -260,6 +287,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
@@ -275,24 +304,24 @@ PageType {
|
|||||||
text: qsTr("Remove AmneziaWG")
|
text: qsTr("Remove AmneziaWG")
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
questionDrawer.headerText = qsTr("Remove AmneziaWG from server?")
|
var headerText = qsTr("Remove AmneziaWG from server?")
|
||||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
@@ -310,7 +339,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Save and Restart Amnezia")
|
text: qsTr("Save and Restart Amnezia")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(AwgConfigModel.getConfig())
|
InstallController.updateContainer(AwgConfigModel.getConfig())
|
||||||
@@ -318,11 +347,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QuestionDrawer {
|
}
|
||||||
id: questionDrawer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: listview.currentItem.trafficFromField.textField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
@@ -58,6 +60,8 @@ PageType {
|
|||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias trafficFromField: trafficFromField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
@@ -77,6 +81,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: trafficFromField
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
@@ -96,9 +102,13 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: portTextField.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: portTextField
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
@@ -112,6 +122,8 @@ PageType {
|
|||||||
port = textFieldText
|
port = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
@@ -122,6 +134,8 @@ PageType {
|
|||||||
descriptionText: qsTr("Cipher")
|
descriptionText: qsTr("Cipher")
|
||||||
headerText: qsTr("Cipher")
|
headerText: qsTr("Cipher")
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
listView: ListViewWithRadioButtonType {
|
listView: ListViewWithRadioButtonType {
|
||||||
id: cipherListView
|
id: cipherListView
|
||||||
|
|
||||||
@@ -138,7 +152,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
cipherDropDown.text = selectedText
|
cipherDropDown.text = selectedText
|
||||||
cipher = cipherDropDown.text
|
cipher = cipherDropDown.text
|
||||||
cipherDropDown.menuVisible = false
|
cipherDropDown.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -154,13 +168,15 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
text: qsTr("Save and Restart Amnezia")
|
text: qsTr("Save and Restart Amnezia")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(CloakConfigModel.getConfig())
|
InstallController.updateContainer(CloakConfigModel.getConfig())
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: listview.currentItem.vpnAddressSubnetTextField.textField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -42,7 +44,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
@@ -53,12 +55,14 @@ PageType {
|
|||||||
clip: true
|
clip: true
|
||||||
interactive: false
|
interactive: false
|
||||||
|
|
||||||
model: OpenVpnConfigModel
|
model: OpenVpnConfigModel
|
||||||
|
|
||||||
delegate: Item {
|
delegate: Item {
|
||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias vpnAddressSubnetTextField: vpnAddressSubnetTextField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
@@ -78,6 +82,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: vpnAddressSubnetTextField
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
@@ -89,6 +95,8 @@ PageType {
|
|||||||
subnetAddress = textFieldText
|
subnetAddress = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: portTextField.enabled ? portTextField.textField : saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
@@ -119,6 +127,9 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: portTextField
|
||||||
|
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
@@ -134,6 +145,8 @@ PageType {
|
|||||||
port = textFieldText
|
port = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
SwitcherType {
|
SwitcherType {
|
||||||
@@ -162,6 +175,8 @@ PageType {
|
|||||||
descriptionText: qsTr("Hash")
|
descriptionText: qsTr("Hash")
|
||||||
headerText: qsTr("Hash")
|
headerText: qsTr("Hash")
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
listView: ListViewWithRadioButtonType {
|
listView: ListViewWithRadioButtonType {
|
||||||
id: hashListView
|
id: hashListView
|
||||||
|
|
||||||
@@ -183,7 +198,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
hashDropDown.text = selectedText
|
hashDropDown.text = selectedText
|
||||||
hash = hashDropDown.text
|
hash = hashDropDown.text
|
||||||
hashDropDown.menuVisible = false
|
hashDropDown.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -208,6 +223,8 @@ PageType {
|
|||||||
descriptionText: qsTr("Cipher")
|
descriptionText: qsTr("Cipher")
|
||||||
headerText: qsTr("Cipher")
|
headerText: qsTr("Cipher")
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
listView: ListViewWithRadioButtonType {
|
listView: ListViewWithRadioButtonType {
|
||||||
id: cipherListView
|
id: cipherListView
|
||||||
|
|
||||||
@@ -229,7 +246,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
cipherDropDown.text = selectedText
|
cipherDropDown.text = selectedText
|
||||||
cipher = cipherDropDown.text
|
cipher = cipherDropDown.text
|
||||||
cipherDropDown.menuVisible = false
|
cipherDropDown.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -363,32 +380,33 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Remove OpenVPN")
|
text: qsTr("Remove OpenVPN")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove OpenVpn from server?")
|
var headerText = qsTr("Remove OpenVpn from server?")
|
||||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
text: qsTr("Save and Restart Amnezia")
|
text: qsTr("Save and Restart Amnezia")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(OpenVpnConfigModel.getConfig())
|
InstallController.updateContainer(OpenVpnConfigModel.getConfig())
|
||||||
@@ -398,9 +416,5 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,71 +90,77 @@ PageType {
|
|||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: configContentDrawer
|
id: configContentDrawer
|
||||||
|
|
||||||
width: parent.width
|
expandedHeight: root.height * 0.9
|
||||||
height: parent.height * 0.9
|
|
||||||
|
|
||||||
BackButtonType {
|
parent: root
|
||||||
id: backButton
|
anchors.fill: parent
|
||||||
|
|
||||||
anchors.top: parent.top
|
expandedContent: Item {
|
||||||
anchors.left: parent.left
|
implicitHeight: configContentDrawer.expandedHeight
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
backButtonFunction: function() {
|
BackButtonType {
|
||||||
configContentDrawer.visible = false
|
id: backButton
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
anchors.top: parent.top
|
||||||
anchors.top: backButton.bottom
|
anchors.left: parent.left
|
||||||
anchors.left: parent.left
|
anchors.right: parent.right
|
||||||
anchors.right: parent.right
|
anchors.topMargin: 16
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
contentHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
|
|
||||||
|
|
||||||
ColumnLayout {
|
backButtonFunction: function() {
|
||||||
id: configContent
|
configContentDrawer.close()
|
||||||
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.rightMargin: 16
|
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.topMargin: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Connection options %1").arg(protocolName)
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextArea {
|
FlickableType {
|
||||||
id: configText
|
anchors.top: backButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
contentHeight: configContent.implicitHeight + configContent.anchors.topMargin + configContent.anchors.bottomMargin
|
||||||
|
|
||||||
Layout.fillWidth: true
|
ColumnLayout {
|
||||||
Layout.topMargin: 16
|
id: configContent
|
||||||
Layout.bottomMargin: 16
|
|
||||||
|
|
||||||
padding: 0
|
anchors.fill: parent
|
||||||
leftPadding: 0
|
anchors.rightMargin: 16
|
||||||
height: 24
|
anchors.leftMargin: 16
|
||||||
|
|
||||||
color: "#D7D8DB"
|
Header2Type {
|
||||||
selectionColor: "#633303"
|
Layout.fillWidth: true
|
||||||
selectedTextColor: "#D7D8DB"
|
Layout.topMargin: 16
|
||||||
|
|
||||||
font.pixelSize: 16
|
headerText: qsTr("Connection options %1").arg(protocolName)
|
||||||
font.weight: Font.Medium
|
}
|
||||||
font.family: "PT Root UI VF"
|
|
||||||
|
|
||||||
text: rawConfig
|
TextArea {
|
||||||
|
id: configText
|
||||||
|
|
||||||
wrapMode: Text.Wrap
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
|
||||||
background: Rectangle {
|
padding: 0
|
||||||
color: "transparent"
|
leftPadding: 0
|
||||||
|
height: 24
|
||||||
|
|
||||||
|
color: "#D7D8DB"
|
||||||
|
selectionColor: "#633303"
|
||||||
|
selectedTextColor: "#D7D8DB"
|
||||||
|
|
||||||
|
font.pixelSize: 16
|
||||||
|
font.weight: Font.Medium
|
||||||
|
font.family: "PT Root UI VF"
|
||||||
|
|
||||||
|
text: rawConfig
|
||||||
|
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: "transparent"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -169,26 +175,25 @@ PageType {
|
|||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
visible: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
visible: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
||||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -200,9 +205,5 @@ PageType {
|
|||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: listview.currentItem.portTextField.textField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
@@ -58,6 +60,8 @@ PageType {
|
|||||||
implicitWidth: listview.width
|
implicitWidth: listview.width
|
||||||
implicitHeight: col.implicitHeight
|
implicitHeight: col.implicitHeight
|
||||||
|
|
||||||
|
property alias portTextField: portTextField
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: col
|
id: col
|
||||||
|
|
||||||
@@ -77,6 +81,8 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: portTextField
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
@@ -90,6 +96,8 @@ PageType {
|
|||||||
port = textFieldText
|
port = textFieldText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveRestartButton
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
@@ -100,6 +108,8 @@ PageType {
|
|||||||
descriptionText: qsTr("Cipher")
|
descriptionText: qsTr("Cipher")
|
||||||
headerText: qsTr("Cipher")
|
headerText: qsTr("Cipher")
|
||||||
|
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
listView: ListViewWithRadioButtonType {
|
listView: ListViewWithRadioButtonType {
|
||||||
id: cipherListView
|
id: cipherListView
|
||||||
|
|
||||||
@@ -116,7 +126,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
cipherDropDown.text = selectedText
|
cipherDropDown.text = selectedText
|
||||||
cipher = cipherDropDown.text
|
cipher = cipherDropDown.text
|
||||||
cipherDropDown.menuVisible = false
|
cipherDropDown.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -132,13 +142,15 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveRestartButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
Layout.bottomMargin: 24
|
Layout.bottomMargin: 24
|
||||||
|
|
||||||
text: qsTr("Save and Restart Amnezia")
|
text: qsTr("Save and Restart Amnezia")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.updateContainer(ShadowSocksConfigModel.getConfig())
|
InstallController.updateContainer(ShadowSocksConfigModel.getConfig())
|
||||||
|
|||||||
@@ -63,19 +63,18 @@ PageType {
|
|||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -86,10 +85,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
enabled: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
enabled: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
id: listview
|
id: listview
|
||||||
@@ -88,7 +88,7 @@ PageType {
|
|||||||
Layout.topMargin: 32
|
Layout.topMargin: 32
|
||||||
|
|
||||||
text: qsTr("Host")
|
text: qsTr("Host")
|
||||||
descriptionText: ServersModel.getCurrentlyProcessedServerHostName()
|
descriptionText: ServersModel.getProcessedServerData("HostName")
|
||||||
|
|
||||||
descriptionOnTop: true
|
descriptionOnTop: true
|
||||||
|
|
||||||
@@ -170,7 +170,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Mount folder on device")
|
text: qsTr("Mount folder on device")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
InstallController.mountSftpDrive(port, password, username)
|
InstallController.mountSftpDrive(port, password, username)
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
@@ -229,7 +229,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Detailed instructions")
|
text: qsTr("Detailed instructions")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
// Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
// Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -247,29 +247,24 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Remove SFTP and all data stored there")
|
text: qsTr("Remove SFTP and all data stored there")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove SFTP and all data stored there?")
|
var headerText = qsTr("Remove SFTP and all data stored there?")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,26 +125,21 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Remove website")
|
text: qsTr("Remove website")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("The site with all data will be removed from the tor network.")
|
var headerText = qsTr("The site with all data will be removed from the tor network.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Card on Patreon")
|
text: qsTr("Card on Patreon")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
Qt.openUrlExternally(qsTr("https://www.patreon.com/amneziavpn"))
|
Qt.openUrlExternally(qsTr("https://www.patreon.com/amneziavpn"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,9 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Show other methods on Github")
|
text: qsTr("Show other methods on Github")
|
||||||
|
|
||||||
onClicked: Qt.openUrlExternally(qsTr("https://github.com/amnezia-vpn/amnezia-client#donate"))
|
clickedFunc: function() {
|
||||||
|
Qt.openUrlExternally(qsTr("https://github.com/amnezia-vpn/amnezia-client#donate"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ParagraphTextType {
|
||||||
@@ -173,7 +175,7 @@ PageType {
|
|||||||
|
|
||||||
horizontalAlignment: Text.AlignHCenter
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
|
||||||
text: SettingsController.getAppVersion()
|
text: qsTr("Software version: %1").arg(SettingsController.getAppVersion())
|
||||||
color: "#878B91"
|
color: "#878B91"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +193,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Check for updates")
|
text: qsTr("Check for updates")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
Qt.openUrlExternally("https://github.com/amnezia-vpn/desktop-client/releases/latest")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,27 @@ PageType {
|
|||||||
visible: !GC.isMobile()
|
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 {
|
SwitcherType {
|
||||||
visible: !GC.isMobile()
|
visible: !GC.isMobile()
|
||||||
|
|
||||||
@@ -117,10 +138,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectLanguageDrawer {
|
|
||||||
id: selectLanguageDrawer
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
@@ -143,30 +160,33 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Reset settings and remove all data from the application")
|
text: qsTr("Reset settings and remove all data from the application")
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Reset settings and remove all data from the application?")
|
var headerText = qsTr("Reset settings and remove all data from the application?")
|
||||||
questionDrawer.descriptionText = qsTr("All settings will be reset to default. All installed AmneziaVPN services will still remain on the server.")
|
var descriptionText = qsTr("All settings will be reset to default. All installed AmneziaVPN services will still remain on the server.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
SettingsController.clearSettings()
|
SettingsController.clearSettings()
|
||||||
PageController.replaceStartPage()
|
PageController.replaceStartPage()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SelectLanguageDrawer {
|
||||||
|
id: selectLanguageDrawer
|
||||||
|
|
||||||
|
width: root.width
|
||||||
|
height: root.height
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Make a backup")
|
text: qsTr("Make a backup")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
var fileName = ""
|
var fileName = ""
|
||||||
if (GC.isMobile()) {
|
if (GC.isMobile()) {
|
||||||
fileName = "AmneziaVPN.backup"
|
fileName = "AmneziaVPN.backup"
|
||||||
@@ -121,7 +121,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Restore from backup")
|
text: qsTr("Restore from backup")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
var filePath = SystemController.getFileName(qsTr("Open backup file"),
|
var filePath = SystemController.getFileName(qsTr("Open backup file"),
|
||||||
qsTr("Backup files (*.backup)"))
|
qsTr("Backup files (*.backup)"))
|
||||||
if (filePath !== "") {
|
if (filePath !== "") {
|
||||||
@@ -133,24 +133,19 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function restoreBackup(filePath) {
|
function restoreBackup(filePath) {
|
||||||
questionDrawer.headerText = qsTr("Import settings from a backup file?")
|
var headerText = qsTr("Import settings from a backup file?")
|
||||||
questionDrawer.descriptionText = qsTr("All current settings will be reset");
|
var descriptionText = qsTr("All current settings will be reset");
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
SettingsController.restoreAppConfig(filePath)
|
SettingsController.restoreAppConfig(filePath)
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
QuestionDrawer {
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
id: questionDrawer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,27 +41,6 @@ PageType {
|
|||||||
headerText: qsTr("Connection")
|
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 {
|
SwitcherType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.margins: 16
|
Layout.margins: 16
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: primaryDns.textField
|
||||||
|
|
||||||
BackButtonType {
|
BackButtonType {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -28,10 +30,12 @@ PageType {
|
|||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
contentHeight: content.height
|
contentHeight: content.height
|
||||||
|
|
||||||
enabled: !ServersModel.isDefaultServerFromApi()
|
property var isServerFromApi: ServersModel.getDefaultServerData("isServerFromApi")
|
||||||
|
|
||||||
|
enabled: !isServerFromApi
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
if (ServersModel.isDefaultServerFromApi()) {
|
if (isServerFromApi) {
|
||||||
PageController.showNotificationMessage(qsTr("Default server does not support custom dns"))
|
PageController.showNotificationMessage(qsTr("Default server does not support custom dns"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,6 +72,8 @@ PageType {
|
|||||||
textField.validator: RegularExpressionValidator {
|
textField.validator: RegularExpressionValidator {
|
||||||
regularExpression: InstallController.ipAddressRegExp()
|
regularExpression: InstallController.ipAddressRegExp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: secondaryDns.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -80,6 +86,8 @@ PageType {
|
|||||||
textField.validator: RegularExpressionValidator {
|
textField.validator: RegularExpressionValidator {
|
||||||
regularExpression: InstallController.ipAddressRegExp()
|
regularExpression: InstallController.ipAddressRegExp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
@@ -94,32 +102,33 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Restore default")
|
text: qsTr("Restore default")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("Restore default DNS settings?")
|
var headerText = qsTr("Restore default DNS settings?")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
SettingsController.primaryDns = "1.1.1.1"
|
SettingsController.primaryDns = "1.1.1.1"
|
||||||
primaryDns.textFieldText = SettingsController.primaryDns
|
primaryDns.textFieldText = SettingsController.primaryDns
|
||||||
SettingsController.secondaryDns = "1.0.0.1"
|
SettingsController.secondaryDns = "1.0.0.1"
|
||||||
secondaryDns.textFieldText = SettingsController.secondaryDns
|
secondaryDns.textFieldText = SettingsController.secondaryDns
|
||||||
PageController.showNotificationMessage(qsTr("Settings have been reset"))
|
PageController.showNotificationMessage(qsTr("Settings have been reset"))
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
if (primaryDns.textFieldText !== SettingsController.primaryDns) {
|
if (primaryDns.textFieldText !== SettingsController.primaryDns) {
|
||||||
SettingsController.primaryDns = primaryDns.textFieldText
|
SettingsController.primaryDns = primaryDns.textFieldText
|
||||||
}
|
}
|
||||||
@@ -130,8 +139,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,21 +143,20 @@ PageType {
|
|||||||
image: "qrc:/images/controls/delete.svg"
|
image: "qrc:/images/controls/delete.svg"
|
||||||
|
|
||||||
onClicked: function() {
|
onClicked: function() {
|
||||||
questionDrawer.headerText = qsTr("Clear logs?")
|
var headerText = qsTr("Clear logs?")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
SettingsController.clearLogs()
|
SettingsController.clearLogs()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
|
PageController.showNotificationMessage(qsTr("Logs have been cleaned up"))
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,10 +169,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ PageType {
|
|||||||
PageController.showErrorMessage(message)
|
PageController.showErrorMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRemoveCurrentlyProcessedServerFinished(finishedMessage) {
|
function onRemoveProcessedServerFinished(finishedMessage) {
|
||||||
if (!ServersModel.getServersCount()) {
|
if (!ServersModel.getServersCount()) {
|
||||||
PageController.replaceStartPage()
|
PageController.replaceStartPage()
|
||||||
} else {
|
} else {
|
||||||
@@ -38,7 +38,7 @@ PageType {
|
|||||||
PageController.showNotificationMessage(finishedMessage)
|
PageController.showNotificationMessage(finishedMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
function onRebootCurrentlyProcessedServerFinished(finishedMessage) {
|
function onRebootProcessedServerFinished(finishedMessage) {
|
||||||
PageController.showNotificationMessage(finishedMessage)
|
PageController.showNotificationMessage(finishedMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,8 +64,8 @@ PageType {
|
|||||||
Connections {
|
Connections {
|
||||||
target: ServersModel
|
target: ServersModel
|
||||||
|
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
function onProcessedServerIndexChanged() {
|
||||||
content.isServerWithWriteAccess = ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
content.isServerWithWriteAccess = ServersModel.isProcessedServerHasWriteAccess()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ PageType {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
|
||||||
property bool isServerWithWriteAccess: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
property bool isServerWithWriteAccess: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
visible: content.isServerWithWriteAccess
|
visible: content.isServerWithWriteAccess
|
||||||
@@ -92,21 +92,20 @@ PageType {
|
|||||||
descriptionText: qsTr("May be needed when changing other settings")
|
descriptionText: qsTr("May be needed when changing other settings")
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Clear cached profiles?")
|
var headerText = qsTr("Clear cached profiles?")
|
||||||
questionDrawer.descriptionText = qsTr("")
|
var descriptionText = qsTr("")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
SettingsController.clearCachedProfiles()
|
SettingsController.clearCachedProfiles()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,24 +139,23 @@ PageType {
|
|||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Do you want to reboot the server?")
|
var headerText = qsTr("Do you want to reboot the server?")
|
||||||
questionDrawer.descriptionText = qsTr("The reboot process may take approximately 30 seconds. Are you sure you wish to proceed?")
|
var descriptionText = qsTr("The reboot process may take approximately 30 seconds. Are you sure you wish to proceed?")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
||||||
ConnectionController.closeConnection()
|
ConnectionController.closeConnection()
|
||||||
}
|
}
|
||||||
InstallController.rebootCurrentlyProcessedServer()
|
InstallController.rebootProcessedServer()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,24 +170,23 @@ PageType {
|
|||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Do you want to remove the server from application?")
|
var headerText = qsTr("Do you want to remove the server from application?")
|
||||||
questionDrawer.descriptionText = qsTr("All installed AmneziaVPN services will still remain on the server.")
|
var descriptionText = qsTr("All installed AmneziaVPN services will still remain on the server.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
||||||
ConnectionController.closeConnection()
|
ConnectionController.closeConnection()
|
||||||
}
|
}
|
||||||
InstallController.removeCurrentlyProcessedServer()
|
InstallController.removeProcessedServer()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,23 +200,22 @@ PageType {
|
|||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Do you want to clear server from Amnezia software?")
|
var headerText = qsTr("Do you want to clear server from Amnezia software?")
|
||||||
questionDrawer.descriptionText = qsTr("All containers will be deleted on the server. This means that configuration files, keys and certificates will be deleted.")
|
var descriptionText = qsTr("All containers will be deleted on the server. This means that configuration files, keys and certificates will be deleted.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
||||||
ConnectionController.closeConnection()
|
ConnectionController.closeConnection()
|
||||||
}
|
}
|
||||||
InstallController.removeAllContainers()
|
InstallController.removeAllContainers()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,69 +224,32 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
LabelWithButtonType {
|
LabelWithButtonType {
|
||||||
visible: content.isServerWithWriteAccess
|
visible: ServersModel.getProcessedServerData("isServerFromApi")
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
text: qsTr("Clear server from Amnezia software")
|
|
||||||
textColor: "#EB5757"
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
questionDrawer.headerText = qsTr("Do you want to clear server from Amnezia software?")
|
|
||||||
questionDrawer.descriptionText = qsTr("All containers will be deleted on the server. This means that configuration files, keys and certificates will be deleted.")
|
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
|
||||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
|
||||||
ConnectionController.closeConnection()
|
|
||||||
}
|
|
||||||
InstallController.removeAllContainers()
|
|
||||||
}
|
|
||||||
questionDrawer.noButtonFunction = function() {
|
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
|
||||||
questionDrawer.visible = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {
|
|
||||||
visible: content.isServerWithWriteAccess
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
visible: ServersModel.isCurrentlyProcessedServerFromApi()
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Reset API config")
|
text: qsTr("Reset API config")
|
||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Do you want to reset API config?")
|
var headerText = qsTr("Do you want to reset API config?")
|
||||||
questionDrawer.descriptionText = ""
|
var descriptionText = ""
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ApiController.clearApiConfig()
|
ApiController.clearApiConfig()
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {
|
DividerType {
|
||||||
visible: ServersModel.isCurrentlyProcessedServerFromApi()
|
visible: ServersModel.getProcessedServerData("isServerFromApi")
|
||||||
}
|
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ PageType {
|
|||||||
|
|
||||||
headerText: name
|
headerText: name
|
||||||
descriptionText: {
|
descriptionText: {
|
||||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
if (ServersModel.isProcessedServerHasWriteAccess()) {
|
||||||
return credentialsLogin + " · " + hostName
|
return credentialsLogin + " · " + hostName
|
||||||
} else {
|
} else {
|
||||||
return hostName
|
return hostName
|
||||||
@@ -71,30 +71,33 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actionButtonFunction: function() {
|
actionButtonFunction: function() {
|
||||||
serverNameEditDrawer.visible = true
|
serverNameEditDrawer.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: serverNameEditDrawer
|
id: serverNameEditDrawer
|
||||||
|
|
||||||
width: root.width
|
parent: root
|
||||||
height: root.height * 0.35
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
anchors.fill: parent
|
||||||
if (serverNameEditDrawer.visible) {
|
expandedHeight: root.height * 0.35
|
||||||
serverName.textField.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
expandedContent: ColumnLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 16
|
anchors.topMargin: 32
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: serverNameEditDrawer
|
||||||
|
function onOpened() {
|
||||||
|
serverName.textField.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
id: serverName
|
id: serverName
|
||||||
|
|
||||||
@@ -103,14 +106,18 @@ PageType {
|
|||||||
textFieldText: name
|
textFieldText: name
|
||||||
textField.maximumLength: 30
|
textField.maximumLength: 30
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (serverName.textFieldText === "") {
|
if (serverName.textFieldText === "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -118,7 +125,13 @@ PageType {
|
|||||||
if (serverName.textFieldText !== name) {
|
if (serverName.textFieldText !== name) {
|
||||||
name = serverName.textFieldText
|
name = serverName.textFieldText
|
||||||
}
|
}
|
||||||
serverNameEditDrawer.visible = false
|
serverNameEditDrawer.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
if (header.itemAt(0)) {
|
||||||
|
defaultActiveFocusItem = serverName.textField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,26 +107,25 @@ PageType {
|
|||||||
|
|
||||||
width: parent.width
|
width: parent.width
|
||||||
|
|
||||||
visible: ServersModel.isCurrentlyProcessedServerHasWriteAccess()
|
visible: ServersModel.isProcessedServerHasWriteAccess()
|
||||||
|
|
||||||
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
text: qsTr("Remove ") + ContainersModel.getCurrentlyProcessedContainerName()
|
||||||
textColor: "#EB5757"
|
textColor: "#EB5757"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
var headerText = qsTr("Remove %1 from server?").arg(ContainersModel.getCurrentlyProcessedContainerName())
|
||||||
questionDrawer.descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
var descriptionText = qsTr("All users with whom you shared a connection will no longer be able to connect to it.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
PageController.goToPage(PageEnum.PageDeinstalling)
|
PageController.goToPage(PageEnum.PageDeinstalling)
|
||||||
InstallController.removeCurrentlyProcessedContainer()
|
InstallController.removeCurrentlyProcessedContainer()
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
@@ -138,9 +137,9 @@ PageType {
|
|||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
QuestionDrawer {
|
||||||
id: questionDrawer
|
id: questionDrawer
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ PageType {
|
|||||||
Connections {
|
Connections {
|
||||||
target: ServersModel
|
target: ServersModel
|
||||||
|
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
function onProcessedServerIndexChanged() {
|
||||||
settingsContainersListView.updateContainersModelFilters()
|
settingsContainersListView.updateContainersModelFilters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateContainersModelFilters() {
|
function updateContainersModelFilters() {
|
||||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
if (ServersModel.isProcessedServerHasWriteAccess()) {
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessProtocolsListFilters()
|
||||||
} else {
|
} else {
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
proxyContainersModel.filters = ContainersModelFilters.getReadAccessProtocolsListFilters()
|
||||||
|
|||||||
@@ -38,13 +38,13 @@ PageType {
|
|||||||
Connections {
|
Connections {
|
||||||
target: ServersModel
|
target: ServersModel
|
||||||
|
|
||||||
function onCurrentlyProcessedServerIndexChanged() {
|
function onProcessedServerIndexChanged() {
|
||||||
settingsContainersListView.updateContainersModelFilters()
|
settingsContainersListView.updateContainersModelFilters()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateContainersModelFilters() {
|
function updateContainersModelFilters() {
|
||||||
if (ServersModel.isCurrentlyProcessedServerHasWriteAccess()) {
|
if (ServersModel.isProcessedServerHasWriteAccess()) {
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessServicesListFilters()
|
proxyContainersModel.filters = ContainersModelFilters.getWriteAccessServicesListFilters()
|
||||||
} else {
|
} else {
|
||||||
proxyContainersModel.filters = ContainersModelFilters.getReadAccessServicesListFilters()
|
proxyContainersModel.filters = ContainersModelFilters.getReadAccessServicesListFilters()
|
||||||
@@ -55,6 +55,9 @@ PageType {
|
|||||||
model: SortFilterProxyModel {
|
model: SortFilterProxyModel {
|
||||||
id: proxyContainersModel
|
id: proxyContainersModel
|
||||||
sourceModel: ContainersModel
|
sourceModel: ContainersModel
|
||||||
|
sorters: [
|
||||||
|
RoleSorter { roleName: "isInstalled"; sortOrder: Qt.DescendingOrder }
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: updateContainersModelFilters()
|
Component.onCompleted: updateContainersModelFilters()
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ PageType {
|
|||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
ServersModel.currentlyProcessedIndex = index
|
ServersModel.processedIndex = index
|
||||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,13 +20,23 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
property var isServerFromApi: ServersModel.getDefaultServerData("isServerFromApi")
|
||||||
|
|
||||||
|
defaultActiveFocusItem: website_ip_field.textField
|
||||||
|
|
||||||
property bool pageEnabled: {
|
property bool pageEnabled: {
|
||||||
return !ConnectionController.isConnected && !ServersModel.isDefaultServerFromApi()
|
return !ConnectionController.isConnected && !isServerFromApi
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
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"))
|
PageController.showNotificationMessage(qsTr("Default server does not support split tunneling function"))
|
||||||
|
root.pageEnabled = false
|
||||||
|
} else {
|
||||||
|
root.pageEnabled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +114,7 @@ PageType {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
checked: SitesModel.isSplitTunnelingEnabled()
|
checked: SitesModel.isTunnelingEnabled
|
||||||
onToggled: {
|
onToggled: {
|
||||||
SitesModel.toggleSplitTunneling(checked)
|
SitesModel.toggleSplitTunneling(checked)
|
||||||
selector.text = root.routeModesModel[getRouteModesModelIndex()].name
|
selector.text = root.routeModesModel[getRouteModesModelIndex()].name
|
||||||
@@ -121,6 +131,7 @@ PageType {
|
|||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.4375
|
drawerHeight: 0.4375
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
enabled: root.pageEnabled
|
enabled: root.pageEnabled
|
||||||
|
|
||||||
@@ -135,7 +146,7 @@ PageType {
|
|||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
selector.text = selectedText
|
selector.text = selectedText
|
||||||
selector.menuVisible = false
|
selector.close()
|
||||||
if (SitesModel.routeMode !== root.routeModesModel[currentIndex].type) {
|
if (SitesModel.routeMode !== root.routeModesModel[currentIndex].type) {
|
||||||
SitesModel.routeMode = root.routeModesModel[currentIndex].type
|
SitesModel.routeMode = root.routeModesModel[currentIndex].type
|
||||||
}
|
}
|
||||||
@@ -202,26 +213,21 @@ PageType {
|
|||||||
rightImageColor: "#D7D8DB"
|
rightImageColor: "#D7D8DB"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
questionDrawer.headerText = qsTr("Remove ") + url + "?"
|
var headerText = qsTr("Remove ") + url + "?"
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
SitesController.removeSite(index)
|
SitesController.removeSite(index)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.visible = false
|
|
||||||
}
|
}
|
||||||
questionDrawer.visible = true
|
|
||||||
|
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -249,6 +255,8 @@ PageType {
|
|||||||
anchors.bottomMargin: 24
|
anchors.bottomMargin: 24
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
|
id: website_ip_field
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
textFieldPlaceholderText: qsTr("website or IP")
|
textFieldPlaceholderText: qsTr("website or IP")
|
||||||
@@ -275,151 +283,155 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: moreActionsDrawer
|
id: moreActionsDrawer
|
||||||
|
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
height: parent.height * 0.4375
|
expandedHeight: parent.height * 0.4375
|
||||||
|
|
||||||
FlickableType {
|
expandedContent: ColumnLayout {
|
||||||
anchors.fill: parent
|
id: moreActionsDrawerContent
|
||||||
contentHeight: moreActionsDrawerContent.height
|
|
||||||
ColumnLayout {
|
|
||||||
id: moreActionsDrawerContent
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
Header2Type {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.margins: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Import / Export Sites")
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
text: qsTr("Import")
|
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
importSitesDrawer.open()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: qsTr("Save site list")
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
var fileName = ""
|
|
||||||
if (GC.isMobile()) {
|
|
||||||
fileName = "amnezia_sites.json"
|
|
||||||
} else {
|
|
||||||
fileName = SystemController.getFileName(qsTr("Save sites"),
|
|
||||||
qsTr("Sites files (*.json)"),
|
|
||||||
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/amnezia_sites",
|
|
||||||
true,
|
|
||||||
".json")
|
|
||||||
}
|
|
||||||
if (fileName !== "") {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
SitesController.exportSites(fileName)
|
|
||||||
moreActionsDrawer.close()
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawerType {
|
|
||||||
id: importSitesDrawer
|
|
||||||
|
|
||||||
width: parent.width
|
|
||||||
height: parent.height * 0.4375
|
|
||||||
|
|
||||||
BackButtonType {
|
|
||||||
id: importSitesDrawerBackButton
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
backButtonFunction: function() {
|
Header2Type {
|
||||||
importSitesDrawer.close()
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 16
|
||||||
|
|
||||||
|
headerText: qsTr("Import / Export Sites")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
text: qsTr("Import")
|
||||||
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
importSitesDrawer.open()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Save site list")
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
var fileName = ""
|
||||||
|
if (GC.isMobile()) {
|
||||||
|
fileName = "amnezia_sites.json"
|
||||||
|
} else {
|
||||||
|
fileName = SystemController.getFileName(qsTr("Save sites"),
|
||||||
|
qsTr("Sites files (*.json)"),
|
||||||
|
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/amnezia_sites",
|
||||||
|
true,
|
||||||
|
".json")
|
||||||
|
}
|
||||||
|
if (fileName !== "") {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
SitesController.exportSites(fileName)
|
||||||
|
moreActionsDrawer.close()
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FlickableType {
|
DrawerType2 {
|
||||||
anchors.top: importSitesDrawerBackButton.bottom
|
id: importSitesDrawer
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
|
|
||||||
contentHeight: importSitesDrawerContent.height
|
anchors.fill: parent
|
||||||
|
expandedHeight: parent.height * 0.4375
|
||||||
|
|
||||||
ColumnLayout {
|
expandedContent: Item {
|
||||||
id: importSitesDrawerContent
|
implicitHeight: importSitesDrawer.expandedHeight
|
||||||
|
|
||||||
|
BackButtonType {
|
||||||
|
id: importSitesDrawerBackButton
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
|
anchors.topMargin: 16
|
||||||
|
|
||||||
Header2Type {
|
backButtonFunction: function() {
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.margins: 16
|
|
||||||
|
|
||||||
headerText: qsTr("Import a list of sites")
|
|
||||||
}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
|
|
||||||
text: qsTr("Replace site list")
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
|
||||||
qsTr("Sites files (*.json)"))
|
|
||||||
if (fileName !== "") {
|
|
||||||
importSitesDrawerContent.importSites(fileName, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DividerType {}
|
|
||||||
|
|
||||||
LabelWithButtonType {
|
|
||||||
Layout.fillWidth: true
|
|
||||||
text: qsTr("Add imported sites to existing ones")
|
|
||||||
|
|
||||||
clickedFunction: function() {
|
|
||||||
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
|
||||||
qsTr("Sites files (*.json)"))
|
|
||||||
if (fileName !== "") {
|
|
||||||
importSitesDrawerContent.importSites(fileName, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function importSites(fileName, replaceExistingSites) {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
SitesController.importSites(fileName, replaceExistingSites)
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
importSitesDrawer.close()
|
importSitesDrawer.close()
|
||||||
moreActionsDrawer.close()
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DividerType {}
|
FlickableType {
|
||||||
|
anchors.top: importSitesDrawerBackButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
contentHeight: importSitesDrawerContent.height
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: importSitesDrawerContent
|
||||||
|
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
Header2Type {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.margins: 16
|
||||||
|
|
||||||
|
headerText: qsTr("Import a list of sites")
|
||||||
|
}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
text: qsTr("Replace site list")
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
||||||
|
qsTr("Sites files (*.json)"))
|
||||||
|
if (fileName !== "") {
|
||||||
|
importSitesDrawerContent.importSites(fileName, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
|
|
||||||
|
LabelWithButtonType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: qsTr("Add imported sites to existing ones")
|
||||||
|
|
||||||
|
clickedFunction: function() {
|
||||||
|
var fileName = SystemController.getFileName(qsTr("Open sites file"),
|
||||||
|
qsTr("Sites files (*.json)"))
|
||||||
|
if (fileName !== "") {
|
||||||
|
importSitesDrawerContent.importSites(fileName, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function importSites(fileName, replaceExistingSites) {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
SitesController.importSites(fileName, replaceExistingSites)
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
importSitesDrawer.close()
|
||||||
|
moreActionsDrawer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
DividerType {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QuestionDrawer {
|
||||||
|
id: questionDrawer
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import "../Controls2/TextTypes"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: hostname.textField
|
||||||
|
|
||||||
BackButtonType {
|
BackButtonType {
|
||||||
id: backButton
|
id: backButton
|
||||||
|
|
||||||
@@ -57,6 +59,8 @@ PageType {
|
|||||||
onFocusChanged: {
|
onFocusChanged: {
|
||||||
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: username.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -65,6 +69,8 @@ PageType {
|
|||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
headerText: qsTr("Login to connect via SSH")
|
headerText: qsTr("Login to connect via SSH")
|
||||||
textFieldPlaceholderText: "root"
|
textFieldPlaceholderText: "root"
|
||||||
|
|
||||||
|
KeyNavigation.tab: secretData.textField
|
||||||
}
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
@@ -85,15 +91,19 @@ PageType {
|
|||||||
onFocusChanged: {
|
onFocusChanged: {
|
||||||
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
textField.text = textField.text.replace(/^\s+|\s+$/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: continueButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: continueButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 24
|
Layout.topMargin: 24
|
||||||
|
|
||||||
text: qsTr("Continue")
|
text: qsTr("Continue")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
forceActiveFocus()
|
forceActiveFocus()
|
||||||
if (!isCredentialsFilled()) {
|
if (!isCredentialsFilled()) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Continue")
|
text: qsTr("Continue")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
if (root.isEasySetup) {
|
if (root.isEasySetup) {
|
||||||
ContainersModel.setCurrentlyProcessedContainerIndex(containers.dockerContainer)
|
ContainersModel.setCurrentlyProcessedContainerIndex(containers.dockerContainer)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
||||||
@@ -192,13 +192,12 @@ PageType {
|
|||||||
return ContainersModel.isAnyContainerInstalled()
|
return ContainersModel.isAnyContainerInstalled()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
text: qsTr("Set up later")
|
text: qsTr("Set up later")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling)
|
||||||
InstallController.addEmptyServer()
|
InstallController.addEmptyServer()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ PageType {
|
|||||||
|
|
||||||
function onInstallContainerFinished(finishedMessage, isServiceInstall) {
|
function onInstallContainerFinished(finishedMessage, isServiceInstall) {
|
||||||
if (!ConnectionController.isConnected && !isServiceInstall) {
|
if (!ConnectionController.isConnected && !isServiceInstall) {
|
||||||
ServersModel.setDefaultContainer(ContainersModel.getCurrentlyProcessedContainerIndex())
|
ServersModel.setDefaultContainer(ServersModel.processedIndex, ContainersModel.getCurrentlyProcessedContainerIndex())
|
||||||
}
|
}
|
||||||
|
|
||||||
PageController.closePage() // close installing page
|
PageController.closePage() // close installing page
|
||||||
@@ -42,7 +42,7 @@ PageType {
|
|||||||
function onInstallServerFinished(finishedMessage) {
|
function onInstallServerFinished(finishedMessage) {
|
||||||
if (!ConnectionController.isConnected) {
|
if (!ConnectionController.isConnected) {
|
||||||
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
PageController.goToStartPage()
|
PageController.goToStartPage()
|
||||||
@@ -55,7 +55,7 @@ PageType {
|
|||||||
|
|
||||||
function onServerAlreadyExists(serverIndex) {
|
function onServerAlreadyExists(serverIndex) {
|
||||||
PageController.goToStartPage()
|
PageController.goToStartPage()
|
||||||
ServersModel.currentlyProcessedIndex = serverIndex
|
ServersModel.processedIndex = serverIndex
|
||||||
PageController.goToPage(PageEnum.PageSettingsServerInfo, false)
|
PageController.goToPage(PageEnum.PageSettingsServerInfo, false)
|
||||||
|
|
||||||
PageController.showErrorMessage(qsTr("The server has already been added to the application"))
|
PageController.showErrorMessage(qsTr("The server has already been added to the application"))
|
||||||
@@ -165,7 +165,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Cancel installation")
|
text: qsTr("Cancel installation")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
InstallController.cancelInstallation()
|
InstallController.cancelInstallation()
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ PageType {
|
|||||||
implicitWidth: processedContainerListView.width
|
implicitWidth: processedContainerListView.width
|
||||||
implicitHeight: (delegateContent.implicitHeight > root.height) ? delegateContent.implicitHeight : root.height
|
implicitHeight: (delegateContent.implicitHeight > root.height) ? delegateContent.implicitHeight : root.height
|
||||||
|
|
||||||
|
property alias port:port
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: delegateContent
|
id: delegateContent
|
||||||
|
|
||||||
@@ -92,81 +94,85 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("More detailed")
|
text: qsTr("More detailed")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
showDetailsDrawer.open()
|
showDetailsDrawer.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: showDetailsDrawer
|
id: showDetailsDrawer
|
||||||
|
parent: root
|
||||||
|
|
||||||
width: parent.width
|
anchors.fill: parent
|
||||||
height: parent.height * 0.9
|
expandedHeight: parent.height * 0.9
|
||||||
|
expandedContent: Item {
|
||||||
|
implicitHeight: showDetailsDrawer.expandedHeight
|
||||||
|
|
||||||
BackButtonType {
|
BackButtonType {
|
||||||
id: showDetailsBackButton
|
id: showDetailsBackButton
|
||||||
|
|
||||||
anchors.top: parent.top
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.topMargin: 16
|
|
||||||
|
|
||||||
backButtonFunction: function() {
|
|
||||||
showDetailsDrawer.close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FlickableType {
|
|
||||||
anchors.top: showDetailsBackButton.bottom
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
contentHeight: {
|
|
||||||
var emptySpaceHeight = parent.height - showDetailsBackButton.implicitHeight - showDetailsBackButton.anchors.topMargin
|
|
||||||
return (showDetailsDrawerContent.height > emptySpaceHeight) ?
|
|
||||||
showDetailsDrawerContent.height : emptySpaceHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
id: showDetailsDrawerContent
|
|
||||||
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.rightMargin: 16
|
anchors.topMargin: 16
|
||||||
anchors.leftMargin: 16
|
|
||||||
|
|
||||||
Header2Type {
|
backButtonFunction: function() {
|
||||||
id: showDetailsDrawerHeader
|
showDetailsDrawer.close()
|
||||||
Layout.fillWidth: true
|
}
|
||||||
Layout.topMargin: 16
|
}
|
||||||
|
|
||||||
headerText: name
|
FlickableType {
|
||||||
|
anchors.top: showDetailsBackButton.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
contentHeight: {
|
||||||
|
var emptySpaceHeight = parent.height - showDetailsBackButton.implicitHeight - showDetailsBackButton.anchors.topMargin
|
||||||
|
return (showDetailsDrawerContent.height > emptySpaceHeight) ?
|
||||||
|
showDetailsDrawerContent.height : emptySpaceHeight
|
||||||
}
|
}
|
||||||
|
|
||||||
ParagraphTextType {
|
ColumnLayout {
|
||||||
Layout.fillWidth: true
|
id: showDetailsDrawerContent
|
||||||
Layout.topMargin: 16
|
|
||||||
Layout.bottomMargin: 16
|
|
||||||
|
|
||||||
text: detailedDescription
|
anchors.top: parent.top
|
||||||
textFormat: Text.MarkdownText
|
anchors.left: parent.left
|
||||||
}
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 16
|
||||||
|
anchors.leftMargin: 16
|
||||||
|
|
||||||
|
Header2Type {
|
||||||
|
id: showDetailsDrawerHeader
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
|
||||||
|
headerText: name
|
||||||
|
}
|
||||||
|
|
||||||
|
ParagraphTextType {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.topMargin: 16
|
||||||
|
Layout.bottomMargin: 16
|
||||||
|
|
||||||
|
text: detailedDescription
|
||||||
|
textFormat: Text.MarkdownText
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.bottomMargin: 32
|
Layout.bottomMargin: 32
|
||||||
|
|
||||||
text: qsTr("Close")
|
text: qsTr("Close")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
showDetailsDrawer.close()
|
showDetailsDrawer.close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,6 +203,8 @@ PageType {
|
|||||||
headerText: qsTr("Port")
|
headerText: qsTr("Port")
|
||||||
textField.maximumLength: 5
|
textField.maximumLength: 5
|
||||||
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
textField.validator: IntValidator { bottom: 1; top: 65535 }
|
||||||
|
|
||||||
|
KeyNavigation.tab: installButton
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -212,7 +220,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Install")
|
text: qsTr("Install")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
PageController.goToPage(PageEnum.PageSetupWizardInstalling);
|
||||||
InstallController.install(dockerContainer, port.textFieldText, transportProtoSelector.currentIndex)
|
InstallController.install(dockerContainer, port.textFieldText, transportProtoSelector.currentIndex)
|
||||||
}
|
}
|
||||||
@@ -232,6 +240,8 @@ PageType {
|
|||||||
var protocolSelectorVisible = ProtocolProps.defaultTransportProtoChangeable(defaultContainerProto)
|
var protocolSelectorVisible = ProtocolProps.defaultTransportProtoChangeable(defaultContainerProto)
|
||||||
transportProtoSelector.visible = protocolSelectorVisible
|
transportProtoSelector.visible = protocolSelectorVisible
|
||||||
transportProtoHeader.visible = protocolSelectorVisible
|
transportProtoHeader.visible = protocolSelectorVisible
|
||||||
|
|
||||||
|
defaultActiveFocusItem = port.textField
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,8 +115,8 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("I have the data to connect")
|
text: qsTr("I have the data to connect")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
connectionTypeSelection.visible = true
|
connectionTypeSelection.open()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,13 +135,15 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("I have nothing")
|
text: qsTr("I have nothing")
|
||||||
|
|
||||||
onClicked: Qt.openUrlExternally(qsTr("https://amnezia.org/instructions/0_starter-guide"))
|
clickedFunc: function() {
|
||||||
|
Qt.openUrlExternally(qsTr("https://amnezia.org/instructions/0_starter-guide"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConnectionTypeSelectionDrawer {
|
ConnectionTypeSelectionDrawer {
|
||||||
id: connectionTypeSelection
|
id: connectionTypeSelection
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BusyIndicatorType {
|
BusyIndicatorType {
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import "../Config"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: textKey.textField
|
||||||
|
|
||||||
FlickableType {
|
FlickableType {
|
||||||
id: fl
|
id: fl
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
@@ -56,11 +58,15 @@ PageType {
|
|||||||
textField.text = ""
|
textField.text = ""
|
||||||
textField.paste()
|
textField.paste()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: continueButton
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: continueButton
|
||||||
|
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -70,7 +76,7 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Continue")
|
text: qsTr("Continue")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
ImportController.extractConfigFromCode(textKey.textFieldText)
|
ImportController.extractConfigFromCode(textKey.textFieldText)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
|
PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ PageType {
|
|||||||
function onImportFinished() {
|
function onImportFinished() {
|
||||||
if (!ConnectionController.isConnected) {
|
if (!ConnectionController.isConnected) {
|
||||||
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
ServersModel.setDefaultServerIndex(ServersModel.getServersCount() - 1);
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
PageController.goToStartPage()
|
PageController.goToStartPage()
|
||||||
@@ -109,7 +109,7 @@ PageType {
|
|||||||
|
|
||||||
text: showContent ? qsTr("Collapse content") : qsTr("Show content")
|
text: showContent ? qsTr("Collapse content") : qsTr("Show content")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
showContent = !showContent
|
showContent = !showContent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ PageType {
|
|||||||
Layout.bottomMargin: 32
|
Layout.bottomMargin: 32
|
||||||
|
|
||||||
text: qsTr("Connect")
|
text: qsTr("Connect")
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
ImportController.importConfig()
|
ImportController.importConfig()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,13 @@ import "../Components"
|
|||||||
PageType {
|
PageType {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
|
defaultActiveFocusItem: clientNameTextField.textField
|
||||||
|
|
||||||
enum ConfigType {
|
enum ConfigType {
|
||||||
AmneziaConnection,
|
AmneziaConnection,
|
||||||
OpenVpn,
|
OpenVpn,
|
||||||
WireGuard,
|
WireGuard,
|
||||||
|
Awg,
|
||||||
ShadowSocks,
|
ShadowSocks,
|
||||||
Cloak
|
Cloak
|
||||||
}
|
}
|
||||||
@@ -29,7 +32,7 @@ PageType {
|
|||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ExportController.revokeConfig(index,
|
ExportController.revokeConfig(index,
|
||||||
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
ServersModel.getCurrentlyProcessedServerCredentials())
|
ServersModel.getProcessedServerCredentials())
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
PageController.showNotificationMessage(qsTr("Config revoked"))
|
PageController.showNotificationMessage(qsTr("Config revoked"))
|
||||||
}
|
}
|
||||||
@@ -41,14 +44,15 @@ PageType {
|
|||||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = false
|
|
||||||
|
|
||||||
shareConnectionDrawer.open()
|
shareConnectionDrawer.open()
|
||||||
shareConnectionDrawer.contentVisible = false
|
shareConnectionDrawer.contentVisible = false
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case PageShare.ConfigType.AmneziaConnection: ExportController.generateConnectionConfig(clientNameTextField.textFieldText); break;
|
case PageShare.ConfigType.AmneziaConnection: {
|
||||||
|
ExportController.generateConnectionConfig(clientNameTextField.textFieldText);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PageShare.ConfigType.OpenVpn: {
|
case PageShare.ConfigType.OpenVpn: {
|
||||||
ExportController.generateOpenVpnConfig(clientNameTextField.textFieldText)
|
ExportController.generateOpenVpnConfig(clientNameTextField.textFieldText)
|
||||||
shareConnectionDrawer.configCaption = qsTr("Save OpenVPN config")
|
shareConnectionDrawer.configCaption = qsTr("Save OpenVPN config")
|
||||||
@@ -63,6 +67,13 @@ PageType {
|
|||||||
shareConnectionDrawer.configFileName = "amnezia_for_wireguard"
|
shareConnectionDrawer.configFileName = "amnezia_for_wireguard"
|
||||||
break
|
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: {
|
case PageShare.ConfigType.ShadowSocks: {
|
||||||
ExportController.generateShadowSocksConfig()
|
ExportController.generateShadowSocksConfig()
|
||||||
shareConnectionDrawer.configCaption = qsTr("Save ShadowSocks config")
|
shareConnectionDrawer.configCaption = qsTr("Save ShadowSocks config")
|
||||||
@@ -80,11 +91,6 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = true
|
|
||||||
PageController.showTopCloseButton(true)
|
|
||||||
|
|
||||||
shareConnectionDrawer.contentVisible = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onExportErrorOccurred(errorMessage) {
|
function onExportErrorOccurred(errorMessage) {
|
||||||
@@ -115,6 +121,11 @@ PageType {
|
|||||||
property string name: qsTr("WireGuard native format")
|
property string name: qsTr("WireGuard native format")
|
||||||
property var type: PageShare.ConfigType.WireGuard
|
property var type: PageShare.ConfigType.WireGuard
|
||||||
}
|
}
|
||||||
|
QtObject {
|
||||||
|
id: awgConnectionFormat
|
||||||
|
property string name: qsTr("AmneziaWG native format")
|
||||||
|
property var type: PageShare.ConfigType.Awg
|
||||||
|
}
|
||||||
QtObject {
|
QtObject {
|
||||||
id: shadowSocksConnectionFormat
|
id: shadowSocksConnectionFormat
|
||||||
property string name: qsTr("ShadowSocks native format")
|
property string name: qsTr("ShadowSocks native format")
|
||||||
@@ -129,7 +140,7 @@ PageType {
|
|||||||
FlickableType {
|
FlickableType {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
contentHeight: content.height
|
contentHeight: content.height + 10
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
id: content
|
id: content
|
||||||
@@ -154,14 +165,15 @@ PageType {
|
|||||||
shareFullAccessDrawer.open()
|
shareFullAccessDrawer.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: shareFullAccessDrawer
|
id: shareFullAccessDrawer
|
||||||
|
|
||||||
width: root.width
|
parent: root
|
||||||
height: root.height * 0.45
|
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
expandedHeight: root.height * 0.45
|
||||||
|
|
||||||
ColumnLayout {
|
expandedContent: ColumnLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -234,7 +246,7 @@ PageType {
|
|||||||
accessTypeSelector.currentIndex = 1
|
accessTypeSelector.currentIndex = 1
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
ServersModel.getCurrentlyProcessedServerCredentials())
|
ServersModel.getProcessedServerCredentials())
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,6 +276,8 @@ PageType {
|
|||||||
textField.maximumLength: 20
|
textField.maximumLength: 20
|
||||||
|
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: shareButton
|
||||||
}
|
}
|
||||||
|
|
||||||
DropDownType {
|
DropDownType {
|
||||||
@@ -276,6 +290,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.4375
|
drawerHeight: 0.4375
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
descriptionText: qsTr("Server")
|
descriptionText: qsTr("Server")
|
||||||
headerText: qsTr("Server")
|
headerText: qsTr("Server")
|
||||||
@@ -305,7 +320,7 @@ PageType {
|
|||||||
serverSelector.severSelectorIndexChanged()
|
serverSelector.severSelectorIndexChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
serverSelector.menuVisible = false
|
serverSelector.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -316,7 +331,7 @@ PageType {
|
|||||||
|
|
||||||
function handler() {
|
function handler() {
|
||||||
serverSelector.text = selectedText
|
serverSelector.text = selectedText
|
||||||
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
|
ServersModel.processedIndex = proxyServersModel.mapToSource(currentIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,6 +343,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.5
|
drawerHeight: 0.5
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
descriptionText: qsTr("Protocol")
|
descriptionText: qsTr("Protocol")
|
||||||
headerText: qsTr("Protocol")
|
headerText: qsTr("Protocol")
|
||||||
@@ -358,14 +374,15 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
handler()
|
handler()
|
||||||
|
|
||||||
protocolSelector.menuVisible = false
|
protocolSelector.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
target: serverSelector
|
target: serverSelector
|
||||||
|
|
||||||
function onSeverSelectorIndexChanged() {
|
function onSeverSelectorIndexChanged() {
|
||||||
protocolSelectorListView.currentIndex = proxyContainersModel.mapFromSource(ServersModel.getDefaultContainer())
|
var defaultContainer = proxyContainersModel.mapFromSource(ServersModel.getProcessedServerData("defaultContainer"))
|
||||||
|
protocolSelectorListView.currentIndex = defaultContainer
|
||||||
protocolSelectorListView.triggerCurrentItem()
|
protocolSelectorListView.triggerCurrentItem()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -387,7 +404,7 @@ PageType {
|
|||||||
if (accessTypeSelector.currentIndex === 1) {
|
if (accessTypeSelector.currentIndex === 1) {
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
ExportController.updateClientManagementModel(ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
ServersModel.getCurrentlyProcessedServerCredentials())
|
ServersModel.getProcessedServerCredentials())
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -401,6 +418,8 @@ PageType {
|
|||||||
root.connectionTypesModel.push(openVpnConnectionFormat)
|
root.connectionTypesModel.push(openVpnConnectionFormat)
|
||||||
} else if (index === ContainerProps.containerFromString("amnezia-wireguard")) {
|
} else if (index === ContainerProps.containerFromString("amnezia-wireguard")) {
|
||||||
root.connectionTypesModel.push(wireGuardConnectionFormat)
|
root.connectionTypesModel.push(wireGuardConnectionFormat)
|
||||||
|
} else if (index === ContainerProps.containerFromString("amnezia-awg")) {
|
||||||
|
root.connectionTypesModel.push(awgConnectionFormat)
|
||||||
} else if (index === ContainerProps.containerFromString("amnezia-shadowsocks")) {
|
} else if (index === ContainerProps.containerFromString("amnezia-shadowsocks")) {
|
||||||
root.connectionTypesModel.push(openVpnConnectionFormat)
|
root.connectionTypesModel.push(openVpnConnectionFormat)
|
||||||
root.connectionTypesModel.push(shadowSocksConnectionFormat)
|
root.connectionTypesModel.push(shadowSocksConnectionFormat)
|
||||||
@@ -422,6 +441,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.4375
|
drawerHeight: 0.4375
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
visible: accessTypeSelector.currentIndex === 0
|
visible: accessTypeSelector.currentIndex === 0
|
||||||
enabled: root.connectionTypesModel.length > 1
|
enabled: root.connectionTypesModel.length > 1
|
||||||
@@ -445,7 +465,7 @@ PageType {
|
|||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
exportTypeSelector.text = selectedText
|
exportTypeSelector.text = selectedText
|
||||||
exportTypeSelector.currentIndex = currentIndex
|
exportTypeSelector.currentIndex = currentIndex
|
||||||
exportTypeSelector.menuVisible = false
|
exportTypeSelector.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -455,11 +475,9 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareConnectionDrawer {
|
|
||||||
id: shareConnectionDrawer
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: shareButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.topMargin: 40
|
Layout.topMargin: 40
|
||||||
|
|
||||||
@@ -469,7 +487,7 @@ PageType {
|
|||||||
text: qsTr("Share")
|
text: qsTr("Share")
|
||||||
imageSource: "qrc:/images/controls/share-2.svg"
|
imageSource: "qrc:/images/controls/share-2.svg"
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function(){
|
||||||
if (clientNameTextField.textFieldText !== "") {
|
if (clientNameTextField.textFieldText !== "") {
|
||||||
ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type)
|
ExportController.generateConfig(root.connectionTypesModel[exportTypeSelector.currentIndex].type)
|
||||||
}
|
}
|
||||||
@@ -560,13 +578,15 @@ PageType {
|
|||||||
|
|
||||||
DividerType {}
|
DividerType {}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: clientInfoDrawer
|
id: clientInfoDrawer
|
||||||
|
|
||||||
width: root.width
|
parent: root
|
||||||
height: root.height * 0.5
|
|
||||||
|
|
||||||
ColumnLayout {
|
anchors.fill: parent
|
||||||
|
expandedHeight: root.height * 0.5
|
||||||
|
|
||||||
|
expandedContent: ColumnLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -597,30 +617,33 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Rename")
|
text: qsTr("Rename")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
clientNameEditDrawer.open()
|
clientNameEditDrawer.open()
|
||||||
}
|
}
|
||||||
|
|
||||||
DrawerType {
|
DrawerType2 {
|
||||||
id: clientNameEditDrawer
|
id: clientNameEditDrawer
|
||||||
|
|
||||||
width: root.width
|
parent: root
|
||||||
height: root.height * 0.35
|
|
||||||
|
|
||||||
onVisibleChanged: {
|
anchors.fill: parent
|
||||||
if (clientNameEditDrawer.visible) {
|
expandedHeight: root.height * 0.35
|
||||||
clientNameEditor.textField.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
expandedContent: ColumnLayout {
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.topMargin: 16
|
anchors.topMargin: 32
|
||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: clientNameEditDrawer
|
||||||
|
function onOpened() {
|
||||||
|
clientNameEditor.textField.forceActiveFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
id: clientNameEditor
|
id: clientNameEditor
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
@@ -628,14 +651,18 @@ PageType {
|
|||||||
textFieldText: clientName
|
textFieldText: clientName
|
||||||
textField.maximumLength: 20
|
textField.maximumLength: 20
|
||||||
checkEmptyText: true
|
checkEmptyText: true
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
if (clientNameEditor.textFieldText === "") {
|
if (clientNameEditor.textFieldText === "") {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -645,7 +672,7 @@ PageType {
|
|||||||
ExportController.renameClient(index,
|
ExportController.renameClient(index,
|
||||||
clientNameEditor.textFieldText,
|
clientNameEditor.textFieldText,
|
||||||
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
ContainersModel.getCurrentlyProcessedContainerIndex(),
|
||||||
ServersModel.getCurrentlyProcessedServerCredentials())
|
ServersModel.getProcessedServerCredentials())
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
clientNameEditDrawer.close()
|
clientNameEditDrawer.close()
|
||||||
}
|
}
|
||||||
@@ -667,21 +694,20 @@ PageType {
|
|||||||
|
|
||||||
text: qsTr("Revoke")
|
text: qsTr("Revoke")
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
questionDrawer.headerText = qsTr("Revoke the config for a user - %1?").arg(clientName)
|
var headerText = qsTr("Revoke the config for a user - %1?").arg(clientName)
|
||||||
questionDrawer.descriptionText = qsTr("The user will no longer be able to connect to your server.")
|
var descriptionText = qsTr("The user will no longer be able to connect to your server.")
|
||||||
questionDrawer.yesButtonText = qsTr("Continue")
|
var yesButtonText = qsTr("Continue")
|
||||||
questionDrawer.noButtonText = qsTr("Cancel")
|
var noButtonText = qsTr("Cancel")
|
||||||
|
|
||||||
questionDrawer.yesButtonFunction = function() {
|
var yesButtonFunction = function() {
|
||||||
questionDrawer.close()
|
|
||||||
clientInfoDrawer.close()
|
clientInfoDrawer.close()
|
||||||
root.revokeConfig(index)
|
root.revokeConfig(index)
|
||||||
}
|
}
|
||||||
questionDrawer.noButtonFunction = function() {
|
var noButtonFunction = function() {
|
||||||
questionDrawer.close()
|
|
||||||
}
|
}
|
||||||
questionDrawer.open()
|
|
||||||
|
showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -689,12 +715,15 @@ PageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QuestionDrawer {
|
|
||||||
id: questionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShareConnectionDrawer {
|
||||||
|
id: shareConnectionDrawer
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
onPressed: function(mouse) {
|
onPressed: function(mouse) {
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ PageType {
|
|||||||
Layout.topMargin: 16
|
Layout.topMargin: 16
|
||||||
|
|
||||||
drawerHeight: 0.4375
|
drawerHeight: 0.4375
|
||||||
|
drawerParent: root
|
||||||
|
|
||||||
descriptionText: qsTr("Server")
|
descriptionText: qsTr("Server")
|
||||||
headerText: qsTr("Server")
|
headerText: qsTr("Server")
|
||||||
@@ -99,7 +100,7 @@ PageType {
|
|||||||
|
|
||||||
shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
|
shareConnectionDrawer.headerText = qsTr("Accessing ") + serverSelector.text
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
|
shareConnectionDrawer.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
|
||||||
serverSelector.menuVisible = false
|
serverSelector.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
@@ -110,7 +111,7 @@ PageType {
|
|||||||
|
|
||||||
function handler() {
|
function handler() {
|
||||||
serverSelector.text = selectedText
|
serverSelector.text = selectedText
|
||||||
ServersModel.currentlyProcessedIndex = proxyServersModel.mapToSource(currentIndex)
|
ServersModel.processedIndex = proxyServersModel.mapToSource(currentIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,12 +123,10 @@ PageType {
|
|||||||
text: qsTr("Share")
|
text: qsTr("Share")
|
||||||
imageSource: "qrc:/images/controls/share-2.svg"
|
imageSource: "qrc:/images/controls/share-2.svg"
|
||||||
|
|
||||||
onClicked: function() {
|
clickedFunc: function() {
|
||||||
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
shareConnectionDrawer.headerText = qsTr("Connection to ") + serverSelector.text
|
||||||
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
shareConnectionDrawer.configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = false
|
|
||||||
|
|
||||||
shareConnectionDrawer.open()
|
shareConnectionDrawer.open()
|
||||||
shareConnectionDrawer.contentVisible = false
|
shareConnectionDrawer.contentVisible = false
|
||||||
PageController.showBusyIndicator(true)
|
PageController.showBusyIndicator(true)
|
||||||
@@ -140,16 +139,15 @@ PageType {
|
|||||||
|
|
||||||
PageController.showBusyIndicator(false)
|
PageController.showBusyIndicator(false)
|
||||||
|
|
||||||
shareConnectionDrawer.needCloseButton = true
|
|
||||||
PageController.showTopCloseButton(true)
|
|
||||||
|
|
||||||
shareConnectionDrawer.contentVisible = true
|
shareConnectionDrawer.contentVisible = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShareConnectionDrawer {
|
|
||||||
id: shareConnectionDrawer
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShareConnectionDrawer {
|
||||||
|
id: shareConnectionDrawer
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,22 +20,16 @@ PageType {
|
|||||||
function onGoToPageHome() {
|
function onGoToPageHome() {
|
||||||
tabBar.setCurrentIndex(0)
|
tabBar.setCurrentIndex(0)
|
||||||
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
||||||
|
|
||||||
PageController.updateDrawerRootPage(PageEnum.PageHome)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGoToPageSettings() {
|
function onGoToPageSettings() {
|
||||||
tabBar.setCurrentIndex(2)
|
tabBar.setCurrentIndex(2)
|
||||||
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
||||||
|
|
||||||
PageController.updateDrawerRootPage(PageEnum.PageSettings)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGoToPageViewConfig() {
|
function onGoToPageViewConfig() {
|
||||||
var pagePath = PageController.getPagePath(PageEnum.PageSetupWizardViewConfig)
|
var pagePath = PageController.getPagePath(PageEnum.PageSetupWizardViewConfig)
|
||||||
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
||||||
|
|
||||||
PageController.updateDrawerRootPage(PageEnum.PageSetupWizardViewConfig)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onShowBusyIndicator(visible) {
|
function onShowBusyIndicator(visible) {
|
||||||
@@ -44,15 +38,14 @@ PageType {
|
|||||||
tabBar.enabled = !visible
|
tabBar.enabled = !visible
|
||||||
}
|
}
|
||||||
|
|
||||||
// function onShowTopCloseButton(visible) {
|
|
||||||
// topCloseButton.visible = visible
|
|
||||||
// }
|
|
||||||
|
|
||||||
function onEnableTabBar(enabled) {
|
function onEnableTabBar(enabled) {
|
||||||
tabBar.enabled = enabled
|
tabBar.enabled = enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
function onClosePage() {
|
function onClosePage() {
|
||||||
|
tabBar.isServerInfoShow = tabBarStackView.currentItem.objectName !== PageController.getPagePath(PageEnum.PageSettingsServerInfo)
|
||||||
|
&& tabBarStackView.currentItem.objectName !== PageController.getPagePath(PageEnum.PageSettingsSplitTunneling)
|
||||||
|
|
||||||
if (tabBarStackView.depth <= 1) {
|
if (tabBarStackView.depth <= 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -61,13 +54,14 @@ PageType {
|
|||||||
|
|
||||||
function onGoToPage(page, slide) {
|
function onGoToPage(page, slide) {
|
||||||
var pagePath = PageController.getPagePath(page)
|
var pagePath = PageController.getPagePath(page)
|
||||||
|
|
||||||
if (slide) {
|
if (slide) {
|
||||||
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
|
||||||
} else {
|
} else {
|
||||||
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
||||||
}
|
}
|
||||||
|
|
||||||
PageController.updateDrawerRootPage(page)
|
tabBar.isServerInfoShow = page === PageEnum.PageSettingsServerInfo || PageEnum.PageSettingsSplitTunneling || tabBar.isServerInfoShow
|
||||||
}
|
}
|
||||||
|
|
||||||
function onGoToStartPage() {
|
function onGoToStartPage() {
|
||||||
@@ -115,20 +109,12 @@ PageType {
|
|||||||
function onNoInstalledContainers() {
|
function onNoInstalledContainers() {
|
||||||
PageController.setTriggeredBtConnectButton(true)
|
PageController.setTriggeredBtConnectButton(true)
|
||||||
|
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.getDefaultServerIndex()
|
ServersModel.processedIndex = ServersModel.getDefaultServerIndex()
|
||||||
InstallController.setShouldCreateServer(false)
|
InstallController.setShouldCreateServer(false)
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardEasy)
|
PageController.goToPage(PageEnum.PageSetupWizardEasy)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
|
||||||
target: ApiController
|
|
||||||
|
|
||||||
function onErrorOccurred(errorMessage) {
|
|
||||||
PageController.showErrorMessage(errorMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StackViewType {
|
StackViewType {
|
||||||
id: tabBarStackView
|
id: tabBarStackView
|
||||||
|
|
||||||
@@ -146,26 +132,21 @@ PageType {
|
|||||||
var pagePath = PageController.getPagePath(page)
|
var pagePath = PageController.getPagePath(page)
|
||||||
tabBarStackView.clear(StackView.Immediate)
|
tabBarStackView.clear(StackView.Immediate)
|
||||||
tabBarStackView.replace(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
tabBarStackView.replace(pagePath, { "objectName" : pagePath }, StackView.Immediate)
|
||||||
|
tabBar.isServerInfoShow = false
|
||||||
PageController.updateDrawerRootPage(page)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
var pagePath = PageController.getPagePath(PageEnum.PageHome)
|
var pagePath = PageController.getPagePath(PageEnum.PageHome)
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||||
tabBarStackView.push(pagePath, { "objectName" : pagePath })
|
tabBarStackView.push(pagePath, { "objectName" : pagePath })
|
||||||
}
|
}
|
||||||
|
|
||||||
// onWidthChanged: {
|
|
||||||
// topCloseButton.x = tabBarStackView.x + tabBarStackView.width -
|
|
||||||
// topCloseButton.buttonWidth - topCloseButton.rightPadding
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TabBar {
|
TabBar {
|
||||||
id: tabBar
|
id: tabBar
|
||||||
|
|
||||||
property int previousIndex: 0
|
property int previousIndex: 0
|
||||||
|
property bool isServerInfoShow: false
|
||||||
|
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@@ -196,11 +177,11 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TabImageButtonType {
|
TabImageButtonType {
|
||||||
isSelected: tabBar.currentIndex === 0
|
isSelected: tabBar.isServerInfoShow ? false : tabBar.currentIndex === 0
|
||||||
image: "qrc:/images/controls/home.svg"
|
image: "qrc:/images/controls/home.svg"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
tabBarStackView.goToTabBarPage(PageEnum.PageHome)
|
||||||
ServersModel.currentlyProcessedIndex = ServersModel.defaultIndex
|
ServersModel.processedIndex = ServersModel.defaultIndex
|
||||||
tabBar.previousIndex = 0
|
tabBar.previousIndex = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -230,7 +211,7 @@ PageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TabImageButtonType {
|
TabImageButtonType {
|
||||||
isSelected: tabBar.currentIndex === 2
|
isSelected: tabBar.isServerInfoShow ? true : tabBar.currentIndex === 2
|
||||||
image: "qrc:/images/controls/settings-2.svg"
|
image: "qrc:/images/controls/settings-2.svg"
|
||||||
onClicked: {
|
onClicked: {
|
||||||
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
tabBarStackView.goToTabBarPage(PageEnum.PageSettings)
|
||||||
@@ -253,13 +234,6 @@ PageType {
|
|||||||
z: 1
|
z: 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// TopCloseButtonType {
|
|
||||||
// id: topCloseButton
|
|
||||||
|
|
||||||
// x: tabBarStackView.width - topCloseButton.buttonWidth - topCloseButton.rightPadding
|
|
||||||
// z: 1
|
|
||||||
// }
|
|
||||||
|
|
||||||
ConnectionTypeSelectionDrawer {
|
ConnectionTypeSelectionDrawer {
|
||||||
id: connectionTypeSelection
|
id: connectionTypeSelection
|
||||||
|
|
||||||
|
|||||||
+60
-23
@@ -8,6 +8,7 @@ import PageEnum 1.0
|
|||||||
|
|
||||||
import "Config"
|
import "Config"
|
||||||
import "Controls2"
|
import "Controls2"
|
||||||
|
import "Components"
|
||||||
|
|
||||||
Window {
|
Window {
|
||||||
id: root
|
id: root
|
||||||
@@ -130,32 +131,15 @@ Window {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
anchors.right: parent.right
|
anchors.fill: parent
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.bottom: parent.bottom
|
|
||||||
|
|
||||||
implicitHeight: popupErrorMessage.height
|
DrawerType2 {
|
||||||
|
|
||||||
DrawerType {
|
|
||||||
id: privateKeyPassphraseDrawer
|
id: privateKeyPassphraseDrawer
|
||||||
|
|
||||||
width: root.width
|
anchors.fill: parent
|
||||||
height: root.height * 0.35
|
expandedHeight: root.height * 0.35
|
||||||
|
|
||||||
onVisibleChanged: {
|
expandedContent: ColumnLayout {
|
||||||
if (privateKeyPassphraseDrawer.visible) {
|
|
||||||
passphrase.textFieldText = ""
|
|
||||||
passphrase.textField.forceActiveFocus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onAboutToHide: {
|
|
||||||
PageController.showBusyIndicator(true)
|
|
||||||
}
|
|
||||||
onAboutToShow: {
|
|
||||||
PageController.showBusyIndicator(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
ColumnLayout {
|
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@@ -163,6 +147,24 @@ Window {
|
|||||||
anchors.leftMargin: 16
|
anchors.leftMargin: 16
|
||||||
anchors.rightMargin: 16
|
anchors.rightMargin: 16
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: privateKeyPassphraseDrawer
|
||||||
|
function onOpened() {
|
||||||
|
passphrase.textFieldText = ""
|
||||||
|
passphrase.textField.forceActiveFocus()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAboutToHide() {
|
||||||
|
if (passphrase.textFieldText !== "") {
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onAboutToShow() {
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TextFieldWithHeaderType {
|
TextFieldWithHeaderType {
|
||||||
id: passphrase
|
id: passphrase
|
||||||
|
|
||||||
@@ -176,9 +178,13 @@ Window {
|
|||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
hidePassword = !hidePassword
|
hidePassword = !hidePassword
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeyNavigation.tab: saveButton
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicButtonType {
|
BasicButtonType {
|
||||||
|
id: saveButton
|
||||||
|
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
defaultColor: "transparent"
|
defaultColor: "transparent"
|
||||||
@@ -190,7 +196,7 @@ Window {
|
|||||||
|
|
||||||
text: qsTr("Save")
|
text: qsTr("Save")
|
||||||
|
|
||||||
onClicked: {
|
clickedFunc: function() {
|
||||||
privateKeyPassphraseDrawer.close()
|
privateKeyPassphraseDrawer.close()
|
||||||
PageController.passphraseRequestDrawerClosed(passphrase.textFieldText)
|
PageController.passphraseRequestDrawerClosed(passphrase.textFieldText)
|
||||||
}
|
}
|
||||||
@@ -199,6 +205,37 @@ Window {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
QuestionDrawer {
|
||||||
|
id: questionDrawer
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showQuestionDrawer(headerText, descriptionText, yesButtonText, noButtonText, yesButtonFunction, noButtonFunction) {
|
||||||
|
questionDrawer.headerText = headerText
|
||||||
|
questionDrawer.descriptionText = descriptionText
|
||||||
|
questionDrawer.yesButtonText = yesButtonText
|
||||||
|
questionDrawer.noButtonText = noButtonText
|
||||||
|
|
||||||
|
questionDrawer.yesButtonFunction = function() {
|
||||||
|
questionDrawer.close()
|
||||||
|
if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
||||||
|
yesButtonFunction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
questionDrawer.noButtonFunction = function() {
|
||||||
|
questionDrawer.close()
|
||||||
|
if (noButtonFunction && typeof noButtonFunction === "function") {
|
||||||
|
noButtonFunction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
questionDrawer.open()
|
||||||
|
}
|
||||||
|
|
||||||
FileDialog {
|
FileDialog {
|
||||||
id: mainFileDialog
|
id: mainFileDialog
|
||||||
|
|
||||||
|
|||||||
@@ -146,7 +146,8 @@ if [ "${MAC_CERT_PW+x}" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Building DMG installer..."
|
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
|
if [ "${MAC_CERT_PW+x}" ]; then
|
||||||
echo "Signing DMG installer..."
|
echo "Signing DMG installer..."
|
||||||
|
|||||||
Reference in New Issue
Block a user