diff --git a/CMakeLists.txt b/CMakeLists.txt index ca4ab5f83..e9146dfd1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR) set(PROJECT AmneziaVPN) -set(AMNEZIAVPN_VERSION 4.8.14.5) +set(AMNEZIAVPN_VERSION 4.8.15.0) project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION} DESCRIPTION "AmneziaVPN" diff --git a/client/resources.qrc b/client/resources.qrc index ad6feea90..581d16188 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -232,8 +232,8 @@ ui/qml/Pages2/PageSettingsNewsDetail.qml ui/qml/Pages2/PageProtocolAwgClientSettings.qml ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml - ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml - ui/qml/Pages2/PageSetupWizardApiPremium.qml + ui/qml/Pages2/PageSetupWizardApiFreeInfo.qml + ui/qml/Pages2/PageSetupWizardApiPremiumInfo.qml ui/qml/Pages2/PageSetupWizardApiServicesList.qml ui/qml/Pages2/PageSetupWizardConfigSource.qml ui/qml/Pages2/PageSetupWizardCredentials.qml diff --git a/client/ui/controllers/pageController.h b/client/ui/controllers/pageController.h index cdeaacfad..2e4cf33db 100644 --- a/client/ui/controllers/pageController.h +++ b/client/ui/controllers/pageController.h @@ -59,7 +59,7 @@ namespace PageLoader PageSetupWizardViewConfig, PageSetupWizardQrReader, PageSetupWizardApiServicesList, - PageSetupWizardApiServiceInfo, + PageSetupWizardApiFreeInfo, PageProtocolOpenVpnSettings, PageProtocolShadowSocksSettings, diff --git a/client/ui/models/api/apiServicesModel.cpp b/client/ui/models/api/apiServicesModel.cpp index 71cb85e20..de66715bb 100644 --- a/client/ui/models/api/apiServicesModel.cpp +++ b/client/ui/models/api/apiServicesModel.cpp @@ -1,6 +1,7 @@ #include "apiServicesModel.h" #include +#include #include #include @@ -36,16 +37,30 @@ namespace constexpr char isAvailable[] = "is_available"; - constexpr char subscriptionPlans[] = "subscription_plans"; + constexpr char supportInfo[] = "support_info"; - constexpr char premiumBenefitCountriesTitle[] = "premium_benefit_countries_title"; - constexpr char premiumBenefitCountriesBody[] = "premium_benefit_countries_body"; - constexpr char premiumBenefitDevicesTitle[] = "premium_benefit_devices_title"; - constexpr char premiumBenefitDevicesBody[] = "premium_benefit_devices_body"; - constexpr char premiumBenefitVideoTitle[] = "premium_benefit_video_title"; - constexpr char premiumBenefitVideoBody[] = "premium_benefit_video_body"; - constexpr char premiumBenefitTrafficTitle[] = "premium_benefit_traffic_title"; - constexpr char premiumBenefitTrafficBody[] = "premium_benefit_traffic_body"; + constexpr char subscriptionPlans[] = "subscription_plans"; + constexpr char benefits[] = "benefits"; + } + + QString iconUrlFromGatewayBenefitIcon(const QString &iconKey) + { + if (iconKey.startsWith(QLatin1String("qrc:"))) { + return iconKey; + } + static const QHash map = { + { QStringLiteral("globe-2"), QStringLiteral("qrc:/images/controls/globe-2.svg") }, + { QStringLiteral("smartphone"), QStringLiteral("qrc:/images/controls/smartphone.svg") }, + { QStringLiteral("gauge"), QStringLiteral("qrc:/images/controls/gauge.svg") }, + { QStringLiteral("infinity"), QStringLiteral("qrc:/images/controls/infinity.svg") }, + { QStringLiteral("tag"), QStringLiteral("qrc:/images/controls/tag.svg") }, + { QStringLiteral("history"), QStringLiteral("qrc:/images/controls/history.svg") }, + { QStringLiteral("info"), QStringLiteral("qrc:/images/controls/info.svg") }, + { QStringLiteral("app"), QStringLiteral("qrc:/images/controls/app.svg") }, + { QStringLiteral("download"), QStringLiteral("qrc:/images/controls/download.svg") }, + { QStringLiteral("help-circle"), QStringLiteral("qrc:/images/controls/help-circle.svg") }, + }; + return map.value(iconKey, QStringLiteral("qrc:/images/controls/info.svg")); } QVariantList jsonObjectArrayToVariantList(const QJsonArray &arr) @@ -161,8 +176,8 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const case SubscriptionPlansRole: { return apiServiceData.subscriptionPlans; } - case PremiumBenefitPanelRowsRole: { - return ApiServicesModel::buildPremiumBenefitPanelRows(apiServiceData); + case BenefitPanelRowsRole: { + return buildBenefitPanelRows(apiServiceData); } } @@ -291,7 +306,7 @@ QHash ApiServicesModel::roleNames() const roles[EndDateRole] = "endDate"; roles[OrderRole] = "order"; roles[SubscriptionPlansRole] = "subscriptionPlans"; - roles[PremiumBenefitPanelRowsRole] = "premiumBenefitRows"; + roles[BenefitPanelRowsRole] = "benefitRows"; return roles; } @@ -318,15 +333,9 @@ ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJs serviceData.serviceInfo.features = serviceDescription.value(configKey::features).toString(); serviceData.subscriptionPlans = jsonObjectArrayToVariantList(serviceDescription.value(configKey::subscriptionPlans).toArray()); + serviceData.benefitsConfig = serviceDescription.value(configKey::benefits).toArray(); - serviceData.premiumBenefitCountriesTitle = serviceDescription.value(configKey::premiumBenefitCountriesTitle).toString(); - serviceData.premiumBenefitCountriesBody = serviceDescription.value(configKey::premiumBenefitCountriesBody).toString(); - serviceData.premiumBenefitDevicesTitle = serviceDescription.value(configKey::premiumBenefitDevicesTitle).toString(); - serviceData.premiumBenefitDevicesBody = serviceDescription.value(configKey::premiumBenefitDevicesBody).toString(); - serviceData.premiumBenefitVideoTitle = serviceDescription.value(configKey::premiumBenefitVideoTitle).toString(); - serviceData.premiumBenefitVideoBody = serviceDescription.value(configKey::premiumBenefitVideoBody).toString(); - serviceData.premiumBenefitTrafficTitle = serviceDescription.value(configKey::premiumBenefitTrafficTitle).toString(); - serviceData.premiumBenefitTrafficBody = serviceDescription.value(configKey::premiumBenefitTrafficBody).toString(); + serviceData.supportInfo = data.value(configKey::supportInfo).toObject(); serviceData.type = serviceType; serviceData.protocol = serviceProtocol; @@ -347,29 +356,74 @@ ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJs return serviceData; } -QVariantList ApiServicesModel::buildPremiumBenefitPanelRows(const ApiServicesData &service) +QString ApiServicesModel::formatPriceForBenefit(const QString &rawPrice) const { - const QStringList icons = { QStringLiteral("qrc:/images/controls/globe-2.svg"), - QStringLiteral("qrc:/images/controls/smartphone.svg"), - QStringLiteral("qrc:/images/controls/gauge.svg"), - QStringLiteral("qrc:/images/controls/infinity.svg") }; + if (rawPrice == QStringLiteral("free")) { + return tr("Free"); + } +#if defined(Q_OS_IOS) || defined(MACOS_NE) + return tr("%1 $").arg(rawPrice); +#else + return tr("%1 $/month").arg(rawPrice); +#endif +} +QString ApiServicesModel::benefitInjectValue(const QString &injectKey, const ServiceInfo &info, + const QJsonObject &supportInfo) const +{ + if (injectKey == QLatin1String("region")) { + return info.region.isEmpty() ? QStringLiteral("—") : info.region; + } + if (injectKey == QLatin1String("speed")) { + return info.speed.isEmpty() ? QStringLiteral("—") : info.speed; + } + if (injectKey == QLatin1String("price")) { + return formatPriceForBenefit(info.price); + } + + if (injectKey == QLatin1String("support_telegram")) { + const QString handle = supportInfo.value(QStringLiteral("telegram")).toString().trimmed(); + if (handle.isEmpty()) { + return QStringLiteral("—"); + } + if (handle.startsWith(QLatin1Char('@'))) { + return handle; + } + return QLatin1Char('@') + handle; + } + return QString(); +} + +QVariantList ApiServicesModel::buildBenefitPanelRows(const ApiServicesData &service) const +{ QVariantList out; - - const auto appendRow = [&out, &icons](int iconIndex, const QString &title, const QString &body) { + for (const QJsonValue &v : service.benefitsConfig) { + if (!v.isObject()) { + continue; + } + const QJsonObject o = v.toObject(); + QString title = o.value(QStringLiteral("title")).toString(); + QString body = o.value(QStringLiteral("body")).toString(); + const QString iconKey = o.value(QStringLiteral("icon")).toString(); + const QString injectKey = o.value(QStringLiteral("inject_key")).toString(); + if (body.contains(QLatin1String("%1")) && !injectKey.isEmpty()) { + QString injected = benefitInjectValue(injectKey, service.serviceInfo, service.supportInfo); + if (injected.isEmpty()) { + injected = QStringLiteral("—"); + } + body = body.arg(injected); + } if (title.isEmpty() && body.isEmpty()) { - return; + continue; } QVariantMap m; - m.insert(QStringLiteral("icon"), icons.at(iconIndex)); + m.insert(QStringLiteral("icon"), iconUrlFromGatewayBenefitIcon(iconKey)); m.insert(QStringLiteral("title"), title); m.insert(QStringLiteral("body"), body); + if (o.value(QStringLiteral("body_accent")).toBool()) { + m.insert(QStringLiteral("body_accent"), true); + } out.append(m); - }; - - appendRow(0, service.premiumBenefitCountriesTitle, service.premiumBenefitCountriesBody); - appendRow(1, service.premiumBenefitDevicesTitle, service.premiumBenefitDevicesBody); - appendRow(2, service.premiumBenefitVideoTitle, service.premiumBenefitVideoBody); - appendRow(3, service.premiumBenefitTrafficTitle, service.premiumBenefitTrafficBody); + } return out; } diff --git a/client/ui/models/api/apiServicesModel.h b/client/ui/models/api/apiServicesModel.h index 58770e9ed..2ac221203 100644 --- a/client/ui/models/api/apiServicesModel.h +++ b/client/ui/models/api/apiServicesModel.h @@ -24,7 +24,7 @@ public: EndDateRole, OrderRole, SubscriptionPlansRole, - PremiumBenefitPanelRowsRole + BenefitPanelRowsRole }; explicit ApiServicesModel(QObject *parent = nullptr); @@ -86,24 +86,21 @@ private: QString storeEndpoint; ServiceInfo serviceInfo; + QJsonObject supportInfo; Subscription subscription; QJsonArray availableCountries; QVariantList subscriptionPlans; - QString premiumBenefitCountriesTitle; - QString premiumBenefitCountriesBody; - QString premiumBenefitDevicesTitle; - QString premiumBenefitDevicesBody; - QString premiumBenefitVideoTitle; - QString premiumBenefitVideoBody; - QString premiumBenefitTrafficTitle; - QString premiumBenefitTrafficBody; + QJsonArray benefitsConfig; }; ApiServicesData getApiServicesData(const QJsonObject &data); - static QVariantList buildPremiumBenefitPanelRows(const ApiServicesData &service); + QVariantList buildBenefitPanelRows(const ApiServicesData &service) const; + QString benefitInjectValue(const QString &injectKey, const ServiceInfo &info, + const QJsonObject &supportInfo) const; + QString formatPriceForBenefit(const QString &rawPrice) const; QString m_countryCode; QVector m_services; diff --git a/client/ui/qml/Components/BenefitRow.qml b/client/ui/qml/Components/BenefitRow.qml index 127146a19..db18254af 100644 --- a/client/ui/qml/Components/BenefitRow.qml +++ b/client/ui/qml/Components/BenefitRow.qml @@ -11,6 +11,7 @@ RowLayout { property string iconSource: "" property string titleText: "" property string bodyText: "" + property bool bodyAccent: false spacing: 12 @@ -35,12 +36,30 @@ RowLayout { wrapMode: Text.Wrap } - LabelTextType { + Item { Layout.fillWidth: true - text: root.bodyText - color: AmneziaStyle.color.mutedGray - font.pixelSize: 14 - wrapMode: Text.Wrap + implicitHeight: bodyLabel.implicitHeight + + LabelTextType { + id: bodyLabel + width: parent.width + text: root.bodyText + color: root.bodyAccent ? AmneziaStyle.color.goldenApricot : AmneziaStyle.color.mutedGray + font.pixelSize: 14 + wrapMode: Text.Wrap + } + + MouseArea { + anchors.fill: bodyLabel + visible: root.bodyAccent && root.bodyText.length > 0 + cursorShape: Qt.PointingHandCursor + onClicked: { + var t = root.bodyText.trim() + if (t.startsWith("@")) { + Qt.openUrlExternally("https://t.me/" + t.substring(1)) + } + } + } } } } diff --git a/client/ui/qml/Components/BenefitsPanel.qml b/client/ui/qml/Components/BenefitsPanel.qml index 3197a7708..8d5244c83 100644 --- a/client/ui/qml/Components/BenefitsPanel.qml +++ b/client/ui/qml/Components/BenefitsPanel.qml @@ -10,6 +10,8 @@ Rectangle { property var benefitItems: [] + visible: benefitItems && benefitItems.length > 0 + radius: 16 color: "#1C1C1E" implicitHeight: inner.implicitHeight + 24 @@ -31,6 +33,7 @@ Rectangle { iconSource: root.benefitItems[index].icon titleText: root.benefitItems[index].title bodyText: root.benefitItems[index].body + bodyAccent: !!root.benefitItems[index].body_accent } } } diff --git a/client/ui/qml/Pages2/PageSetupWizardApiFreeInfo.qml b/client/ui/qml/Pages2/PageSetupWizardApiFreeInfo.qml new file mode 100644 index 000000000..2728de3f2 --- /dev/null +++ b/client/ui/qml/Pages2/PageSetupWizardApiFreeInfo.qml @@ -0,0 +1,213 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import Style 1.0 + +import "./" +import "../Controls2" +import "../Controls2/TextTypes" +import "../Config" +import "../Components" + +PageType { + id: root + + property string freeHeaderName: "" + property string freeHeaderDescription: "" + property string freeFeaturesHtml: "" + property var benefitRows: [] + + function syncFromModel() { + root.freeHeaderName = String(ApiServicesModel.getSelectedServiceData("name")) + root.freeHeaderDescription = String(ApiServicesModel.getSelectedServiceData("serviceDescription")) + var text = ApiServicesModel.getSelectedServiceData("features") + root.freeFeaturesHtml = String(text).replace("%1", LanguageModel.getCurrentSiteUrl("free")).replace("/free", "") + + var rows = ApiServicesModel.getSelectedServiceData("benefitRows") + root.benefitRows = rows !== undefined && rows !== null ? rows : [] + } + + Component.onCompleted: syncFromModel() + + Connections { + target: ApiServicesModel + + function onModelReset() { + root.syncFromModel() + } + } + + BackButtonType { + id: backButton + + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.topMargin: 20 + SettingsController.safeAreaTopMargin + + onFocusChanged: { + if (activeFocus) { + flick.contentY = 0 + } + } + } + + FlickableType { + id: flick + + anchors.top: backButton.bottom + anchors.bottom: continueButton.top + anchors.left: parent.left + anchors.right: parent.right + + contentHeight: scrollColumn.implicitHeight + 24 + + ColumnLayout { + id: scrollColumn + + width: flick.width + spacing: 0 + + BaseHeaderType { + Layout.fillWidth: true + Layout.topMargin: 8 + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 24 + + headerText: root.freeHeaderName + descriptionText: root.freeHeaderDescription + } + + LabelTextType { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 12 + + text: qsTr("Available with Free") + color: AmneziaStyle.color.mutedGray + font.pixelSize: 13 + } + + BenefitsPanel { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 24 + + benefitItems: root.benefitRows + } + + ParagraphTextType { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 16 + + visible: root.freeFeaturesHtml.length > 0 && (!root.benefitRows || root.benefitRows.length === 0) + + textFormat: Text.RichText + text: root.freeFeaturesHtml + + onLinkActivated: function(link) { + Qt.openUrlExternally(link) + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton + cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + } + } + + ParagraphTextType { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 16 + + visible: !(Qt.platform.os === "ios" || IsMacOsNeBuild) + + horizontalAlignment: Text.AlignHCenter + textFormat: Text.RichText + color: AmneziaStyle.color.mutedGray + font.pixelSize: 12 + + text: { + var termsUrl = LanguageModel.getCurrentSiteUrl() + var privacyUrl = LanguageModel.getCurrentSiteUrl("policy") + return qsTr("By continuing, you agree to the Terms of Use and Privacy Policy").arg(termsUrl).arg(privacyUrl) + } + + onLinkActivated: function(link) { + Qt.openUrlExternally(link) + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton + cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + } + } + + ParagraphTextType { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 24 + + visible: (Qt.platform.os === "ios" || IsMacOsNeBuild) + + horizontalAlignment: Text.AlignHCenter + textFormat: Text.RichText + color: AmneziaStyle.color.mutedGray + font.pixelSize: 12 + + text: { + var termsUrl = "https://www.apple.com/legal/internet-services/itunes/dev/stdeula/" + var privacyUrl = LanguageModel.getCurrentSiteUrl("policy") + return qsTr("By continuing, you agree to the Terms of Use and Privacy Policy").arg(termsUrl).arg(privacyUrl) + } + + onLinkActivated: function(link) { + Qt.openUrlExternally(link) + } + + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.NoButton + cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor + } + } + } + } + + BasicButtonType { + id: continueButton + + z: 2 + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.leftMargin: 16 + anchors.rightMargin: 16 + anchors.bottomMargin: 16 + SettingsController.safeAreaBottomMargin + + text: ApiServicesModel.getSelectedServiceType() === "amnezia-trial" ? qsTr("Try Trial") : qsTr("Continue") + + clickedFunc: function() { + PageController.showBusyIndicator(true) + var result = ApiConfigsController.importService() + PageController.showBusyIndicator(false) + + if (!result) { + var endpoint = ApiServicesModel.getStoreEndpoint() + Qt.openUrlExternally(endpoint) + PageController.closePage() + PageController.closePage() + } + } + } +} diff --git a/client/ui/qml/Pages2/PageSetupWizardApiPremiumInfo.qml b/client/ui/qml/Pages2/PageSetupWizardApiPremiumInfo.qml index 2ad03a784..cb634fca1 100644 --- a/client/ui/qml/Pages2/PageSetupWizardApiPremiumInfo.qml +++ b/client/ui/qml/Pages2/PageSetupWizardApiPremiumInfo.qml @@ -26,7 +26,7 @@ PageType { function syncFromModel() { root.subscriptionPlans = ApiServicesModel.getSelectedServiceData("subscriptionPlans") - root.benefitRows = ApiServicesModel.getSelectedServiceData("premiumBenefitRows") + root.benefitRows = ApiServicesModel.getSelectedServiceData("benefitRows") root.selectedGatewayPlanIndex = 0 for (var i = 0; i < root.subscriptionPlans.length; ++i) { diff --git a/client/ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml b/client/ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml deleted file mode 100644 index 8ddeeefcc..000000000 --- a/client/ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml +++ /dev/null @@ -1,180 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import QtQuick.Dialogs - -import PageEnum 1.0 -import Style 1.0 - -import "./" -import "../Controls2" -import "../Controls2/TextTypes" -import "../Config" -import "../Components" - -PageType { - id: root - - BackButtonType { - id: backButton - - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.topMargin: 20 + SettingsController.safeAreaTopMargin - - onFocusChanged: { - if (this.activeFocus) { - listView.positionViewAtBeginning() - } - } - } - - ListViewType { - id: listView - - anchors.top: backButton.bottom - anchors.bottom: parent.bottom - anchors.right: parent.right - anchors.left: parent.left - - header: ColumnLayout { - width: listView.width - - BaseHeaderType { - Layout.fillWidth: true - Layout.topMargin: 8 - Layout.rightMargin: 16 - Layout.leftMargin: 16 - Layout.bottomMargin: 32 - - headerText: ApiServicesModel.getSelectedServiceData("name") - descriptionText: ApiServicesModel.getSelectedServiceData("serviceDescription") - } - } - - model: inputFields - spacing: 0 - - delegate: ColumnLayout { - width: listView.width - - LabelWithImageType { - Layout.fillWidth: true - Layout.margins: 16 - - imageSource: imagePath - leftText: lText - rightText: rText - - visible: isVisible - } - } - - footer: ColumnLayout { - width: listView.width - - spacing: 0 - - ParagraphTextType { - Layout.fillWidth: true - Layout.rightMargin: 16 - Layout.leftMargin: 16 - - onLinkActivated: function(link) { - Qt.openUrlExternally(link) - } - textFormat: Text.RichText - text: { - var text = ApiServicesModel.getSelectedServiceData("features") - return text.replace("%1", LanguageModel.getCurrentSiteUrl("free")).replace("/free", "") // todo link should come from gateway - } - - MouseArea { - anchors.fill: parent - acceptedButtons: Qt.NoButton - cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor - } - } - - BasicButtonType { - id: continueButton - - Layout.fillWidth: true - Layout.topMargin: 32 - Layout.bottomMargin: 16 - Layout.leftMargin: 16 - Layout.rightMargin: 16 - - text: ApiServicesModel.getSelectedServiceType() === "amnezia-trial" ? qsTr("Try Trial") : qsTr("Connect") - - clickedFunc: function() { - PageController.showBusyIndicator(true) - var result = ApiConfigsController.importService() - PageController.showBusyIndicator(false) - - if (!result) { - var endpoint = ApiServicesModel.getStoreEndpoint() - Qt.openUrlExternally(endpoint) - PageController.closePage() - PageController.closePage() - } - } - } - - } - } - - property list inputFields: [ - region, - price, - timeLimit, - speed, - features - ] - - QtObject { - id: region - - readonly property string imagePath: "qrc:/images/controls/map-pin.svg" - readonly property string lText: qsTr("For the region") - readonly property string rText: ApiServicesModel.getSelectedServiceData("region") - property bool isVisible: true - } - - QtObject { - id: price - - readonly property string imagePath: "qrc:/images/controls/tag.svg" - readonly property string lText: qsTr("Price") - readonly property string rText: ApiServicesModel.getSelectedServiceData("price") - property bool isVisible: true - } - - QtObject { - id: timeLimit - - readonly property string imagePath: "qrc:/images/controls/history.svg" - readonly property string lText: qsTr("Work period") - readonly property string rText: ApiServicesModel.getSelectedServiceData("timeLimit") - property bool isVisible: rText !== "" - } - - QtObject { - id: speed - - readonly property string imagePath: "qrc:/images/controls/gauge.svg" - readonly property string lText: qsTr("Speed") - readonly property string rText: ApiServicesModel.getSelectedServiceData("speed") - property bool isVisible: true - } - - QtObject { - id: features - - readonly property string imagePath: "qrc:/images/controls/info.svg" - readonly property string lText: qsTr("Features") - readonly property string rText: "" - property bool isVisible: true - } -} diff --git a/client/ui/qml/Pages2/PageSetupWizardApiServicesList.qml b/client/ui/qml/Pages2/PageSetupWizardApiServicesList.qml index a2b27562e..f0c1c4e49 100644 --- a/client/ui/qml/Pages2/PageSetupWizardApiServicesList.qml +++ b/client/ui/qml/Pages2/PageSetupWizardApiServicesList.qml @@ -92,7 +92,7 @@ PageType { if (ApiServicesModel.getSelectedServiceType() === "amnezia-premium") { PageController.goToPage(PageEnum.PageSetupWizardApiPremiumInfo) } else { - PageController.goToPage(PageEnum.PageSetupWizardApiServiceInfo) + PageController.goToPage(PageEnum.PageSetupWizardApiFreeInfo) } } }