Compare commits

...

43 Commits

Author SHA1 Message Date
Garegin866
1e8909c50c Removed defaultActiveFocusItem property, now FocusChainType takes it from focus chain, it is first element in chain.
Minor changes on FocusChainType.qml file.
2024-08-13 23:23:54 +04:00
Garegin866
699b2e8a4e Improved tab navigation functional. WIP 2024-08-06 23:04:32 +04:00
pokamest
1343d10aa7 Merge pull request #919 from amnezia-vpn/fix/android-clipboard
Fix calling paste from clipboard when launching app on android
2024-08-06 12:42:11 +01:00
pokamest
6f96ebd8bf Merge pull request #942 from amnezia-vpn/version-bump
Bump version to 4.6.1.0
2024-08-06 10:53:38 +01:00
albexk
cb531dacb3 Bump version to 4.6.1.0 2024-08-06 12:51:23 +03:00
albexk
dfd0b4d0e5 Fix Android bugs (#941)
* Add an explicit value for the hasFragileUserData parameter

* Fix app crashes when canceling file opening

* Fix requestNetwork bug for Android 11

* Fix activity onStop method
2024-08-06 10:44:51 +01:00
albexk
f978f55e7f Android TV (#933)
* Disable touchscreen requirement

* Add Android TV feature

* Add Android TV draft banner

* Add Android TV check method
2024-08-06 10:41:44 +01:00
albexk
ef06fcb4f4 Fix calling paste from clipboard when launching app on android 2024-08-03 13:02:34 +03:00
pokamest
ffe2314d47 Merge pull request #912 from amnezia-vpn/bugfix/qt6.7-ui-fix
Fixed ui bug on qt6.7
2024-07-29 12:03:37 +01:00
pokamest
4e970322d0 Merge pull request #901 from amnezia-vpn/update-translation
update the Arabic translation
2024-07-27 18:45:05 +01:00
Nikita Titov
8dee0d27cf Rename Shadowsocks (#891) 2024-07-27 18:42:11 +01:00
Mykola Baibuz
c520f9a2a4 Update OpenVPN to last version (#837)
* Update OpenVPN to least version

* Fix iOS build

* Fix client config for new OpenVPN3

* Update iOS submodule

* Resolve 3rd-prebuilt merge conflict
2024-07-27 18:38:55 +01:00
Garegin866
003c3a23c4 Fixed ui bug on qt6.7 2024-07-26 22:26:15 +04:00
pokamest
1754a82f67 iOS build fix 2024-07-22 15:29:48 +03:00
pokamest
3384008277 Merge pull request #899 from amnezia-vpn/bugfix/udp-for-ios
bugfix for udp for ios
2024-07-22 14:40:24 +03:00
pokamest
af22115706 Merge pull request #896 from amnezia-vpn/bugfix/dns-for-xray-ios
dns fix for xray(ios)
2024-07-22 14:39:44 +03:00
Nikita Titov
4b114fd3b6 Fix imgs and list in README (#900)
* Fix imgs and list in README

* Reorder download badges in README
2024-07-22 02:42:56 +03:00
Shehab Ahmed
9d531f5d74 update the Arabic translation 2024-07-19 21:24:28 +03:00
Boris Verbitskii
a5564148f5 bugfix for udp for ios 2024-07-19 11:23:00 +07:00
KsZnak
196f7778fc Im gs for readme (#898)
Update README.md
2024-07-16 12:56:52 +01:00
Boris Verbitskii
de20add857 dns fix for xray(ios) 2024-07-16 16:39:39 +07:00
pokamest
c59216b58a Merge pull request #880 from StrikerRUS/translation
add artifact with translations and update Russian translation
2024-07-11 02:59:14 -07:00
Nethius
acf7fa261a fixed qml warnings and hindi language warnings (#805) 2024-07-11 10:36:24 +01:00
pokamest
c3eddc92bd Merge pull request #889 from amnezia-vpn/feature/shadow-socks-by-xray-for-ios
ssXray support for ios
2024-07-11 02:34:04 -07:00
Boris Verbitskii
18c74f4b02 add ssXray for ios 2024-07-09 14:56:39 +07:00
pokamest
3f90ee915d Merge pull request #879 from amnezia-vpn/rename_open_over_ss
Renaming OpenVPN over ShadowsSocks
2024-07-07 16:13:47 +01:00
Nethius
401ad0db0e fixed wg/awg macos firewall rules for 0.0.0.0/0 (#883)
* fixed wg/awg macos/linux firewall rules for 0.0.0.0/0
2024-07-07 14:56:38 +01:00
Vladyslav Miachkov
5945133d30 Create AmneziaStyle qml object (#830) 2024-07-07 11:42:38 +01:00
Nethius
ff4fbde0b0 go to the home page after server installation (#878) 2024-07-07 11:42:14 +01:00
albexk
74ae4f3e67 SSXray for Android (#885) 2024-07-06 16:44:34 +01:00
pokamest
ae4b33d042 Merge pull request #884 from amnezia-vpn/fix/android-xray-config
Fix logging configuration for XRay
2024-07-06 14:10:12 +01:00
albexk
53fa280037 Fix logging configuration for XRay 2024-07-05 18:42:53 +03:00
pokamest
8ecde90bc7 Update README.md, fix crlf 2024-07-04 21:04:56 +01:00
pokamest
34a583f272 Update README.md 2024-07-04 20:58:48 +01:00
StrikerRUS
5de4b8eeb8 add artifact with translations and update Russian translation 2024-07-04 19:32:50 +03:00
StrikerRUS
aae420e469 create translations artifact 2024-07-04 14:27:30 +03:00
pokamest
0612f70c06 Merge pull request #877 from amnezia-vpn/feature/reorder-containers-installing-list
moved xray higher on the list of containers during installation
2024-07-03 14:06:56 +01:00
lunardunno
d0c82efa1c rename OpenVPN over ShadowsSocks 2024-07-03 12:06:31 +04:00
vladimir.kuznetsov
cf8492240e moved xray higher on the list of containers during installation 2024-07-02 22:00:28 +02:00
Boris Verbitckii
2bceb9f7ba Xray and wg fix (#875)
Xray support on iOS fixes
2024-07-01 17:27:53 +01:00
Iurii Egorov
760f935965 iOS Xray support (#864)
Xray for ios
2024-06-30 10:19:38 +01:00
pokamest
eeeb2805c5 Merge pull request #872 from amnezia-vpn/bugfix/torsetup
Fix TorWebsite setup in UI
2024-06-29 21:23:29 +01:00
Mykola Baibuz
9a592d67ad Fix TorWebsite setup in UI 2024-06-28 22:47:22 +03:00
157 changed files with 9331 additions and 5552 deletions

View File

@@ -65,6 +65,13 @@ jobs:
path: deploy/AppDir
retention-days: 7
- name: 'Upload translations artifact'
uses: actions/upload-artifact@v4
with:
name: AmneziaVPN_translations
path: client/translations
retention-days: 7
# ------------------------------------------------------
Build-Windows:

View File

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
set(PROJECT AmneziaVPN)
project(${PROJECT} VERSION 4.6.0.1
project(${PROJECT} VERSION 4.6.1.0
DESCRIPTION "AmneziaVPN"
HOMEPAGE_URL "https://amnezia.org/"
)
@@ -11,7 +11,7 @@ string(TIMESTAMP CURRENT_DATE "%Y-%m-%d")
set(RELEASE_DATE "${CURRENT_DATE}")
set(APP_MAJOR_VERSION ${CMAKE_PROJECT_VERSION_MAJOR}.${CMAKE_PROJECT_VERSION_MINOR}.${CMAKE_PROJECT_VERSION_PATCH})
set(APP_ANDROID_VERSION_CODE 54)
set(APP_ANDROID_VERSION_CODE 56)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(MZ_PLATFORM_NAME "linux")

View File

@@ -6,6 +6,26 @@
Amnezia is an open-source VPN client, with a key feature that enables you to deploy your own VPN server on your server.
![Image](https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/uipic4.png)
<br>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.6.0.3/AmneziaVPN_4.6.0.3_x64.exe"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/win.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.6.0.3/AmneziaVPN_4.6.0.3.dmg"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/mac.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/download/4.6.0.3/AmneziaVPN_Linux_4.6.0.3.tar.zip"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/lin.png" width="150" style="max-width: 100%;"></a>
<a href="https://github.com/amnezia-vpn/amnezia-client/releases/tag/4.6.0.3"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/andr.png" width="150" style="max-width: 100%;"></a>
<br>
<a href="https://play.google.com/store/search?q=amnezia+vpn&c=apps"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/play.png" width="150" style="max-width: 100%;"></a>
<a href="https://apps.apple.com/us/app/amneziavpn/id1600529900"><img src="https://github.com/amnezia-vpn/amnezia-client/blob/dev/metadata/img-readme/apl.png" width="150" style="max-width: 100%;"></a>
[All releases](https://github.com/amnezia-vpn/amnezia-client/releases)
<br>
## Features
- Very easy to use - enter your IP address, SSH login, and password, and Amnezia will automatically install VPN docker containers to your server and connect to the VPN.
@@ -16,10 +36,12 @@ Amnezia is an open-source VPN client, with a key feature that enables you to dep
## Links
[https://amnezia.org](https://amnezia.org) - project website
[https://www.reddit.com/r/AmneziaVPN](https://www.reddit.com/r/AmneziaVPN) - Reddit
[https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Telegram support channel (English)
[https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Telegram support channel (Russian)
- [https://amnezia.org](https://amnezia.org) - project website
- [https://www.reddit.com/r/AmneziaVPN](https://www.reddit.com/r/AmneziaVPN) - Reddit
- [https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Telegram support channel (English)
- [https://t.me/amnezia_vpn_ir](https://t.me/amnezia_vpn_ir) - Telegram support channel (Farsi)
- [https://t.me/amnezia_vpn_mm](https://t.me/amnezia_vpn_mm) - Telegram support channel (Myanmar)
- [https://t.me/amnezia_vpn](https://t.me/amnezia_vpn) - Telegram support channel (Russian)
## Tech
@@ -44,6 +66,19 @@ git submodule update --init --recursive
Want to contribute? Welcome!
### Help with translations
Download the most actual translation files.
Go to ["Actions" tab](https://github.com/amnezia-vpn/amnezia-client/actions?query=is%3Asuccess+branch%3Adev), click on the first line.
Then scroll down to the "Artifacts" section and download "AmneziaVPN_translations".
Unzip this file.
Each *.ts file contains strings for one corresponding language.
Translate or correct some strings in one or multiple *.ts files and commit them back to this repository into the ``client/translations`` folder.
You can do it via a web-interface or any other method you're familiar with.
### Building sources and deployment
Check deploy folder for build scripts.
@@ -52,7 +87,7 @@ Check deploy folder for build scripts.
1. First, make sure you have [XCode](https://developer.apple.com/xcode/) installed, at least version 14 or higher.
2. We use QT to generate the XCode project. We need QT version 6.6.1. Install QT for MacOS [here](https://doc.qt.io/qt-6/macos.html) or [QT Online Installer](https://www.qt.io/download-open-source). Required modules:
2. We use QT to generate the XCode project. We need QT version 6.6.2. Install QT for MacOS [here](https://doc.qt.io/qt-6/macos.html) or [QT Online Installer](https://www.qt.io/download-open-source). Required modules:
- MacOS
- iOS
- Qt 5 Compatibility Module
@@ -142,10 +177,11 @@ GPL v3.0
## Donate
Bitcoin: bc1qn9rhsffuxwnhcuuu4qzrwp4upkrq94xnh8r26u
Patreon: [https://www.patreon.com/amneziavpn](https://www.patreon.com/amneziavpn)
USDT BEP20: 0x6abD576765a826f87D1D95183438f9408C901bE4 <br>
USDT TRC20: TELAitazF1MZGmiNjTcnxDjEiH5oe7LC9d <br>
XMR: 48spms39jt1L2L5vyw2RQW6CXD6odUd4jFu19GZcDyKKQV9U88wsJVjSbL4CfRys37jVMdoaWVPSvezCQPhHXUW5UKLqUp3
payeer.com: P2561305
ko-fi.com: [https://ko-fi.com/amnezia_vpn](https://ko-fi.com/amnezia_vpn)
## Acknowledgments

View File

@@ -157,6 +157,7 @@ void AmneziaApplication::init()
connect(this, &AmneziaApplication::translationsUpdated, m_notificationHandler.get(), &NotificationHandler::onTranslationsUpdated);
#endif
m_engine->addImportPath("qrc:/ui/qml/Modules/");
m_engine->load(url);
m_systemController->setQmlRoot(m_engine->rootObjects().value(0));

View File

@@ -11,6 +11,9 @@
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.any" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<!-- for TV -->
<uses-feature android:name="android.software.leanback" android:required="false" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<!-- The following comment will be replaced upon deployment with default features based on the dependencies
of the application. Remove the comment if you do not require these default features. -->
@@ -31,9 +34,11 @@
android:label="-- %%INSERT_APP_NAME%% --"
android:icon="@mipmap/icon"
android:roundIcon="@mipmap/icon_round"
android:banner="@mipmap/ic_banner"
android:theme="@style/NoActionBar"
android:fullBackupContent="@xml/backup_content"
android:dataExtractionRules="@xml/data_extraction_rules"
android:hasFragileUserData="false"
tools:targetApi="s">
<activity
@@ -47,6 +52,7 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<category android:name="android.intent.category.LEANBACK_LAUNCHER" />
</intent-filter>
<intent-filter>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_banner_background"/>
<foreground android:drawable="@mipmap/ic_banner_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_banner_background">#1E1E1F</color>
</resources>

View File

@@ -1,6 +1,7 @@
package org.amnezia.vpn
import android.Manifest
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.app.NotificationManager
import android.content.BroadcastReceiver
@@ -230,7 +231,10 @@ class AmneziaActivity : QtActivity() {
override fun onStop() {
Log.d(TAG, "Stop Amnezia activity")
doUnbindService()
QtAndroidController.onServiceDisconnected()
mainScope.launch {
qtInitialized.await()
QtAndroidController.onServiceDisconnected()
}
super.onStop()
}
@@ -384,7 +388,8 @@ class AmneziaActivity : QtActivity() {
getVpnProto(vpnConfig)?.let { proto ->
Log.d(TAG, "Proto from config: $proto, current proto: $vpnProto")
if (isServiceConnected) {
if (proto == vpnProto) {
if (proto.serviceClass == vpnProto?.serviceClass) {
vpnProto = proto
connectToVpn(vpnConfig)
return
}
@@ -541,7 +546,7 @@ class AmneziaActivity : QtActivity() {
}
}.also {
startActivityForResult(it, OPEN_FILE_ACTION_CODE, ActivityResultHandler(
onSuccess = {
onAny = {
val uri = it?.data?.toString() ?: ""
Log.d(TAG, "Open file: $uri")
mainScope.launch {
@@ -555,8 +560,12 @@ class AmneziaActivity : QtActivity() {
}
@Suppress("unused")
@SuppressLint("UnsupportedChromeOsCameraSystemFeature")
fun isCameraPresent(): Boolean = applicationContext.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)
@Suppress("unused")
fun isOnTv(): Boolean = applicationContext.packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)
@Suppress("unused")
fun startQrCodeReader() {
Log.v(TAG, "Start camera")

View File

@@ -49,7 +49,15 @@ enum class VpnProto(
"org.amnezia.vpn:amneziaXrayService",
XrayService::class.java
) {
override fun createProtocol(): Protocol = Xray()
override fun createProtocol(): Protocol = Xray.instance
},
SSXRAY(
"SSXRay",
"org.amnezia.vpn:amneziaXrayService",
XrayService::class.java
) {
override fun createProtocol(): Protocol = Xray.instance
};
private var _protocol: Protocol? = null

View File

@@ -88,16 +88,24 @@ class NetworkState(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
connectivityManager.registerBestMatchingNetworkCallback(networkRequest, networkCallback, handler)
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
connectivityManager.requestNetwork(networkRequest, networkCallback, handler)
} catch (e: SecurityException) {
Log.e(TAG, "Failed to bind network listener: $e")
// Android 11 bug: https://issuetracker.google.com/issues/175055271
if (e.message?.startsWith("Package android does not belong to") == true) {
delay(1000)
val numberAttempts = 3
var attemptCount = 0
while(true) {
try {
connectivityManager.requestNetwork(networkRequest, networkCallback, handler)
} else {
throw e
break
} catch (e: SecurityException) {
Log.e(TAG, "Failed to bind network listener: $e")
// Android 11 bug: https://issuetracker.google.com/issues/175055271
if (e.message?.startsWith("Package android does not belong to") == true) {
if (++attemptCount > numberAttempts) {
throw e
}
delay(1000)
continue
} else {
throw e
}
}
}
} else {

View File

@@ -5,6 +5,7 @@ import android.net.VpnService.Builder
import java.io.File
import java.io.IOException
import go.Seq
import org.amnezia.vpn.protocol.BadConfigException
import org.amnezia.vpn.protocol.Protocol
import org.amnezia.vpn.protocol.ProtocolState.CONNECTED
import org.amnezia.vpn.protocol.ProtocolState.DISCONNECTED
@@ -114,17 +115,14 @@ class Xray : Protocol() {
return
}
val xrayJsonConfig = config.getJSONObject("xray_config_data")
val xrayJsonConfig = config.optJSONObject("xray_config_data")
?: config.optJSONObject("ssxray_config_data")
?: throw BadConfigException("config_data not found")
val xrayConfig = parseConfig(config, xrayJsonConfig)
// for debug
// xrayJsonConfig.getJSONObject("log").put("loglevel", "debug")
xrayJsonConfig.getJSONObject("log").put("loglevel", "warning")
// disable access log
xrayJsonConfig.getJSONObject("log").put("access", "none")
// replace socks address
// (xrayJsonConfig.getJSONArray("inbounds")[0] as JSONObject).put("listen", "::1")
(xrayJsonConfig.optJSONObject("log") ?: JSONObject().also { xrayJsonConfig.put("log", it) })
.put("loglevel", "warning")
.put("access", "none") // disable access log
start(xrayConfig, xrayJsonConfig.toString(), vpnBuilder, protect)
state.value = CONNECTED
@@ -228,6 +226,10 @@ class Xray : Protocol() {
throw VpnStartException("Failed to start tun2socks: $err")
}
}
companion object {
val instance: Xray by lazy { Xray() }
}
}
private fun String?.isNotNullOrBlank(block: (String) -> Unit) {

View File

@@ -119,18 +119,21 @@ QString OpenVpnConfigurator::processConfigWithLocalSettings(const QPair<QString,
if (!m_settings->isSitesSplitTunnelingEnabled()) {
config.append("\nredirect-gateway def1 ipv6 bypass-dhcp\n");
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
// Prevent ipv6 leak
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
#endif
config.append("block-ipv6\n");
} else if (m_settings->routeMode() == Settings::VpnOnlyForwardSites) {
// no redirect-gateway
} else if (m_settings->routeMode() == Settings::VpnAllExceptSites) {
#ifndef Q_OS_ANDROID
#if !defined(Q_OS_ANDROID) && !defined(Q_OS_IOS)
config.append("\nredirect-gateway ipv6 !ipv4 bypass-dhcp\n");
#endif
// Prevent ipv6 leak
config.append("ifconfig-ipv6 fd15:53b6:dead::2/64 fd15:53b6:dead::1\n");
#endif
config.append("block-ipv6\n");
}
}

View File

@@ -90,13 +90,13 @@ QMap<DockerContainer, QString> ContainerProps::containerHumanNames()
{
return { { DockerContainer::None, "Not installed" },
{ DockerContainer::OpenVpn, "OpenVPN" },
{ DockerContainer::ShadowSocks, "ShadowSocks" },
{ DockerContainer::ShadowSocks, "OpenVPN over SS" },
{ DockerContainer::Cloak, "OpenVPN over Cloak" },
{ DockerContainer::WireGuard, "WireGuard" },
{ DockerContainer::Awg, "AmneziaWG" },
{ DockerContainer::Xray, "XRay" },
{ DockerContainer::Ipsec, QObject::tr("IPsec") },
{ DockerContainer::SSXray, "ShadowSocks"},
{ DockerContainer::SSXray, "Shadowsocks"},
{ DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
{ DockerContainer::Dns, QObject::tr("AmneziaDNS") },
@@ -285,8 +285,9 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
case DockerContainer::WireGuard: return true;
case DockerContainer::OpenVpn: return true;
case DockerContainer::Awg: return true;
case DockerContainer::Cloak:
return true;
case DockerContainer::Xray: return true;
case DockerContainer::Cloak: return true;
case DockerContainer::SSXray: return true;
// case DockerContainer::ShadowSocks: return true;
default: return false;
}
@@ -305,6 +306,7 @@ bool ContainerProps::isSupportedByCurrentPlatform(DockerContainer c)
case DockerContainer::Awg: return true;
case DockerContainer::Cloak: return true;
case DockerContainer::Xray: return true;
case DockerContainer::SSXray: return true;
default: return false;
}
@@ -388,3 +390,18 @@ QJsonObject ContainerProps::getProtocolConfigFromContainer(const Proto protocol,
return QJsonDocument::fromJson(protocolConfigString.toUtf8()).object();
}
int ContainerProps::installPageOrder(DockerContainer container)
{
switch (container) {
case DockerContainer::OpenVpn: return 4;
case DockerContainer::Cloak: return 5;
case DockerContainer::ShadowSocks: return 6;
case DockerContainer::WireGuard: return 2;
case DockerContainer::Awg: return 1;
case DockerContainer::Xray: return 3;
case DockerContainer::Ipsec: return 7;
case DockerContainer::SSXray: return 8;
default: return 0;
}
}

View File

@@ -72,6 +72,8 @@ namespace amnezia
static bool isShareable(amnezia::DockerContainer container);
static QJsonObject getProtocolConfigFromContainer(const amnezia::Proto protocol, const QJsonObject &containerConfig);
static int installPageOrder(amnezia::DockerContainer container);
};
static void declareQmlContainerEnum()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -50,10 +50,12 @@ set_target_properties("networkextension" PROPERTIES
find_library(FW_ASSETS_LIBRARY AssetsLibrary)
find_library(FW_MOBILE_CORE MobileCoreServices)
find_library(FW_UI_KIT UIKit)
find_library(FW_LIBRESOLV libresolv.9.tbd)
target_link_libraries(networkextension PRIVATE ${FW_ASSETS_LIBRARY})
target_link_libraries(networkextension PRIVATE ${FW_MOBILE_CORE})
target_link_libraries(networkextension PRIVATE ${FW_UI_KIT})
target_link_libraries(networkextension PRIVATE ${FW_LIBRESOLV})
target_compile_options(networkextension PRIVATE -DGROUP_ID=\"${BUILD_IOS_GROUP_IDENTIFIER}\")
target_compile_options(networkextension PRIVATE -DNETWORK_EXTENSION=1)
@@ -80,13 +82,16 @@ target_sources(networkextension PRIVATE
${WG_APPLE_SOURCE_DIR}/WireGuardKit/Array+ConcurrentMap.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/IPAddress+AddrInfo.swift
${WG_APPLE_SOURCE_DIR}/WireGuardKit/PrivateKey.swift
${CLIENT_ROOT_DIR}/platforms/ios/HevSocksTunnel.swift
${CLIENT_ROOT_DIR}/platforms/ios/NELogController.swift
${CLIENT_ROOT_DIR}/platforms/ios/Log.swift
${CLIENT_ROOT_DIR}/platforms/ios/LogRecord.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+WireGuard.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+OpenVPN.swift
${CLIENT_ROOT_DIR}/platforms/ios/PacketTunnelProvider+Xray.swift
${CLIENT_ROOT_DIR}/platforms/ios/WGConfig.swift
${CLIENT_ROOT_DIR}/platforms/ios/XrayConfig.swift
${CLIENT_ROOT_DIR}/platforms/ios/iosglue.mm
)
@@ -114,3 +119,5 @@ target_include_directories(networkextension PRIVATE ${CLIENT_ROOT_DIR})
target_include_directories(networkextension PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/wireguard/ios/arm64/libwg-go.a)
target_link_libraries(networkextension PRIVATE ${CLIENT_ROOT_DIR}/3rd-prebuilt/3rd-prebuilt/xray/HevSocks5Tunnel.xcframework)

View File

@@ -33,6 +33,10 @@ void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, cons
}
// Skip annoying messages from Qt
if (msg.contains("OpenType support missing for")) {
return;
}
if (msg.startsWith("Unknown property") || msg.startsWith("Could not create pixmap") || msg.startsWith("Populating font") || msg.startsWith("stale focus object")) {
return;
}

View File

@@ -179,6 +179,11 @@ bool AndroidController::isCameraPresent()
return callActivityMethod<jboolean>("isCameraPresent", "()Z");
}
bool AndroidController::isOnTv()
{
return callActivityMethod<jboolean>("isOnTv", "()Z");
}
void AndroidController::startQrReaderActivity()
{
callActivityMethod("startQrCodeReader", "()V");

View File

@@ -35,6 +35,7 @@ public:
void saveFile(const QString &fileName, const QString &data);
QString openFile(const QString &filter);
bool isCameraPresent();
bool isOnTv();
void startQrReaderActivity();
void setSaveLogs(bool enabled);
void exportLogsFile(const QString &fileName);

View File

@@ -0,0 +1,73 @@
import HevSocks5Tunnel
public enum Socks5Tunnel {
private static var tunnelFileDescriptor: Int32? {
var ctlInfo = ctl_info()
withUnsafeMutablePointer(to: &ctlInfo.ctl_name) {
$0.withMemoryRebound(to: CChar.self, capacity: MemoryLayout.size(ofValue: $0.pointee)) {
_ = strcpy($0, "com.apple.net.utun_control")
}
}
for fd: Int32 in 0...1024 {
var addr = sockaddr_ctl()
var ret: Int32 = -1
var len = socklen_t(MemoryLayout.size(ofValue: addr))
withUnsafeMutablePointer(to: &addr) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
ret = getpeername(fd, $0, &len)
}
}
if ret != 0 || addr.sc_family != AF_SYSTEM {
continue
}
if ctlInfo.ctl_id == 0 {
ret = ioctl(fd, CTLIOCGINFO, &ctlInfo)
if ret != 0 {
continue
}
}
if addr.sc_id == ctlInfo.ctl_id {
return fd
}
}
return nil
}
private static var interfaceName: String? {
guard let tunnelFileDescriptor = self.tunnelFileDescriptor else {
return nil
}
var buffer = [UInt8](repeating: 0, count: Int(IFNAMSIZ))
return buffer.withUnsafeMutableBufferPointer { mutableBufferPointer in
guard let baseAddress = mutableBufferPointer.baseAddress else {
return nil
}
var ifnameSize = socklen_t(IFNAMSIZ)
let result = getsockopt(
tunnelFileDescriptor,
2 /* SYSPROTO_CONTROL */,
2 /* UTUN_OPT_IFNAME */,
baseAddress,
&ifnameSize
)
if result == 0 {
return String(cString: baseAddress)
} else {
return nil
}
}
}
@discardableResult
public static func run(withConfig filePath: String) -> Int32 {
guard let fileDescriptor = self.tunnelFileDescriptor else {
fatalError("Get tunnel file descriptor failed.")
}
return hev_socks5_tunnel_main(filePath.cString(using: .utf8), fileDescriptor)
}
public static func quit() {
hev_socks5_tunnel_quit()
}
}

View File

@@ -13,6 +13,10 @@ public func ovpnLog(_ type: OSLogType, title: String = "", message: String) {
neLog(type, title: "OVPN: \(title)", message: message)
}
public func xrayLog(_ type: OSLogType, title: String = "", message: String) {
neLog(type, title: "XRAY: \(title)", message: message)
}
public func neLog(_ type: OSLogType, title: String = "", message: String) {
Log.log(type, title: "NE: \(title)", message: message)
}

View File

@@ -0,0 +1,187 @@
import Foundation
import NetworkExtension
import WireGuardKitGo
enum XrayErrors: Error {
case noXrayConfig
case xrayConfigIsWrong
case cantSaveXrayConfig
case cantParseListenAndPort
case cantSaveHevSocksConfig
}
extension Constants {
static let cachesDirectory: URL = {
if let cachesDirectoryURL = FileManager.default.urls(for: .cachesDirectory,
in: .userDomainMask).first {
return cachesDirectoryURL
} else {
fatalError("Unable to retrieve caches directory.")
}
}()
}
extension PacketTunnelProvider {
func startXray(completionHandler: @escaping (Error?) -> Void) {
// Xray configuration
guard let protocolConfiguration = self.protocolConfiguration as? NETunnelProviderProtocol,
let providerConfiguration = protocolConfiguration.providerConfiguration,
let configData = providerConfiguration[Constants.xrayConfigKey] as? Data else {
xrayLog(.error, message: "Can't get xray configuration")
completionHandler(XrayErrors.noXrayConfig)
return
}
// Tunnel settings
let ipv6Enabled = false
let hideVPNIcon = false
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "254.1.1.1")
settings.mtu = 9000
settings.ipv4Settings = {
let settings = NEIPv4Settings(addresses: ["198.18.0.1"], subnetMasks: ["255.255.0.0"])
settings.includedRoutes = [NEIPv4Route.default()]
return settings
}()
settings.ipv6Settings = {
guard ipv6Enabled else {
return nil
}
let settings = NEIPv6Settings(addresses: ["fd6e:a81b:704f:1211::1"], networkPrefixLengths: [64])
settings.includedRoutes = [NEIPv6Route.default()]
if hideVPNIcon {
settings.excludedRoutes = [NEIPv6Route(destinationAddress: "::", networkPrefixLength: 128)]
}
return settings
}()
do {
let xrayConfig = try JSONDecoder().decode(XrayConfig.self,
from: configData)
var dnsArray = [String]()
if let dns1 = xrayConfig.dns1 {
dnsArray.append(dns1)
}
if let dns2 = xrayConfig.dns2 {
dnsArray.append(dns2)
}
settings.dnsSettings = !dnsArray.isEmpty
? NEDNSSettings(servers: dnsArray)
: NEDNSSettings(servers: ["1.1.1.1"])
let xrayConfigData = xrayConfig.config.data(using: .utf8)
guard let xrayConfigData else {
xrayLog(.error, message: "Can't encode config to data")
completionHandler(XrayErrors.xrayConfigIsWrong)
return
}
let jsonDict = try JSONSerialization.jsonObject(with: xrayConfigData,
options: []) as? [String: Any]
guard var jsonDict else {
xrayLog(.error, message: "Can't parse address and port for hevSocks")
completionHandler(XrayErrors.cantParseListenAndPort)
return
}
let port = 10808
let address = "::1"
if var inboundsArray = jsonDict["inbounds"] as? [[String: Any]], !inboundsArray.isEmpty {
inboundsArray[0]["port"] = port
inboundsArray[0]["listen"] = address
jsonDict["inbounds"] = inboundsArray
}
let updatedData = try JSONSerialization.data(withJSONObject: jsonDict, options: [])
setTunnelNetworkSettings(settings) { [weak self] error in
if let error {
completionHandler(error)
return
}
// Launch xray
self?.setupAndStartXray(configData: updatedData) { xrayError in
if let xrayError {
completionHandler(xrayError)
return
}
// Launch hevSocks
self?.setupAndRunTun2socks(configData: updatedData,
address: address,
port: port,
completionHandler: completionHandler)
}
}
} catch {
completionHandler(error)
return
}
}
func stopXray(completionHandler: () -> Void) {
Socks5Tunnel.quit()
LibXrayStopXray()
completionHandler()
}
private func setupAndStartXray(configData: Data,
completionHandler: @escaping (Error?) -> Void) {
let path = Constants.cachesDirectory.appendingPathComponent("config.json", isDirectory: false).path
guard FileManager.default.createFile(atPath: path, contents: configData) else {
xrayLog(.error, message: "Can't save xray configuration")
completionHandler(XrayErrors.cantSaveXrayConfig)
return
}
LibXrayRunXray(nil,
path,
Int64.max)
completionHandler(nil)
xrayLog(.info, message: "Xray started")
}
private func setupAndRunTun2socks(configData: Data,
address: String,
port: Int,
completionHandler: @escaping (Error?) -> Void) {
let config = """
tunnel:
mtu: 9000
socks5:
port: \(port)
address: \(address)
udp: 'udp'
misc:
task-stack-size: 20480
connect-timeout: 5000
read-write-timeout: 60000
log-file: stderr
log-level: error
limit-nofile: 65535
"""
let configurationFilePath = Constants.cachesDirectory.appendingPathComponent("config.yml", isDirectory: false).path
guard FileManager.default.createFile(atPath: configurationFilePath, contents: config.data(using: .utf8)!) else {
xrayLog(.info, message: "Cant save hevSocks configuration")
completionHandler(XrayErrors.cantSaveHevSocksConfig)
return
}
DispatchQueue.global().async {
xrayLog(.info, message: "Hev socks started")
completionHandler(nil)
Socks5Tunnel.run(withConfig: configurationFilePath)
}
}
}

View File

@@ -5,7 +5,8 @@ import Darwin
import OpenVPNAdapter
enum TunnelProtoType: String {
case wireguard, openvpn
case wireguard, openvpn, xray
}
struct Constants {
@@ -13,6 +14,7 @@ struct Constants {
static let processQueueName = "org.amnezia.process-packets"
static let kActivationAttemptId = "activationAttemptId"
static let ovpnConfigKey = "ovpn"
static let xrayConfigKey = "xray"
static let wireGuardConfigKey = "wireguard"
static let loggerTag = "NET"
@@ -91,6 +93,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
protoType = .openvpn
} else if (providerConfiguration?[Constants.wireGuardConfigKey] as? Data) != nil {
protoType = .wireguard
} else if (providerConfiguration?[Constants.xrayConfigKey] as? Data) != nil {
protoType = .xray
}
}
@@ -107,6 +111,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
completionHandler: completionHandler)
case .openvpn:
startOpenVPN(completionHandler: completionHandler)
case .xray:
startXray(completionHandler: completionHandler)
}
}
@@ -124,6 +131,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
case .openvpn:
stopOpenVPN(with: reason,
completionHandler: completionHandler)
case .xray:
stopXray(completionHandler: completionHandler)
}
}
@@ -138,6 +147,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
handleWireguardStatusMessage(messageData, completionHandler: completionHandler)
case .openvpn:
handleOpenVPNStatusMessage(messageData, completionHandler: completionHandler)
case .xray:
break;
}
}

View File

@@ -13,7 +13,7 @@ struct WGConfig: Decodable {
let clientIP: String
let clientPrivateKey: String
let serverPublicKey: String
let presharedKey: String
let presharedKey: String?
var allowedIPs: [String]
var persistentKeepAlive: String
let splitTunnelType: Int
@@ -65,7 +65,7 @@ struct WGConfig: Decodable {
\(settings)
[Peer]
PublicKey = \(serverPublicKey)
PresharedKey = \(presharedKey)
\(presharedKey == nil ? "" : "PresharedKey = \(presharedKey!)")
AllowedIPs = \(allowedIPs.joined(separator: ", "))
Endpoint = \(hostName):\(port)
PersistentKeepalive = \(persistentKeepAlive)

View File

@@ -0,0 +1,7 @@
import Foundation
struct XrayConfig: Decodable {
let dns1: String?
let dns2: String?
let config: String
}

View File

@@ -72,9 +72,12 @@ private:
bool setupCloak();
bool setupWireGuard();
bool setupAwg();
bool setupXray();
bool setupSSXray();
bool startOpenVPN(const QString &config);
bool startWireGuard(const QString &jsonConfig);
bool startXray(const QString &jsonConfig);
void startTunnel();

View File

@@ -216,6 +216,12 @@ bool IosController::connectVpn(amnezia::Proto proto, const QJsonObject& configur
if (proto == amnezia::Proto::Awg) {
return setupAwg();
}
if (proto == amnezia::Proto::Xray) {
return setupXray();
}
if (proto == amnezia::Proto::SSXray) {
return setupSSXray();
}
return false;
}
@@ -501,6 +507,42 @@ bool IosController::setupWireGuard()
return startWireGuard(wgConfigDocStr);
}
bool IosController::setupXray()
{
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Xray)].toObject();
QJsonDocument xrayConfigDoc(config);
QString xrayConfigStr(xrayConfigDoc.toJson(QJsonDocument::Compact));
QJsonObject finalConfig;
finalConfig.insert(config_key::dns1, m_rawConfig[config_key::dns1].toString());
finalConfig.insert(config_key::dns2, m_rawConfig[config_key::dns2].toString());
finalConfig.insert(config_key::config, xrayConfigStr);
QJsonDocument finalConfigDoc(finalConfig);
QString finalConfigStr(finalConfigDoc.toJson(QJsonDocument::Compact));
return startXray(finalConfigStr);
}
bool IosController::setupSSXray()
{
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::SSXray)].toObject();
QJsonDocument ssXrayConfigDoc(config);
QString ssXrayConfigStr(ssXrayConfigDoc.toJson(QJsonDocument::Compact));
QJsonObject finalConfig;
finalConfig.insert(config_key::dns1, m_rawConfig[config_key::dns1]);
finalConfig.insert(config_key::dns2, m_rawConfig[config_key::dns2]);
finalConfig.insert(config_key::config, ssXrayConfigStr);
QJsonDocument finalConfigDoc(finalConfig);
QString finalConfigStr(finalConfigDoc.toJson(QJsonDocument::Compact));
return startXray(finalConfigStr);
}
bool IosController::setupAwg()
{
QJsonObject config = m_rawConfig[ProtocolProps::key_proto_config_data(amnezia::Proto::Awg)].toObject();
@@ -590,6 +632,20 @@ bool IosController::startWireGuard(const QString &config)
startTunnel();
}
bool IosController::startXray(const QString &config)
{
qDebug() << "IosController::startXray";
NETunnelProviderProtocol *tunnelProtocol = [[NETunnelProviderProtocol alloc] init];
tunnelProtocol.providerBundleIdentifier = [NSString stringWithUTF8String:VPN_NE_BUNDLEID];
tunnelProtocol.providerConfiguration = @{@"xray": [[NSString stringWithUTF8String:config.toStdString().c_str()] dataUsingEncoding:NSUTF8StringEncoding]};
tunnelProtocol.serverAddress = m_serverAddress;
m_currentTunnel.protocolConfiguration = tunnelProtocol;
startTunnel();
}
void IosController::startTunnel()
{
NSString *protocolName = @"Unknown";

View File

@@ -139,7 +139,7 @@ bool WireguardUtilsLinux::addInterface(const InterfaceConfig& config) {
if (config.m_killSwitchEnabled) {
FirewallParams params { };
params.dnsServers.append(config.m_dnsServer);
if (config.m_allowedIPAddressRanges.at(0).toString() == "0.0.0.0/0"){
if (config.m_allowedIPAddressRanges.contains(IPAddress("0.0.0.0/0"))) {
params.blockAll = true;
if (config.m_excludedAddresses.size()) {
params.allowNets = true;

View File

@@ -137,7 +137,8 @@ bool WireguardUtilsMacos::addInterface(const InterfaceConfig& config) {
if (config.m_killSwitchEnabled) {
FirewallParams params { };
params.dnsServers.append(config.m_dnsServer);
if (config.m_allowedIPAddressRanges.at(0).toString() == "0.0.0.0/0"){
if (config.m_allowedIPAddressRanges.contains(IPAddress("0.0.0.0/0"))) {
params.blockAll = true;
if (config.m_excludedAddresses.size()) {
params.allowNets = true;

View File

@@ -65,14 +65,14 @@ QString ProtocolProps::transportProtoToString(TransportProto proto, Proto p)
QMap<amnezia::Proto, QString> ProtocolProps::protocolHumanNames()
{
return { { Proto::OpenVpn, "OpenVPN" },
{ Proto::ShadowSocks, "ShadowSocks" },
{ Proto::ShadowSocks, "Shadowsocks" },
{ Proto::Cloak, "Cloak" },
{ Proto::WireGuard, "WireGuard" },
{ Proto::Awg, "AmneziaWG" },
{ Proto::Ikev2, "IKEv2" },
{ Proto::L2tp, "L2TP" },
{ Proto::Xray, "XRay" },
{ Proto::SSXray, "ShadowSocks"},
{ Proto::SSXray, "Shadowsocks"},
{ Proto::TorWebSite, "Website in Tor network" },

View File

@@ -11,16 +11,6 @@
<file>images/tray/default.png</file>
<file>images/tray/error.png</file>
<file>images/arrow_left.png</file>
<file>fonts/Lato-Black.ttf</file>
<file>fonts/Lato-BlackItalic.ttf</file>
<file>fonts/Lato-Bold.ttf</file>
<file>fonts/Lato-BoldItalic.ttf</file>
<file>fonts/Lato-Italic.ttf</file>
<file>fonts/Lato-Light.ttf</file>
<file>fonts/Lato-LightItalic.ttf</file>
<file>fonts/Lato-Regular.ttf</file>
<file>fonts/Lato-Thin.ttf</file>
<file>fonts/Lato-ThinItalic.ttf</file>
<file>images/AmneziaVPN.png</file>
<file>images/share.png</file>
<file>server_scripts/remove_container.sh</file>
@@ -95,7 +85,6 @@
<file>server_scripts/check_user_in_sudo.sh</file>
<file>ui/qml/Controls2/BasicButtonType.qml</file>
<file>ui/qml/Controls2/TextFieldWithHeaderType.qml</file>
<file>fonts/pt-root-ui_vf.ttf</file>
<file>ui/qml/Controls2/LabelWithButtonType.qml</file>
<file>images/controls/arrow-right.svg</file>
<file>images/controls/chevron-right.svg</file>
@@ -239,10 +228,14 @@
<file>images/controls/alert-circle.svg</file>
<file>images/controls/file-check-2.svg</file>
<file>ui/qml/Controls2/WarningType.qml</file>
<file>fonts/pt-root-ui_vf.ttf</file>
<file>ui/qml/Modules/Style/qmldir</file>
<file>ui/qml/Modules/Style/AmneziaStyle.qml</file>
<file>ui/qml/Pages2/PageServiceSocksProxySettings.qml</file>
<file>server_scripts/socks5_proxy/run_container.sh</file>
<file>server_scripts/socks5_proxy/Dockerfile</file>
<file>server_scripts/socks5_proxy/configure_container.sh</file>
<file>server_scripts/socks5_proxy/start.sh</file>
<file>ui/qml/Controls2/FocusChainType.qml</file>
</qresource>
</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

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

View File

@@ -41,6 +41,7 @@ QVariant ContainersModel::data(const QModelIndex &index, int role) const
case IsCurrentlyProcessedRole: return container == static_cast<DockerContainer>(m_processedContainerIndex);
case IsSupportedRole: return ContainerProps::isSupportedByCurrentPlatform(container);
case IsShareableRole: return ContainerProps::isShareable(container);
case InstallPageOrderRole: return ContainerProps::installPageOrder(container);
}
return QVariant();
@@ -112,5 +113,7 @@ QHash<int, QByteArray> ContainersModel::roleNames() const
roles[IsCurrentlyProcessedRole] = "isCurrentlyProcessed";
roles[IsSupportedRole] = "isSupported";
roles[IsShareableRole] = "isShareable";
roles[InstallPageOrderRole] = "installPageOrder";
return roles;
}

View File

@@ -31,7 +31,9 @@ public:
IsCurrentlyProcessedRole,
IsDefaultRole,
IsSupportedRole,
IsShareableRole
IsShareableRole,
InstallPageOrderRole
};
int rowCount(const QModelIndex &parent = QModelIndex()) const override;

View File

@@ -92,9 +92,9 @@ int LanguageModel::getCurrentLanguageIndex()
int LanguageModel::getLineHeightAppend()
{
int langIndex = getCurrentLanguageIndex();
switch (langIndex) {
case 5: return 10; break; // Burmese
auto language = static_cast<LanguageSettings::AvailableLanguageEnum>(getCurrentLanguageIndex());
switch (language) {
case LanguageSettings::AvailableLanguageEnum::Burmese: return 10; break;
default: return 0; break;
}
}

View File

@@ -6,13 +6,14 @@ import Qt5Compat.GraphicalEffects
import ConnectionState 1.0
import PageEnum 1.0
import Style 1.0
Button {
id: root
property string defaultButtonColor: "#D7D8DB"
property string progressButtonColor: "#D7D8DB"
property string connectedButtonColor: "#FBB26A"
property string defaultButtonColor: AmneziaStyle.color.white
property string progressButtonColor: AmneziaStyle.color.white
property string connectedButtonColor: AmneziaStyle.color.orange
implicitWidth: 190
implicitHeight: 190
@@ -49,13 +50,13 @@ Button {
verticalOffset: 0
radius: 10
samples: 25
color: root.activeFocus ? "#D7D8DB" : "#FBB26A"
color: root.activeFocus ? AmneziaStyle.color.white : AmneziaStyle.color.orange
source: backgroundCircle
}
ShapePath {
fillColor: "transparent"
strokeColor: "#D7D8DB"
fillColor: AmneziaStyle.color.transparent
strokeColor: AmneziaStyle.color.white
strokeWidth: root.activeFocus ? 1 : 0
capStyle: ShapePath.RoundCap
@@ -70,10 +71,10 @@ Button {
}
ShapePath {
fillColor: "transparent"
fillColor: AmneziaStyle.color.transparent
strokeColor: {
if (ConnectionController.isConnectionInProgress) {
return "#261E1A"
return AmneziaStyle.color.connectionInProgress
} else if (ConnectionController.isConnected) {
return connectedButtonColor
} else {
@@ -113,8 +114,8 @@ Button {
visible: ConnectionController.isConnectionInProgress
ShapePath {
fillColor: "transparent"
strokeColor: "#D7D8DB"
fillColor: AmneziaStyle.color.transparent
strokeColor: AmneziaStyle.color.white
strokeWidth: 3
capStyle: ShapePath.RoundCap

View File

@@ -14,74 +14,71 @@ DrawerType2 {
width: parent.width
height: parent.height
expandedContent: ColumnLayout {
id: content
expandedContent: FocusChainType {
focus: root.visible
focusTabBarOnLastItem: false
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
ColumnLayout {
id: content
Component.onCompleted: {
root.expandedHeight = content.implicitHeight + 32
}
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
Connections {
target: root
enabled: !GC.isMobile()
function onOpened() {
focusItem.forceActiveFocus()
}
}
Header2Type {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.rightMargin: 16
Layout.leftMargin: 16
Layout.bottomMargin: 16
headerText: qsTr("Add new connection")
}
Item {
id: focusItem
KeyNavigation.tab: ip.rightButton
}
LabelWithButtonType {
id: ip
Layout.fillWidth: true
Layout.topMargin: 16
text: qsTr("Configure your server")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
PageController.goToPage(PageEnum.PageSetupWizardCredentials)
root.close()
Component.onCompleted: {
root.expandedHeight = content.implicitHeight + 32
}
KeyNavigation.tab: qrCode.rightButton
}
Header2Type {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.rightMargin: 16
Layout.leftMargin: 16
Layout.bottomMargin: 16
DividerType {}
LabelWithButtonType {
id: qrCode
Layout.fillWidth: true
text: qsTr("Open config file, key or QR code")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
root.close()
headerText: qsTr("Add new connection")
}
KeyNavigation.tab: focusItem
}
// Item {
// id: focusItem
// KeyNavigation.tab: ip.rightButton
// }
DividerType {}
LabelWithButtonType {
id: ip
Layout.fillWidth: true
Layout.topMargin: 16
text: qsTr("Configure your server")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
PageController.goToPage(PageEnum.PageSetupWizardCredentials)
root.close()
}
// KeyNavigation.tab: qrCode.rightButton
}
DividerType {}
LabelWithButtonType {
id: qrCode
Layout.fillWidth: true
text: qsTr("Open config file, key or QR code")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
clickedFunction: function() {
PageController.goToPage(PageEnum.PageSetupWizardConfigSource)
root.close()
}
// KeyNavigation.tab: focusItem
}
DividerType {}
}
}
}

View File

@@ -14,105 +14,111 @@ DrawerType2 {
property bool isAppSplitTinnelingEnabled: Qt.platform.os === "windows" || Qt.platform.os === "android"
anchors.fill: parent
expandedHeight: parent.height * 0.7
expandedHeight: parent.height * 0.9
expandedContent: ColumnLayout {
id: content
expandedContent: FocusChainType {
focus: root.visible
focusTabBarOnLastItem: false
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
ColumnLayout {
id: content
Connections {
target: root
enabled: !GC.isMobile()
function onOpened() {
focusItem.forceActiveFocus()
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
// onActiveFocusChanged: {
// if (activeFocus) {
// focusItem.forceActiveFocus()
// }
// }
// Connections {
// target: root
// enabled: !GC.isMobile()
// function onOpened() {
// focusItem.forceActiveFocus()
// }
// }
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")
}
}
Header2Type {
Layout.fillWidth: true
Layout.topMargin: 24
Layout.rightMargin: 16
Layout.leftMargin: 16
Layout.bottomMargin: 16
LabelWithButtonType {
id: splitTunnelingSwitch
Layout.fillWidth: true
Layout.topMargin: 16
headerText: qsTr("Split tunneling")
descriptionText: qsTr("Allows you to connect to some sites or applications through a VPN connection and bypass others")
}
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi")
Item {
id: focusItem
KeyNavigation.tab: splitTunnelingSwitch.visible ? splitTunnelingSwitch : siteBasedSplitTunnelingSwitch.rightButton
}
text: qsTr("Split tunneling on the server")
descriptionText: qsTr("Enabled \nCan't be disabled for current server")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
LabelWithButtonType {
id: splitTunnelingSwitch
Layout.fillWidth: true
Layout.topMargin: 16
// KeyNavigation.tab: siteBasedSplitTunnelingSwitch.visible ? siteBasedSplitTunnelingSwitch.rightButton : focusItem
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"
KeyNavigation.tab: siteBasedSplitTunnelingSwitch.visible ? siteBasedSplitTunnelingSwitch.rightButton : focusItem
clickedFunction: function() {
// PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
// root.close()
clickedFunction: function() {
// PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
// root.close()
}
}
}
DividerType {
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi")
}
LabelWithButtonType {
id: siteBasedSplitTunnelingSwitch
Layout.fillWidth: true
Layout.topMargin: 16
text: qsTr("Site-based split tunneling")
descriptionText: enabled && SitesModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: appSplitTunnelingSwitch.visible ?
appSplitTunnelingSwitch.rightButton :
focusItem
clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
root.close()
DividerType {
visible: ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && ServersModel.getDefaultServerData("isServerFromApi")
}
}
DividerType {
}
LabelWithButtonType {
id: siteBasedSplitTunnelingSwitch
Layout.fillWidth: true
Layout.topMargin: 16
LabelWithButtonType {
id: appSplitTunnelingSwitch
visible: isAppSplitTinnelingEnabled
text: qsTr("Site-based split tunneling")
descriptionText: enabled && SitesModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
Layout.fillWidth: true
// KeyNavigation.tab: appSplitTunnelingSwitch.visible ?
// appSplitTunnelingSwitch.rightButton :
// focusItem
text: qsTr("App-based split tunneling")
descriptionText: AppSplitTunnelingModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
KeyNavigation.tab: focusItem
clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsAppSplitTunneling)
root.close()
clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsSplitTunneling)
root.close()
}
}
}
DividerType {
visible: isAppSplitTinnelingEnabled
DividerType {
}
LabelWithButtonType {
id: appSplitTunnelingSwitch
visible: isAppSplitTinnelingEnabled
Layout.fillWidth: true
text: qsTr("App-based split tunneling")
descriptionText: AppSplitTunnelingModel.isTunnelingEnabled ? qsTr("Enabled") : qsTr("Disabled")
rightImageSource: "qrc:/images/controls/chevron-right.svg"
// KeyNavigation.tab: focusItem
clickedFunction: function() {
PageController.goToPage(PageEnum.PageSettingsAppSplitTunneling)
root.close()
}
}
DividerType {
visible: isAppSplitTinnelingEnabled
}
}
}
}

View File

@@ -8,6 +8,7 @@ import "../Controls2/TextTypes"
import SortFilterProxyModel 0.2
import InstalledAppsModel 1.0
import Style 1.0
DrawerType2 {
id: root
@@ -133,7 +134,7 @@ DrawerType2 {
anchors.rightMargin: 16
anchors.leftMargin: 16
backgroundColor: "#2C2D30"
backgroundColor: AmneziaStyle.color.greyDark
textFieldPlaceholderText: qsTr("application name")
}

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "../Controls2"
import "../Controls2/TextTypes"
@@ -86,11 +88,11 @@ DrawerType2 {
Layout.rightMargin: 16
Layout.leftMargin: 16
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.blackHovered
pressedColor: AmneziaStyle.color.blackPressed
disabledColor: AmneziaStyle.color.grey
textColor: AmneziaStyle.color.white
borderWidth: 1
text: noButtonText

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "../Controls2"
import "../Controls2/TextTypes"
import "../Config"
@@ -145,8 +147,8 @@ DrawerType2 {
indicator: Rectangle {
width: parent.width - 1
height: parent.height
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
border.color: radioButton.focus ? "#D7D8DB" : "transparent"
color: radioButton.hovered ? AmneziaStyle.color.greyDark : AmneziaStyle.color.blackLight
border.color: radioButton.focus ? AmneziaStyle.color.white : AmneziaStyle.color.transparent
border.width: radioButton.focus ? 1 : 0
Behavior on color {

View File

@@ -93,20 +93,11 @@ ListView {
PageController.goToPage(PageEnum.PageProtocolRaw)
break
}
case ContainerEnum.Sftp: {
SftpConfigModel.updateModel(config)
PageController.goToPage(PageEnum.PageServiceSftpSettings)
break
}
case ContainerEnum.TorWebSite: {
PageController.goToPage(PageEnum.PageServiceTorWebsiteSettings)
break
}
case ContainerEnum.Dns: {
PageController.goToPage(PageEnum.PageServiceDnsSettings)
break
}
default: { // go to the settings page of the container with multiple protocols
default: {
ProtocolsModel.updateModel(config)
PageController.goToPage(PageEnum.PageSettingsServerProtocol)
}

View File

@@ -9,6 +9,7 @@ import SortFilterProxyModel 0.2
import PageEnum 1.0
import ContainerProps 1.0
import Style 1.0
import "./"
import "../Controls2"
@@ -111,11 +112,11 @@ DrawerType2 {
Layout.fillWidth: true
Layout.topMargin: 8
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.blackHovered
pressedColor: AmneziaStyle.color.blackPressed
disabledColor: AmneziaStyle.color.grey
textColor: AmneziaStyle.color.white
borderWidth: 1
text: qsTr("Copy")
@@ -134,11 +135,11 @@ DrawerType2 {
visible: false
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.blackHovered
pressedColor: AmneziaStyle.color.blackPressed
disabledColor: AmneziaStyle.color.grey
textColor: AmneziaStyle.color.white
borderWidth: 1
text: qsTr("Copy config string")
@@ -153,11 +154,11 @@ DrawerType2 {
Layout.fillWidth: true
Layout.topMargin: 24
defaultColor: "transparent"
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
pressedColor: Qt.rgba(1, 1, 1, 0.12)
disabledColor: "#878B91"
textColor: "#D7D8DB"
defaultColor: AmneziaStyle.color.transparent
hoveredColor: AmneziaStyle.color.blackHovered
pressedColor: AmneziaStyle.color.blackPressed
disabledColor: AmneziaStyle.color.grey
textColor: AmneziaStyle.color.white
borderWidth: 1
text: qsTr("Show connection settings")
@@ -281,9 +282,9 @@ DrawerType2 {
readOnly: true
activeFocusOnTab: false
color: "#D7D8DB"
selectionColor: "#633303"
selectedTextColor: "#D7D8DB"
color: AmneziaStyle.color.white
selectionColor: AmneziaStyle.color.brown
selectedTextColor: AmneziaStyle.color.white
font.pixelSize: 16
font.weight: Font.Medium
@@ -294,7 +295,7 @@ DrawerType2 {
wrapMode: Text.Wrap
background: Rectangle {
color: "transparent"
color: AmneziaStyle.color.transparent
}
}
}

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "../Controls2"
import "../Controls2/TextTypes"
@@ -14,7 +16,7 @@ Rectangle {
implicitWidth: transportProtoButtonGroup.implicitWidth
implicitHeight: transportProtoButtonGroup.implicitHeight
color: "#1C1D21"
color: AmneziaStyle.color.blackLight
radius: 16
onFocusChanged: {

View File

@@ -2,7 +2,9 @@ import QtQuick
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
Item {
import Style 1.0
FocusScope {
id: root
property string backButtonImage: "qrc:/images/controls/arrow-left.svg"
@@ -13,12 +15,6 @@ Item {
visible: backButtonImage !== ""
onActiveFocusChanged: {
if (activeFocus) {
backButton.forceActiveFocus()
}
}
RowLayout {
id: content
@@ -28,7 +24,7 @@ Item {
ImageButtonType {
id: backButton
image: backButtonImage
imageColor: "#D7D8DB"
imageColor: AmneziaStyle.color.white
implicitWidth: 40
implicitHeight: 40
@@ -46,7 +42,7 @@ Item {
id: background
Layout.fillWidth: true
color: "transparent"
color: AmneziaStyle.color.transparent
}
}

View File

@@ -3,20 +3,22 @@ import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import Style 1.0
import "TextTypes"
Button {
id: root
property string hoveredColor: "#C1C2C5"
property string defaultColor: "#D7D8DB"
property string disabledColor: "#494B50"
property string pressedColor: "#979799"
property string hoveredColor: AmneziaStyle.color.whiteHovered
property string defaultColor: AmneziaStyle.color.white
property string disabledColor: AmneziaStyle.color.greyDisabled
property string pressedColor: AmneziaStyle.color.grey
property string textColor: "#0E0E11"
property string textColor: AmneziaStyle.color.black
property string borderColor: "#D7D8DB"
property string borderFocusedColor: "#D7D8DB"
property string borderColor: AmneziaStyle.color.white
property string borderFocusedColor: AmneziaStyle.color.white
property int borderWidth: 0
property int borderFocusedWidth: 1
@@ -30,6 +32,8 @@ Button {
property var clickedFunc
property alias buttonTextLabel: buttonText
implicitHeight: 56
hoverEnabled: true
@@ -46,8 +50,8 @@ Button {
background: Rectangle {
id: focusBorder
color: "transparent"
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
color: AmneziaStyle.color.transparent
border.color: root.activeFocus ? root.borderFocusedColor : AmneziaStyle.color.transparent
border.width: root.activeFocus ? root.borderFocusedWidth : 0
anchors.fill: parent
@@ -138,6 +142,8 @@ Button {
}
ButtonTextType {
id: buttonText
color: textColor
text: root.text
visible: root.text === "" ? false : true

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Shapes
import Style 1.0
Popup {
id: root
anchors.centerIn: parent
@@ -16,7 +18,7 @@ Popup {
}
background: Rectangle {
color: "transparent"
color: AmneziaStyle.color.transparent
}
BusyIndicator {
@@ -40,8 +42,8 @@ Popup {
layer.samples: 4
ShapePath {
fillColor: "transparent"
strokeColor: "#787878"
fillColor: AmneziaStyle.color.transparent
strokeColor: AmneziaStyle.color.greyDisabled
strokeWidth: 3
capStyle: ShapePath.RoundCap

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
RadioButton {
id: root
@@ -9,17 +11,17 @@ RadioButton {
property string bodyText
property string footerText
property string hoveredColor: Qt.rgba(1, 1, 1, 0.05)
property string defaultColor: Qt.rgba(1, 1, 1, 0)
property string disabledColor: Qt.rgba(1, 1, 1, 0)
property string pressedColor: Qt.rgba(1, 1, 1, 0.05)
property string selectedColor: Qt.rgba(1, 1, 1, 0)
property string hoveredColor: AmneziaStyle.color.blackHovered
property string defaultColor: AmneziaStyle.color.transparent
property string disabledColor: AmneziaStyle.color.transparent
property string pressedColor: AmneziaStyle.color.blackPressed
property string selectedColor: AmneziaStyle.color.transparent
property string textColor: "#0E0E11"
property string textColor: AmneziaStyle.color.black
property string pressedBorderColor: Qt.rgba(251/255, 178/255, 106/255, 0.3)
property string selectedBorderColor: "#FBB26A"
property string defaultBodredColor: "transparent"
property string selectedBorderColor: AmneziaStyle.color.orange
property string defaultBodredColor: AmneziaStyle.color.transparent
property int borderWidth: 0
implicitWidth: content.implicitWidth
@@ -82,7 +84,7 @@ RadioButton {
Text {
text: root.headerText
wrapMode: Text.WordWrap
color: "#D7D8DB"
color: AmneziaStyle.color.white
font.pixelSize: 25
font.weight: 700
font.family: "PT Root UI VF"
@@ -97,7 +99,7 @@ RadioButton {
Text {
text: root.bodyText
wrapMode: Text.WordWrap
color: "#D7D8DB"
color: AmneziaStyle.color.white
font.pixelSize: 16
font.weight: 400
font.family: "PT Root UI VF"
@@ -113,7 +115,7 @@ RadioButton {
text: root.footerText
wrapMode: Text.WordWrap
visible: root.footerText !== ""
color: "#878B91"
color: AmneziaStyle.color.grey
font.pixelSize: 13
font.weight: 400
font.family: "PT Root UI VF"

View File

@@ -3,32 +3,34 @@ import QtQuick.Controls
import QtQuick.Layouts
import Qt5Compat.GraphicalEffects
import Style 1.0
import "TextTypes"
CheckBox {
id: root
property string descriptionText
property string descriptionTextColor: "#878B91"
property string descriptionTextDisabledColor: "#494B50"
property string descriptionTextColor: AmneziaStyle.color.grey
property string descriptionTextDisabledColor: AmneziaStyle.color.greyDisabled
property string textColor: "#D7D8DB"
property string textDisabledColor: "#878B91"
property string textColor: AmneziaStyle.color.white
property string textDisabledColor: AmneziaStyle.color.grey
property string hoveredColor: Qt.rgba(1, 1, 1, 0.05)
property string defaultColor: "transparent"
property string pressedColor: Qt.rgba(1, 1, 1, 0.05)
property string hoveredColor: AmneziaStyle.color.blackHovered
property string defaultColor: AmneziaStyle.color.transparent
property string pressedColor: AmneziaStyle.color.blackPressed
property string defaultBorderColor: "#D7D8DB"
property string checkedBorderColor: "#FBB26A"
property string checkedBorderDisabledColor: "#402102"
property string defaultBorderColor: AmneziaStyle.color.white
property string checkedBorderColor: AmneziaStyle.color.orange
property string checkedBorderDisabledColor: AmneziaStyle.color.brownDark
property string borderFocusedColor: "#D7D8DB"
property string borderFocusedColor: AmneziaStyle.color.white
property string checkedImageColor: "#FBB26A"
property string pressedImageColor: "#A85809"
property string defaultImageColor: "transparent"
property string checkedDisabledImageColor: "#84603D"
property string checkedImageColor: AmneziaStyle.color.orange
property string pressedImageColor: AmneziaStyle.color.orangeDark
property string defaultImageColor: AmneziaStyle.color.transparent
property string checkedDisabledImageColor: AmneziaStyle.color.brownLight
property string imageSource: "qrc:/images/controls/check.svg"
@@ -45,8 +47,8 @@ CheckBox {
focusPolicy: Qt.NoFocus
background: Rectangle {
color: "transparent"
border.color: root.focus ? borderFocusedColor : "transparent"
color: AmneziaStyle.color.transparent
border.color: root.focus ? borderFocusedColor : AmneziaStyle.color.transparent
border.width: 1
radius: 16
}
@@ -77,7 +79,7 @@ CheckBox {
anchors.centerIn: parent
width: 24
height: 24
color: "transparent"
color: AmneziaStyle.color.transparent
border.color: root.checked ?
(root.enabled ?
checkedBorderColor :

View File

@@ -20,7 +20,8 @@ Menu {
MenuItem {
text: qsTr("&Paste")
shortcut: StandardKey.Paste
enabled: textObj.canPaste
// Fix calling paste from clipboard when launching app on android
enabled: Qt.platform.os === "android" ? true : textObj.canPaste
onTriggered: textObj.paste()
}

View File

@@ -1,6 +1,8 @@
import QtQuick
import QtQuick.Layouts
import Style 1.0
Rectangle {
Layout.fillWidth: true
@@ -8,5 +10,5 @@ Rectangle {
Layout.rightMargin: 16
height: 1
color: "#2C2D30"
color: AmneziaStyle.color.greyDark
}

View File

@@ -2,9 +2,12 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "../Config"
import "TextTypes"
Item {
FocusScope {
id: root
readonly property string drawerExpanded: "expanded"
@@ -19,8 +22,8 @@ Item {
property Component collapsedContent
property Component expandedContent
property string defaultColor: "#1C1D21"
property string borderColor: "#2C2D30"
property string defaultColor: AmneziaStyle.color.blackLight
property string borderColor: AmneziaStyle.color.greyDark
property real expandedHeight
property real collapsedHeight: 0
@@ -38,6 +41,50 @@ Item {
signal closed
signal opened
onClosed: {
if (GC.isMobile()) {
return
}
// if (parent && parent instanceof PageType) {
// parent.focusItem_.forceActiveFocus()
// }
// tabBarStackView.currentItem.focusItem_.forceActiveFocus()
// PageController.forceStackActiveFocus()
}
// onOpened: {
// if (GC.isMobile()) {
// return
// }
// if (root.expandedContent) {
// expandedLoader.item.forceActiveFocus()
// }
// }
onActiveFocusChanged: {
if (GC.isMobile()) {
return
}
if (root.activeFocus && !root.isOpened && root.collapsedContent) {
collapsedLoader.item.forceActiveFocus()
}
}
onOpened: {
if (isOpened) {
if (drawerContent.state === root.drawerExpanded) {
expandedLoader.item.forceActiveFocus()
} else {
collapsedLoader.item.forceActiveFocus()
}
}
}
Connections {
target: PageController
@@ -90,7 +137,7 @@ Item {
id: background
anchors.fill: parent
color: root.isCollapsed ? "transparent" : Qt.rgba(14/255, 14/255, 17/255, 0.8)
color: root.isCollapsed ? AmneziaStyle.color.transparent : Qt.rgba(14/255, 14/255, 17/255, 0.8)
Behavior on color {
PropertyAnimation { duration: 200 }
@@ -173,6 +220,7 @@ Item {
Item {
id: drawerContent
focus: true
Drag.active: dragArea.drag.active
anchors.right: root.right
anchors.left: root.left

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
import "../Config"
@@ -9,31 +11,31 @@ Item {
id: root
property string text
property string textColor: "#d7d8db"
property string textDisabledColor: "#878B91"
property string textColor: AmneziaStyle.color.white
property string textDisabledColor: AmneziaStyle.color.grey
property int textMaximumLineCount: 2
property int textElide: Qt.ElideRight
property string descriptionText
property string descriptionTextColor: "#878B91"
property string descriptionTextDisabledColor: "#494B50"
property string descriptionTextColor: AmneziaStyle.color.grey
property string descriptionTextDisabledColor: AmneziaStyle.color.greyDisabled
property string headerText
property string headerBackButtonImage
property var rootButtonClickedFunction
property string rootButtonImage: "qrc:/images/controls/chevron-down.svg"
property string rootButtonImageColor: "#D7D8DB"
property string rootButtonBackgroundColor: "#1C1D21"
property string rootButtonBackgroundHoveredColor: "#1C1D21"
property string rootButtonBackgroundPressedColor: "#1C1D21"
property string rootButtonImageColor: AmneziaStyle.color.white
property string rootButtonBackgroundColor: AmneziaStyle.color.blackLight
property string rootButtonBackgroundHoveredColor: AmneziaStyle.color.blackLight
property string rootButtonBackgroundPressedColor: AmneziaStyle.color.blackLight
property string borderFocusedColor: "#D7D8DB"
property string borderFocusedColor: AmneziaStyle.color.white
property int borderFocusedWidth: 1
property string rootButtonHoveredBorderColor: "#494B50"
property string rootButtonDefaultBorderColor: "#2C2D30"
property string rootButtonPressedBorderColor: "#D7D8DB"
property string rootButtonHoveredBorderColor: AmneziaStyle.color.greyDisabled
property string rootButtonDefaultBorderColor: AmneziaStyle.color.greyDark
property string rootButtonPressedBorderColor: AmneziaStyle.color.white
property int rootButtonTextLeftMargins: 16
property int rootButtonTextTopMargin: 16
@@ -75,8 +77,8 @@ Item {
Rectangle {
id: focusBorder
color: "transparent"
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
color: AmneziaStyle.color.transparent
border.color: root.activeFocus ? root.borderFocusedColor : AmneziaStyle.color.transparent
border.width: root.activeFocus ? root.borderFocusedWidth : 0
anchors.fill: rootButtonContent
radius: 16
@@ -96,7 +98,7 @@ Item {
}
return root.hovered ? root.rootButtonBackgroundHoveredColor : root.rootButtonBackgroundColor
} else {
return "transparent"
return AmneziaStyle.color.transparent
}
}

View File

@@ -0,0 +1,131 @@
import QtQuick
import "../Config"
import "../Components"
FocusScope {
id: root
property bool focusTabBarOnLastItem: true
property alias focusItem_: focusItem
QtObject {
id: internal
property var firstActiveFocusItem: null
property var focusChain: []
}
onVisibleChanged: {
focusItem_.focus = true
}
function getChildren(parent) {
for (var i = 0; i < parent.children.length; i++) {
var child = parent.children[i]
if (child.children) {
getChildren(child)
}
}
}
function isFocusableItem(item) {
if (!item || !item.visible || !item.enabled) {
return false
}
return item instanceof BasicButtonType ||
item instanceof ConnectButton ||
item instanceof LabelWithButtonType ||
item instanceof SwitcherType ||
item instanceof ImageButtonType ||
item instanceof TextFieldWithHeaderType ||
item instanceof BackButtonType ||
item instanceof HorizontalRadioButton ||
item instanceof DrawerType2 && !item.isOpened && item.collapsedContent
}
function getFocusChain(parent) {
let focusChain = []
for (var i = 0; i < parent.children.length; i++) {
var child = parent.children[i]
if (child instanceof DropDownType ||
child instanceof HomeSplitTunnelingDrawer ||
child instanceof ConnectionTypeSelectionDrawer
) {
continue
}
if (isFocusableItem(child)) {
focusChain.push(child)
continue
}
if (child.children) {
focusChain = focusChain.concat(getFocusChain(child))
}
}
return focusChain
}
Component.onCompleted: {
internal.focusChain = getFocusChain(root)
if (internal.focusChain.length === 0) {
return
}
for (let i = 0; i < internal.focusChain.length; i++) {
internal.focusChain[i].KeyNavigation.tab = internal.focusChain[(i + 1) % internal.focusChain.length]
internal.focusChain[i].KeyNavigation.backtab = internal.focusChain[(i + internal.focusChain.length - 1) % internal.focusChain.length]
}
internal.firstActiveFocusItem = internal.focusChain[0]
const lastItem = internal.focusChain[internal.focusChain.length - 1]
lastItem.Keys.onTabPressed.connect(function() {
lastItemTabClicked(lastItem)
})
for (let j = 0; j < internal.focusChain.length; j++) {
if (internal.focusChain[j] instanceof TextFieldWithHeaderType) {
internal.focusChain[j].forceActiveFocus()
break
}
}
}
Item {
id: focusItem
focus: true
Keys.onTabPressed: {
if (internal.firstActiveFocusItem) {
internal.firstActiveFocusItem.focus = true
internal.firstActiveFocusItem.forceActiveFocus()
}
}
}
function lastItemTabClicked() {
focusItem.focus = true
if (GC.isMobile()) {
return
}
if (focusTabBarOnLastItem) {
PageController.forceTabBarActiveFocus()
}
if (lastItem && lastItem.parentFlickable) {
lastItem.parentFlickable.contentY = 0
}
}
}

View File

@@ -1,6 +1,8 @@
import QtQuick
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
Item {
@@ -37,7 +39,7 @@ Item {
implicitHeight: 40
image: root.actionButtonImage
imageColor: "#D7D8DB"
imageColor: AmneziaStyle.color.white
visible: image ? true : false
@@ -57,7 +59,7 @@ Item {
text: root.descriptionText
color: "#878B91"
color: AmneziaStyle.color.grey
visible: root.descriptionText !== ""
}

View File

@@ -1,6 +1,8 @@
import QtQuick
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
Item {
@@ -46,7 +48,7 @@ Item {
Layout.alignment: Qt.AlignRight
image: root.actionButtonImage
imageColor: "#D7D8DB"
imageColor: AmneziaStyle.color.white
visible: image ? true : false
@@ -66,7 +68,7 @@ Item {
text: root.descriptionText
color: "#878B91"
color: AmneziaStyle.color.grey
visible: root.descriptionText !== ""
}

View File

@@ -2,24 +2,26 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
RadioButton {
id: root
property string hoveredColor: Qt.rgba(1, 1, 1, 0.05)
property string defaultColor: Qt.rgba(1, 1, 1, 0)
property string checkedColor: Qt.rgba(1, 1, 1, 0)
property string disabledColor: "transparent"
property string hoveredColor: AmneziaStyle.color.blackHovered
property string defaultColor: AmneziaStyle.color.transparent
property string checkedColor: AmneziaStyle.color.transparent
property string disabledColor: AmneziaStyle.color.transparent
property string textColor: "#D7D8DB"
property string textDisabledColor: "#878B91"
property string textColor: AmneziaStyle.color.white
property string textDisabledColor: AmneziaStyle.color.grey
property string pressedBorderColor: "#494B50"
property string checkedBorderColor: "#FBB26A"
property string defaultBodredColor: "transparent"
property string checkedDisabledBorderColor: "#84603D"
property string borderFocusedColor: "#D7D8DB"
property string pressedBorderColor: AmneziaStyle.color.greyDisabled
property string checkedBorderColor: AmneziaStyle.color.orange
property string defaultBodredColor: AmneziaStyle.color.transparent
property string checkedDisabledBorderColor: AmneziaStyle.color.brownLight
property string borderFocusedColor: AmneziaStyle.color.white
property int borderWidth: 0
implicitWidth: content.implicitWidth

View File

@@ -2,23 +2,25 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
Button {
id: root
property string image
property string hoveredColor: Qt.rgba(1, 1, 1, 0.08)
property string defaultColor: "transparent"
property string pressedColor: Qt.rgba(1, 1, 1, 0.12)
property string disableColor: "#2C2D30"
property string hoveredColor: AmneziaStyle.color.blackHovered
property string defaultColor: AmneziaStyle.color.transparent
property string pressedColor: AmneziaStyle.color.blackPressed
property string disableColor: AmneziaStyle.color.greyDark
property string imageColor: "#878B91"
property string disableImageColor: "#2C2D30"
property string imageColor: AmneziaStyle.color.grey
property string disableImageColor: AmneziaStyle.color.greyDark
property alias backgroundColor: background.color
property alias backgroundRadius: background.radius
property string borderFocusedColor: "#D7D8DB"
property string borderFocusedColor: AmneziaStyle.color.white
property int borderFocusedWidth: 1
hoverEnabled: true
@@ -46,7 +48,7 @@ Button {
id: background
anchors.fill: parent
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
border.color: root.activeFocus ? root.borderFocusedColor : AmneziaStyle.color.transparent
border.width: root.activeFocus ? root.borderFocusedWidth : 0
color: {

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
Item {
@@ -24,16 +26,16 @@ Item {
property alias eyeButton: eyeImage
property FlickableType parentFlickable
property string textColor: "#d7d8db"
property string textDisabledColor: "#878B91"
property string descriptionColor: "#878B91"
property string descriptionDisabledColor: "#494B50"
property string textColor: AmneziaStyle.color.white
property string textDisabledColor: AmneziaStyle.color.grey
property string descriptionColor: AmneziaStyle.color.grey
property string descriptionDisabledColor: AmneziaStyle.color.greyDisabled
property real textOpacity: 1.0
property string borderFocusedColor: "#D7D8DB"
property string borderFocusedColor: AmneziaStyle.color.white
property int borderFocusedWidth: 1
property string rightImageColor: "#d7d8db"
property string rightImageColor: AmneziaStyle.color.white
property bool descriptionOnTop: false
property bool hideDescription: true
@@ -41,25 +43,17 @@ Item {
implicitWidth: content.implicitWidth + content.anchors.topMargin + content.anchors.bottomMargin
implicitHeight: content.implicitHeight + content.anchors.leftMargin + content.anchors.rightMargin
onFocusChanged: {
onActiveFocusChanged: {
if (root.activeFocus) {
if (rightImage.visible) {
rightImage.forceActiveFocus()
}
if (root.parentFlickable) {
root.parentFlickable.ensureVisible(root)
}
}
}
Connections {
target: rightImage
function onFocusChanged() {
if (rightImage.activeFocus) {
if (root.parentFlickable) {
root.parentFlickable.ensureVisible(root)
}
}
}
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
@@ -117,7 +111,7 @@ Item {
Layout.rightMargin: rightImageSource || !isLeftImageHoverEnabled ? 16 : 0
radius: 12
color: "transparent"
color: AmneziaStyle.color.transparent
Behavior on color {
PropertyAnimation { duration: 200 }
@@ -220,7 +214,7 @@ Item {
id: eyeImageBackground
anchors.fill: parent
radius: 12
color: "transparent"
color: AmneziaStyle.color.transparent
Behavior on color {
PropertyAnimation { duration: 200 }
@@ -249,6 +243,7 @@ Item {
hoverEnabled: false
image: rightImageSource
imageColor: rightImageColor
// focus: visible
visible: rightImageSource ? true : false
Layout.alignment: Qt.AlignRight
@@ -257,7 +252,7 @@ Item {
id: rightImageBackground
anchors.fill: parent
radius: 12
color: "transparent"
color: AmneziaStyle.color.transparent
Behavior on color {
PropertyAnimation { duration: 200 }
@@ -274,9 +269,10 @@ Item {
Rectangle {
id: background
anchors.fill: root
color: "transparent"
color: AmneziaStyle.color.transparent
visible: !rightImageSource
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
border.color: root.activeFocus ? root.borderFocusedColor : AmneziaStyle.color.transparent
border.width: root.activeFocus ? root.borderFocusedWidth : 0

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
ListView {
@@ -103,8 +105,8 @@ ListView {
indicator: Rectangle {
width: parent.width - 1
height: parent.height
color: radioButton.hovered ? "#2C2D30" : "#1C1D21"
border.color: radioButton.focus ? "#D7D8DB" : "transparent"
color: radioButton.hovered ? AmneziaStyle.color.greyDark : AmneziaStyle.color.blackLight
border.color: radioButton.focus ? AmneziaStyle.color.white : AmneziaStyle.color.transparent
border.width: radioButton.focus ? 1 : 0
Behavior on color {

View File

@@ -1,37 +1,19 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import "../Config"
import "../Components"
Item {
FocusChainType {
id: root
property StackView stackView: StackView.view
property var defaultActiveFocusItem: null
onVisibleChanged: {
if (visible && !GC.isMobile()) {
timer.start()
}
}
function lastItemTabClicked(focusItem) {
if (GC.isMobile()) {
return
}
if (focusItem) {
focusItem.forceActiveFocus()
PageController.forceTabBarActiveFocus()
} else {
if (defaultActiveFocusItem) {
defaultActiveFocusItem.forceActiveFocus()
}
PageController.forceTabBarActiveFocus()
}
}
// onVisibleChanged: {
// if (visible && !GC.isMobile()) {
// timer.start()
// }
// }
// MouseArea {
// id: globalMouseArea
@@ -47,15 +29,13 @@ Item {
// }
// 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: !GC.isMobile() // Start the timer
}
// Timer {
// id: timer
// interval: 100 // Milliseconds
// onTriggered: {
// focusItem.forceActiveFocus()
// }
// repeat: false // Stop the timer after one trigger
// running: !GC.isMobile() // Start the timer
// }
}

View File

@@ -2,6 +2,8 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
Popup {
@@ -82,11 +84,11 @@ Popup {
implicitHeight: 32
defaultColor: "white"
hoveredColor: "#C1C2C5"
pressedColor: "#AEB0B7"
disabledColor: "#494B50"
hoveredColor: AmneziaStyle.color.whiteHovered
pressedColor: AmneziaStyle.color.whiteHovered
disabledColor: AmneziaStyle.color.greyDisabled
textColor: "#0E0E11"
textColor: AmneziaStyle.color.black
borderWidth: 0
text: qsTr("Close")

View File

@@ -2,20 +2,22 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
ProgressBar {
id: root
implicitHeight: 4
background: Rectangle {
color: "#633303"
color: AmneziaStyle.color.brown
}
contentItem: Item {
Rectangle {
width: root.visualPosition * parent.width
height: parent.height
color: "#FBB26A"
color: AmneziaStyle.color.orange
}
}
}

View File

@@ -2,36 +2,38 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
Switch {
id: root
property alias descriptionText: description.text
property string descriptionTextColor: "#878B91"
property string descriptionTextDisabledColor: "#494B50"
property string descriptionTextColor: AmneziaStyle.color.grey
property string descriptionTextDisabledColor: AmneziaStyle.color.greyDisabled
property string textColor: "#D7D8DB"
property string textDisabledColor: "#878B91"
property string textColor: AmneziaStyle.color.white
property string textDisabledColor: AmneziaStyle.color.grey
property string checkedIndicatorColor: "#633303"
property string defaultIndicatorColor: "transparent"
property string checkedDisabledIndicatorColor: "#402102"
property string checkedIndicatorColor: AmneziaStyle.color.brown
property string defaultIndicatorColor: AmneziaStyle.color.transparent
property string checkedDisabledIndicatorColor: AmneziaStyle.color.brownDark
property string borderFocusedColor: "#D7D8DB"
property string borderFocusedColor: AmneziaStyle.color.white
property int borderFocusedWidth: 1
property string checkedIndicatorBorderColor: "#633303"
property string defaultIndicatorBorderColor: "#494B50"
property string checkedDisabledIndicatorBorderColor: "#402102"
property string checkedIndicatorBorderColor: AmneziaStyle.color.brown
property string defaultIndicatorBorderColor: AmneziaStyle.color.greyDisabled
property string checkedDisabledIndicatorBorderColor: AmneziaStyle.color.brownDark
property string checkedInnerCircleColor: "#FBB26A"
property string defaultInnerCircleColor: "#D7D8DB"
property string checkedDisabledInnerCircleColor: "#84603D"
property string defaultDisabledInnerCircleColor: "#494B50"
property string checkedInnerCircleColor: AmneziaStyle.color.orange
property string defaultInnerCircleColor: AmneziaStyle.color.white
property string checkedDisabledInnerCircleColor: AmneziaStyle.color.brownLight
property string defaultDisabledInnerCircleColor: AmneziaStyle.color.greyDisabled
property string hoveredIndicatorBackgroundColor: Qt.rgba(1, 1, 1, 0.08)
property string defaultIndicatorBackgroundColor: "transparent"
property string hoveredIndicatorBackgroundColor: AmneziaStyle.color.blackHovered
property string defaultIndicatorBackgroundColor: AmneziaStyle.color.transparent
hoverEnabled: enabled ? true : false
focusPolicy: Qt.TabFocus
@@ -100,7 +102,8 @@ Switch {
contentItem: ColumnLayout {
id: content
anchors.verticalCenter: parent.verticalCenter
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: parent.left
ListItemTitleType {

View File

@@ -1,16 +1,18 @@
import QtQuick
import QtQuick.Controls
import Style 1.0
TabButton {
id: root
property string hoveredColor: "#633303"
property string defaultColor: "#2C2D30"
property string selectedColor: "#FBB26A"
property string hoveredColor: AmneziaStyle.color.brown
property string defaultColor: AmneziaStyle.color.greyDark
property string selectedColor: AmneziaStyle.color.orange
property string textColor: "#D7D8DB"
property string textColor: AmneziaStyle.color.white
property string borderFocusedColor: "#D7D8DB"
property string borderFocusedColor: AmneziaStyle.color.white
property int borderFocusedWidth: 1
property bool isSelected: false
@@ -24,9 +26,9 @@ TabButton {
id: background
anchors.fill: parent
color: "transparent"
color: AmneziaStyle.color.transparent
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
border.color: root.activeFocus ? root.borderFocusedColor : AmneziaStyle.color.transparent
border.width: root.activeFocus ? root.borderFocusedWidth : 0
Rectangle {

View File

@@ -1,22 +1,25 @@
import QtQuick
import QtQuick.Controls
import Style 1.0
TabButton {
id: root
property string hoveredColor: "#633303"
property string defaultColor: "#D7D8DB"
property string selectedColor: "#FBB26A"
property string hoveredColor: AmneziaStyle.color.brown
property string defaultColor: AmneziaStyle.color.white
property string selectedColor: AmneziaStyle.color.orange
property string image
property bool isSelected: false
property string borderFocusedColor: "#D7D8DB"
property string borderFocusedColor: AmneziaStyle.color.white
property int borderFocusedWidth: 1
property var clickedFunc
focus: true
hoverEnabled: true
focusPolicy: Qt.TabFocus
@@ -26,10 +29,10 @@ TabButton {
background: Rectangle {
id: background
anchors.fill: parent
color: "transparent"
color: AmneziaStyle.color.transparent
radius: 10
border.color: root.activeFocus ? root.borderFocusedColor : "transparent"
border.color: root.activeFocus ? root.borderFocusedColor : AmneziaStyle.color.transparent
border.width: root.activeFocus ? root.borderFocusedWidth : 0
}

View File

@@ -1,6 +1,8 @@
import QtQuick
import QtQuick.Controls
import Style 1.0
Rectangle {
id: root
@@ -9,12 +11,12 @@ Rectangle {
property alias textArea: textArea
property alias textAreaText: textArea.text
property string borderHoveredColor: "#494B50"
property string borderNormalColor: "#2C2D30"
property string borderFocusedColor: "#d7d8db"
property string borderHoveredColor: AmneziaStyle.color.greyDisabled
property string borderNormalColor: AmneziaStyle.color.greyDark
property string borderFocusedColor: AmneziaStyle.color.white
height: 148
color: "#1C1D21"
color: AmneziaStyle.color.blackLight
border.width: 1
border.color: getBorderColor(borderNormalColor)
radius: 16
@@ -52,10 +54,10 @@ Rectangle {
anchors.topMargin: 16
anchors.bottomMargin: 16
color: "#D7D8DB"
selectionColor: "#633303"
selectedTextColor: "#D7D8DB"
placeholderTextColor: "#878B91"
color: AmneziaStyle.color.white
selectionColor: AmneziaStyle.color.brown
selectedTextColor: AmneziaStyle.color.white
placeholderTextColor: AmneziaStyle.color.grey
font.pixelSize: 16
font.weight: Font.Medium

View File

@@ -2,14 +2,16 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Style 1.0
import "TextTypes"
Item {
FocusScope {
id: root
property string headerText
property string headerTextDisabledColor: "#494B50"
property string headerTextColor: "#878b91"
property string headerTextDisabledColor: AmneziaStyle.color.greyDisabled
property string headerTextColor: AmneziaStyle.color.grey
property alias errorText: errorField.text
property bool checkEmptyText: false
@@ -21,33 +23,34 @@ Item {
property alias textField: textField
property alias textFieldText: textField.text
property string textFieldTextColor: "#d7d8db"
property string textFieldTextDisabledColor: "#878B91"
property string textFieldTextColor: AmneziaStyle.color.white
property string textFieldTextDisabledColor: AmneziaStyle.color.grey
property string textFieldPlaceholderText
property bool textFieldEditable: true
property string borderColor: "#2C2D30"
property string borderFocusedColor: "#d7d8db"
property string borderColor: AmneziaStyle.color.greyDark
property string borderFocusedColor: AmneziaStyle.color.white
property string backgroundColor: "#1c1d21"
property string backgroundDisabledColor: "transparent"
property string bgBorderHoveredColor: "#494B50"
property string backgroundColor: AmneziaStyle.color.blackLight
property string backgroundDisabledColor: AmneziaStyle.color.transparent
property string bgBorderHoveredColor: AmneziaStyle.color.greyDisabled
implicitWidth: content.implicitWidth
implicitHeight: content.implicitHeight
property FlickableType parentFlickable
Connections {
target: textField
function onFocusChanged() {
if (textField.activeFocus) {
if (root.parentFlickable) {
root.parentFlickable.ensureVisible(root)
}
}
}
}
// Connections {
// target: textField
// function onFocusChanged() {
// if (textField.activeFocus) {
// if (root.parentFlickable) {
// root.parentFlickable.ensureVisible(root)
// }
// }
// }
// }
ColumnLayout {
id: content
@@ -83,6 +86,7 @@ Item {
TextField {
id: textField
activeFocusOnTab: false
focus: true
enabled: root.textFieldEditable
color: root.enabled ? root.textFieldTextColor : root.textFieldTextDisabledColor
@@ -90,10 +94,10 @@ Item {
inputMethodHints: Qt.ImhNoAutoUppercase | Qt.ImhSensitiveData | Qt.ImhNoPredictiveText
placeholderText: root.textFieldPlaceholderText
placeholderTextColor: "#494B50"
placeholderTextColor: AmneziaStyle.color.greyDisabled
selectionColor: "#633303"
selectedTextColor: "#D7D8DB"
selectionColor: AmneziaStyle.color.brown
selectedTextColor: AmneziaStyle.color.white
font.pixelSize: 16
font.weight: 400
@@ -117,6 +121,7 @@ Item {
}
onActiveFocusChanged: {
backgroud.border.color = getBackgroundBorderColor(root.borderColor)
if (checkEmptyText && textFieldText === "") {
errorText = qsTr("The field can't be empty")
}
@@ -134,9 +139,6 @@ Item {
textObj: textField
}
onFocusChanged: {
backgroud.border.color = getBackgroundBorderColor(root.borderColor)
}
}
}
}
@@ -147,7 +149,7 @@ Item {
text: root.errorText
visible: root.errorText !== ""
color: "#EB5757"
color: AmneziaStyle.color.red
}
}
@@ -197,7 +199,7 @@ Item {
}
function getBackgroundBorderColor(noneFocusedColor) {
return textField.focus ? root.borderFocusedColor : noneFocusedColor
return textField.activeFocus ? root.borderFocusedColor : noneFocusedColor
}
Keys.onEnterPressed: {

View File

@@ -1,10 +1,12 @@
import QtQuick
import Style 1.0
Text {
lineHeight: 24
lineHeightMode: Text.FixedHeight
color: "#D7D8DB"
color: AmneziaStyle.color.white
font.pixelSize: 16
font.weight: 600
font.family: "PT Root UI VF"

View File

@@ -1,10 +1,12 @@
import QtQuick
import Style 1.0
Text {
lineHeight: 16 + LanguageModel.getLineHeightAppend()
lineHeightMode: Text.FixedHeight
color: "#0E0E11"
color: AmneziaStyle.color.black
font.pixelSize: 13
font.weight: 400
font.family: "PT Root UI VF"

View File

@@ -1,14 +1,16 @@
import QtQuick
import Style 1.0
Text {
lineHeight: 38 + LanguageModel.getLineHeightAppend()
lineHeightMode: Text.FixedHeight
color: "#D7D8DB"
font.pixelSize: 36
color: AmneziaStyle.color.white
font.pixelSize: 32
font.weight: 700
font.family: "PT Root UI VF"
font.letterSpacing: -1.08
font.letterSpacing: -1.0
wrapMode: Text.WordWrap
}

Some files were not shown because too many files have changed in this diff Show More