mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
feat: add new free info page
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.25.0 FATAL_ERROR)
|
||||||
|
|
||||||
set(PROJECT AmneziaVPN)
|
set(PROJECT AmneziaVPN)
|
||||||
set(AMNEZIAVPN_VERSION 4.8.14.5)
|
set(AMNEZIAVPN_VERSION 4.8.15.0)
|
||||||
|
|
||||||
project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION}
|
project(${PROJECT} VERSION ${AMNEZIAVPN_VERSION}
|
||||||
DESCRIPTION "AmneziaVPN"
|
DESCRIPTION "AmneziaVPN"
|
||||||
|
|||||||
@@ -232,8 +232,8 @@
|
|||||||
<file>ui/qml/Pages2/PageSettingsNewsDetail.qml</file>
|
<file>ui/qml/Pages2/PageSettingsNewsDetail.qml</file>
|
||||||
<file>ui/qml/Pages2/PageProtocolAwgClientSettings.qml</file>
|
<file>ui/qml/Pages2/PageProtocolAwgClientSettings.qml</file>
|
||||||
<file>ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml</file>
|
<file>ui/qml/Pages2/PageProtocolWireGuardClientSettings.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSetupWizardApiServiceInfo.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardApiFreeInfo.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSetupWizardApiPremium.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardApiPremiumInfo.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardApiServicesList.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSetupWizardConfigSource.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardConfigSource.qml</file>
|
||||||
<file>ui/qml/Pages2/PageSetupWizardCredentials.qml</file>
|
<file>ui/qml/Pages2/PageSetupWizardCredentials.qml</file>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ namespace PageLoader
|
|||||||
PageSetupWizardViewConfig,
|
PageSetupWizardViewConfig,
|
||||||
PageSetupWizardQrReader,
|
PageSetupWizardQrReader,
|
||||||
PageSetupWizardApiServicesList,
|
PageSetupWizardApiServicesList,
|
||||||
PageSetupWizardApiServiceInfo,
|
PageSetupWizardApiFreeInfo,
|
||||||
|
|
||||||
PageProtocolOpenVpnSettings,
|
PageProtocolOpenVpnSettings,
|
||||||
PageProtocolShadowSocksSettings,
|
PageProtocolShadowSocksSettings,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "apiServicesModel.h"
|
#include "apiServicesModel.h"
|
||||||
|
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
#include <QHash>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
|
||||||
@@ -36,16 +37,30 @@ namespace
|
|||||||
|
|
||||||
constexpr char isAvailable[] = "is_available";
|
constexpr char isAvailable[] = "is_available";
|
||||||
|
|
||||||
constexpr char subscriptionPlans[] = "subscription_plans";
|
constexpr char supportInfo[] = "support_info";
|
||||||
|
|
||||||
constexpr char premiumBenefitCountriesTitle[] = "premium_benefit_countries_title";
|
constexpr char subscriptionPlans[] = "subscription_plans";
|
||||||
constexpr char premiumBenefitCountriesBody[] = "premium_benefit_countries_body";
|
constexpr char benefits[] = "benefits";
|
||||||
constexpr char premiumBenefitDevicesTitle[] = "premium_benefit_devices_title";
|
}
|
||||||
constexpr char premiumBenefitDevicesBody[] = "premium_benefit_devices_body";
|
|
||||||
constexpr char premiumBenefitVideoTitle[] = "premium_benefit_video_title";
|
QString iconUrlFromGatewayBenefitIcon(const QString &iconKey)
|
||||||
constexpr char premiumBenefitVideoBody[] = "premium_benefit_video_body";
|
{
|
||||||
constexpr char premiumBenefitTrafficTitle[] = "premium_benefit_traffic_title";
|
if (iconKey.startsWith(QLatin1String("qrc:"))) {
|
||||||
constexpr char premiumBenefitTrafficBody[] = "premium_benefit_traffic_body";
|
return iconKey;
|
||||||
|
}
|
||||||
|
static const QHash<QString, QString> 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)
|
QVariantList jsonObjectArrayToVariantList(const QJsonArray &arr)
|
||||||
@@ -161,8 +176,8 @@ QVariant ApiServicesModel::data(const QModelIndex &index, int role) const
|
|||||||
case SubscriptionPlansRole: {
|
case SubscriptionPlansRole: {
|
||||||
return apiServiceData.subscriptionPlans;
|
return apiServiceData.subscriptionPlans;
|
||||||
}
|
}
|
||||||
case PremiumBenefitPanelRowsRole: {
|
case BenefitPanelRowsRole: {
|
||||||
return ApiServicesModel::buildPremiumBenefitPanelRows(apiServiceData);
|
return buildBenefitPanelRows(apiServiceData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,7 +306,7 @@ QHash<int, QByteArray> ApiServicesModel::roleNames() const
|
|||||||
roles[EndDateRole] = "endDate";
|
roles[EndDateRole] = "endDate";
|
||||||
roles[OrderRole] = "order";
|
roles[OrderRole] = "order";
|
||||||
roles[SubscriptionPlansRole] = "subscriptionPlans";
|
roles[SubscriptionPlansRole] = "subscriptionPlans";
|
||||||
roles[PremiumBenefitPanelRowsRole] = "premiumBenefitRows";
|
roles[BenefitPanelRowsRole] = "benefitRows";
|
||||||
|
|
||||||
return roles;
|
return roles;
|
||||||
}
|
}
|
||||||
@@ -318,15 +333,9 @@ ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJs
|
|||||||
serviceData.serviceInfo.features = serviceDescription.value(configKey::features).toString();
|
serviceData.serviceInfo.features = serviceDescription.value(configKey::features).toString();
|
||||||
|
|
||||||
serviceData.subscriptionPlans = jsonObjectArrayToVariantList(serviceDescription.value(configKey::subscriptionPlans).toArray());
|
serviceData.subscriptionPlans = jsonObjectArrayToVariantList(serviceDescription.value(configKey::subscriptionPlans).toArray());
|
||||||
|
serviceData.benefitsConfig = serviceDescription.value(configKey::benefits).toArray();
|
||||||
|
|
||||||
serviceData.premiumBenefitCountriesTitle = serviceDescription.value(configKey::premiumBenefitCountriesTitle).toString();
|
serviceData.supportInfo = data.value(configKey::supportInfo).toObject();
|
||||||
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.type = serviceType;
|
serviceData.type = serviceType;
|
||||||
serviceData.protocol = serviceProtocol;
|
serviceData.protocol = serviceProtocol;
|
||||||
@@ -347,29 +356,74 @@ ApiServicesModel::ApiServicesData ApiServicesModel::getApiServicesData(const QJs
|
|||||||
return serviceData;
|
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"),
|
if (rawPrice == QStringLiteral("free")) {
|
||||||
QStringLiteral("qrc:/images/controls/smartphone.svg"),
|
return tr("Free");
|
||||||
QStringLiteral("qrc:/images/controls/gauge.svg"),
|
}
|
||||||
QStringLiteral("qrc:/images/controls/infinity.svg") };
|
#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;
|
QVariantList out;
|
||||||
|
for (const QJsonValue &v : service.benefitsConfig) {
|
||||||
const auto appendRow = [&out, &icons](int iconIndex, const QString &title, const QString &body) {
|
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()) {
|
if (title.isEmpty() && body.isEmpty()) {
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
QVariantMap m;
|
QVariantMap m;
|
||||||
m.insert(QStringLiteral("icon"), icons.at(iconIndex));
|
m.insert(QStringLiteral("icon"), iconUrlFromGatewayBenefitIcon(iconKey));
|
||||||
m.insert(QStringLiteral("title"), title);
|
m.insert(QStringLiteral("title"), title);
|
||||||
m.insert(QStringLiteral("body"), body);
|
m.insert(QStringLiteral("body"), body);
|
||||||
|
if (o.value(QStringLiteral("body_accent")).toBool()) {
|
||||||
|
m.insert(QStringLiteral("body_accent"), true);
|
||||||
|
}
|
||||||
out.append(m);
|
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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public:
|
|||||||
EndDateRole,
|
EndDateRole,
|
||||||
OrderRole,
|
OrderRole,
|
||||||
SubscriptionPlansRole,
|
SubscriptionPlansRole,
|
||||||
PremiumBenefitPanelRowsRole
|
BenefitPanelRowsRole
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ApiServicesModel(QObject *parent = nullptr);
|
explicit ApiServicesModel(QObject *parent = nullptr);
|
||||||
@@ -86,24 +86,21 @@ private:
|
|||||||
QString storeEndpoint;
|
QString storeEndpoint;
|
||||||
|
|
||||||
ServiceInfo serviceInfo;
|
ServiceInfo serviceInfo;
|
||||||
|
QJsonObject supportInfo;
|
||||||
Subscription subscription;
|
Subscription subscription;
|
||||||
|
|
||||||
QJsonArray availableCountries;
|
QJsonArray availableCountries;
|
||||||
|
|
||||||
QVariantList subscriptionPlans;
|
QVariantList subscriptionPlans;
|
||||||
QString premiumBenefitCountriesTitle;
|
QJsonArray benefitsConfig;
|
||||||
QString premiumBenefitCountriesBody;
|
|
||||||
QString premiumBenefitDevicesTitle;
|
|
||||||
QString premiumBenefitDevicesBody;
|
|
||||||
QString premiumBenefitVideoTitle;
|
|
||||||
QString premiumBenefitVideoBody;
|
|
||||||
QString premiumBenefitTrafficTitle;
|
|
||||||
QString premiumBenefitTrafficBody;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ApiServicesData getApiServicesData(const QJsonObject &data);
|
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;
|
QString m_countryCode;
|
||||||
QVector<ApiServicesData> m_services;
|
QVector<ApiServicesData> m_services;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ RowLayout {
|
|||||||
property string iconSource: ""
|
property string iconSource: ""
|
||||||
property string titleText: ""
|
property string titleText: ""
|
||||||
property string bodyText: ""
|
property string bodyText: ""
|
||||||
|
property bool bodyAccent: false
|
||||||
|
|
||||||
spacing: 12
|
spacing: 12
|
||||||
|
|
||||||
@@ -35,12 +36,30 @@ RowLayout {
|
|||||||
wrapMode: Text.Wrap
|
wrapMode: Text.Wrap
|
||||||
}
|
}
|
||||||
|
|
||||||
LabelTextType {
|
Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
text: root.bodyText
|
implicitHeight: bodyLabel.implicitHeight
|
||||||
color: AmneziaStyle.color.mutedGray
|
|
||||||
font.pixelSize: 14
|
LabelTextType {
|
||||||
wrapMode: Text.Wrap
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ Rectangle {
|
|||||||
|
|
||||||
property var benefitItems: []
|
property var benefitItems: []
|
||||||
|
|
||||||
|
visible: benefitItems && benefitItems.length > 0
|
||||||
|
|
||||||
radius: 16
|
radius: 16
|
||||||
color: "#1C1C1E"
|
color: "#1C1C1E"
|
||||||
implicitHeight: inner.implicitHeight + 24
|
implicitHeight: inner.implicitHeight + 24
|
||||||
@@ -31,6 +33,7 @@ Rectangle {
|
|||||||
iconSource: root.benefitItems[index].icon
|
iconSource: root.benefitItems[index].icon
|
||||||
titleText: root.benefitItems[index].title
|
titleText: root.benefitItems[index].title
|
||||||
bodyText: root.benefitItems[index].body
|
bodyText: root.benefitItems[index].body
|
||||||
|
bodyAccent: !!root.benefitItems[index].body_accent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
213
client/ui/qml/Pages2/PageSetupWizardApiFreeInfo.qml
Normal file
213
client/ui/qml/Pages2/PageSetupWizardApiFreeInfo.qml
Normal file
@@ -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 <a href=\"%1\" style=\"color: #FBB26A;\">Terms of Use</a> and <a href=\"%2\" style=\"color: #FBB26A;\">Privacy Policy</a>").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 <a href=\"%1\" style=\"color: #FBB26A;\">Terms of Use</a> and <a href=\"%2\" style=\"color: #FBB26A;\">Privacy Policy</a>").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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,7 +26,7 @@ PageType {
|
|||||||
|
|
||||||
function syncFromModel() {
|
function syncFromModel() {
|
||||||
root.subscriptionPlans = ApiServicesModel.getSelectedServiceData("subscriptionPlans")
|
root.subscriptionPlans = ApiServicesModel.getSelectedServiceData("subscriptionPlans")
|
||||||
root.benefitRows = ApiServicesModel.getSelectedServiceData("premiumBenefitRows")
|
root.benefitRows = ApiServicesModel.getSelectedServiceData("benefitRows")
|
||||||
|
|
||||||
root.selectedGatewayPlanIndex = 0
|
root.selectedGatewayPlanIndex = 0
|
||||||
for (var i = 0; i < root.subscriptionPlans.length; ++i) {
|
for (var i = 0; i < root.subscriptionPlans.length; ++i) {
|
||||||
|
|||||||
@@ -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<QtObject> 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -92,7 +92,7 @@ PageType {
|
|||||||
if (ApiServicesModel.getSelectedServiceType() === "amnezia-premium") {
|
if (ApiServicesModel.getSelectedServiceType() === "amnezia-premium") {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardApiPremiumInfo)
|
PageController.goToPage(PageEnum.PageSetupWizardApiPremiumInfo)
|
||||||
} else {
|
} else {
|
||||||
PageController.goToPage(PageEnum.PageSetupWizardApiServiceInfo)
|
PageController.goToPage(PageEnum.PageSetupWizardApiFreeInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user