Compare commits

...

8 Commits

Author SHA1 Message Date
vkamn 1ea716a163 fix: fix page share connection headers and config description 2025-08-27 16:41:20 +08:00
vkamn 4551659c2a fix: minor ui fixes with services list 2025-08-27 15:15:53 +08:00
MrMirDan c568bf8c24 chore: ru translation update (#1812)
* ru translation update

* fixes
2025-08-26 20:32:00 +08:00
vkamn a412d91105 feat: subscription expiration processing (#1814) 2025-08-26 20:31:41 +08:00
vkamn ad01f23bbe feat: add service description customization (#1811) 2025-08-26 12:17:37 +08:00
vkamn 656070b132 feat: add request id (#1809) 2025-08-25 22:05:00 +08:00
MrMirDan c907f5ca36 fix: removed service logs section for mobile platforms (#1810) 2025-08-25 22:04:48 +08:00
Mykola Baibuz 94a13b2b54 fix: set guid for windows tun2socks tun interface (#1808) 2025-08-25 11:03:42 +08:00
21 changed files with 1024 additions and 897 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ namespace
bool apiUtils::isSubscriptionExpired(const QString &subscriptionEndDate) bool apiUtils::isSubscriptionExpired(const QString &subscriptionEndDate)
{ {
QDateTime now = QDateTime::currentDateTime(); QDateTime now = QDateTime::currentDateTimeUtc();
QDateTime endDate = QDateTime::fromString(subscriptionEndDate, Qt::ISODateWithMs); QDateTime endDate = QDateTime::fromString(subscriptionEndDate, Qt::ISODateWithMs);
return endDate < now; return endDate < now;
} }
@@ -60,6 +60,7 @@ ErrorCode GatewayController::get(const QString &endpoint, QByteArray &responseBo
QNetworkRequest request; QNetworkRequest request;
request.setTransferTimeout(m_requestTimeoutMsecs); request.setTransferTimeout(m_requestTimeoutMsecs);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader(QString("X-Client-Request-ID").toUtf8(), QUuid::createUuid().toString(QUuid::WithoutBraces).toUtf8());
request.setUrl(QString(endpoint).arg(m_proxyUrl.isEmpty() ? m_gatewayEndpoint : m_proxyUrl)); request.setUrl(QString(endpoint).arg(m_proxyUrl.isEmpty() ? m_gatewayEndpoint : m_proxyUrl));
@@ -122,6 +123,7 @@ ErrorCode GatewayController::post(const QString &endpoint, const QJsonObject api
QNetworkRequest request; QNetworkRequest request;
request.setTransferTimeout(m_requestTimeoutMsecs); request.setTransferTimeout(m_requestTimeoutMsecs);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader(QString("X-Client-Request-ID").toUtf8(), QUuid::createUuid().toString(QUuid::WithoutBraces).toUtf8());
request.setUrl(endpoint.arg(m_proxyUrl.isEmpty() ? m_gatewayEndpoint : m_proxyUrl)); request.setUrl(endpoint.arg(m_proxyUrl.isEmpty() ? m_gatewayEndpoint : m_proxyUrl));
+1
View File
@@ -120,6 +120,7 @@ namespace amnezia
ApiNotFoundError = 1109, ApiNotFoundError = 1109,
ApiMigrationError = 1110, ApiMigrationError = 1110,
ApiUpdateRequestError = 1111, ApiUpdateRequestError = 1111,
ApiSubscriptionExpiredError = 1112,
// QFile errors // QFile errors
OpenError = 1200, OpenError = 1200,
+1
View File
@@ -77,6 +77,7 @@ QString errorString(ErrorCode code) {
case (ErrorCode::ApiNotFoundError): errorMessage = QObject::tr("Error when retrieving configuration from API"); break; case (ErrorCode::ApiNotFoundError): errorMessage = QObject::tr("Error when retrieving configuration from API"); break;
case (ErrorCode::ApiMigrationError): errorMessage = QObject::tr("A migration error has occurred. Please contact our technical support"); break; case (ErrorCode::ApiMigrationError): errorMessage = QObject::tr("A migration error has occurred. Please contact our technical support"); break;
case (ErrorCode::ApiUpdateRequestError): errorMessage = QObject::tr("Please update the application to use this feature"); break; case (ErrorCode::ApiUpdateRequestError): errorMessage = QObject::tr("Please update the application to use this feature"); break;
case (ErrorCode::ApiSubscriptionExpiredError): errorMessage = QObject::tr("Your Amnezia Premium subscription has expired.\n Please check your email for renewal instructions.\n If you haven't received an email, please contact our support."); break;
// QFile errors // QFile errors
case(ErrorCode::OpenError): errorMessage = QObject::tr("QFile error: The file could not be opened"); break; case(ErrorCode::OpenError): errorMessage = QObject::tr("QFile error: The file could not be opened"); break;
File diff suppressed because it is too large Load Diff
@@ -29,6 +29,7 @@ namespace
constexpr char uuid[] = "installation_uuid"; constexpr char uuid[] = "installation_uuid";
constexpr char osVersion[] = "os_version"; constexpr char osVersion[] = "os_version";
constexpr char appVersion[] = "app_version"; constexpr char appVersion[] = "app_version";
constexpr char appLanguage[] = "app_language";
constexpr char userCountryCode[] = "user_country_code"; constexpr char userCountryCode[] = "user_country_code";
constexpr char serverCountryCode[] = "server_country_code"; constexpr char serverCountryCode[] = "server_country_code";
@@ -43,6 +44,9 @@ namespace
constexpr char authData[] = "auth_data"; constexpr char authData[] = "auth_data";
constexpr char config[] = "config"; constexpr char config[] = "config";
constexpr char subscription[] = "subscription";
constexpr char endDate[] = "end_date";
} }
struct ProtocolData struct ProtocolData
@@ -163,7 +167,7 @@ namespace
auto clientProtocolConfig = auto clientProtocolConfig =
QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object(); QJsonDocument::fromJson(serverProtocolConfig.value(config_key::last_config).toString().toUtf8()).object();
//TODO looks like this block can be removed after v1 configs EOL // TODO looks like this block can be removed after v1 configs EOL
serverProtocolConfig[config_key::junkPacketCount] = clientProtocolConfig.value(config_key::junkPacketCount); serverProtocolConfig[config_key::junkPacketCount] = clientProtocolConfig.value(config_key::junkPacketCount);
serverProtocolConfig[config_key::junkPacketMinSize] = clientProtocolConfig.value(config_key::junkPacketMinSize); serverProtocolConfig[config_key::junkPacketMinSize] = clientProtocolConfig.value(config_key::junkPacketMinSize);
@@ -223,6 +227,19 @@ namespace
return ErrorCode::NoError; return ErrorCode::NoError;
} }
bool isSubscriptionExpired(const QJsonObject &apiConfig)
{
auto subscription = apiConfig.value(configKey::subscription).toObject();
if (subscription.isEmpty()) {
return false;
}
auto subscriptionEndDate = subscription.value(configKey::endDate).toString();
if (apiUtils::isSubscriptionExpired(subscriptionEndDate)) {
return true;
}
return false;
}
} }
ApiConfigsController::ApiConfigsController(const QSharedPointer<ServersModel> &serversModel, ApiConfigsController::ApiConfigsController(const QSharedPointer<ServersModel> &serversModel,
@@ -242,6 +259,11 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex()); auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
if (isSubscriptionExpired(apiConfigObject)) {
emit errorOccurred(ErrorCode::ApiSubscriptionExpiredError);
return false;
}
GatewayRequestData gatewayRequestData { QSysInfo::productType(), GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION), QString(APP_VERSION),
m_settings->getInstallationUuid(true), m_settings->getInstallationUuid(true),
@@ -277,6 +299,11 @@ bool ApiConfigsController::revokeNativeConfig(const QString &serverCountryCode)
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex()); auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject(); auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
if (isSubscriptionExpired(apiConfigObject)) {
emit errorOccurred(ErrorCode::ApiSubscriptionExpiredError);
return false;
}
GatewayRequestData gatewayRequestData { QSysInfo::productType(), GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION), QString(APP_VERSION),
m_settings->getInstallationUuid(true), m_settings->getInstallationUuid(true),
@@ -322,6 +349,7 @@ bool ApiConfigsController::fillAvailableServices()
{ {
QJsonObject apiPayload; QJsonObject apiPayload;
apiPayload[configKey::osVersion] = QSysInfo::productType(); apiPayload[configKey::osVersion] = QSysInfo::productType();
apiPayload[configKey::appLanguage] = m_settings->getAppLanguage().name().split("_").first();
QByteArray responseBody; QByteArray responseBody;
ErrorCode errorCode = executeRequest(QString("%1v1/services"), apiPayload, responseBody); ErrorCode errorCode = executeRequest(QString("%1v1/services"), apiPayload, responseBody);
@@ -396,6 +424,11 @@ bool ApiConfigsController::updateServiceFromGateway(const int serverIndex, const
auto serverConfig = m_serversModel->getServerConfig(serverIndex); auto serverConfig = m_serversModel->getServerConfig(serverIndex);
auto apiConfig = serverConfig.value(configKey::apiConfig).toObject(); auto apiConfig = serverConfig.value(configKey::apiConfig).toObject();
if (isSubscriptionExpired(apiConfig)) {
emit errorOccurred(ErrorCode::ApiSubscriptionExpiredError);
return false;
}
GatewayRequestData gatewayRequestData { QSysInfo::productType(), GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION), QString(APP_VERSION),
m_settings->getInstallationUuid(true), m_settings->getInstallationUuid(true),
@@ -502,6 +535,11 @@ bool ApiConfigsController::deactivateDevice()
return true; return true;
} }
if (isSubscriptionExpired(apiConfigObject)) {
emit errorOccurred(ErrorCode::ApiSubscriptionExpiredError);
return false;
}
GatewayRequestData gatewayRequestData { QSysInfo::productType(), GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION), QString(APP_VERSION),
m_settings->getInstallationUuid(true), m_settings->getInstallationUuid(true),
@@ -536,6 +574,11 @@ bool ApiConfigsController::deactivateExternalDevice(const QString &uuid, const Q
return true; return true;
} }
if (isSubscriptionExpired(apiConfigObject)) {
emit errorOccurred(ErrorCode::ApiSubscriptionExpiredError);
return false;
}
GatewayRequestData gatewayRequestData { QSysInfo::productType(), GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION), QString(APP_VERSION),
uuid, uuid,
+3 -1
View File
@@ -40,7 +40,7 @@ namespace PageLoader
PageSettingsApiDevices, PageSettingsApiDevices,
PageSettingsApiSubscriptionKey, PageSettingsApiSubscriptionKey,
PageSettingsKillSwitchExceptions, PageSettingsKillSwitchExceptions,
PageServiceSftpSettings, PageServiceSftpSettings,
PageServiceTorWebsiteSettings, PageServiceTorWebsiteSettings,
PageServiceDnsSettings, PageServiceDnsSettings,
@@ -125,6 +125,8 @@ signals:
void goToPageViewConfig(); void goToPageViewConfig();
void goToPageSettingsServerServices(); void goToPageSettingsServerServices();
void goToPageSettingsBackup(); void goToPageSettingsBackup();
void goToShareConnectionPage(QString headerText, QString configContentHeaderText, QString configCaption, QString configExtension,
QString configFileName);
void closePage(); void closePage();
+1 -1
View File
@@ -31,7 +31,7 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
return tr("Active"); return tr("Active");
} }
return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("Inactive") : tr("Active"); return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("<p><a style=\"color: #EB5757;\">Inactive</a>") : tr("Active");
} }
case EndDateRole: { case EndDateRole: {
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) { if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) {
+22 -17
View File
@@ -15,6 +15,7 @@ namespace
constexpr char serviceInfo[] = "service_info"; constexpr char serviceInfo[] = "service_info";
constexpr char serviceType[] = "service_type"; constexpr char serviceType[] = "service_type";
constexpr char serviceProtocol[] = "service_protocol"; constexpr char serviceProtocol[] = "service_protocol";
constexpr char serviceDescription[] = "service_description";
constexpr char name[] = "name"; constexpr char name[] = "name";
constexpr char price[] = "price"; constexpr char price[] = "price";
@@ -22,6 +23,10 @@ namespace
constexpr char timelimit[] = "timelimit"; constexpr char timelimit[] = "timelimit";
constexpr char region[] = "region"; constexpr char region[] = "region";
constexpr char description[] = "description";
constexpr char cardDescription[] = "card_description";
constexpr char features[] = "features";
constexpr char availableCountries[] = "available_countries"; constexpr char availableCountries[] = "available_countries";
constexpr char storeEndpoint[] = "store_endpoint"; constexpr char storeEndpoint[] = "store_endpoint";
@@ -65,11 +70,9 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
case CardDescriptionRole: { case CardDescriptionRole: {
auto speed = apiServiceData.serviceInfo.speed; auto speed = apiServiceData.serviceInfo.speed;
if (serviceType == serviceType::amneziaPremium) { if (serviceType == serviceType::amneziaPremium) {
return tr("Amnezia Premium is classic VPN for seamless work, downloading large files, and watching videos. " return apiServiceData.serviceInfo.cardDescription.arg(speed);
"Access all websites and online resources. Speeds up to %1 Mbps.")
.arg(speed);
} else if (serviceType == serviceType::amneziaFree) { } else if (serviceType == serviceType::amneziaFree) {
QString description = tr("Amnezia Free provides unlimited, free access to a basic set of websites and apps, including Facebook, Instagram, Twitter (X), Discord, Telegram, and more. YouTube is not included in the free plan."); QString description = apiServiceData.serviceInfo.cardDescription;
if (!isServiceAvailable) { if (!isServiceAvailable) {
description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, " description += tr("<p><a style=\"color: #EB5757;\">Not available in your region. If you have VPN enabled, disable it, "
"return to the previous screen, and try again.</a>"); "return to the previous screen, and try again.</a>");
@@ -78,12 +81,7 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
} }
} }
case ServiceDescriptionRole: { case ServiceDescriptionRole: {
if (serviceType == serviceType::amneziaPremium) { return apiServiceData.serviceInfo.description;
return tr("Amnezia Premium is classic VPN for for seamless work, downloading large files, and watching videos. "
"Access all websites and online resources.");
} else {
return tr("Amnezia Free provides unlimited, free access to a basic set of websites and apps, including Facebook, Instagram, Twitter (X), Discord, Telegram, and more. YouTube is not included in the free plan.");
}
} }
case IsServiceAvailableRole: { case IsServiceAvailableRole: {
if (serviceType == serviceType::amneziaFree) { if (serviceType == serviceType::amneziaFree) {
@@ -107,13 +105,7 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
return apiServiceData.serviceInfo.region; return apiServiceData.serviceInfo.region;
} }
case FeaturesRole: { case FeaturesRole: {
if (serviceType == serviceType::amneziaPremium) { return apiServiceData.serviceInfo.features;
return tr("");
} else {
return tr("VPN will open only popular sites blocked in your region, such as Instagram, Facebook, Twitter and others. "
"Other sites will be opened from your real IP address, "
"<a href=\"%1\" style=\"color: #FBB26A;\">more details on the website.</a>");
}
} }
case PriceRole: { case PriceRole: {
auto price = apiServiceData.serviceInfo.price; auto price = apiServiceData.serviceInfo.price;
@@ -125,6 +117,13 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
case EndDateRole: { case EndDateRole: {
return QDateTime::fromString(apiServiceData.subscription.endDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy"); return QDateTime::fromString(apiServiceData.subscription.endDate, Qt::ISODate).toLocalTime().toString("d MMM yyyy");
} }
case OrderRole: {
if (serviceType == serviceType::amneziaPremium) {
return 0;
} else if (serviceType == serviceType::amneziaFree) {
return 1;
}
}
} }
return QVariant(); return QVariant();
@@ -224,6 +223,7 @@ QHash<int, QByteArray> ApiServicesModel::roleNames() const
roles[FeaturesRole] = "features"; roles[FeaturesRole] = "features";
roles[PriceRole] = "price"; roles[PriceRole] = "price";
roles[EndDateRole] = "endDate"; roles[EndDateRole] = "endDate";
roles[OrderRole] = "order";
return roles; return roles;
} }
@@ -234,6 +234,7 @@ ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJs
auto serviceType = data.value(configKey::serviceType).toString(); auto serviceType = data.value(configKey::serviceType).toString();
auto serviceProtocol = data.value(configKey::serviceProtocol).toString(); auto serviceProtocol = data.value(configKey::serviceProtocol).toString();
auto availableCountries = data.value(configKey::availableCountries).toArray(); auto availableCountries = data.value(configKey::availableCountries).toArray();
auto serviceDescription = data.value(configKey::serviceDescription).toObject();
auto subscriptionObject = data.value(configKey::subscription).toObject(); auto subscriptionObject = data.value(configKey::subscription).toObject();
@@ -244,6 +245,10 @@ ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJs
serviceData.serviceInfo.speed = serviceInfo.value(configKey::speed).toString(); serviceData.serviceInfo.speed = serviceInfo.value(configKey::speed).toString();
serviceData.serviceInfo.timeLimit = serviceInfo.value(configKey::timelimit).toString(); serviceData.serviceInfo.timeLimit = serviceInfo.value(configKey::timelimit).toString();
serviceData.serviceInfo.cardDescription = serviceDescription.value(configKey::cardDescription).toString();
serviceData.serviceInfo.description = serviceDescription.value(configKey::description).toString();
serviceData.serviceInfo.features = serviceDescription.value(configKey::features).toString();
serviceData.type = serviceType; serviceData.type = serviceType;
serviceData.protocol = serviceProtocol; serviceData.protocol = serviceProtocol;
+6 -1
View File
@@ -20,7 +20,8 @@ public:
RegionRole, RegionRole,
FeaturesRole, FeaturesRole,
PriceRole, PriceRole,
EndDateRole EndDateRole,
OrderRole
}; };
explicit ApiServicesModel(QObject *parent = nullptr); explicit ApiServicesModel(QObject *parent = nullptr);
@@ -58,6 +59,10 @@ private:
QString region; QString region;
QString price; QString price;
QString description;
QString features;
QString cardDescription;
QJsonObject object; QJsonObject object;
}; };
@@ -7,17 +7,20 @@ import Style 1.0
import "TextTypes" import "TextTypes"
RowLayout { RowLayout {
id: root
property string imageSource property string imageSource
property string leftText property string leftText
property var rightText property var rightText
property bool isRightTextUndefined: rightText === undefined property bool isRightTextUndefined: rightText === undefined
property int rightTextFormat: Text.PlainText
visible: !isRightTextUndefined visible: !isRightTextUndefined
Image { Image {
Layout.preferredHeight: 18 Layout.preferredHeight: 18
Layout.preferredWidth: 18 Layout.preferredWidth: 18
source: imageSource source: root.imageSource
} }
ListItemTitleType { ListItemTitleType {
@@ -25,14 +28,15 @@ RowLayout {
Layout.rightMargin: 10 Layout.rightMargin: 10
Layout.alignment: Qt.AlignRight Layout.alignment: Qt.AlignRight
text: leftText text: root.leftText
} }
ParagraphTextType { ParagraphTextType {
visible: rightText !== "" visible: root.rightText !== ""
Layout.alignment: Qt.AlignLeft Layout.alignment: Qt.AlignLeft
text: isRightTextUndefined ? "" : rightText text: root.isRightTextUndefined ? "" : root.rightText
textFormat: root.rightTextFormat
} }
} }
@@ -29,6 +29,7 @@ PageType {
readonly property string title: qsTr("Subscription Status") readonly property string title: qsTr("Subscription Status")
readonly property string contentKey: "subscriptionStatus" readonly property string contentKey: "subscriptionStatus"
readonly property string objectImageSource: "qrc:/images/controls/info.svg" readonly property string objectImageSource: "qrc:/images/controls/info.svg"
readonly property bool isRichText: true
} }
QtObject { QtObject {
@@ -37,6 +38,7 @@ PageType {
readonly property string title: qsTr("Valid Until") readonly property string title: qsTr("Valid Until")
readonly property string contentKey: "endDate" readonly property string contentKey: "endDate"
readonly property string objectImageSource: "qrc:/images/controls/history.svg" readonly property string objectImageSource: "qrc:/images/controls/history.svg"
readonly property bool isRichText: false
} }
QtObject { QtObject {
@@ -45,6 +47,7 @@ PageType {
readonly property string title: qsTr("Active Connections") readonly property string title: qsTr("Active Connections")
readonly property string contentKey: "connectedDevices" readonly property string contentKey: "connectedDevices"
readonly property string objectImageSource: "qrc:/images/controls/monitor.svg" readonly property string objectImageSource: "qrc:/images/controls/monitor.svg"
readonly property bool isRichText: false
} }
property var processedServer property var processedServer
@@ -134,6 +137,7 @@ PageType {
imageSource: objectImageSource imageSource: objectImageSource
leftText: title leftText: title
rightText: ApiAccountInfoModel.data(contentKey) rightText: ApiAccountInfoModel.data(contentKey)
rightTextFormat: isRichText ? Text.RichText : Text.PlainText
visible: rightText !== "" visible: rightText !== ""
} }
@@ -214,9 +218,6 @@ PageType {
ApiConfigsController.prepareVpnKeyExport() ApiConfigsController.prepareVpnKeyExport()
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
// Navigate to PageShareConnection page
//PageController.goToPage(PageEnum.PageShareConnection)
} }
} }
@@ -53,14 +53,6 @@ PageType {
Layout.leftMargin: 16 Layout.leftMargin: 16
Layout.rightMargin: 16 Layout.rightMargin: 16
defaultColor: AmneziaStyle.color.paleGray
hoveredColor: AmneziaStyle.color.sheerWhite
pressedColor: AmneziaStyle.color.translucentWhite
disabledColor: AmneziaStyle.color.mutedGray
textColor: AmneziaStyle.color.black
leftImageColor: "black"
borderWidth: 1
text: qsTr("Copy key") text: qsTr("Copy key")
leftImageSource: "qrc:/images/controls/copy.svg" leftImageSource: "qrc:/images/controls/copy.svg"
@@ -194,7 +186,7 @@ PageType {
font.pixelSize: 16 font.pixelSize: 16
font.weight: Font.Medium font.weight: Font.Medium
font.family: "PT Root UI VF" font.family: "PT Root UI VF"
text: ApiConfigsController.vpnKey //|| "" text: ApiConfigsController.vpnKey
wrapMode: Text.Wrap wrapMode: Text.Wrap
background: Rectangle { color: AmneziaStyle.color.transparent } background: Rectangle { color: AmneziaStyle.color.transparent }
} }
+7 -10
View File
@@ -167,7 +167,8 @@ PageType {
// Show service logs only if this is NOT a macOS build with // Show service logs only if this is NOT a macOS build with
// Network-Extension (IsMacOsNeBuild is injected from C++ at run-time) // Network-Extension (IsMacOsNeBuild is injected from C++ at run-time)
property list<QtObject> logTypes: IsMacOsNeBuild ? [ // or if this is NOT a mobile build
property list<QtObject> logTypes: (IsMacOsNeBuild || GC.isMobile()) ? [
clientLogs clientLogs
] : [ ] : [
clientLogs, clientLogs,
@@ -214,15 +215,11 @@ PageType {
} }
readonly property var exportLogsHandler: function() { readonly property var exportLogsHandler: function() {
var fileName = "" var fileName = ""
if (GC.isMobile()) { fileName = SystemController.getFileName(qsTr("Save"),
fileName = "AmneziaVPN-service.log" qsTr("Logs files (*.log)"),
} else { StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN-service",
fileName = SystemController.getFileName(qsTr("Save"), true,
qsTr("Logs files (*.log)"), ".log")
StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/AmneziaVPN-service",
true,
".log")
}
if (fileName !== "") { if (fileName !== "") {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
SettingsController.exportServiceLogsFile(fileName) SettingsController.exportServiceLogsFile(fileName)
@@ -66,6 +66,8 @@ PageType {
imageSource: imagePath imageSource: imagePath
leftText: lText leftText: lText
rightText: rText rightText: rText
visible: isVisible
} }
} }
@@ -3,6 +3,8 @@ import QtQuick.Controls
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Dialogs import QtQuick.Dialogs
import SortFilterProxyModel 0.2
import PageEnum 1.0 import PageEnum 1.0
import Style 1.0 import Style 1.0
@@ -54,7 +56,15 @@ PageType {
spacing: 0 spacing: 0
model: ApiServicesModel model: SortFilterProxyModel {
id: proxyApiServicesModel
sourceModel: ApiServicesModel
sorters: RoleSorter {
roleName: "order"
sortOrder: Qt.AscendingOrder
}
}
delegate: ColumnLayout { delegate: ColumnLayout {
@@ -78,7 +88,7 @@ PageType {
onClicked: { onClicked: {
if (isServiceAvailable) { if (isServiceAvailable) {
ApiServicesModel.setServiceIndex(index) ApiServicesModel.setServiceIndex(proxyApiServicesModel.mapToSource(index))
PageController.goToPage(PageEnum.PageSetupWizardApiServiceInfo) PageController.goToPage(PageEnum.PageSetupWizardApiServiceInfo)
} }
} }
+28 -1
View File
@@ -45,40 +45,67 @@ PageType {
function onGenerateConfig(type) { function onGenerateConfig(type) {
PageController.showBusyIndicator(true) PageController.showBusyIndicator(true)
var configCaption
var configExtension
var configFileName
switch (type) { switch (type) {
case PageShare.ConfigType.AmneziaConnection: { case PageShare.ConfigType.AmneziaConnection: {
ExportController.generateConnectionConfig(clientNameTextField.textField.text); ExportController.generateConnectionConfig(clientNameTextField.textField.text);
configCaption = qsTr("Save AmneziaVPN config")
configExtension = ".vpn"
configFileName = "amnezia_config"
break; break;
} }
case PageShare.ConfigType.OpenVpn: { case PageShare.ConfigType.OpenVpn: {
ExportController.generateOpenVpnConfig(clientNameTextField.textField.text) ExportController.generateOpenVpnConfig(clientNameTextField.textField.text)
configCaption = qsTr("Save OpenVPN config")
configExtension = ".ovpn"
configFileName = "amnezia_for_openvpn"
break break
} }
case PageShare.ConfigType.WireGuard: { case PageShare.ConfigType.WireGuard: {
ExportController.generateWireGuardConfig(clientNameTextField.textField.text) ExportController.generateWireGuardConfig(clientNameTextField.textField.text)
configCaption = qsTr("Save WireGuard config")
configExtension = ".conf"
configFileName = "amnezia_for_wireguard"
break break
} }
case PageShare.ConfigType.Awg: { case PageShare.ConfigType.Awg: {
ExportController.generateAwgConfig(clientNameTextField.textField.text) ExportController.generateAwgConfig(clientNameTextField.textField.text)
configCaption = qsTr("Save AmneziaWG config")
configExtension = ".conf"
configFileName = "amnezia_for_awg"
break break
} }
case PageShare.ConfigType.ShadowSocks: { case PageShare.ConfigType.ShadowSocks: {
ExportController.generateShadowSocksConfig() ExportController.generateShadowSocksConfig()
configCaption = qsTr("Save Shadowsocks config")
configExtension = ".json"
configFileName = "amnezia_for_shadowsocks"
break break
} }
case PageShare.ConfigType.Cloak: { case PageShare.ConfigType.Cloak: {
ExportController.generateCloakConfig() ExportController.generateCloakConfig()
configCaption = qsTr("Save Cloak config")
configExtension = ".json"
configFileName = "amnezia_for_cloak"
break break
} }
case PageShare.ConfigType.Xray: { case PageShare.ConfigType.Xray: {
ExportController.generateXrayConfig(clientNameTextField.textField.text) ExportController.generateXrayConfig(clientNameTextField.textField.text)
configCaption = qsTr("Save XRay config")
configExtension = ".json"
configFileName = "amnezia_for_xray"
break break
} }
} }
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
PageController.goToPage(PageEnum.PageShareConnection) var headerText = qsTr("Connection to ") + serverSelector.text
var configContentHeaderText = qsTr("File with connection settings to ") + serverSelector.text
PageController.goToShareConnectionPage(headerText, configContentHeaderText, configCaption, configExtension, configFileName)
} }
function onExportErrorOccurred(error) { function onExportErrorOccurred(error) {
+10 -16
View File
@@ -21,12 +21,6 @@ PageType {
id: pageShareConnection id: pageShareConnection
property string headerText property string headerText
Component.onCompleted: {
var serverName = ServersModel.getProcessedServerData("name") || ServersModel.getProcessedServerData("hostName") || "Server"
headerText = qsTr("Connection to ") + serverName
configContentHeaderText = qsTr("File with connection settings to ") + serverName
}
property string configContentHeaderText property string configContentHeaderText
property string shareButtonText: qsTr("Share") property string shareButtonText: qsTr("Share")
property string copyButtonText: qsTr("Copy") property string copyButtonText: qsTr("Copy")
@@ -36,17 +30,17 @@ PageType {
property string configCaption: qsTr("Save AmneziaVPN config") property string configCaption: qsTr("Save AmneziaVPN config")
property string configFileName: "amnezia_config" property string configFileName: "amnezia_config"
onVisibleChanged: { // onVisibleChanged: {
configExtension = ".vpn" // configExtension = ".vpn"
configCaption = qsTr("Save AmneziaVPN config") // configCaption = qsTr("Save AmneziaVPN config")
configFileName = "amnezia_config" // configFileName = "amnezia_config"
if (visible) { // if (visible) {
var serverName = ServersModel.getProcessedServerData("name") || ServersModel.getProcessedServerData("hostName") || "Server" // var serverName = ServersModel.getProcessedServerData("name") || ServersModel.getProcessedServerData("hostName") || "Server"
headerText = qsTr("Connection to ") + serverName // headerText = qsTr("Connection to ") + serverName
configContentHeaderText = qsTr("File with connection settings to ") + serverName // configContentHeaderText = qsTr("File with connection settings to ") + serverName
} // }
} // }
BackButtonType { BackButtonType {
id: backButton id: backButton
+6 -3
View File
@@ -37,6 +37,9 @@ PageType {
ListViewType { ListViewType {
id: listView id: listView
property string headerText: ""
property string configContentHeaderText: ""
anchors.top: backButton.bottom anchors.top: backButton.bottom
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
@@ -108,8 +111,8 @@ PageType {
serverSelector.currentIndex = serverSelectorListView.currentIndex serverSelector.currentIndex = serverSelectorListView.currentIndex
} }
shareConnectionPage.headerText = qsTr("Accessing ") + serverSelector.text listView.headerText = qsTr("Accessing ") + serverSelector.text
shareConnectionPage.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text listView.configContentHeaderText = qsTr("File with accessing settings to ") + serverSelector.text
serverSelector.closeTriggered() serverSelector.closeTriggered()
} }
@@ -156,7 +159,7 @@ PageType {
PageController.showBusyIndicator(false) PageController.showBusyIndicator(false)
PageController.goToPage(PageEnum.PageShareConnection) PageController.goToShareConnectionPage(listView.headerText, listView.configContentHeaderText, "", "", "")
} }
} }
} }
+13
View File
@@ -44,6 +44,19 @@ PageType {
tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition) tabBarStackView.push(pagePath, { "objectName" : pagePath }, StackView.PushTransition)
} }
function onGoToShareConnectionPage(headerText, configContentHeaderText, configCaption, configExtension, configFileName) {
var pagePath = PageController.getPagePath(PageEnum.PageShareConnection)
tabBarStackView.push(pagePath,
{ "objectName" : pagePath,
"headerText" : headerText,
"configContentHeaderText" : configContentHeaderText,
"configCaption" : configCaption,
"configExtension" : configExtension,
"configFileName" : configFileName
},
StackView.PushTransition)
}
function onDisableControls(disabled) { function onDisableControls(disabled) {
isControlsDisabled = disabled isControlsDisabled = disabled
} }
+1 -1
View File
@@ -29,7 +29,7 @@ void IpcProcessTun2Socks::start()
QString XrayConStr = "socks5://127.0.0.1:10808"; QString XrayConStr = "socks5://127.0.0.1:10808";
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QStringList arguments({"-device", "tun://tun2", "-proxy", XrayConStr, "-tun-post-up", QStringList arguments({"-device", "tun://tun2?guid={081A8A84-8D12-4DF5-B8C4-396D5B0053E4}", "-proxy", XrayConStr, "-tun-post-up",
QString("cmd /c netsh interface ip set address name=\"tun2\" static %1 255.255.255.255") QString("cmd /c netsh interface ip set address name=\"tun2\" static %1 255.255.255.255")
.arg(amnezia::protocols::xray::defaultLocalAddr)}); .arg(amnezia::protocols::xray::defaultLocalAddr)});
#endif #endif