feature: added share vpn key to subscription settings page
This commit is contained in:
parent
07baf0ed65
commit
db3164223a
12 changed files with 147 additions and 52 deletions
|
@ -59,6 +59,7 @@ endif()
|
||||||
qt_standard_project_setup()
|
qt_standard_project_setup()
|
||||||
qt_add_executable(${PROJECT} MANUAL_FINALIZATION
|
qt_add_executable(${PROJECT} MANUAL_FINALIZATION
|
||||||
core/api/apiDefs.h
|
core/api/apiDefs.h
|
||||||
|
core/qrCodeUtils.h core/qrCodeUtils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
if(WIN32 OR (APPLE AND NOT IOS) OR (LINUX AND NOT ANDROID))
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace apiDefs
|
||||||
|
|
||||||
constexpr QLatin1String apiConfig("api_config");
|
constexpr QLatin1String apiConfig("api_config");
|
||||||
constexpr QLatin1String stackType("stack_type");
|
constexpr QLatin1String stackType("stack_type");
|
||||||
|
|
||||||
|
constexpr QLatin1String vpnKey("vpn_key");
|
||||||
}
|
}
|
||||||
|
|
||||||
const int requestTimeoutMsecs = 12 * 1000; // 12 secs
|
const int requestTimeoutMsecs = 12 * 1000; // 12 secs
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
|
|
||||||
namespace amnezia
|
namespace amnezia
|
||||||
{
|
{
|
||||||
|
|
||||||
constexpr const qint16 qrMagicCode = 1984;
|
|
||||||
|
|
||||||
struct ServerCredentials
|
struct ServerCredentials
|
||||||
{
|
{
|
||||||
QString hostName;
|
QString hostName;
|
||||||
|
|
35
client/core/qrCodeUtils.cpp
Normal file
35
client/core/qrCodeUtils.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
#include "qrCodeUtils.h"
|
||||||
|
|
||||||
|
#include <QIODevice>
|
||||||
|
#include <QList>
|
||||||
|
|
||||||
|
QList<QString> qrCodeUtuls::generateQrCodeImageSeries(const QByteArray &data)
|
||||||
|
{
|
||||||
|
double k = 850;
|
||||||
|
|
||||||
|
quint8 chunksCount = std::ceil(data.size() / k);
|
||||||
|
QList<QString> chunks;
|
||||||
|
for (int i = 0; i < data.size(); i = i + k) {
|
||||||
|
QByteArray chunk;
|
||||||
|
QDataStream s(&chunk, QIODevice::WriteOnly);
|
||||||
|
s << qrCodeUtuls::qrMagicCode << chunksCount << (quint8)std::round(i / k) << data.mid(i, k);
|
||||||
|
|
||||||
|
QByteArray ba = chunk.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||||
|
|
||||||
|
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(ba, qrcodegen::QrCode::Ecc::LOW);
|
||||||
|
QString svg = QString::fromStdString(toSvgString(qr, 1));
|
||||||
|
chunks.append(svgToBase64(svg));
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString qrCodeUtuls::svgToBase64(const QString &image)
|
||||||
|
{
|
||||||
|
return "data:image/svg;base64," + QString::fromLatin1(image.toUtf8().toBase64().data());
|
||||||
|
}
|
||||||
|
|
||||||
|
qrcodegen::QrCode qrCodeUtuls::generateQrCode(const QByteArray &data)
|
||||||
|
{
|
||||||
|
return qrcodegen::QrCode::encodeText(data, qrcodegen::QrCode::Ecc::LOW);
|
||||||
|
}
|
17
client/core/qrCodeUtils.h
Normal file
17
client/core/qrCodeUtils.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef QRCODEUTILS_H
|
||||||
|
#define QRCODEUTILS_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "qrcodegen.hpp"
|
||||||
|
|
||||||
|
namespace qrCodeUtuls
|
||||||
|
{
|
||||||
|
constexpr const qint16 qrMagicCode = 1984;
|
||||||
|
|
||||||
|
QList<QString> generateQrCodeImageSeries(const QByteArray &data);
|
||||||
|
qrcodegen::QrCode generateQrCode(const QByteArray &data);
|
||||||
|
QString svgToBase64(const QString &image);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QRCODEUTILS_H
|
|
@ -1,10 +1,11 @@
|
||||||
#include "ApiConfigsController.h"
|
#include "apiConfigsController.h"
|
||||||
|
|
||||||
#include "configurators/wireguard_configurator.h"
|
#include "configurators/wireguard_configurator.h"
|
||||||
#include "core/api/apiDefs.h"
|
#include "core/api/apiDefs.h"
|
||||||
#include "core/controllers/gatewayController.h"
|
#include "core/controllers/gatewayController.h"
|
||||||
#include "version.h"
|
#include "core/qrCodeUtils.h"
|
||||||
#include "ui/controllers/systemController.h"
|
#include "ui/controllers/systemController.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
@ -84,6 +85,19 @@ bool ApiConfigsController::exportNativeConfig(const QString &serverCountryCode,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApiConfigsController::prepareVpnKeyExport()
|
||||||
|
{
|
||||||
|
auto serverConfigObject = m_serversModel->getServerConfig(m_serversModel->getProcessedServerIndex());
|
||||||
|
auto apiConfigObject = serverConfigObject.value(configKey::apiConfig).toObject();
|
||||||
|
|
||||||
|
auto vpnKey = apiConfigObject.value(apiDefs::key::vpnKey).toString();
|
||||||
|
|
||||||
|
auto qr = qrCodeUtuls::generateQrCode(vpnKey.toUtf8());
|
||||||
|
m_qrCodes << qrCodeUtuls::svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
||||||
|
|
||||||
|
emit vpnKeyExportReady();
|
||||||
|
}
|
||||||
|
|
||||||
ApiConfigsController::ApiPayloadData ApiConfigsController::generateApiPayloadData(const QString &protocol)
|
ApiConfigsController::ApiPayloadData ApiConfigsController::generateApiPayloadData(const QString &protocol)
|
||||||
{
|
{
|
||||||
ApiConfigsController::ApiPayloadData apiPayload;
|
ApiConfigsController::ApiPayloadData apiPayload;
|
||||||
|
@ -111,3 +125,13 @@ QJsonObject ApiConfigsController::fillApiPayload(const QString &protocol, const
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QString> ApiConfigsController::getQrCodes()
|
||||||
|
{
|
||||||
|
return m_qrCodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ApiConfigsController::getQrCodesCount()
|
||||||
|
{
|
||||||
|
return m_qrCodes.size();
|
||||||
|
}
|
||||||
|
|
|
@ -13,11 +13,17 @@ public:
|
||||||
ApiConfigsController(const QSharedPointer<ServersModel> &serversModel, const std::shared_ptr<Settings> &settings,
|
ApiConfigsController(const QSharedPointer<ServersModel> &serversModel, const std::shared_ptr<Settings> &settings,
|
||||||
QObject *parent = nullptr);
|
QObject *parent = nullptr);
|
||||||
|
|
||||||
|
Q_PROPERTY(QList<QString> qrCodes READ getQrCodes NOTIFY vpnKeyExportReady)
|
||||||
|
Q_PROPERTY(int qrCodesCount READ getQrCodesCount NOTIFY vpnKeyExportReady)
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool exportNativeConfig(const QString &serverCountryCode, const QString &fileName);
|
bool exportNativeConfig(const QString &serverCountryCode, const QString &fileName);
|
||||||
|
// bool exportVpnKey(const QString &fileName);
|
||||||
|
void prepareVpnKeyExport();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void errorOccurred(ErrorCode errorCode);
|
void errorOccurred(ErrorCode errorCode);
|
||||||
|
void vpnKeyExportReady();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ApiPayloadData
|
struct ApiPayloadData
|
||||||
|
@ -31,6 +37,11 @@ private:
|
||||||
ApiPayloadData generateApiPayloadData(const QString &protocol);
|
ApiPayloadData generateApiPayloadData(const QString &protocol);
|
||||||
QJsonObject fillApiPayload(const QString &protocol, const ApiPayloadData &apiPayloadData);
|
QJsonObject fillApiPayload(const QString &protocol, const ApiPayloadData &apiPayloadData);
|
||||||
|
|
||||||
|
QList<QString> getQrCodes();
|
||||||
|
int getQrCodesCount();
|
||||||
|
|
||||||
|
QList<QString> m_qrCodes;
|
||||||
|
|
||||||
QSharedPointer<ServersModel> m_serversModel;
|
QSharedPointer<ServersModel> m_serversModel;
|
||||||
std::shared_ptr<Settings> m_settings;
|
std::shared_ptr<Settings> m_settings;
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
#include "core/controllers/vpnConfigurationController.h"
|
#include "core/controllers/vpnConfigurationController.h"
|
||||||
|
#include "core/qrCodeUtils.h"
|
||||||
#include "systemController.h"
|
#include "systemController.h"
|
||||||
#include "qrcodegen.hpp"
|
|
||||||
|
|
||||||
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
|
ExportController::ExportController(const QSharedPointer<ServersModel> &serversModel, const QSharedPointer<ContainersModel> &containersModel,
|
||||||
const QSharedPointer<ClientManagementModel> &clientManagementModel,
|
const QSharedPointer<ClientManagementModel> &clientManagementModel,
|
||||||
|
@ -50,7 +50,7 @@ void ExportController::generateFullAccessConfig()
|
||||||
compressedConfig = qCompress(compressedConfig, 8);
|
compressedConfig = qCompress(compressedConfig, 8);
|
||||||
m_config = QString("vpn://%1").arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)));
|
m_config = QString("vpn://%1").arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)));
|
||||||
|
|
||||||
m_qrCodes = generateQrCodeImageSeries(compressedConfig);
|
m_qrCodes = qrCodeUtuls::generateQrCodeImageSeries(compressedConfig);
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@ void ExportController::generateConnectionConfig(const QString &clientName)
|
||||||
compressedConfig = qCompress(compressedConfig, 8);
|
compressedConfig = qCompress(compressedConfig, 8);
|
||||||
m_config = QString("vpn://%1").arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)));
|
m_config = QString("vpn://%1").arg(QString(compressedConfig.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)));
|
||||||
|
|
||||||
m_qrCodes = generateQrCodeImageSeries(compressedConfig);
|
m_qrCodes = qrCodeUtuls::generateQrCodeImageSeries(compressedConfig);
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ void ExportController::generateOpenVpnConfig(const QString &clientName)
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
m_qrCodes = generateQrCodeImageSeries(m_config.toUtf8());
|
m_qrCodes = qrCodeUtuls::generateQrCodeImageSeries(m_config.toUtf8());
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,8 +167,8 @@ void ExportController::generateWireGuardConfig(const QString &clientName)
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(m_config.toUtf8(), qrcodegen::QrCode::Ecc::LOW);
|
auto qr = qrCodeUtuls::generateQrCode(m_config.toUtf8());
|
||||||
m_qrCodes << svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
m_qrCodes << qrCodeUtuls::svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
||||||
|
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
@ -187,8 +187,8 @@ void ExportController::generateAwgConfig(const QString &clientName)
|
||||||
m_config.append(line + "\n");
|
m_config.append(line + "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(m_config.toUtf8(), qrcodegen::QrCode::Ecc::LOW);
|
auto qr = qrCodeUtuls::generateQrCode(m_config.toUtf8());
|
||||||
m_qrCodes << svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
m_qrCodes << qrCodeUtuls::svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
||||||
|
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
@ -221,8 +221,8 @@ void ExportController::generateShadowSocksConfig()
|
||||||
|
|
||||||
m_nativeConfigString = "ss://" + m_nativeConfigString.toUtf8().toBase64();
|
m_nativeConfigString = "ss://" + m_nativeConfigString.toUtf8().toBase64();
|
||||||
|
|
||||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(m_nativeConfigString.toUtf8(), qrcodegen::QrCode::Ecc::LOW);
|
auto qr = qrCodeUtuls::generateQrCode(m_nativeConfigString.toUtf8());
|
||||||
m_qrCodes << svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
m_qrCodes << qrCodeUtuls::svgToBase64(QString::fromStdString(toSvgString(qr, 1)));
|
||||||
|
|
||||||
emit exportConfigChanged();
|
emit exportConfigChanged();
|
||||||
}
|
}
|
||||||
|
@ -312,32 +312,6 @@ void ExportController::renameClient(const int row, const QString &clientName, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QString> ExportController::generateQrCodeImageSeries(const QByteArray &data)
|
|
||||||
{
|
|
||||||
double k = 850;
|
|
||||||
|
|
||||||
quint8 chunksCount = std::ceil(data.size() / k);
|
|
||||||
QList<QString> chunks;
|
|
||||||
for (int i = 0; i < data.size(); i = i + k) {
|
|
||||||
QByteArray chunk;
|
|
||||||
QDataStream s(&chunk, QIODevice::WriteOnly);
|
|
||||||
s << amnezia::qrMagicCode << chunksCount << (quint8)std::round(i / k) << data.mid(i, k);
|
|
||||||
|
|
||||||
QByteArray ba = chunk.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
|
||||||
|
|
||||||
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(ba, qrcodegen::QrCode::Ecc::LOW);
|
|
||||||
QString svg = QString::fromStdString(toSvgString(qr, 1));
|
|
||||||
chunks.append(svgToBase64(svg));
|
|
||||||
}
|
|
||||||
|
|
||||||
return chunks;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString ExportController::svgToBase64(const QString &image)
|
|
||||||
{
|
|
||||||
return "data:image/svg;base64," + QString::fromLatin1(image.toUtf8().toBase64().data());
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExportController::getQrCodesCount()
|
int ExportController::getQrCodesCount()
|
||||||
{
|
{
|
||||||
return m_qrCodes.size();
|
return m_qrCodes.size();
|
||||||
|
|
|
@ -50,9 +50,6 @@ signals:
|
||||||
void saveFile(const QString &fileName, const QString &data);
|
void saveFile(const QString &fileName, const QString &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QList<QString> generateQrCodeImageSeries(const QByteArray &data);
|
|
||||||
QString svgToBase64(const QString &image);
|
|
||||||
|
|
||||||
int getQrCodesCount();
|
int getQrCodesCount();
|
||||||
|
|
||||||
void clearPreviousConfig();
|
void clearPreviousConfig();
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
#include "core/api/apiDefs.h"
|
||||||
|
#include "core/api/apiUtils.h"
|
||||||
#include "core/errorstrings.h"
|
#include "core/errorstrings.h"
|
||||||
#include "core/serialization/serialization.h"
|
#include "core/serialization/serialization.h"
|
||||||
#include "systemController.h"
|
#include "systemController.h"
|
||||||
|
@ -45,7 +47,8 @@ namespace
|
||||||
|
|
||||||
if (config.contains(backupPattern)) {
|
if (config.contains(backupPattern)) {
|
||||||
return ConfigTypes::Backup;
|
return ConfigTypes::Backup;
|
||||||
} else if (config.contains(amneziaConfigPattern) || config.contains(amneziaFreeConfigPattern) || config.contains(amneziaPremiumConfigPattern)
|
} else if (config.contains(amneziaConfigPattern) || config.contains(amneziaFreeConfigPattern)
|
||||||
|
|| config.contains(amneziaPremiumConfigPattern)
|
||||||
|| (config.contains(amneziaConfigPatternHostName) && config.contains(amneziaConfigPatternUserName)
|
|| (config.contains(amneziaConfigPatternHostName) && config.contains(amneziaConfigPatternUserName)
|
||||||
&& config.contains(amneziaConfigPatternPassword))) {
|
&& config.contains(amneziaConfigPatternPassword))) {
|
||||||
return ConfigTypes::Amnezia;
|
return ConfigTypes::Amnezia;
|
||||||
|
@ -149,8 +152,8 @@ bool ImportController::extractConfigFromData(QString data)
|
||||||
|
|
||||||
m_configType = checkConfigFormat(config);
|
m_configType = checkConfigFormat(config);
|
||||||
if (m_configType == ConfigTypes::Invalid) {
|
if (m_configType == ConfigTypes::Invalid) {
|
||||||
data.replace("vpn://", "");
|
config.replace("vpn://", "");
|
||||||
QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
QByteArray ba = QByteArray::fromBase64(config.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||||
QByteArray ba_uncompressed = qUncompress(ba);
|
QByteArray ba_uncompressed = qUncompress(ba);
|
||||||
if (!ba_uncompressed.isEmpty()) {
|
if (!ba_uncompressed.isEmpty()) {
|
||||||
ba = ba_uncompressed;
|
ba = ba_uncompressed;
|
||||||
|
@ -180,6 +183,13 @@ bool ImportController::extractConfigFromData(QString data)
|
||||||
}
|
}
|
||||||
case ConfigTypes::Amnezia: {
|
case ConfigTypes::Amnezia: {
|
||||||
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
|
m_config = QJsonDocument::fromJson(config.toUtf8()).object();
|
||||||
|
|
||||||
|
if (apiUtils::isServerFromApi(m_config)) {
|
||||||
|
auto apiConfig = m_config.value(apiDefs::key::apiConfig).toObject();
|
||||||
|
apiConfig[apiDefs::key::vpnKey] = data;
|
||||||
|
m_config[apiDefs::key::apiConfig] = apiConfig;
|
||||||
|
}
|
||||||
|
|
||||||
processAmneziaConfig(m_config);
|
processAmneziaConfig(m_config);
|
||||||
if (!m_config.empty()) {
|
if (!m_config.empty()) {
|
||||||
checkForMaliciousStrings(m_config);
|
checkForMaliciousStrings(m_config);
|
||||||
|
@ -680,7 +690,8 @@ void ImportController::processAmneziaConfig(QJsonObject &config)
|
||||||
}
|
}
|
||||||
|
|
||||||
QJsonObject jsonConfig = QJsonDocument::fromJson(protocolConfig.toUtf8()).object();
|
QJsonObject jsonConfig = QJsonDocument::fromJson(protocolConfig.toUtf8()).object();
|
||||||
jsonConfig[config_key::mtu] = dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
jsonConfig[config_key::mtu] =
|
||||||
|
dockerContainer == DockerContainer::Awg ? protocols::awg::defaultMtu : protocols::wireguard::defaultMtu;
|
||||||
|
|
||||||
containerConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
containerConfig[config_key::last_config] = QString(QJsonDocument(jsonConfig).toJson());
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,11 @@ DrawerType2 {
|
||||||
|
|
||||||
property string headerText
|
property string headerText
|
||||||
property string configContentHeaderText
|
property string configContentHeaderText
|
||||||
property string contentVisible
|
property string shareButtonText: qsTr("Share")
|
||||||
|
property string copyButtonText: qsTr("Copy")
|
||||||
|
property bool showSettingsButtonVisible: true
|
||||||
|
|
||||||
|
property bool contentVisible
|
||||||
|
|
||||||
property string configExtension: ".vpn"
|
property string configExtension: ".vpn"
|
||||||
property string configCaption: qsTr("Save AmneziaVPN config")
|
property string configCaption: qsTr("Save AmneziaVPN config")
|
||||||
|
@ -80,7 +84,7 @@ DrawerType2 {
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
text: qsTr("Share")
|
text: root.shareButtonText
|
||||||
leftImageSource: "qrc:/images/controls/share-2.svg"
|
leftImageSource: "qrc:/images/controls/share-2.svg"
|
||||||
|
|
||||||
clickedFunc: function() {
|
clickedFunc: function() {
|
||||||
|
@ -116,7 +120,7 @@ DrawerType2 {
|
||||||
textColor: AmneziaStyle.color.paleGray
|
textColor: AmneziaStyle.color.paleGray
|
||||||
borderWidth: 1
|
borderWidth: 1
|
||||||
|
|
||||||
text: qsTr("Copy")
|
text: root.copyButtonText
|
||||||
leftImageSource: "qrc:/images/controls/copy.svg"
|
leftImageSource: "qrc:/images/controls/copy.svg"
|
||||||
|
|
||||||
Keys.onReturnPressed: { copyConfigTextButton.clicked() }
|
Keys.onReturnPressed: { copyConfigTextButton.clicked() }
|
||||||
|
@ -153,6 +157,8 @@ DrawerType2 {
|
||||||
Layout.leftMargin: 16
|
Layout.leftMargin: 16
|
||||||
Layout.rightMargin: 16
|
Layout.rightMargin: 16
|
||||||
|
|
||||||
|
visible: root.showSettingsButtonVisible
|
||||||
|
|
||||||
defaultColor: AmneziaStyle.color.transparent
|
defaultColor: AmneziaStyle.color.transparent
|
||||||
hoveredColor: AmneziaStyle.color.translucentWhite
|
hoveredColor: AmneziaStyle.color.translucentWhite
|
||||||
pressedColor: AmneziaStyle.color.sheerWhite
|
pressedColor: AmneziaStyle.color.sheerWhite
|
||||||
|
|
|
@ -160,6 +160,20 @@ PageType {
|
||||||
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
rightImageSource: "qrc:/images/controls/chevron-right.svg"
|
||||||
|
|
||||||
clickedFunction: function() {
|
clickedFunction: function() {
|
||||||
|
shareConnectionDrawer.headerText = qsTr("Amnezia Premium subscription key")
|
||||||
|
|
||||||
|
shareConnectionDrawer.openTriggered()
|
||||||
|
shareConnectionDrawer.contentVisible = false
|
||||||
|
shareConnectionDrawer.showSettingsButtonVisible = false;
|
||||||
|
shareConnectionDrawer.shareButtonText = qsTr("Save VPN key to file")
|
||||||
|
shareConnectionDrawer.copyButtonText = qsTr("Copy VPN key")
|
||||||
|
|
||||||
|
|
||||||
|
PageController.showBusyIndicator(true)
|
||||||
|
|
||||||
|
ApiConfigsController.prepareVpnKeyExport()
|
||||||
|
|
||||||
|
PageController.showBusyIndicator(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,4 +306,10 @@ PageType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShareConnectionDrawer {
|
||||||
|
id: shareConnectionDrawer
|
||||||
|
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue