mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-29 23:00:35 +03:00
Compare commits
46 Commits
feature/an
...
bugfix/ips
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e08b62df40 | ||
|
|
90912f9231 | ||
|
|
1754a82f67 | ||
|
|
3384008277 | ||
|
|
af22115706 | ||
|
|
4b114fd3b6 | ||
|
|
a5564148f5 | ||
|
|
196f7778fc | ||
|
|
de20add857 | ||
|
|
c59216b58a | ||
|
|
acf7fa261a | ||
|
|
c3eddc92bd | ||
|
|
18c74f4b02 | ||
|
|
3f90ee915d | ||
|
|
401ad0db0e | ||
|
|
5945133d30 | ||
|
|
ff4fbde0b0 | ||
|
|
74ae4f3e67 | ||
|
|
ae4b33d042 | ||
|
|
53fa280037 | ||
|
|
8ecde90bc7 | ||
|
|
34a583f272 | ||
|
|
5de4b8eeb8 | ||
|
|
aae420e469 | ||
|
|
0612f70c06 | ||
|
|
d0c82efa1c | ||
|
|
cf8492240e | ||
|
|
2bceb9f7ba | ||
|
|
760f935965 | ||
|
|
eeeb2805c5 | ||
|
|
9a592d67ad | ||
|
|
ea6618b2f6 | ||
|
|
7b092e73ad | ||
|
|
b2e25c42c7 | ||
|
|
c8dd38ac31 | ||
|
|
563ee4703f | ||
|
|
beceed81de | ||
|
|
3bf96253db | ||
|
|
da2d0ec203 | ||
|
|
008b858203 | ||
|
|
130fc8277d | ||
|
|
468d3357b8 | ||
|
|
f1271da527 | ||
|
|
249a7c7ca3 | ||
|
|
0094d0ebc4 | ||
|
|
834b504dff |
7
.github/workflows/deploy.yml
vendored
7
.github/workflows/deploy.yml
vendored
@@ -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:
|
||||
|
||||
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
||||
|
||||
set(PROJECT AmneziaVPN)
|
||||
|
||||
project(${PROJECT} VERSION 4.6.0.0
|
||||
project(${PROJECT} VERSION 4.6.0.4
|
||||
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 53)
|
||||
set(APP_ANDROID_VERSION_CODE 55)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(MZ_PLATFORM_NAME "linux")
|
||||
|
||||
56
README.md
56
README.md
@@ -6,20 +6,42 @@
|
||||
|
||||
Amnezia is an open-source VPN client, with a key feature that enables you to deploy your own VPN server on your server.
|
||||
|
||||

|
||||
|
||||
<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.
|
||||
- OpenVPN, ShadowSocks, WireGuard, and IKEv2 protocols support.
|
||||
- OpenVPN, Shadowsocks, WireGuard, and IKEv2 protocols support.
|
||||
- Masking VPN with OpenVPN over Cloak plugin
|
||||
- Split tunneling support - add any sites to the client to enable VPN only for them (only for desktops)
|
||||
- Windows, MacOS, Linux, Android, iOS releases.
|
||||
|
||||
## Links
|
||||
|
||||
[https://amnezia.org](https://amnezia.org) - project website
|
||||
[https://www.reddit.com/r/AmneziaVPN](https://www.reddit.com/r/AmneziaVPN) - Reddit
|
||||
[https://t.me/amnezia_vpn_en](https://t.me/amnezia_vpn_en) - Telegram support channel (English)
|
||||
[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
|
||||
|
||||
@@ -27,7 +49,7 @@ AmneziaVPN uses several open-source projects to work:
|
||||
|
||||
- [OpenSSL](https://www.openssl.org/)
|
||||
- [OpenVPN](https://openvpn.net/)
|
||||
- [ShadowSocks](https://shadowsocks.org/)
|
||||
- [Shadowsocks](https://shadowsocks.org/)
|
||||
- [Qt](https://www.qt.io/)
|
||||
- [LibSsh](https://libssh.org) - forked from Qt Creator
|
||||
- and more...
|
||||
@@ -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
|
||||
|
||||
|
||||
Submodule client/3rd-prebuilt updated: ea49bf8796...ff8445c8aa
2
client/3rd/amneziawg-apple
vendored
2
client/3rd/amneziawg-apple
vendored
Submodule client/3rd/amneziawg-apple updated: 0829e99ea9...76e7db556a
@@ -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));
|
||||
|
||||
|
||||
@@ -69,6 +69,12 @@ android {
|
||||
}
|
||||
signingConfig = signingConfigs["release"]
|
||||
}
|
||||
|
||||
create("fdroid") {
|
||||
initWith(getByName("release"))
|
||||
signingConfig = null
|
||||
matchingFallbacks += "release"
|
||||
}
|
||||
}
|
||||
|
||||
splits {
|
||||
|
||||
@@ -384,7 +384,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
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ class CameraActivity : ComponentActivity() {
|
||||
}
|
||||
}
|
||||
}.addOnFailureListener {
|
||||
Log.e(TAG, "Processing QR-code image failed: ${it.message}")
|
||||
Log.e(TAG, "Processing QR code image failed: ${it.message}")
|
||||
}.addOnCompleteListener {
|
||||
imageProxy.close()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -90,7 +90,7 @@ 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" },
|
||||
@@ -99,8 +99,8 @@ QMap<DockerContainer, QString> ContainerProps::containerHumanNames()
|
||||
{ DockerContainer::SSXray, "ShadowSocks"},
|
||||
|
||||
{ DockerContainer::TorWebSite, QObject::tr("Website in Tor network") },
|
||||
{ DockerContainer::Dns, QObject::tr("Amnezia DNS") },
|
||||
{ DockerContainer::Sftp, QObject::tr("Sftp file sharing service") },
|
||||
{ DockerContainer::Dns, QObject::tr("AmneziaDNS") },
|
||||
{ DockerContainer::Sftp, QObject::tr("SFTP file sharing service") },
|
||||
{ DockerContainer::Socks5Proxy, QObject::tr("SOCKS5 proxy server") } };
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ QMap<DockerContainer, QString> ContainerProps::containerDescriptions()
|
||||
QObject::tr("OpenVPN is the most popular VPN protocol, with flexible configuration options. It uses its "
|
||||
"own security protocol with SSL/TLS for key exchange.") },
|
||||
{ DockerContainer::ShadowSocks,
|
||||
QObject::tr("ShadowSocks - masks VPN traffic, making it similar to normal web traffic, but it "
|
||||
QObject::tr("Shadowsocks - masks VPN traffic, making it similar to normal web traffic, but it "
|
||||
"may be recognized by analysis systems in some highly censored regions.") },
|
||||
{ DockerContainer::Cloak,
|
||||
QObject::tr("OpenVPN over Cloak - OpenVPN with VPN masquerading as web traffic and protection against "
|
||||
@@ -127,7 +127,7 @@ QMap<DockerContainer, QString> ContainerProps::containerDescriptions()
|
||||
QObject::tr("XRay with REALITY - Suitable for countries with the highest level of internet censorship. "
|
||||
"Traffic masking as web traffic at the TLS level, and protection against detection by active probing methods.") },
|
||||
{ DockerContainer::Ipsec,
|
||||
QObject::tr("IKEv2 - Modern stable protocol, a bit faster than others, restores connection after "
|
||||
QObject::tr("IKEv2/IPsec - Modern stable protocol, a bit faster than others, restores connection after "
|
||||
"signal loss. It has native support on the latest versions of Android and iOS.") },
|
||||
|
||||
{ DockerContainer::TorWebSite, QObject::tr("Deploy a WordPress site on the Tor network in two clicks.") },
|
||||
@@ -164,7 +164,6 @@ QMap<DockerContainer, QString> ContainerProps::containerDetailedDescriptions()
|
||||
"However, certain traffic analysis systems might still detect a Shadowsocks connection. "
|
||||
"Due to limited support in Amnezia, it's recommended to use AmneziaWG protocol.\n\n"
|
||||
"* Available in the AmneziaVPN only on desktop platforms\n"
|
||||
"* Normal power consumption on mobile devices\n\n"
|
||||
"* Configurable encryption protocol\n"
|
||||
"* Detectable by some DPI systems\n"
|
||||
"* Works over TCP network protocol.") },
|
||||
@@ -286,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;
|
||||
}
|
||||
@@ -306,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;
|
||||
}
|
||||
|
||||
@@ -389,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -106,7 +106,7 @@ ErrorCode ServerController::runContainerScript(const ServerCredentials &credenti
|
||||
if (e)
|
||||
return e;
|
||||
|
||||
QString runner = QString("sudo docker exec -i $CONTAINER_NAME sh %1 ").arg(fileName);
|
||||
QString runner = QString("sudo docker exec -i $CONTAINER_NAME %2 %1 ").arg(fileName, (container == DockerContainer::Socks5Proxy ? "sh" : "bash"));
|
||||
e = runScript(credentials, replaceVars(runner, genVarsForScript(credentials, container)), cbReadStdOut, cbReadStdErr);
|
||||
|
||||
QString remover = QString("sudo docker exec -i $CONTAINER_NAME rm %1 ").arg(fileName);
|
||||
|
||||
@@ -9,7 +9,7 @@ QString errorString(ErrorCode code) {
|
||||
|
||||
// General error codes
|
||||
case(ErrorCode::NoError): errorMessage = QObject::tr("No error"); break;
|
||||
case(ErrorCode::UnknownError): errorMessage = QObject::tr("Unknown Error"); break;
|
||||
case(ErrorCode::UnknownError): errorMessage = QObject::tr("Unknown error"); break;
|
||||
case(ErrorCode::NotImplementedError): errorMessage = QObject::tr("Function not implemented"); break;
|
||||
case(ErrorCode::AmneziaServiceNotRunning): errorMessage = QObject::tr("Background service is not running"); break;
|
||||
|
||||
@@ -23,15 +23,15 @@ QString errorString(ErrorCode code) {
|
||||
case(ErrorCode::ServerPacketManagerError): errorMessage = QObject::tr("Server error: Packet manager error"); break;
|
||||
|
||||
// Libssh errors
|
||||
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("Ssh request was denied"); break;
|
||||
case(ErrorCode::SshInterruptedError): errorMessage = QObject::tr("Ssh request was interrupted"); break;
|
||||
case(ErrorCode::SshInternalError): errorMessage = QObject::tr("Ssh internal error"); break;
|
||||
case(ErrorCode::SshRequestDeniedError): errorMessage = QObject::tr("SSH request was denied"); break;
|
||||
case(ErrorCode::SshInterruptedError): errorMessage = QObject::tr("SSH request was interrupted"); break;
|
||||
case(ErrorCode::SshInternalError): errorMessage = QObject::tr("SSH internal error"); break;
|
||||
case(ErrorCode::SshPrivateKeyError): errorMessage = QObject::tr("Invalid private key or invalid passphrase entered"); break;
|
||||
case(ErrorCode::SshPrivateKeyFormatError): errorMessage = QObject::tr("The selected private key format is not supported, use openssh ED25519 key types or PEM key types"); break;
|
||||
case(ErrorCode::SshTimeoutError): errorMessage = QObject::tr("Timeout connecting to server"); break;
|
||||
|
||||
// Ssh scp errors
|
||||
case(ErrorCode::SshScpFailureError): errorMessage = QObject::tr("Scp error: Generic failure"); break;
|
||||
case(ErrorCode::SshScpFailureError): errorMessage = QObject::tr("SCP error: Generic failure"); break;
|
||||
|
||||
// Local errors
|
||||
case (ErrorCode::OpenVpnConfigMissing): errorMessage = QObject::tr("OpenVPN config missing"); break;
|
||||
@@ -39,7 +39,7 @@ QString errorString(ErrorCode code) {
|
||||
|
||||
// Distro errors
|
||||
case (ErrorCode::OpenVpnExecutableMissing): errorMessage = QObject::tr("OpenVPN executable missing"); break;
|
||||
case (ErrorCode::ShadowSocksExecutableMissing): errorMessage = QObject::tr("ShadowSocks (ss-local) executable missing"); break;
|
||||
case (ErrorCode::ShadowSocksExecutableMissing): errorMessage = QObject::tr("Shadowsocks (ss-local) executable missing"); break;
|
||||
case (ErrorCode::CloakExecutableMissing): errorMessage = QObject::tr("Cloak (ck-client) executable missing"); break;
|
||||
case (ErrorCode::AmneziaServiceConnectionFailed): errorMessage = QObject::tr("Amnezia helper service error"); break;
|
||||
case (ErrorCode::OpenSslFailed): errorMessage = QObject::tr("OpenSSL failed"); break;
|
||||
|
||||
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.
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
73
client/platforms/ios/HevSocksTunnel.swift
Normal file
73
client/platforms/ios/HevSocksTunnel.swift
Normal 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()
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
187
client/platforms/ios/PacketTunnelProvider+Xray.swift
Normal file
187
client/platforms/ios/PacketTunnelProvider+Xray.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
7
client/platforms/ios/XrayConfig.swift
Normal file
7
client/platforms/ios/XrayConfig.swift
Normal file
@@ -0,0 +1,7 @@
|
||||
import Foundation
|
||||
|
||||
struct XrayConfig: Decodable {
|
||||
let dns1: String?
|
||||
let dns2: String?
|
||||
let config: String
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "ikev2_vpn_protocol_windows.h"
|
||||
#include "utilities.h"
|
||||
|
||||
|
||||
static Ikev2Protocol* self = nullptr;
|
||||
static std::mutex rasDialFuncMutex;
|
||||
|
||||
@@ -80,10 +81,10 @@ void Ikev2Protocol::newConnectionStateEventReceived(UINT unMsg, tagRASCONNSTATE
|
||||
case RASCS_AuthNotify:
|
||||
//qDebug()<<__FUNCTION__ << __LINE__;
|
||||
if (dwError != 0) {
|
||||
//qDebug() << "have error" << dwError;
|
||||
qDebug() << "have error" << dwError;
|
||||
setConnectionState(Vpn::ConnectionState::Disconnected);
|
||||
} else {
|
||||
//qDebug() << "RASCS_AuthNotify but no error" << dwError;
|
||||
qDebug() << "RASCS_AuthNotify but no error" << dwError;
|
||||
}
|
||||
break;
|
||||
case RASCS_AuthRetry:
|
||||
@@ -179,11 +180,13 @@ ErrorCode Ikev2Protocol::start()
|
||||
QByteArray cert = QByteArray::fromBase64(m_config[config_key::cert].toString().toUtf8());
|
||||
setConnectionState(Vpn::ConnectionState::Connecting);
|
||||
|
||||
QTemporaryFile certFile;
|
||||
certFile.setAutoRemove(false);
|
||||
certFile.open();
|
||||
certFile.write(cert);
|
||||
certFile.close();
|
||||
QTemporaryFile * certFile = new QTemporaryFile;
|
||||
certFile->setAutoRemove(false);
|
||||
certFile->open();
|
||||
QString m_filename = certFile->fileName();
|
||||
certFile->write(cert);
|
||||
certFile->close();
|
||||
delete certFile;
|
||||
|
||||
{
|
||||
auto certInstallProcess = IpcClient::CreatePrivilegedProcess();
|
||||
@@ -193,19 +196,19 @@ ErrorCode Ikev2Protocol::start()
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
|
||||
certInstallProcess->waitForSource(1000);
|
||||
certInstallProcess->waitForSource();
|
||||
if (!certInstallProcess->isInitialized()) {
|
||||
qWarning() << "IpcProcess replica is not connected!";
|
||||
setLastError(ErrorCode::AmneziaServiceConnectionFailed);
|
||||
return ErrorCode::AmneziaServiceConnectionFailed;
|
||||
}
|
||||
certInstallProcess->setProgram(PermittedProcess::CertUtil);
|
||||
QStringList arguments({"-f" , "-importpfx",
|
||||
"-p", m_config[config_key::password].toString(),
|
||||
certFile.fileName(), "NoExport"
|
||||
});
|
||||
certInstallProcess->setArguments(arguments);
|
||||
|
||||
QStringList arguments({"-f", "-importpfx", "-p", m_config[config_key::password].toString(),
|
||||
QDir::toNativeSeparators(m_filename), "NoExport"
|
||||
});
|
||||
|
||||
certInstallProcess->setArguments(arguments);
|
||||
certInstallProcess->start();
|
||||
}
|
||||
// /*
|
||||
@@ -219,40 +222,40 @@ ErrorCode Ikev2Protocol::start()
|
||||
}
|
||||
|
||||
{
|
||||
{
|
||||
if ( !create_new_vpn(tunnelName(), m_config[config_key::hostName].toString())){
|
||||
qDebug() <<"Can't create the VPN connect";
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
if ( !create_new_vpn(tunnelName(), m_config[config_key::hostName].toString())){
|
||||
qDebug() <<"Can't create the VPN connect";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto adapterConfigProcess = new QProcess;
|
||||
{
|
||||
QProcess adapterConfigProcess;
|
||||
adapterConfigProcess.setProgram("powershell");
|
||||
QString arguments = QString("-command \"Set-VpnConnectionIPsecConfiguration\" "
|
||||
"-ConnectionName '%1' "
|
||||
"-AuthenticationTransformConstants GCMAES128 "
|
||||
"-CipherTransformConstants GCMAES128 "
|
||||
"-EncryptionMethod AES256 "
|
||||
"-IntegrityCheckMethod SHA256 "
|
||||
"-PfsGroup None "
|
||||
"-DHGroup Group14 "
|
||||
"-PassThru -Force\"")
|
||||
.arg(tunnelName());
|
||||
|
||||
adapterConfigProcess->setProgram("powershell");
|
||||
QString arguments = QString("-command \"Set-VpnConnectionIPsecConfiguration\" "
|
||||
"-ConnectionName '%1' "
|
||||
"-AuthenticationTransformConstants GCMAES128 "
|
||||
"-CipherTransformConstants GCMAES128 "
|
||||
"-EncryptionMethod AES256 "
|
||||
"-IntegrityCheckMethod SHA256 "
|
||||
"-PfsGroup None "
|
||||
"-DHGroup Group14 "
|
||||
"-PassThru -Force\"")
|
||||
.arg(tunnelName());
|
||||
adapterConfigProcess->setNativeArguments(arguments);
|
||||
adapterConfigProcess.setNativeArguments(arguments);
|
||||
|
||||
adapterConfigProcess->start();
|
||||
adapterConfigProcess->waitForFinished(5000);
|
||||
adapterConfigProcess.start();
|
||||
adapterConfigProcess.waitForFinished(5000);
|
||||
}
|
||||
//*/
|
||||
{
|
||||
if (!connect_to_vpn(tunnelName())) {
|
||||
qDebug()<<"We can't connect to VPN";
|
||||
}
|
||||
//*/
|
||||
{
|
||||
if (!connect_to_vpn(tunnelName())) {
|
||||
qDebug()<<"We can't connect to VPN";
|
||||
}
|
||||
}
|
||||
//setConnectionState(Connecting);
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
//setConnectionState(Connecting);
|
||||
return ErrorCode::NoError;
|
||||
}
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
bool Ikev2Protocol::create_new_vpn(const QString & vpn_name,
|
||||
@@ -299,6 +302,7 @@ bool Ikev2Protocol::connect_to_vpn(const QString & vpn_name){
|
||||
auto ret = RasDial(NULL, NULL, &RasDialParams, 0,
|
||||
&RasDialFuncCallback,
|
||||
&hRasConn);
|
||||
|
||||
if (ret == ERROR_SUCCESS){
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ QMap<amnezia::Proto, QString> ProtocolProps::protocolHumanNames()
|
||||
|
||||
{ Proto::TorWebSite, "Website in Tor network" },
|
||||
{ Proto::Dns, "DNS Service" },
|
||||
{ Proto::Sftp, QObject::tr("Sftp service") },
|
||||
{ Proto::Sftp, QObject::tr("SFTP service") },
|
||||
{ Proto::Socks5Proxy, QObject::tr("SOCKS5 proxy server") } };
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +228,9 @@
|
||||
<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 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
@@ -123,7 +123,7 @@ void ConnectionController::onConnectionStateChanged(Vpn::ConnectionState state)
|
||||
void ConnectionController::onCurrentContainerUpdated()
|
||||
{
|
||||
if (m_isConnected || m_isConnectionInProgress) {
|
||||
emit reconnectWithUpdatedContainer(tr("Settings updated successfully, Reconnnection..."));
|
||||
emit reconnectWithUpdatedContainer(tr("Settings updated successfully, reconnnection..."));
|
||||
openConnection();
|
||||
} else {
|
||||
emit reconnectWithUpdatedContainer(tr("Settings updated successfully"));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,9 @@ public:
|
||||
IsCurrentlyProcessedRole,
|
||||
IsDefaultRole,
|
||||
IsSupportedRole,
|
||||
IsShareableRole
|
||||
IsShareableRole,
|
||||
|
||||
InstallPageOrderRole
|
||||
};
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ 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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -2,6 +2,8 @@ import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Style 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
@@ -28,7 +30,7 @@ Item {
|
||||
ImageButtonType {
|
||||
id: backButton
|
||||
image: backButtonImage
|
||||
imageColor: "#D7D8DB"
|
||||
imageColor: AmneziaStyle.color.white
|
||||
|
||||
implicitWidth: 40
|
||||
implicitHeight: 40
|
||||
@@ -46,7 +48,7 @@ Item {
|
||||
id: background
|
||||
Layout.fillWidth: true
|
||||
|
||||
color: "transparent"
|
||||
color: AmneziaStyle.color.transparent
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 :
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Style 1.0
|
||||
|
||||
import "TextTypes"
|
||||
|
||||
Item {
|
||||
@@ -19,8 +21,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
|
||||
@@ -90,7 +92,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 }
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 !== ""
|
||||
}
|
||||
|
||||
@@ -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 !== ""
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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
|
||||
@@ -117,7 +119,7 @@ Item {
|
||||
Layout.rightMargin: rightImageSource || !isLeftImageHoverEnabled ? 16 : 0
|
||||
|
||||
radius: 12
|
||||
color: "transparent"
|
||||
color: AmneziaStyle.color.transparent
|
||||
|
||||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
@@ -220,7 +222,7 @@ Item {
|
||||
id: eyeImageBackground
|
||||
anchors.fill: parent
|
||||
radius: 12
|
||||
color: "transparent"
|
||||
color: AmneziaStyle.color.transparent
|
||||
|
||||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
@@ -257,7 +259,7 @@ Item {
|
||||
id: rightImageBackground
|
||||
anchors.fill: parent
|
||||
radius: 12
|
||||
color: "transparent"
|
||||
color: AmneziaStyle.color.transparent
|
||||
|
||||
Behavior on color {
|
||||
PropertyAnimation { duration: 200 }
|
||||
@@ -274,9 +276,9 @@ Item {
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: root
|
||||
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
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
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
|
||||
@@ -26,10 +28,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
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2,14 +2,16 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import Style 1.0
|
||||
|
||||
import "TextTypes"
|
||||
|
||||
Item {
|
||||
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,18 +23,18 @@ 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
|
||||
@@ -90,10 +92,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
|
||||
@@ -147,7 +149,7 @@ Item {
|
||||
|
||||
text: root.errorText
|
||||
visible: root.errorText !== ""
|
||||
color: "#EB5757"
|
||||
color: AmneziaStyle.color.red
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import QtQuick
|
||||
|
||||
import Style 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 30 + LanguageModel.getLineHeightAppend()
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: "#D7D8DB"
|
||||
color: AmneziaStyle.color.white
|
||||
font.pixelSize: 25
|
||||
font.weight: 700
|
||||
font.family: "PT Root UI VF"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import QtQuick
|
||||
|
||||
import Style 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 16 + LanguageModel.getLineHeightAppend()
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: "#878B91"
|
||||
color: AmneziaStyle.color.grey
|
||||
font.pixelSize: 13
|
||||
font.weight: 400
|
||||
font.family: "PT Root UI VF"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import QtQuick
|
||||
|
||||
import Style 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 21.6 + LanguageModel.getLineHeightAppend()
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: "#D7D8DB"
|
||||
color: AmneziaStyle.color.white
|
||||
font.pixelSize: 18
|
||||
font.weight: 400
|
||||
font.family: "PT Root UI VF"
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import QtQuick
|
||||
import Style 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 24 + LanguageModel.getLineHeightAppend()
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: "#D7D8DB"
|
||||
color: AmneziaStyle.color.white
|
||||
font.pixelSize: 16
|
||||
font.weight: 400
|
||||
font.family: "PT Root UI VF"
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import QtQuick
|
||||
|
||||
import Style 1.0
|
||||
|
||||
Text {
|
||||
lineHeight: 20 + LanguageModel.getLineHeightAppend()
|
||||
lineHeightMode: Text.FixedHeight
|
||||
|
||||
color: "#D7D8DB"
|
||||
color: AmneziaStyle.color.white
|
||||
font.pixelSize: 14
|
||||
font.weight: 400
|
||||
font.family: "PT Root UI VF"
|
||||
|
||||
@@ -18,14 +18,14 @@ Popup {
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: "transparent"
|
||||
color: AmneziaStyle.color.transparent
|
||||
}
|
||||
|
||||
ImageButtonType {
|
||||
id: button
|
||||
|
||||
image: "qrc:/images/svg/close_black_24dp.svg"
|
||||
imageColor: "#D7D8DB"
|
||||
imageColor: AmneziaStyle.color.white
|
||||
|
||||
implicitWidth: 40
|
||||
implicitHeight: 40
|
||||
|
||||
@@ -3,6 +3,8 @@ import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Style 1.0
|
||||
|
||||
import "TextTypes"
|
||||
|
||||
RadioButton {
|
||||
@@ -12,15 +14,15 @@ RadioButton {
|
||||
property int textElide: Qt.ElideRight
|
||||
property string descriptionText
|
||||
|
||||
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 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 selectedColor: AmneziaStyle.color.transparent
|
||||
|
||||
property string textColor: "#D7D8DB"
|
||||
property string selectedTextColor: "#FBB26A"
|
||||
property string textColor: AmneziaStyle.color.white
|
||||
property string selectedTextColor: AmneziaStyle.color.orange
|
||||
|
||||
property string borderFocusedColor: "#D7D8DB"
|
||||
property string borderFocusedColor: AmneziaStyle.color.white
|
||||
property int borderFocusedWidth: 1
|
||||
|
||||
property string imageSource
|
||||
@@ -34,7 +36,7 @@ RadioButton {
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
border.color: root.focus ? root.borderFocusedColor : "transparent"
|
||||
border.color: root.focus ? root.borderFocusedColor : AmneziaStyle.color.transparent
|
||||
border.width: root.focus ? root.borderFocusedWidth : 0
|
||||
|
||||
implicitWidth: 56
|
||||
@@ -137,7 +139,7 @@ RadioButton {
|
||||
CaptionTextType {
|
||||
id: description
|
||||
|
||||
color: "#878B91"
|
||||
color: AmneziaStyle.color.grey
|
||||
text: root.descriptionText
|
||||
|
||||
visible: root.descriptionText !== ""
|
||||
|
||||
@@ -3,14 +3,16 @@ import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
import Style 1.0
|
||||
|
||||
import "TextTypes"
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
|
||||
property string textColor: "#D7D8DB"
|
||||
property string backGroundColor: "#1C1D21"
|
||||
property string imageColor: "#D7D8DB"
|
||||
property string textColor: AmneziaStyle.color.white
|
||||
property string backGroundColor: AmneziaStyle.color.blackLight
|
||||
property string imageColor: AmneziaStyle.color.white
|
||||
property string textString
|
||||
property int textFormat: Text.PlainText
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user