SettingsController
-
+
All settings have been reset to default values
Все настройки сброшены до значений по умолчанию
-
+
Backup file is corrupted
Файл резервной копии поврежден
diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp
index 026224c5..41756462 100644
--- a/client/ui/controllers/api/apiConfigsController.cpp
+++ b/client/ui/controllers/api/apiConfigsController.cpp
@@ -29,7 +29,6 @@ namespace
constexpr char uuid[] = "installation_uuid";
constexpr char osVersion[] = "os_version";
constexpr char appVersion[] = "app_version";
- constexpr char appLanguage[] = "app_language";
constexpr char userCountryCode[] = "user_country_code";
constexpr char serverCountryCode[] = "server_country_code";
@@ -65,6 +64,7 @@ namespace
{
QString osVersion;
QString appVersion;
+ QString appLanguage;
QString installationUuid;
@@ -84,6 +84,9 @@ namespace
if (!appVersion.isEmpty()) {
obj[configKey::appVersion] = appVersion;
}
+ if (!appLanguage.isEmpty()) {
+ obj[apiDefs::key::appLanguage] = appLanguage;
+ }
if (!installationUuid.isEmpty()) {
obj[configKey::uuid] = installationUuid;
}
@@ -223,6 +226,9 @@ namespace
if (newServerConfig.value(config_key::configVersion).toInt() == apiDefs::ConfigSource::AmneziaGateway) {
apiConfig.insert(apiDefs::key::supportedProtocols,
QJsonDocument::fromJson(apiResponseBody).object().value(apiDefs::key::supportedProtocols).toArray());
+
+ apiConfig.insert(apiDefs::key::serviceInfo,
+ QJsonDocument::fromJson(apiResponseBody).object().value(apiDefs::key::serviceInfo).toObject());
}
serverConfig[configKey::apiConfig] = apiConfig;
@@ -285,6 +291,7 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION),
+ m_settings->getAppLanguage().name().split("_").first(),
m_settings->getInstallationUuid(true),
apiConfigObject.value(configKey::userCountryCode).toString(),
serverCountryCode,
@@ -325,6 +332,7 @@ bool ApiConfigsController::revokeNativeConfig(const QString &serverCountryCode)
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION),
+ m_settings->getAppLanguage().name().split("_").first(),
m_settings->getInstallationUuid(true),
apiConfigObject.value(configKey::userCountryCode).toString(),
serverCountryCode,
@@ -375,7 +383,7 @@ bool ApiConfigsController::fillAvailableServices()
{
QJsonObject apiPayload;
apiPayload[configKey::osVersion] = QSysInfo::productType();
- apiPayload[configKey::appLanguage] = m_settings->getAppLanguage().name().split("_").first();
+ apiPayload[apiDefs::key::appLanguage] = m_settings->getAppLanguage().name().split("_").first();
QByteArray responseBody;
ErrorCode errorCode = executeRequest(QString("%1v1/services"), apiPayload, responseBody);
@@ -399,6 +407,7 @@ bool ApiConfigsController::importServiceFromGateway()
{
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION),
+ m_settings->getAppLanguage().name().split("_").first(),
m_settings->getInstallationUuid(true),
m_apiServicesModel->getCountryCode(),
"",
@@ -457,6 +466,7 @@ bool ApiConfigsController::updateServiceFromGateway(const int serverIndex, const
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION),
+ m_settings->getAppLanguage().name().split("_").first(),
m_settings->getInstallationUuid(true),
apiConfig.value(configKey::userCountryCode).toString(),
newCountryCode,
@@ -577,6 +587,7 @@ bool ApiConfigsController::deactivateDevice(const bool isRemoveEvent)
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION),
+ m_settings->getAppLanguage().name().split("_").first(),
m_settings->getInstallationUuid(true),
apiConfigObject.value(configKey::userCountryCode).toString(),
apiConfigObject.value(configKey::serverCountryCode).toString(),
@@ -616,6 +627,7 @@ bool ApiConfigsController::deactivateExternalDevice(const QString &uuid, const Q
GatewayRequestData gatewayRequestData { QSysInfo::productType(),
QString(APP_VERSION),
+ m_settings->getAppLanguage().name().split("_").first(),
uuid,
apiConfigObject.value(configKey::userCountryCode).toString(),
serverCountryCode,
diff --git a/client/ui/controllers/api/apiSettingsController.cpp b/client/ui/controllers/api/apiSettingsController.cpp
index c4a75a5b..58ba9af9 100644
--- a/client/ui/controllers/api/apiSettingsController.cpp
+++ b/client/ui/controllers/api/apiSettingsController.cpp
@@ -62,6 +62,7 @@ bool ApiSettingsController::getAccountInfo(bool reload)
apiPayload[configKey::serviceType] = apiConfig.value(configKey::serviceType).toString();
apiPayload[configKey::authData] = authData;
apiPayload[apiDefs::key::cliVersion] = QString(APP_VERSION);
+ apiPayload[apiDefs::key::appLanguage] = m_settings->getAppLanguage().name().split("_").first();
QByteArray responseBody;
diff --git a/client/ui/models/api/apiAccountInfoModel.cpp b/client/ui/models/api/apiAccountInfoModel.cpp
index bdd7d68d..0f3a8a4e 100644
--- a/client/ui/models/api/apiAccountInfoModel.cpp
+++ b/client/ui/models/api/apiAccountInfoModel.cpp
@@ -31,7 +31,8 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
return tr("Active");
}
- return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("Inactive") : tr("Active");
+ return apiUtils::isSubscriptionExpired(m_accountInfoData.subscriptionEndDate) ? tr("
Inactive")
+ : tr("Active");
}
case EndDateRole: {
if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) {
@@ -47,16 +48,7 @@ QVariant ApiAccountInfoModel::data(const QModelIndex &index, int role) const
return tr("%1 out of %2").arg(m_accountInfoData.activeDeviceCount).arg(m_accountInfoData.maxDeviceCount);
}
case ServiceDescriptionRole: {
- if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2) {
- return tr("Classic VPN for seamless work, downloading large files, and watching videos. Access all websites and online "
- "resources. "
- "Speeds up to 200 Mbps");
- } else if (m_accountInfoData.configType == apiDefs::ConfigType::AmneziaFreeV3) {
- return tr("Free unlimited access to a basic set of websites such as Facebook, Instagram, Twitter (X), Discord, Telegram and "
- "more. YouTube is not included in the free plan.");
- } else {
- return "";
- }
+ return m_accountInfoData.subscriptionDescription;
}
case IsComponentVisibleRole: {
return m_accountInfoData.configType == apiDefs::ConfigType::AmneziaPremiumV2
@@ -101,6 +93,8 @@ void ApiAccountInfoModel::updateModel(const QJsonObject &accountInfoObject, cons
accountInfoData.configType = apiUtils::getConfigType(serverConfig);
+ accountInfoData.subscriptionDescription = accountInfoObject.value(apiDefs::key::subscriptionDescription).toString();
+
for (const auto &protocol : accountInfoObject.value(apiDefs::key::supportedProtocols).toArray()) {
accountInfoData.supportedProtocols.push_back(protocol.toString());
}
diff --git a/client/ui/models/api/apiAccountInfoModel.h b/client/ui/models/api/apiAccountInfoModel.h
index f0203967..836bc892 100644
--- a/client/ui/models/api/apiAccountInfoModel.h
+++ b/client/ui/models/api/apiAccountInfoModel.h
@@ -54,6 +54,8 @@ private:
apiDefs::ConfigType configType;
QStringList supportedProtocols;
+
+ QString subscriptionDescription;
};
AccountInfoData m_accountInfoData;
diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp
index 5d8910d0..1a2bb150 100644
--- a/client/ui/models/servers_model.cpp
+++ b/client/ui/models/servers_model.cpp
@@ -158,6 +158,18 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
QString primaryDns = server.value(config_key::dns1).toString();
return primaryDns == protocols::dns::amneziaDnsIp;
}
+ case IsAdVisibleRole:{
+ return apiConfig.value(apiDefs::key::serviceInfo).toObject().value(apiDefs::key::isAdVisible).toBool(false);
+ }
+ case AdHeaderRole: {
+ return apiConfig.value(apiDefs::key::serviceInfo).toObject().value(apiDefs::key::adHeader).toString();
+ }
+ case AdDescriptionRole: {
+ return apiConfig.value(apiDefs::key::serviceInfo).toObject().value(apiDefs::key::adDescription).toString();
+ }
+ case AdEndpointRole: {
+ return apiConfig.value(apiDefs::key::serviceInfo).toObject().value(apiDefs::key::adEndpoint).toString();
+ }
}
return QVariant();
@@ -403,6 +415,12 @@ QHash ServersModel::roleNames() const
roles[IsCountrySelectionAvailableRole] = "isCountrySelectionAvailable";
roles[ApiAvailableCountriesRole] = "apiAvailableCountries";
roles[ApiServerCountryCodeRole] = "apiServerCountryCode";
+
+ roles[IsAdVisibleRole] = "isAdVisible";
+ roles[AdHeaderRole] = "adHeader";
+ roles[AdDescriptionRole] = "adDescription";
+ roles[AdEndpointRole] = "adEndpoint";
+
return roles;
}
@@ -784,22 +802,22 @@ void ServersModel::recomputeGatewayStacks()
const bool wasEmpty = m_gatewayStacks.isEmpty();
GatewayStacks computed;
bool hasNewTags = false;
-
+
for (int i = 0; i < m_servers.count(); ++i) {
if (data(i, IsServerFromGatewayApiRole).toBool()) {
const QJsonObject server = m_servers.at(i).toObject();
const QJsonObject apiConfig = server.value(configKey::apiConfig).toObject();
-
+
const QString userCountryCode = apiConfig.value(configKey::userCountryCode).toString();
const QString serviceType = apiConfig.value(configKey::serviceType).toString();
-
+
if (!userCountryCode.isEmpty()) {
if (!m_gatewayStacks.userCountryCodes.contains(userCountryCode)) {
hasNewTags = true;
}
computed.userCountryCodes.insert(userCountryCode);
}
-
+
if (!serviceType.isEmpty()) {
if (!m_gatewayStacks.serviceTypes.contains(serviceType)) {
hasNewTags = true;
@@ -808,12 +826,12 @@ void ServersModel::recomputeGatewayStacks()
}
}
}
-
+
m_gatewayStacks = std::move(computed);
if (hasNewTags) {
emit gatewayStacksExpanded();
}
-
+
if (wasEmpty != m_gatewayStacks.isEmpty()) {
emit hasServersFromGatewayApiChanged();
}
@@ -885,3 +903,18 @@ bool ServersModel::processedServerIsPremium() const
{
return apiUtils::isPremiumServer(getServerConfig(m_processedServerIndex));
}
+
+bool ServersModel::isAdVisible()
+{
+ return data(m_defaultServerIndex, IsAdVisibleRole).toBool();
+}
+
+QString ServersModel::adHeader()
+{
+ return data(m_defaultServerIndex, AdHeaderRole).toString();
+}
+
+QString ServersModel::adDescription()
+{
+ return data(m_defaultServerIndex, AdDescriptionRole).toString();
+}
diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h
index 973b5418..8a0406bb 100644
--- a/client/ui/models/servers_model.h
+++ b/client/ui/models/servers_model.h
@@ -47,6 +47,10 @@ public:
IsCountrySelectionAvailableRole,
ApiAvailableCountriesRole,
ApiServerCountryCodeRole,
+ IsAdVisibleRole,
+ AdHeaderRole,
+ AdDescriptionRole,
+ AdEndpointRole,
HasAmneziaDns
};
@@ -79,6 +83,10 @@ public:
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
Q_PROPERTY(bool processedServerIsPremium READ processedServerIsPremium NOTIFY processedServerChanged)
+ Q_PROPERTY(bool isAdVisible READ isAdVisible NOTIFY defaultServerIndexChanged)
+ Q_PROPERTY(QString adHeader READ adHeader NOTIFY defaultServerIndexChanged)
+ Q_PROPERTY(QString adDescription READ adDescription NOTIFY defaultServerIndexChanged)
+
bool processedServerIsPremium() const;
public slots:
@@ -144,6 +152,10 @@ public slots:
bool isApiKeyExpired(const int serverIndex);
void removeApiConfig(const int serverIndex);
+ bool isAdVisible();
+ QString adHeader();
+ QString adDescription();
+
protected:
QHash roleNames() const override;
diff --git a/client/ui/qml/Components/AdLabel.qml b/client/ui/qml/Components/AdLabel.qml
index 3ef0fc69..fedaa0e5 100644
--- a/client/ui/qml/Components/AdLabel.qml
+++ b/client/ui/qml/Components/AdLabel.qml
@@ -2,7 +2,6 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Shapes
-import Qt5Compat.GraphicalEffects
import Style 1.0
@@ -13,61 +12,139 @@ import "../Controls2/TextTypes"
Rectangle {
id: root
- property real contentHeight: ad.implicitHeight + ad.anchors.topMargin + ad.anchors.bottomMargin
+ property real contentHeight: content.implicitHeight + content.anchors.topMargin + content.anchors.bottomMargin
+ property bool isFocusable: true
+ gradient: Gradient {
+ orientation: Gradient.Horizontal
+ GradientStop { position: 0.0; color: AmneziaStyle.color.translucentSlateGray }
+ GradientStop { position: 1.0; color: AmneziaStyle.color.translucentOnyxBlack }
+ }
border.width: 1
- border.color: AmneziaStyle.color.goldenApricot
- color: AmneziaStyle.color.transparent
+ border.color: AmneziaStyle.color.onyxBlack
radius: 13
- visible: false
- // visible: GC.isDesktop() && ServersModel.isDefaultServerFromApi
- // && ServersModel.isDefaultServerDefaultContainerHasSplitTunneling && SettingsController.isHomeAdLabelVisible
+ visible: ServersModel.isAdVisible
- MouseArea {
- anchors.fill: parent
- cursorShape: Qt.PointingHandCursor
+ Keys.onTabPressed: {
+ FocusController.nextKeyTabItem()
+ }
- onClicked: function() {
- Qt.openUrlExternally(LanguageModel.getCurrentSiteUrl("premium"))
- }
+ Keys.onBacktabPressed: {
+ FocusController.previousKeyTabItem()
+ }
+
+ Keys.onUpPressed: {
+ FocusController.nextKeyUpItem()
+ }
+
+ Keys.onDownPressed: {
+ FocusController.nextKeyDownItem()
+ }
+
+ Keys.onLeftPressed: {
+ FocusController.nextKeyLeftItem()
+ }
+
+ Keys.onRightPressed: {
+ FocusController.nextKeyRightItem()
+ }
+
+ Keys.onEnterPressed: {
+ Qt.openUrlExternally(ServersModel.getDefaultServerData("adEndpoint"))
+ }
+
+ Keys.onReturnPressed: {
+ Qt.openUrlExternally(ServersModel.getDefaultServerData("adEndpoint"))
}
RowLayout {
- id: ad
+ id: content
anchors.fill: parent
- anchors.margins: 16
+ anchors.leftMargin: 16
+ anchors.rightMargin: 12
+ anchors.topMargin: 12
+ anchors.bottomMargin: 12
+ spacing: 20
- Image {
- source: "qrc:/images/controls/amnezia.svg"
- sourceSize: Qt.size(36, 36)
+ ColumnLayout {
+ Layout.fillWidth: true
+ spacing: 4
- layer {
- effect: ColorOverlay {
- color: AmneziaStyle.color.paleGray
- }
+ CaptionTextType {
+ Layout.fillWidth: true
+ text: ServersModel.adHeader
+ color: AmneziaStyle.color.paleGray
+ font.pixelSize: 14
+ font.weight: 700
+
+ textFormat: Text.RichText
+ }
+
+ CaptionTextType {
+ Layout.fillWidth: true
+ text: ServersModel.adDescription
+ color: AmneziaStyle.color.mutedGray
+ wrapMode: Text.WordWrap
+ lineHeight: 18
+ lineHeightMode: Text.FixedHeight
+ font.pixelSize: 14
+
+ visible: text !== ""
}
}
- CaptionTextType {
- Layout.fillWidth: true
- Layout.rightMargin: 10
- Layout.leftMargin: 10
+ Item {
+ implicitWidth: 40
+ implicitHeight: 40
+ Layout.alignment: Qt.AlignVCenter
- text: qsTr("Amnezia Premium - for access to all websites and online resources")
- color: AmneziaStyle.color.pearlGray
+ Rectangle {
+ id: chevronBackground
+ anchors.fill: parent
+ radius: 12
+ color: AmneziaStyle.color.transparent
+ border.width: root.activeFocus ? 1 : 0
+ border.color: AmneziaStyle.color.paleGray
- lineHeight: 18
- font.pixelSize: 15
- }
+ Behavior on color {
+ PropertyAnimation { duration: 200 }
+ }
- ImageButtonType {
- image: "qrc:/images/controls/close.svg"
- imageColor: AmneziaStyle.color.paleGray
+ Behavior on border.width {
+ PropertyAnimation { duration: 200 }
+ }
+ }
- onClicked: function() {
- SettingsController.disableHomeAdLabel()
+ Image {
+ anchors.centerIn: parent
+ source: "qrc:/images/controls/chevron-right.svg"
+ sourceSize: Qt.size(24, 24)
}
}
}
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ cursorShape: Qt.PointingHandCursor
+ hoverEnabled: true
+
+ onEntered: {
+ chevronBackground.color = AmneziaStyle.color.slateGray
+ }
+
+ onExited: {
+ chevronBackground.color = AmneziaStyle.color.transparent
+ }
+
+ onPressedChanged: {
+ chevronBackground.color = pressed ? AmneziaStyle.color.charcoalGray : containsMouse ? AmneziaStyle.color.slateGray : AmneziaStyle.color.transparent
+ }
+
+ onClicked: function() {
+ root.forceActiveFocus()
+ Qt.openUrlExternally(ServersModel.getDefaultServerData("adEndpoint"))
+ }
+ }
}
diff --git a/client/ui/qml/Modules/Style/AmneziaStyle.qml b/client/ui/qml/Modules/Style/AmneziaStyle.qml
index 4e2e80f0..20b56336 100644
--- a/client/ui/qml/Modules/Style/AmneziaStyle.qml
+++ b/client/ui/qml/Modules/Style/AmneziaStyle.qml
@@ -28,5 +28,7 @@ QtObject {
readonly property color cloudyGray: Qt.rgba(215/255, 216/255, 219/255, 0.65)
readonly property color pearlGray: '#EAEAEC'
readonly property color translucentRichBrown: Qt.rgba(99/255, 51/255, 3/255, 0.26)
+ readonly property color translucentSlateGray: Qt.rgba(85/255, 86/255, 92/255, 0.13)
+ readonly property color translucentOnyxBlack: Qt.rgba(28/255, 29/255, 33/255, 0.13)
}
}
diff --git a/client/ui/qml/Pages2/PageHome.qml b/client/ui/qml/Pages2/PageHome.qml
index d2289ab0..09a13e67 100644
--- a/client/ui/qml/Pages2/PageHome.qml
+++ b/client/ui/qml/Pages2/PageHome.qml
@@ -71,16 +71,6 @@ PageType {
anchors.topMargin: 12
anchors.bottomMargin: 16
- AdLabel {
- id: adLabel
-
- Layout.fillWidth: true
- Layout.preferredHeight: adLabel.contentHeight
- Layout.leftMargin: 16
- Layout.rightMargin: 16
- Layout.bottomMargin: 22
- }
-
BasicButtonType {
id: loggingButton
objectName: "loggingButton"
@@ -189,6 +179,16 @@ PageType {
parent: root
}
}
+
+ AdLabel {
+ id: adLabel
+
+ Layout.fillWidth: true
+ Layout.preferredHeight: adLabel.contentHeight
+ Layout.leftMargin: 16
+ Layout.rightMargin: 16
+ Layout.topMargin: 22
+ }
}
}