mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-06-22 02:01:08 +07:00
feat: add xray subscription link support
This commit is contained in:
@@ -31,6 +31,41 @@ ImportUiController::ImportUiController(ImportController* importController, QObje
|
||||
connect(m_importController, &ImportController::restoreAppConfig, this, &ImportUiController::restoreAppConfig);
|
||||
}
|
||||
|
||||
bool ImportUiController::importLink(const QUrl &url)
|
||||
{
|
||||
auto result = m_importController->importLink(url);
|
||||
|
||||
if (result.errorCode != ErrorCode::NoError) {
|
||||
emit importErrorOccurred(result.errorCode, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_config = result.config;
|
||||
m_configFileName = result.configFileName;
|
||||
m_maliciousWarningText = result.maliciousWarningText;
|
||||
m_isNativeWireGuardConfig = result.isNativeWireGuardConfig;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImportUiController::editServerConfigWithData(QString data, int serverIndex)
|
||||
{
|
||||
auto result = m_importController->editServerConfigWithData(data, serverIndex, m_config);
|
||||
|
||||
if (result.errorCode != ErrorCode::NoError) {
|
||||
emit importErrorOccurred(result.errorCode, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_config = result.config;
|
||||
m_configFileName = result.configFileName;
|
||||
m_maliciousWarningText = result.maliciousWarningText;
|
||||
m_isNativeWireGuardConfig = result.isNativeWireGuardConfig;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ImportUiController::extractConfigFromFile(const QString &fileName)
|
||||
{
|
||||
QString data;
|
||||
|
||||
@@ -20,6 +20,8 @@ public:
|
||||
public slots:
|
||||
void importConfig();
|
||||
void clearConfigFileName();
|
||||
bool importLink(const QUrl &url);
|
||||
bool editServerConfigWithData(QString data, int serverIndex);
|
||||
bool extractConfigFromFile(const QString &fileName);
|
||||
bool extractConfigFromData(QString data);
|
||||
bool extractConfigFromQr(const QByteArray &data);
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace PageLoader
|
||||
PageSettingsApiNativeConfigs,
|
||||
PageSettingsApiDevices,
|
||||
PageSettingsApiSubscriptionKey,
|
||||
PageSettingsXRayAvailableConfigs,
|
||||
PageSettingsXRayServerInfo,
|
||||
PageSettingsKillSwitchExceptions,
|
||||
|
||||
PageServiceSftpSettings,
|
||||
|
||||
@@ -159,7 +159,11 @@ QString ServersUiController::getDefaultServerDescriptionCollapsed() const
|
||||
if (server.isApiConfig()) {
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
if (server.isXRayConfig()) {
|
||||
return getConfigName(getCurrentConfigIndex());
|
||||
}
|
||||
|
||||
DockerContainer container = server.defaultContainer();
|
||||
QString containerName = ContainerUtils::containerHumanNames().value(container);
|
||||
QString protocolVersion;
|
||||
@@ -210,6 +214,10 @@ QString ServersUiController::getDefaultServerDescriptionExpanded() const
|
||||
if (server.isApiConfig()) {
|
||||
return description;
|
||||
}
|
||||
|
||||
if (server.isXRayConfig()) {
|
||||
return getConfigName(getCurrentConfigIndex());
|
||||
}
|
||||
|
||||
return description + server.hostName();
|
||||
}
|
||||
@@ -272,6 +280,13 @@ bool ServersUiController::isDefaultServerFromApi() const
|
||||
|| configVersion == apiDefs::ConfigSource::AmneziaGateway;
|
||||
}
|
||||
|
||||
bool ServersUiController::isDefaultServerContainXRayConfigs() const
|
||||
{
|
||||
int defaultIndex = getDefaultServerIndex();
|
||||
const ServerConfig server = m_serversController->getServerConfig(defaultIndex);
|
||||
return server.isXRayConfig();
|
||||
}
|
||||
|
||||
int ServersUiController::getProcessedServerIndex() const
|
||||
{
|
||||
return m_processedServerIndex;
|
||||
@@ -444,6 +459,31 @@ QString ServersUiController::adDescription() const
|
||||
return QString();
|
||||
}
|
||||
|
||||
void ServersUiController::setCurrentConfigIndex(const int index)
|
||||
{
|
||||
m_serversController->setCurrentConfigIndex(index);
|
||||
}
|
||||
|
||||
int ServersUiController::getCurrentConfigIndex() const
|
||||
{
|
||||
return m_serversController->getCurrentConfigIndex();
|
||||
}
|
||||
|
||||
QString ServersUiController::getConfigString(const int index) const
|
||||
{
|
||||
return m_serversController->getConfigString(index);
|
||||
}
|
||||
|
||||
QString ServersUiController::getConfigName(const int index) const
|
||||
{
|
||||
return m_serversController->getConfigName(index);
|
||||
}
|
||||
|
||||
QJsonArray ServersUiController::getConfigNames() const
|
||||
{
|
||||
return m_serversController->getConfigNames();
|
||||
}
|
||||
|
||||
void ServersUiController::updateContainersModel()
|
||||
{
|
||||
if (m_processedServerIndex < 0 || m_processedServerIndex >= m_serversController->getServersCount()) {
|
||||
|
||||
@@ -26,6 +26,8 @@ class ServersUiController : public QObject
|
||||
Q_PROPERTY(bool isDefaultServerDefaultContainerHasSplitTunneling READ isDefaultServerDefaultContainerHasSplitTunneling NOTIFY defaultServerIndexChanged)
|
||||
Q_PROPERTY(bool isDefaultServerFromApi READ isDefaultServerFromApi NOTIFY defaultServerIndexChanged)
|
||||
|
||||
Q_PROPERTY(bool isDefaultServerContainXRayConfigs READ isDefaultServerContainXRayConfigs NOTIFY defaultServerIndexChanged)
|
||||
|
||||
Q_PROPERTY(int processedIndex READ getProcessedServerIndex WRITE setProcessedServerIndex NOTIFY processedServerIndexChanged)
|
||||
Q_PROPERTY(int processedContainerIndex READ getProcessedContainerIndex WRITE setProcessedContainerIndex NOTIFY processedContainerIndexChanged)
|
||||
Q_PROPERTY(bool processedServerIsPremium READ processedServerIsPremium NOTIFY processedServerIndexChanged)
|
||||
@@ -61,6 +63,7 @@ public slots:
|
||||
QString getDefaultServerDescriptionExpanded() const;
|
||||
bool isDefaultServerDefaultContainerHasSplitTunneling() const;
|
||||
bool isDefaultServerFromApi() const;
|
||||
bool isDefaultServerContainXRayConfigs() const;
|
||||
|
||||
int getProcessedServerIndex() const;
|
||||
void setProcessedServerIndex(int index);
|
||||
@@ -77,6 +80,12 @@ public slots:
|
||||
bool isAdVisible() const;
|
||||
QString adHeader() const;
|
||||
QString adDescription() const;
|
||||
|
||||
void setCurrentConfigIndex(int index);
|
||||
int getCurrentConfigIndex() const;
|
||||
QString getConfigString(const int index) const;
|
||||
QString getConfigName(const int index) const;
|
||||
QJsonArray getConfigNames() const;
|
||||
|
||||
QStringList getAllInstalledServicesName(int serverIndex) const;
|
||||
|
||||
|
||||
@@ -34,6 +34,10 @@ namespace
|
||||
|
||||
constexpr char publicKeyInfo[] = "public_key";
|
||||
constexpr char expiresAt[] = "expires_at";
|
||||
|
||||
constexpr char xraySubscriptionConfig[] = "xray_subscription_config";
|
||||
constexpr char xraySubscriptionConfigName[] = "xray_subscription_config_name";
|
||||
constexpr char xraySubscriptionConfigCurrent[] = "xray_subscription_config_current";
|
||||
}
|
||||
|
||||
QString normalizeVpnKey(const QString &vpnKey)
|
||||
@@ -207,6 +211,11 @@ QVariant ServersModel::data(const QModelIndex &index, int role) const
|
||||
}
|
||||
return apiUtils::isSubscriptionExpiringSoon(apiConfig.subscription.endDate);
|
||||
}
|
||||
case IsXRayConfigSelectionAvailableRole: {
|
||||
if (server.isXRayConfig()) {
|
||||
return server.as<NativeServerConfig>()->configString.has_value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
@@ -301,6 +310,11 @@ bool ServersModel::isDefaultServerFromApi()
|
||||
|| data(m_defaultServerIndex, IsServerFromGatewayApiRole).toBool();
|
||||
}
|
||||
|
||||
bool ServersModel::isDefaultServerContainXRayConfigs()
|
||||
{
|
||||
return data(m_defaultServerIndex, IsXRayConfigSelectionAvailableRole).toBool();
|
||||
}
|
||||
|
||||
bool ServersModel::isProcessedServerHasWriteAccess()
|
||||
{
|
||||
return qvariant_cast<bool>(data(m_processedServerIndex, HasWriteAccessRole));
|
||||
@@ -350,6 +364,8 @@ QHash<int, QByteArray> ServersModel::roleNames() const
|
||||
roles[IsSubscriptionExpiredRole] = "isSubscriptionExpired";
|
||||
roles[IsSubscriptionExpiringSoonRole] = "isSubscriptionExpiringSoon";
|
||||
|
||||
roles[IsXRayConfigSelectionAvailableRole] = "isXRayConfigSelectionAvailable";
|
||||
|
||||
return roles;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ public:
|
||||
IsSubscriptionExpiredRole,
|
||||
IsSubscriptionExpiringSoonRole,
|
||||
|
||||
IsXRayConfigSelectionAvailableRole,
|
||||
|
||||
HasAmneziaDns
|
||||
};
|
||||
|
||||
@@ -60,6 +62,8 @@ public slots:
|
||||
bool isDefaultServerCurrentlyProcessed();
|
||||
bool isDefaultServerFromApi();
|
||||
|
||||
bool isDefaultServerContainXRayConfigs();
|
||||
|
||||
bool isProcessedServerHasWriteAccess();
|
||||
bool isDefaultServerHasWriteAccess();
|
||||
bool hasServerWithWriteAccess();
|
||||
|
||||
@@ -68,7 +68,7 @@ ListViewType {
|
||||
text: name
|
||||
descriptionText: isServerFromGatewayApi && (isSubscriptionExpired || isSubscriptionExpiringSoon)
|
||||
? (isSubscriptionExpired ? qsTr("Subscription expired. Please renew") : qsTr("Subscription expiring soon"))
|
||||
: serverDescription
|
||||
: (isXRayConfigSelectionAvailable ? ServersUiController.getConfigName(ServersUiController.getCurrentConfigIndex()) : serverDescription)
|
||||
descriptionColor: isServerFromGatewayApi && (isSubscriptionExpired || isSubscriptionExpiringSoon)
|
||||
? (isSubscriptionExpired ? AmneziaStyle.color.vibrantRed : AmneziaStyle.color.goldenApricot)
|
||||
: AmneziaStyle.color.mutedGray
|
||||
@@ -121,6 +121,8 @@ ListViewType {
|
||||
|
||||
PageController.goToPage(PageEnum.PageSettingsApiServerInfo)
|
||||
}
|
||||
} else if (ServersModel.getProcessedServerData("isXRayConfigSelectionAvailable")) {
|
||||
PageController.goToPage(PageEnum.PageSettingsXRayAvailableConfigs)
|
||||
} else {
|
||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||
}
|
||||
|
||||
@@ -311,11 +311,11 @@ PageType {
|
||||
objectName: "rowLayoutLabel"
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
Layout.topMargin: 8
|
||||
Layout.bottomMargin: drawer.isCollapsedStateActive ? 44 : ServersUiController.isDefaultServerFromApi ? 61 : 16
|
||||
Layout.bottomMargin: drawer.isCollapsedStateActive ? 44 : (ServersUiController.isDefaultServerFromApi || ServersUiController.isDefaultServerContainXRayConfigs) ? 61 : 16
|
||||
spacing: 0
|
||||
|
||||
BasicButtonType {
|
||||
enabled: (ServersUiController.defaultServerImagePathCollapsed !== "") && drawer.isCollapsedStateActive
|
||||
enabled: (ServersUiController.defaultServerImagePathCollapsed !== "" || ServersUiController.isDefaultServerContainXRayConfigs) && drawer.isCollapsedStateActive
|
||||
hoverEnabled: enabled
|
||||
|
||||
implicitHeight: 36
|
||||
@@ -359,6 +359,8 @@ PageType {
|
||||
|
||||
PageController.goToPage(PageEnum.PageSettingsApiServerInfo)
|
||||
}
|
||||
} else if (ServersModel.getProcessedServerData("isXRayConfigSelectionAvailable")) {
|
||||
PageController.goToPage(PageEnum.PageSettingsXRayAvailableConfigs)
|
||||
} else {
|
||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||
}
|
||||
@@ -379,7 +381,7 @@ PageType {
|
||||
Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter
|
||||
spacing: 8
|
||||
|
||||
visible: !ServersUiController.isDefaultServerFromApi
|
||||
visible: !ServersUiController.isDefaultServerFromApi && !ServersUiController.isDefaultServerContainXRayConfigs
|
||||
|
||||
DropDownType {
|
||||
id: containersDropDown
|
||||
|
||||
@@ -97,6 +97,8 @@ PageType {
|
||||
}
|
||||
|
||||
PageController.goToPage(PageEnum.PageSettingsApiServerInfo)
|
||||
} else if (ServersModel.getProcessedServerData("isXRayConfigSelectionAvailable")) {
|
||||
PageController.goToPage(PageEnum.PageSettingsXRayServerInfo)
|
||||
} else {
|
||||
PageController.goToPage(PageEnum.PageSettingsServerInfo)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Dialogs
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import PageEnum 1.0
|
||||
import Style 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
import "../Components"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
property var processedServer
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
function onProcessedServerChanged() {
|
||||
root.processedServer = proxyServersModel.get(0)
|
||||
}
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: proxyServersModel
|
||||
objectName: "proxyServersModel"
|
||||
|
||||
sourceModel: ServersModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "isCurrentlyProcessed"
|
||||
value: true
|
||||
}
|
||||
]
|
||||
|
||||
Component.onCompleted: {
|
||||
root.processedServer = proxyServersModel.get(0)
|
||||
}
|
||||
}
|
||||
|
||||
ListViewType {
|
||||
id: menuContent
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
model: xrayConfigs
|
||||
|
||||
currentIndex: 0
|
||||
|
||||
ButtonGroup {
|
||||
id: containersRadioButtonGroup
|
||||
}
|
||||
|
||||
header: ColumnLayout {
|
||||
width: menuContent.width
|
||||
|
||||
spacing: 4
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
objectName: "backButton"
|
||||
|
||||
Layout.topMargin: 20 + PageController.safeAreaTopMargin
|
||||
}
|
||||
|
||||
HeaderTypeWithButton {
|
||||
id: headerContent
|
||||
objectName: "headerContent"
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.bottomMargin: 10
|
||||
|
||||
actionButtonImage: "qrc:/images/controls/settings.svg"
|
||||
|
||||
headerText: root.processedServer.name
|
||||
|
||||
actionButtonFunction: function() {
|
||||
PageController.goToPage(PageEnum.PageSettingsXRayServerInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delegate: ColumnLayout {
|
||||
id: content
|
||||
|
||||
width: menuContent.width
|
||||
height: content.implicitHeight
|
||||
|
||||
RowLayout {
|
||||
VerticalRadioButton {
|
||||
id: containerRadioButton
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
|
||||
text: model.title
|
||||
|
||||
ButtonGroup.group: containersRadioButtonGroup
|
||||
|
||||
imageSource: "qrc:/images/controls/download.svg"
|
||||
|
||||
checked: index === ServersUiController.getCurrentConfigIndex()
|
||||
checkable: !ConnectionController.isConnected
|
||||
|
||||
onClicked: {
|
||||
if (ConnectionController.isConnectionInProgress) {
|
||||
PageController.showNotificationMessage(qsTr("Unable change config while trying to make an active connection"))
|
||||
return
|
||||
}
|
||||
if (ConnectionController.isConnected) {
|
||||
PageController.showNotificationMessage(qsTr("Unable change config while there is an active connection"))
|
||||
return
|
||||
}
|
||||
|
||||
if (index !== ServersUiController.getCurrentConfigIndex()) {
|
||||
PageController.showBusyIndicator(true)
|
||||
ServersUiController.setCurrentConfigIndex(index)
|
||||
ImportController.editServerConfigWithData(ServersUiController.getConfigString(index), ServersUiController.getProcessedServerIndex())
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onEnterPressed: {
|
||||
if (checkable) {
|
||||
checked = true
|
||||
}
|
||||
containerRadioButton.clicked()
|
||||
}
|
||||
Keys.onReturnPressed: {
|
||||
if (checkable) {
|
||||
checked = true
|
||||
}
|
||||
containerRadioButton.clicked()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DividerType {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListModel {
|
||||
id: xrayConfigs
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
xrayConfigs.clear()
|
||||
const names = ServersUiController.getConfigNames()
|
||||
|
||||
for (let i = 0; i < names.length; ++i) {
|
||||
xrayConfigs.append({ title: names[i] })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import QtQuick.Dialogs
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
import PageEnum 1.0
|
||||
import Style 1.0
|
||||
|
||||
import "./"
|
||||
import "../Controls2"
|
||||
import "../Controls2/TextTypes"
|
||||
import "../Config"
|
||||
import "../Components"
|
||||
|
||||
PageType {
|
||||
id: root
|
||||
|
||||
property var processedServer
|
||||
|
||||
Connections {
|
||||
target: ServersModel
|
||||
|
||||
function onProcessedServerChanged() {
|
||||
root.processedServer = proxyServersModel.get(0)
|
||||
}
|
||||
}
|
||||
|
||||
SortFilterProxyModel {
|
||||
id: proxyServersModel
|
||||
objectName: "proxyServersModel"
|
||||
|
||||
sourceModel: ServersModel
|
||||
filters: [
|
||||
ValueFilter {
|
||||
roleName: "isCurrentlyProcessed"
|
||||
value: true
|
||||
}
|
||||
]
|
||||
|
||||
Component.onCompleted: {
|
||||
root.processedServer = proxyServersModel.get(0)
|
||||
}
|
||||
}
|
||||
|
||||
ListViewType {
|
||||
id: listView
|
||||
|
||||
anchors.fill: parent
|
||||
|
||||
model: 1
|
||||
|
||||
header: ColumnLayout {
|
||||
width: listView.width
|
||||
|
||||
spacing: 4
|
||||
|
||||
BackButtonType {
|
||||
id: backButton
|
||||
objectName: "backButton"
|
||||
|
||||
Layout.topMargin: 20 + PageController.safeAreaTopMargin
|
||||
}
|
||||
|
||||
HeaderTypeWithButton {
|
||||
id: headerContent
|
||||
objectName: "headerContent"
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.leftMargin: 16
|
||||
Layout.rightMargin: 16
|
||||
Layout.bottomMargin: 10
|
||||
|
||||
actionButtonImage: "qrc:/images/controls/edit-3.svg"
|
||||
|
||||
headerText: root.processedServer.name
|
||||
|
||||
actionButtonFunction: function() {
|
||||
serverNameEditDrawer.openTriggered()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
footer: ColumnLayout {
|
||||
id: footer
|
||||
|
||||
width: listView.width
|
||||
spacing: 0
|
||||
|
||||
BasicButtonType {
|
||||
id: resetButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.topMargin: 24
|
||||
Layout.bottomMargin: 16
|
||||
Layout.leftMargin: 8
|
||||
implicitHeight: 32
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: AmneziaStyle.color.translucentWhite
|
||||
pressedColor: AmneziaStyle.color.sheerWhite
|
||||
textColor: AmneziaStyle.color.vibrantRed
|
||||
|
||||
text: qsTr("Reload config")
|
||||
|
||||
clickedFunc: function() {
|
||||
var headerText = qsTr("Reload config?")
|
||||
var yesButtonText = qsTr("Continue")
|
||||
var noButtonText = qsTr("Cancel")
|
||||
|
||||
var yesButtonFunction = function() {
|
||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
||||
PageController.showNotificationMessage(qsTr("Cannot reload config during active connection"))
|
||||
} else {
|
||||
PageController.showBusyIndicator(true)
|
||||
InstallController.rebootProcessedServer()
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
}
|
||||
}
|
||||
|
||||
BasicButtonType {
|
||||
id: removeButton
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.bottomMargin: 16
|
||||
Layout.leftMargin: 8
|
||||
implicitHeight: 32
|
||||
|
||||
defaultColor: "transparent"
|
||||
hoveredColor: AmneziaStyle.color.translucentWhite
|
||||
pressedColor: AmneziaStyle.color.sheerWhite
|
||||
textColor: AmneziaStyle.color.vibrantRed
|
||||
|
||||
text: qsTr("Remove from application")
|
||||
|
||||
clickedFunc: function() {
|
||||
var headerText = qsTr("Remove from application?")
|
||||
var yesButtonText = qsTr("Continue")
|
||||
var noButtonText = qsTr("Cancel")
|
||||
|
||||
var yesButtonFunction = function() {
|
||||
if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) {
|
||||
PageController.showNotificationMessage(qsTr("Cannot remove server during active connection"))
|
||||
} else {
|
||||
PageController.showBusyIndicator(true)
|
||||
InstallController.removeServer(ServersUiController.getProcessedServerIndex())
|
||||
PageController.showBusyIndicator(false)
|
||||
}
|
||||
}
|
||||
var noButtonFunction = function() {
|
||||
}
|
||||
|
||||
showQuestionDrawer(headerText, "", yesButtonText, noButtonText, yesButtonFunction, noButtonFunction)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RenameServerDrawer {
|
||||
id: serverNameEditDrawer
|
||||
|
||||
anchors.fill: parent
|
||||
expandedHeight: parent.height * 0.35
|
||||
|
||||
serverNameText: root.processedServer.name
|
||||
}
|
||||
}
|
||||
@@ -187,8 +187,19 @@ PageType {
|
||||
|
||||
text: qsTr("Continue")
|
||||
|
||||
function isValidUrl(text) {
|
||||
try {
|
||||
var u = new URL(text)
|
||||
return u.protocol === "http:" || u.protocol === "https:"
|
||||
} catch(e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
clickedFunc: function() {
|
||||
if (ImportController.extractConfigFromData(textKey.textField.text)) {
|
||||
if (isValidUrl(textKey.textField.text) && ImportController.importLink(textKey.textField.text)) {
|
||||
PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
|
||||
}else if (ImportController.extractConfigFromData(textKey.textField.text)) {
|
||||
PageController.goToPage(PageEnum.PageSetupWizardViewConfig)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@
|
||||
<file>Pages2/PageSettingsServerServices.qml</file>
|
||||
<file>Pages2/PageSettingsServersList.qml</file>
|
||||
<file>Pages2/PageSettingsSplitTunneling.qml</file>
|
||||
<file>Pages2/PageSettingsXRayAvailableConfigs.qml</file>
|
||||
<file>Pages2/PageSettingsXRayServerInfo.qml</file>
|
||||
<file>Pages2/PageSettingsNewsNotifications.qml</file>
|
||||
<file>Pages2/PageSettingsNewsDetail.qml</file>
|
||||
<file>Pages2/PageProtocolAwgClientSettings.qml</file>
|
||||
|
||||
Reference in New Issue
Block a user