added PageSetupWizardViewConfig
- added a popup with a question when deleting containers/servers - added import from code and import error handling
This commit is contained in:
parent
de0cd976de
commit
420c33d3ba
37 changed files with 701 additions and 312 deletions
|
@ -68,7 +68,10 @@ enum ErrorCode
|
|||
OpenSslFailed,
|
||||
OpenVpnExecutableCrashed,
|
||||
ShadowSocksExecutableCrashed,
|
||||
CloakExecutableCrashed
|
||||
CloakExecutableCrashed,
|
||||
|
||||
// import and install errors
|
||||
ImportInvalidConfigError
|
||||
};
|
||||
|
||||
} // namespace amnezia
|
||||
|
|
|
@ -57,6 +57,8 @@ QString errorString(ErrorCode code){
|
|||
case (OpenVpnTapAdapterError): return QObject::tr("Can't setup OpenVPN TAP network adapter");
|
||||
case (AddressPoolError): return QObject::tr("VPN pool error: no available addresses");
|
||||
|
||||
case (ImportInvalidConfigError): return QObject::tr("The config does not contain any containers and credentiaks for connecting to the server");
|
||||
|
||||
case(InternalError):
|
||||
default:
|
||||
return QObject::tr("Internal error");
|
||||
|
|
11
client/images/controls/file-cog-2.svg
Normal file
11
client/images/controls/file-cog-2.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M14.5 2H6C5.46957 2 4.96086 2.21071 4.58579 2.58579C4.21071 2.96086 4 3.46957 4 4V20C4 20.5304 4.21071 21.0391 4.58579 21.4142C4.96086 21.7893 5.46957 22 6 22H18C18.5304 22 19.0391 21.7893 19.4142 21.4142C19.7893 21.0391 20 20.5304 20 20V7.5L14.5 2Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14 2V8H20" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12 17C13.1046 17 14 16.1046 14 15C14 13.8954 13.1046 13 12 13C10.8954 13 10 13.8954 10 15C10 16.1046 10.8954 17 12 17Z" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12 12V13" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M12 17V18" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.6 13.5L13.73 14" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10.27 16L9.40002 16.5" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.6 16.5L13.73 16" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10.27 14L9.40002 13.5" stroke="#CBCBCB" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
|
@ -249,5 +249,10 @@
|
|||
<file>images/controls/server.svg</file>
|
||||
<file>ui/qml/Pages2/PageSettingsServerProtocols.qml</file>
|
||||
<file>ui/qml/Pages2/PageSettingsServerServices.qml</file>
|
||||
<file>ui/qml/Pages2/PageSetupWizardViewConfig.qml</file>
|
||||
<file>images/controls/file-cog-2.svg</file>
|
||||
<file>ui/qml/Components/QuestionDrawer.qml</file>
|
||||
<file>ui/qml/Pages2/PageDeinstalling.qml</file>
|
||||
<file>ui/qml/Controls2/BackButtonType.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
|
@ -9,21 +9,7 @@ ConnectionController::ConnectionController(const QSharedPointer<ServersModel> &s
|
|||
|
||||
}
|
||||
|
||||
bool ConnectionController::onConnectionButtonClicked()
|
||||
{
|
||||
if (!isConnected()) {
|
||||
openVpnConnection();
|
||||
} else {
|
||||
closeVpnConnection();
|
||||
}
|
||||
}
|
||||
|
||||
bool ConnectionController::isConnected()
|
||||
{
|
||||
return m_isConnected;
|
||||
}
|
||||
|
||||
bool ConnectionController::openVpnConnection()
|
||||
void ConnectionController::openConnection()
|
||||
{
|
||||
int serverIndex = m_serversModel->getDefaultServerIndex();
|
||||
QModelIndex serverModelIndex = m_serversModel->index(serverIndex);
|
||||
|
@ -35,16 +21,6 @@ bool ConnectionController::openVpnConnection()
|
|||
const QJsonObject &containerConfig = qvariant_cast<QJsonObject>(m_containersModel->data(containerModelIndex,
|
||||
ContainersModel::Roles::ConfigRole));
|
||||
|
||||
//todo error handling
|
||||
qApp->processEvents();
|
||||
emit connectToVpn(serverIndex, credentials, container, containerConfig);
|
||||
m_isConnected = true;
|
||||
|
||||
|
||||
// int serverIndex = m_settings->defaultServerIndex();
|
||||
// ServerCredentials credentials = m_settings->serverCredentials(serverIndex);
|
||||
// DockerContainer container = m_settings->defaultContainer(serverIndex);
|
||||
|
||||
// if (m_settings->containers(serverIndex).isEmpty()) {
|
||||
// set_labelErrorText(tr("VPN Protocols is not installed.\n Please install VPN container at first"));
|
||||
// set_pushButtonConnectChecked(false);
|
||||
|
@ -57,20 +33,23 @@ bool ConnectionController::openVpnConnection()
|
|||
// return;
|
||||
// }
|
||||
|
||||
|
||||
// const QJsonObject &containerConfig = m_settings->containerConfig(serverIndex, container);
|
||||
|
||||
// set_labelErrorText("");
|
||||
// set_pushButtonConnectChecked(true);
|
||||
// set_pushButtonConnectEnabled(false);
|
||||
|
||||
// qApp->processEvents();
|
||||
|
||||
// emit connectToVpn(serverIndex, credentials, container, containerConfig);
|
||||
//todo error handling
|
||||
qApp->processEvents();
|
||||
emit connectToVpn(serverIndex, credentials, container, containerConfig);
|
||||
}
|
||||
|
||||
bool ConnectionController::closeVpnConnection()
|
||||
void ConnectionController::closeConnection()
|
||||
{
|
||||
emit disconnectFromVpn();
|
||||
m_isConnected = false;
|
||||
}
|
||||
|
||||
bool ConnectionController::isConnected()
|
||||
{
|
||||
return m_isConnected;
|
||||
}
|
||||
|
||||
void ConnectionController::setIsConnected(bool isConnected)
|
||||
{
|
||||
m_isConnected = isConnected;
|
||||
emit isConnectedChanged();
|
||||
}
|
||||
|
|
|
@ -10,24 +10,26 @@ class ConnectionController : public QObject
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Q_PROPERTY(bool isConnected READ isConnected WRITE setIsConnected NOTIFY isConnectedChanged)
|
||||
|
||||
explicit ConnectionController(const QSharedPointer<ServersModel> &serversModel,
|
||||
const QSharedPointer<ContainersModel> &containersModel,
|
||||
QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
bool onConnectionButtonClicked();
|
||||
|
||||
bool isConnected();
|
||||
void setIsConnected(bool isConnected);
|
||||
|
||||
public slots:
|
||||
void openConnection();
|
||||
void closeConnection();
|
||||
|
||||
signals:
|
||||
void connectToVpn(int serverIndex, const ServerCredentials &credentials, DockerContainer container, const QJsonObject &containerConfig);
|
||||
void disconnectFromVpn();
|
||||
void connectionStateChanged(Vpn::ConnectionState state);
|
||||
void isConnectedChanged();
|
||||
|
||||
private:
|
||||
bool openVpnConnection();
|
||||
bool closeVpnConnection();
|
||||
|
||||
QSharedPointer<ServersModel> m_serversModel;
|
||||
QSharedPointer<ContainersModel> m_containersModel;
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "importController.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "core/errorstrings.h"
|
||||
|
||||
namespace {
|
||||
enum class ConfigTypes {
|
||||
|
@ -39,50 +42,68 @@ ImportController::ImportController(const QSharedPointer<ServersModel> &serversMo
|
|||
|
||||
}
|
||||
|
||||
bool ImportController::importFromFile(const QUrl &fileUrl)
|
||||
void ImportController::extractConfigFromFile(const QUrl &fileUrl)
|
||||
{
|
||||
QFile file(fileUrl.toLocalFile());
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
QByteArray data = file.readAll();
|
||||
QString data = file.readAll();
|
||||
|
||||
auto configFormat = checkConfigFormat(data);
|
||||
if (configFormat == ConfigTypes::OpenVpn) {
|
||||
return importOpenVpnConfig(data);
|
||||
m_config = extractOpenVpnConfig(data);
|
||||
} else if (configFormat == ConfigTypes::WireGuard) {
|
||||
return importWireGuardConfig(data);
|
||||
m_config = extractWireGuardConfig(data);
|
||||
} else {
|
||||
return importAmneziaConfig(data);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
m_config = extractAmneziaConfig(data);
|
||||
}
|
||||
|
||||
bool ImportController::import(const QJsonObject &config)
|
||||
m_configFileName = QFileInfo(file.fileName()).fileName();
|
||||
}
|
||||
}
|
||||
|
||||
void ImportController::extractConfigFromCode(QString code)
|
||||
{
|
||||
m_config = extractAmneziaConfig(code);
|
||||
}
|
||||
|
||||
QString ImportController::getConfig()
|
||||
{
|
||||
return QJsonDocument(m_config).toJson(QJsonDocument::Indented);
|
||||
}
|
||||
|
||||
QString ImportController::getConfigFileName()
|
||||
{
|
||||
return m_configFileName;
|
||||
}
|
||||
|
||||
void ImportController::importConfig()
|
||||
{
|
||||
ServerCredentials credentials;
|
||||
credentials.hostName = config.value(config_key::hostName).toString();
|
||||
credentials.port = config.value(config_key::port).toInt();
|
||||
credentials.userName = config.value(config_key::userName).toString();
|
||||
credentials.secretData = config.value(config_key::password).toString();
|
||||
credentials.hostName = m_config.value(config_key::hostName).toString();
|
||||
credentials.port = m_config.value(config_key::port).toInt();
|
||||
credentials.userName = m_config.value(config_key::userName).toString();
|
||||
credentials.secretData = m_config.value(config_key::password).toString();
|
||||
|
||||
if (credentials.isValid() || config.contains(config_key::containers)) {
|
||||
m_settings->addServer(config);
|
||||
if (credentials.isValid() || m_config.contains(config_key::containers)) {
|
||||
m_serversModel->addServer(m_config);
|
||||
|
||||
if (config.value(config_key::containers).toArray().isEmpty()) {
|
||||
m_settings->setDefaultServer(m_settings->serversCount() - 1);
|
||||
if (!m_config.value(config_key::containers).toArray().isEmpty()) {
|
||||
auto newServerIndex = m_serversModel->index(m_serversModel->getServersCount() - 1);
|
||||
m_serversModel->setData(newServerIndex, true, ServersModel::ServersModelRoles::IsDefaultRole);
|
||||
}
|
||||
|
||||
emit importFinished();
|
||||
} else {
|
||||
qDebug() << "Failed to import profile";
|
||||
qDebug().noquote() << QJsonDocument(config).toJson();
|
||||
return false;
|
||||
qDebug().noquote() << QJsonDocument(m_config).toJson();
|
||||
emit importErrorOccurred(errorString(ErrorCode::ImportInvalidConfigError));
|
||||
}
|
||||
|
||||
return true;
|
||||
m_config = {};
|
||||
m_configFileName.clear();
|
||||
}
|
||||
|
||||
bool ImportController::importAmneziaConfig(QString data)
|
||||
QJsonObject ImportController::extractAmneziaConfig(QString &data)
|
||||
{
|
||||
data.replace("vpn://", "");
|
||||
QByteArray ba = QByteArray::fromBase64(data.toUtf8(), QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
|
||||
|
@ -92,13 +113,7 @@ bool ImportController::importAmneziaConfig(QString data)
|
|||
ba = ba_uncompressed;
|
||||
}
|
||||
|
||||
QJsonObject config;
|
||||
config = QJsonDocument::fromJson(ba).object();
|
||||
if (!config.isEmpty()) {
|
||||
return import(config);
|
||||
}
|
||||
|
||||
return false;
|
||||
return QJsonDocument::fromJson(ba).object();
|
||||
}
|
||||
|
||||
//bool ImportController::importConnectionFromQr(const QByteArray &data)
|
||||
|
@ -116,7 +131,7 @@ bool ImportController::importAmneziaConfig(QString data)
|
|||
// return false;
|
||||
//}
|
||||
|
||||
bool ImportController::importOpenVpnConfig(const QString &data)
|
||||
QJsonObject ImportController::extractOpenVpnConfig(const QString &data)
|
||||
{
|
||||
QJsonObject openVpnConfig;
|
||||
openVpnConfig[config_key::config] = data;
|
||||
|
@ -156,10 +171,10 @@ bool ImportController::importOpenVpnConfig(const QString &data)
|
|||
|
||||
config[config_key::hostName] = hostName;
|
||||
|
||||
return import(config);
|
||||
return config;
|
||||
}
|
||||
|
||||
bool ImportController::importWireGuardConfig(const QString &data)
|
||||
QJsonObject ImportController::extractWireGuardConfig(const QString &data)
|
||||
{
|
||||
QJsonObject lastConfig;
|
||||
lastConfig[config_key::config] = data;
|
||||
|
@ -200,5 +215,5 @@ bool ImportController::importWireGuardConfig(const QString &data)
|
|||
|
||||
config[config_key::hostName] = hostName;
|
||||
|
||||
return import(config);
|
||||
return config;
|
||||
}
|
||||
|
|
|
@ -18,20 +18,27 @@ public:
|
|||
QObject *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
bool importFromFile(const QUrl &fileUrl);
|
||||
void importConfig();
|
||||
void extractConfigFromFile(const QUrl &fileUrl);
|
||||
void extractConfigFromCode(QString code);
|
||||
QString getConfig();
|
||||
QString getConfigFileName();
|
||||
|
||||
signals:
|
||||
void importFinished();
|
||||
void importErrorOccurred(QString errorMessage);
|
||||
private:
|
||||
bool import(const QJsonObject &config);
|
||||
bool importAmneziaConfig(QString data);
|
||||
bool importOpenVpnConfig(const QString &data);
|
||||
bool importWireGuardConfig(const QString &data);
|
||||
QJsonObject extractAmneziaConfig(QString &data);
|
||||
QJsonObject extractOpenVpnConfig(const QString &data);
|
||||
QJsonObject extractWireGuardConfig(const QString &data);
|
||||
|
||||
QSharedPointer<ServersModel> m_serversModel;
|
||||
QSharedPointer<ContainersModel> m_containersModel;
|
||||
std::shared_ptr<Settings> m_settings;
|
||||
|
||||
QJsonObject m_config;
|
||||
QString m_configFileName;
|
||||
|
||||
};
|
||||
|
||||
#endif // IMPORTCONTROLLER_H
|
||||
|
|
|
@ -9,14 +9,14 @@
|
|||
namespace PageLoader
|
||||
{
|
||||
Q_NAMESPACE
|
||||
enum class PageEnum { PageStart = 0, PageHome, PageShare,
|
||||
enum class PageEnum { PageStart = 0, PageHome, PageShare, PageDeinstalling,
|
||||
|
||||
PageSettingsServersList, PageSettings, PageSettingsServerData, PageSettingsServerInfo,
|
||||
PageSettingsServerProtocols, PageSettingsServerServices,
|
||||
|
||||
PageSetupWizardStart, PageTest, PageSetupWizardCredentials, PageSetupWizardProtocols, PageSetupWizardEasy,
|
||||
PageSetupWizardProtocolSettings, PageSetupWizardInstalling, PageSetupWizardConfigSource,
|
||||
PageSetupWizardTextKey
|
||||
PageSetupWizardTextKey, PageSetupWizardViewConfig
|
||||
};
|
||||
Q_ENUM_NS(PageEnum)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ Button {
|
|||
id: border
|
||||
|
||||
source: connectionProccess.running ? "/images/connectionProgress.svg" :
|
||||
ConnectionController.isConnected() ? "/images/connectionOff.svg" : "/images/connectionOn.svg"
|
||||
ConnectionController.isConnected ? "/images/connectionOff.svg" : "/images/connectionOn.svg"
|
||||
|
||||
RotationAnimator {
|
||||
id: connectionProccess
|
||||
|
@ -46,7 +46,7 @@ Button {
|
|||
}
|
||||
|
||||
onClicked: {
|
||||
ConnectionController.onConnectionButtonClicked()
|
||||
ConnectionController.isConnected ? ConnectionController.closeConnection() : ConnectionController.openConnection()
|
||||
}
|
||||
|
||||
Connections {
|
||||
|
@ -61,6 +61,7 @@ Button {
|
|||
console.log("Disconnected")
|
||||
connectionProccess.running = false
|
||||
root.text = qsTr("Connect")
|
||||
ConnectionController.isConnected = false
|
||||
break
|
||||
}
|
||||
case ConnectionState.Preparing: {
|
||||
|
@ -78,7 +79,8 @@ Button {
|
|||
case ConnectionState.Connected: {
|
||||
console.log("Connected")
|
||||
connectionProccess.running = false
|
||||
root.text = qsTr("Connected")
|
||||
root.text = qsTr("Disconnect")
|
||||
ConnectionController.isConnected = true
|
||||
break
|
||||
}
|
||||
case ConnectionState.Disconnecting: {
|
||||
|
|
|
@ -14,20 +14,6 @@ DrawerType {
|
|||
width: parent.width
|
||||
height: parent.height * 0.4375
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: -radius
|
||||
radius: 16
|
||||
color: "#1C1D21"
|
||||
|
||||
border.color: "#2C2D30"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
|
|
@ -27,15 +27,20 @@ ListView {
|
|||
|
||||
delegate: Item {
|
||||
implicitWidth: rootWidth
|
||||
implicitHeight: containerRadioButton.implicitHeight
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
VerticalRadioButton {
|
||||
id: containerRadioButton
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
VerticalRadioButton {
|
||||
id: containerRadioButton
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: name
|
||||
descriptionText: description
|
||||
|
||||
|
@ -68,6 +73,11 @@ ListView {
|
|||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
if (isDefault) {
|
||||
root.currentContainerName = name
|
||||
|
|
77
client/ui/qml/Components/QuestionDrawer.qml
Normal file
77
client/ui/qml/Components/QuestionDrawer.qml
Normal file
|
@ -0,0 +1,77 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
|
||||
DrawerType {
|
||||
id: root
|
||||
|
||||
property string headerText
|
||||
property string descriptionText
|
||||
property string yesButtonText
|
||||
property string noButtonText
|
||||
|
||||
property var yesButtonFunction
|
||||
property var noButtonFunction
|
||||
|
||||
width: parent.width
|
||||
height: parent.height * 0.5
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.topMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
spacing: 8
|
||||
|
||||
Header2TextType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: headerText
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
|
||||
text: descriptionText
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
text: yesButtonText
|
||||
|
||||
onClicked: {
|
||||
if (yesButtonFunction && typeof yesButtonFunction === "function") {
|
||||
yesButtonFunction()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#D7D8DB"
|
||||
borderWidth: 1
|
||||
|
||||
text: noButtonText
|
||||
|
||||
onClicked: {
|
||||
if (noButtonFunction && typeof noButtonFunction === "function") {
|
||||
noButtonFunction()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
55
client/ui/qml/Controls2/BackButtonType.qml
Normal file
55
client/ui/qml/Controls2/BackButtonType.qml
Normal file
|
@ -0,0 +1,55 @@
|
|||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property string backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
property var backButtonFunction
|
||||
|
||||
implicitWidth: content.implicitWidth
|
||||
implicitHeight: content.implicitHeight
|
||||
|
||||
RowLayout {
|
||||
id: content
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
ImageButtonType {
|
||||
image: backButtonImage
|
||||
imageColor: "#D7D8DB"
|
||||
|
||||
onClicked: {
|
||||
if (backButtonFunction && typeof backButtonFunction === "function") {
|
||||
backButtonFunction()
|
||||
} else {
|
||||
closePage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
Layout.fillWidth: true
|
||||
|
||||
color: "transparent"
|
||||
|
||||
ShaderEffectSource {
|
||||
id: effectSource
|
||||
|
||||
sourceItem: background
|
||||
anchors.fill: background
|
||||
sourceRect: Qt.rect(x,y, width, height)
|
||||
}
|
||||
|
||||
FastBlur {
|
||||
id: blur
|
||||
anchors.fill: effectSource
|
||||
|
||||
source: effectSource
|
||||
radius: 100
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,4 +17,18 @@ Drawer {
|
|||
velocity: 4
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: -radius
|
||||
radius: 16
|
||||
color: "#1C1D21"
|
||||
|
||||
border.color: "#2C2D30"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,28 +117,9 @@ Item {
|
|||
width: parent.width
|
||||
height: parent.height * 0.9
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: -radius
|
||||
radius: 16
|
||||
color: "#1C1D21"
|
||||
|
||||
border.color: "#494B50"
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||
}
|
||||
|
||||
Header2Type {
|
||||
ColumnLayout {
|
||||
id: header
|
||||
|
||||
headerText: root.headerText
|
||||
backButtonImage: root.headerBackButtonImage
|
||||
|
||||
width: parent.width
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
@ -146,10 +127,13 @@ Item {
|
|||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
BackButtonType {
|
||||
backButtonImage: root.headerBackButtonImage
|
||||
backButtonFunction: function() {
|
||||
root.menuVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
anchors.top: header.bottom
|
||||
|
@ -164,6 +148,17 @@ Item {
|
|||
|
||||
spacing: 16
|
||||
|
||||
Header2Type {
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
headerText: root.headerText
|
||||
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: listViewLoader
|
||||
sourceComponent: root.listView
|
||||
|
|
|
@ -6,10 +6,7 @@ import "TextTypes"
|
|||
Item {
|
||||
id: root
|
||||
|
||||
property string backButtonImage
|
||||
property string actionButtonImage
|
||||
|
||||
property var backButtonFunction
|
||||
property var actionButtonFunction
|
||||
|
||||
property string headerText
|
||||
|
@ -22,25 +19,6 @@ Item {
|
|||
id: content
|
||||
anchors.fill: parent
|
||||
|
||||
ImageButtonType {
|
||||
id: backButton
|
||||
|
||||
Layout.leftMargin: -6
|
||||
|
||||
image: root.backButtonImage
|
||||
imageColor: "#D7D8DB"
|
||||
|
||||
visible: image ? true : false
|
||||
|
||||
onClicked: {
|
||||
if (backButtonFunction && typeof backButtonFunction === "function") {
|
||||
backButtonFunction()
|
||||
} else {
|
||||
closePage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Header2TextType {
|
||||
id: header
|
||||
|
|
|
@ -6,10 +6,7 @@ import "TextTypes"
|
|||
Item {
|
||||
id: root
|
||||
|
||||
property string backButtonImage
|
||||
property string actionButtonImage
|
||||
|
||||
property var backButtonFunction
|
||||
property var actionButtonFunction
|
||||
|
||||
property string headerText
|
||||
|
@ -22,25 +19,6 @@ Item {
|
|||
id: content
|
||||
anchors.fill: parent
|
||||
|
||||
ImageButtonType {
|
||||
id: backButton
|
||||
|
||||
Layout.leftMargin: -6
|
||||
|
||||
image: root.backButtonImage
|
||||
imageColor: "#D7D8DB"
|
||||
|
||||
visible: image ? true : false
|
||||
|
||||
onClicked: {
|
||||
if (backButtonFunction && typeof backButtonFunction === "function") {
|
||||
backButtonFunction()
|
||||
} else {
|
||||
closePage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Header1TextType {
|
||||
id: header
|
||||
|
|
|
@ -11,9 +11,11 @@ ProgressBar {
|
|||
color: "#412102"
|
||||
}
|
||||
|
||||
contentItem: Rectangle {
|
||||
width: root.visualPosition * root.width
|
||||
height: root.height
|
||||
contentItem: Item {
|
||||
Rectangle {
|
||||
width: root.visualPosition * parent.width
|
||||
height: parent.height
|
||||
color: "#FBB26A"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,6 @@ Switch {
|
|||
}
|
||||
}
|
||||
|
||||
contentItem: ColumnLayout {
|
||||
contentItem: ColumnLayout {
|
||||
id: content
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ Item {
|
|||
id: root
|
||||
|
||||
property string headerText
|
||||
property string textFieldText
|
||||
property string textFieldPlaceholderText
|
||||
property bool textFieldEditable: true
|
||||
|
||||
|
@ -14,6 +13,7 @@ Item {
|
|||
property var clickedFunc
|
||||
|
||||
property alias textField: textField
|
||||
property alias textFieldText: textField.text
|
||||
|
||||
implicitHeight: 74
|
||||
|
||||
|
@ -53,7 +53,6 @@ Item {
|
|||
id: textField
|
||||
|
||||
enabled: root.textFieldEditable
|
||||
text: root.textFieldText
|
||||
color: "#d7d8db"
|
||||
|
||||
placeholderText: textFieldPlaceholderText
|
||||
|
|
91
client/ui/qml/Pages2/PageDeinstalling.qml
Normal file
91
client/ui/qml/Pages2/PageDeinstalling.qml
Normal file
|
@ -0,0 +1,91 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: proxyServersModel
|
||||
sourceModel: ServersModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "isCurrentlyProcessed"
|
||||
value: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.fill: parent
|
||||
contentHeight: content.height
|
||||
|
||||
Column {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
spacing: 16
|
||||
|
||||
Repeater {
|
||||
model: proxyServersModel
|
||||
delegate: Item {
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: delegateContent.implicitHeight
|
||||
|
||||
ColumnLayout {
|
||||
id: delegateContent
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
|
||||
headerText: qsTr("Removing services from ") + name
|
||||
}
|
||||
|
||||
ProgressBarType {
|
||||
id: progressBar
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
|
||||
interval: 300
|
||||
repeat: true
|
||||
running: true
|
||||
onTriggered: {
|
||||
progressBar.value += 0.001
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ParagraphTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 8
|
||||
|
||||
text: "Обычно это занимает не больше 5 минут"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -113,20 +113,6 @@ PageType {
|
|||
width: parent.width
|
||||
height: parent.height * 0.90
|
||||
|
||||
background: Rectangle {
|
||||
anchors.fill: parent
|
||||
anchors.bottomMargin: -radius
|
||||
radius: 16
|
||||
|
||||
color: "#1C1D21"
|
||||
border.color: root.borderColor
|
||||
border.width: 1
|
||||
}
|
||||
|
||||
Overlay.modal: Rectangle {
|
||||
color: Qt.rgba(14/255, 14/255, 17/255, 0.8)
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: serversMenuHeader
|
||||
anchors.top: parent.top
|
||||
|
|
|
@ -71,7 +71,6 @@ PageType {
|
|||
iconImage: "qrc:/images/controls/app.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSetupWizardTextKey)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +84,6 @@ PageType {
|
|||
iconImage: "qrc:/images/controls/save.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSetupWizardTextKey)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,7 +97,6 @@ PageType {
|
|||
iconImage: "qrc:/images/controls/amnezia.svg"
|
||||
|
||||
clickedFunction: function() {
|
||||
goToPage(PageEnum.PageSetupWizardTextKey)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import ProtocolEnum 1.0
|
|||
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Components"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
@ -33,8 +34,20 @@ PageType {
|
|||
descriptionText: "May be needed when changing other settings"
|
||||
|
||||
clickedFunction: function() {
|
||||
questionDrawer.headerText = qsTr("Clear cached profiles?")
|
||||
questionDrawer.descriptionText = qsTr("some description")
|
||||
questionDrawer.yesButtonText = qsTr("Continue")
|
||||
questionDrawer.noButtonText = qsTr("Cancel")
|
||||
|
||||
questionDrawer.yesButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
ContainersModel.clearCachedProfiles()
|
||||
}
|
||||
questionDrawer.noButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
}
|
||||
questionDrawer.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
@ -46,8 +59,15 @@ PageType {
|
|||
textColor: "#EB5757"
|
||||
|
||||
clickedFunction: function() {
|
||||
if (ServersModel.isDefaultServerCurrentlyProcessed && ConnectionController.isConnected()) {
|
||||
ConnectionController.closeVpnConnection()
|
||||
questionDrawer.headerText = qsTr("Remove server?")
|
||||
questionDrawer.descriptionText = qsTr("All installed AmneziaVPN services will still remain on the server.")
|
||||
questionDrawer.yesButtonText = qsTr("Continue")
|
||||
questionDrawer.noButtonText = qsTr("Cancel")
|
||||
|
||||
questionDrawer.yesButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
if (ServersModel.isDefaultServerCurrentlyProcessed && ConnectionController.isConnected) {
|
||||
ConnectionController.closeConnection()
|
||||
}
|
||||
ServersModel.removeServer()
|
||||
if (!ServersModel.getServersCount()) {
|
||||
|
@ -56,6 +76,11 @@ PageType {
|
|||
goToStartPage()
|
||||
}
|
||||
}
|
||||
questionDrawer.noButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
}
|
||||
questionDrawer.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
@ -67,14 +92,32 @@ PageType {
|
|||
textColor: "#EB5757"
|
||||
|
||||
clickedFunction: function() {
|
||||
if (ServersModel.isDefaultServerCurrentlyProcessed && ConnectionController.isConnected()) {
|
||||
questionDrawer.headerText = qsTr("Clear server from Amnezia software?")
|
||||
questionDrawer.descriptionText = qsTr(" All containers will be deleted on the server. This means that configuration files, keys and certificates will be deleted.")
|
||||
questionDrawer.yesButtonText = qsTr("Continue")
|
||||
questionDrawer.noButtonText = qsTr("Cancel")
|
||||
|
||||
questionDrawer.yesButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
goToPage(PageEnum.PageDeinstalling)
|
||||
if (ServersModel.isDefaultServerCurrentlyProcessed && ConnectionController.isConnected) {
|
||||
ConnectionController.closeVpnConnection()
|
||||
}
|
||||
ContainersModel.removeAllContainers()
|
||||
closePage()
|
||||
}
|
||||
questionDrawer.noButtonFunction = function() {
|
||||
questionDrawer.visible = false
|
||||
}
|
||||
questionDrawer.visible = true
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {}
|
||||
|
||||
QuestionDrawer {
|
||||
id: questionDrawer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,8 +30,6 @@ PageType {
|
|||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
spacing: 16
|
||||
|
@ -40,14 +38,20 @@ PageType {
|
|||
id: header
|
||||
model: proxyServersModel
|
||||
|
||||
delegate: HeaderType {
|
||||
Layout.fillWidth: true
|
||||
delegate: ColumnLayout {
|
||||
id: content
|
||||
|
||||
Layout.topMargin: 20
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
|
||||
BackButtonType {
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
actionButtonImage: "qrc:/images/controls/edit-3.svg"
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
headerText: name
|
||||
descriptionText: hostName
|
||||
|
@ -55,9 +59,6 @@ PageType {
|
|||
actionButtonFunction: function() {
|
||||
connectionTypeSelection.visible = true
|
||||
}
|
||||
|
||||
backButtonFunction: function() {
|
||||
closePage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,23 +75,14 @@ PageType {
|
|||
TabButtonType {
|
||||
isSelected: tabBar.currentIndex === 0
|
||||
text: qsTr("Protocols")
|
||||
// onClicked: {
|
||||
// tabBarStackView.goToTabBarPage(PageEnum.PageSettingsServerProtocols)
|
||||
// }
|
||||
}
|
||||
TabButtonType {
|
||||
isSelected: tabBar.currentIndex === 1
|
||||
text: qsTr("Services")
|
||||
// onClicked: {
|
||||
// tabBarStackView.goToTabBarPage(PageEnum.PageSettingsServerServices)
|
||||
// }
|
||||
}
|
||||
TabButtonType {
|
||||
isSelected: tabBar.currentIndex === 2
|
||||
text: qsTr("Data")
|
||||
// onClicked: {
|
||||
// tabBarStackView.goToTabBarPage(PageEnum.PageSettingsServerData)
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,25 +102,5 @@ PageType {
|
|||
stackView: root.stackView
|
||||
}
|
||||
}
|
||||
|
||||
// StackViewType {
|
||||
// id: tabBarStackView
|
||||
|
||||
// Layout.preferredWidth: root.width
|
||||
// Layout.preferredHeight: root.height - tabBar.implicitHeight - header.implicitHeight
|
||||
|
||||
// function goToTabBarPage(page) {
|
||||
// var pagePath = PageController.getPagePath(page)
|
||||
// while (tabBarStackView.depth > 1) {
|
||||
// tabBarStackView.pop()
|
||||
// }
|
||||
// tabBarStackView.replace(pagePath, { "objectName" : pagePath })
|
||||
// }
|
||||
|
||||
// Component.onCompleted: {
|
||||
// var pagePath = PageController.getPagePath(PageEnum.PageSettingsServerProtocols)
|
||||
// tabBarStackView.push(pagePath, { "objectName" : pagePath })
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ import "../Components"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
HeaderType {
|
||||
ColumnLayout {
|
||||
id: header
|
||||
|
||||
anchors.top: parent.top
|
||||
|
@ -28,8 +28,13 @@ PageType {
|
|||
anchors.leftMargin: 16
|
||||
anchors.rightMargin: 16
|
||||
|
||||
BackButtonType {
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
|
||||
actionButtonImage: "qrc:/images/controls/plus.svg"
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
headerText: "Серверы"
|
||||
|
||||
|
@ -37,6 +42,7 @@ PageType {
|
|||
connectionTypeSelection.visible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionTypeSelectionDrawer {
|
||||
id: connectionTypeSelection
|
||||
|
|
|
@ -13,14 +13,6 @@ import "../Config"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
Connections {
|
||||
target: ImportController
|
||||
|
||||
function onImportFinished() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: root.top
|
||||
|
@ -34,13 +26,18 @@ PageType {
|
|||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
BackButtonType {
|
||||
Layout.topMargin: 20
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
Layout.rightMargin: 16
|
||||
Layout.leftMargin: 16
|
||||
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
headerText: "Подключение к серверу"
|
||||
descriptionText: "Не используйте код подключения из публичных источников. Его могли создать, чтобы перехватывать ваши данные.\n
|
||||
|
@ -71,7 +68,8 @@ PageType {
|
|||
FileDialog {
|
||||
id: fileDialog
|
||||
onAccepted: {
|
||||
ImportController.importFromFile(selectedFile)
|
||||
ImportController.extractConfigFromFile(selectedFile)
|
||||
goToPage(PageEnum.PageSetupWizardViewConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,20 @@ import "../Config"
|
|||
PageType {
|
||||
id: root
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: root.top
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: content.height
|
||||
|
||||
|
@ -30,9 +41,6 @@ PageType {
|
|||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
headerText: "Подключение к серверу"
|
||||
}
|
||||
|
|
|
@ -30,11 +30,22 @@ PageType {
|
|||
}
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: root.top
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: content.implicitHeight + buttonContinue.anchors.bottomMargin
|
||||
contentHeight: content.implicitHeight + continueButton.anchors.bottomMargin
|
||||
|
||||
Column {
|
||||
id: content
|
||||
|
@ -44,7 +55,6 @@ PageType {
|
|||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
|
||||
spacing: 16
|
||||
|
||||
|
@ -53,9 +63,7 @@ PageType {
|
|||
|
||||
implicitWidth: parent.width
|
||||
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
headerText: qsTr("What is the level of Internet control in your region?")
|
||||
headerText: qsTr("What is the level of internet control in your region?")
|
||||
}
|
||||
|
||||
ListView {
|
||||
|
@ -118,11 +126,10 @@ PageType {
|
|||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: buttonContinue
|
||||
id: continueButton
|
||||
|
||||
implicitWidth: parent.width
|
||||
anchors.topMargin: 24
|
||||
anchors.bottomMargin: 32
|
||||
anchors.bottomMargin: 24
|
||||
|
||||
text: qsTr("Continue")
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ PageType {
|
|||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
|
||||
value: progressBarValue
|
||||
// value: progressBarValue
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
|
@ -118,7 +118,7 @@ PageType {
|
|||
repeat: true
|
||||
running: true
|
||||
onTriggered: {
|
||||
progressBarValue += 0.001
|
||||
progressBar.value += 0.001
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,13 +62,14 @@ PageType {
|
|||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
BackButtonType {
|
||||
Layout.topMargin: 20
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
id: header
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
headerText: "Установка " + name
|
||||
descriptionText: "Эти настройки можно будет изменить позже"
|
||||
|
|
|
@ -48,9 +48,12 @@ PageType {
|
|||
|
||||
spacing: 16
|
||||
|
||||
BackButtonType {
|
||||
width: parent.width
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
width: parent.width
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
headerText: "Протокол подключения"
|
||||
descriptionText: "Выберите более приоритетный для вас. Позже можно будет установить остальные протоколы и доп сервисы, вроде DNS-прокси и SFTP."
|
||||
|
|
|
@ -29,23 +29,26 @@ PageType {
|
|||
|
||||
spacing: 16
|
||||
|
||||
BackButtonType {
|
||||
Layout.topMargin: 20
|
||||
}
|
||||
|
||||
HeaderType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 20
|
||||
|
||||
backButtonImage: "qrc:/images/controls/arrow-left.svg"
|
||||
|
||||
headerText: "Ключ для подключения"
|
||||
descriptionText: "Строка, которая начинается с vpn://..."
|
||||
headerText: qsTr("Connection key")
|
||||
descriptionText: qsTr("A line that starts with vpn://...")
|
||||
}
|
||||
|
||||
TextFieldWithHeaderType {
|
||||
id: textKey
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 32
|
||||
|
||||
headerText: "Ключ"
|
||||
headerText: qsTr("Key")
|
||||
textFieldPlaceholderText: "vpn://"
|
||||
buttonText: "Вставить"
|
||||
buttonText: qsTr("Insert")
|
||||
|
||||
clickedFunc: function() {
|
||||
textField.text = ""
|
||||
|
@ -63,10 +66,11 @@ PageType {
|
|||
anchors.leftMargin: 16
|
||||
anchors.bottomMargin: 32
|
||||
|
||||
text: qsTr("Подключиться")
|
||||
text: qsTr("Continue")
|
||||
|
||||
onClicked: function() {
|
||||
// goToPage(PageEnum.PageSetupWizardInstalling)
|
||||
ImportController.extractConfigFromCode(textKey.textFieldText)
|
||||
goToPage(PageEnum.PageSetupWizardViewConfig)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
152
client/ui/qml/Pages2/PageSetupWizardViewConfig.qml
Normal file
152
client/ui/qml/Pages2/PageSetupWizardViewConfig.qml
Normal file
|
@ -0,0 +1,152 @@
|
|||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Dialogs
|
||||
|
||||
import PageEnum 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
property bool showContent: false
|
||||
|
||||
Connections {
|
||||
target: ImportController
|
||||
|
||||
function onImportErrorOccurred(errorMessage) {
|
||||
closePage()
|
||||
PageController.showErrorMessage(errorMessage)
|
||||
}
|
||||
|
||||
function onImportFinished() {
|
||||
goToStartPage()
|
||||
if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageHome)) {
|
||||
PageController.restorePageHomeState()
|
||||
} else if (stackView.currentItem.objectName === PageController.getPagePath(PageEnum.PageSettings)) {
|
||||
goToPage(PageEnum.PageSettingsServersList, false)
|
||||
} else {
|
||||
var pagePath = PageController.getPagePath(PageEnum.PageStart)
|
||||
stackView.replace(pagePath, { "objectName" : pagePath })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
anchors.topMargin: 20
|
||||
}
|
||||
|
||||
FlickableType {
|
||||
id: fl
|
||||
anchors.top: backButton.bottom
|
||||
anchors.bottom: root.bottom
|
||||
contentHeight: content.implicitHeight + connectButton.implicitHeight
|
||||
|
||||
ColumnLayout {
|
||||
id: content
|
||||
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
HeaderType {
|
||||
headerText: qsTr("New connection")
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.topMargin: 32
|
||||
spacing: 8
|
||||
|
||||
visible: fileName.text !== ""
|
||||
|
||||
Image {
|
||||
source: "qrc:/images/controls/file-cog-2.svg"
|
||||
}
|
||||
|
||||
Header2TextType {
|
||||
id: fileName
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
text: ImportController.getConfigFileName()
|
||||
}
|
||||
}
|
||||
|
||||
CaptionTextType {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 16
|
||||
|
||||
text: qsTr("Do not use connection code from public sources. It could be created to intercept your data.")
|
||||
color: "#878B91"
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: Qt.rgba(1, 1, 1, 0.08)
|
||||
pressedColor: Qt.rgba(1, 1, 1, 0.12)
|
||||
disabledColor: "#878B91"
|
||||
textColor: "#D7D8DB"
|
||||
|
||||
text: showContent ? qsTr("Collapse content") : qsTr("Show content")
|
||||
|
||||
onClicked: {
|
||||
showContent = !showContent
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 16
|
||||
|
||||
implicitHeight: configContent.implicitHeight
|
||||
|
||||
radius: 10
|
||||
color: "#1C1D21"
|
||||
|
||||
visible: showContent
|
||||
|
||||
ParagraphTextType {
|
||||
id: configContent
|
||||
|
||||
anchors.fill: parent
|
||||
anchors.margins: 16
|
||||
|
||||
text: ImportController.getConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: connectButton
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.leftMargin: 16
|
||||
|
||||
BasicButtonType {
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 32
|
||||
|
||||
text: qsTr("Connect")
|
||||
onClicked: {
|
||||
ImportController.importConfig()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -46,6 +46,8 @@ PageType {
|
|||
Component.onCompleted: {
|
||||
var pagePath = PageController.getPagePath(PageEnum.PageHome)
|
||||
tabBarStackView.push(pagePath, { "objectName" : pagePath })
|
||||
ServersModel.setCurrentlyProcessedServerIndex(ServersModel.getDefaultServerIndex())
|
||||
ContainersModel.setCurrentlyProcessedServerIndex(ServersModel.getDefaultServerIndex())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ Window {
|
|||
focus: true
|
||||
|
||||
Component.onCompleted: {
|
||||
var pagePath = PageController.getPagePath(PageEnum.PageStart)
|
||||
var pagePath = PageController.getInitialPage()
|
||||
rootStackView.push(pagePath, { "objectName" : pagePath })
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue