diff --git a/client/core/controllers/coreController.cpp b/client/core/controllers/coreController.cpp index 34d8d7f73..644ecdd1d 100644 --- a/client/core/controllers/coreController.cpp +++ b/client/core/controllers/coreController.cpp @@ -87,8 +87,8 @@ void CoreController::initModels() m_xrayConfigModel = new XrayConfigModel(this); setQmlContextProperty("XrayConfigModel", m_xrayConfigModel); - m_xrayConfigsModel = new XrayConfigsModel(m_appSettingsRepository, this); - setQmlContextProperty("XrayConfigsModel", m_xrayConfigsModel); + m_xrayConfigSnapshotsModel = new XrayConfigSnapshotsModel(m_appSettingsRepository, m_xrayConfigModel, this); + setQmlContextProperty("XrayConfigSnapshotsModel", m_xrayConfigSnapshotsModel); m_torConfigModel = new TorConfigModel(this); setQmlContextProperty("TorConfigModel", m_torConfigModel); diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 2ec3314df..5f78cb9f0 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -64,7 +64,7 @@ #include "ui/models/protocols/openvpnConfigModel.h" #include "ui/models/protocols/wireguardConfigModel.h" #include "ui/models/protocols/xrayConfigModel.h" -#include "ui/models/protocols/xrayConfigsModel.h" +#include "ui/models/protocols/xrayConfigSnapshotsModel.h" #include "ui/models/protocolsModel.h" #include "ui/models/services/torConfigModel.h" #include "ui/models/serversModel.h" @@ -203,7 +203,7 @@ private: OpenVpnConfigModel* m_openVpnConfigModel; XrayConfigModel* m_xrayConfigModel; - XrayConfigsModel* m_xrayConfigsModel; + XrayConfigSnapshotsModel* m_xrayConfigSnapshotsModel; TorConfigModel* m_torConfigModel; WireGuardConfigModel* m_wireGuardConfigModel; AwgConfigModel* m_awgConfigModel; diff --git a/client/ui/controllers/qml/pageController.h b/client/ui/controllers/qml/pageController.h index 8eac73c8a..045dc9bc3 100644 --- a/client/ui/controllers/qml/pageController.h +++ b/client/ui/controllers/qml/pageController.h @@ -82,7 +82,7 @@ namespace PageLoader PageDevMenu, - PageProtocolXrayConfigsSettings, + PageProtocolXraySnapshots, PageProtocolXrayTransportSettings, PageProtocolXrayXmuxSettings, PageProtocolXrayXPaddingSettings, diff --git a/client/ui/models/protocols/xrayConfigsModel.cpp b/client/ui/models/protocols/xrayConfigSnapshotsModel.cpp similarity index 75% rename from client/ui/models/protocols/xrayConfigsModel.cpp rename to client/ui/models/protocols/xrayConfigSnapshotsModel.cpp index cd4a95d34..8a023212f 100644 --- a/client/ui/models/protocols/xrayConfigsModel.cpp +++ b/client/ui/models/protocols/xrayConfigSnapshotsModel.cpp @@ -1,4 +1,4 @@ -#include "xrayConfigsModel.h" +#include "xrayConfigSnapshotsModel.h" #include #include @@ -26,13 +26,14 @@ XrayConfigSnapshot XrayConfigSnapshot::fromJson(const QJsonObject &json) return s; } -XrayConfigsModel::XrayConfigsModel(SecureAppSettingsRepository *appSettings, QObject *parent) - : QAbstractListModel(parent), m_appSettings(appSettings) +XrayConfigSnapshotsModel::XrayConfigSnapshotsModel(SecureAppSettingsRepository *appSettings, + XrayConfigModel *xrayConfigModel, QObject *parent) + : QAbstractListModel(parent), m_appSettings(appSettings), m_xrayConfigModel(xrayConfigModel) { loadAll(); } -void XrayConfigsModel::loadAll() +void XrayConfigSnapshotsModel::loadAll() { m_configs.clear(); QByteArray raw = m_appSettings->xraySavedConfigs(); @@ -46,7 +47,7 @@ void XrayConfigsModel::loadAll() } } -void XrayConfigsModel::persistAll() +void XrayConfigSnapshotsModel::persistAll() { QJsonArray arr; for (const XrayConfigSnapshot &s : m_configs) { @@ -55,13 +56,13 @@ void XrayConfigsModel::persistAll() m_appSettings->setXraySavedConfigs(QJsonDocument(arr).toJson(QJsonDocument::Compact)); } -int XrayConfigsModel::rowCount(const QModelIndex &parent) const +int XrayConfigSnapshotsModel::rowCount(const QModelIndex &parent) const { Q_UNUSED(parent); return m_configs.size(); } -QVariant XrayConfigsModel::data(const QModelIndex &index, int role) const +QVariant XrayConfigSnapshotsModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || index.row() < 0 || index.row() >= m_configs.size()) { return QVariant(); @@ -83,7 +84,7 @@ QVariant XrayConfigsModel::data(const QModelIndex &index, int role) const return QVariant(); } -QHash XrayConfigsModel::roleNames() const +QHash XrayConfigSnapshotsModel::roleNames() const { QHash roles; roles[IdRole] = "configId"; @@ -92,14 +93,14 @@ QHash XrayConfigsModel::roleNames() const return roles; } -void XrayConfigsModel::reload() +void XrayConfigSnapshotsModel::reload() { beginResetModel(); loadAll(); endResetModel(); } -void XrayConfigsModel::createFromCurrent(const amnezia::XrayServerConfig &serverConfig) +void XrayConfigSnapshotsModel::createFromCurrent(const amnezia::XrayServerConfig &serverConfig) { XrayConfigSnapshot snapshot; snapshot.id = QUuid::createUuid().toString(QUuid::WithoutBraces); @@ -114,7 +115,7 @@ void XrayConfigsModel::createFromCurrent(const amnezia::XrayServerConfig &server persistAll(); } -amnezia::XrayServerConfig XrayConfigsModel::applyConfig(int index) const +amnezia::XrayServerConfig XrayConfigSnapshotsModel::applyConfig(int index) const { if (index < 0 || index >= m_configs.size()) { return amnezia::XrayServerConfig {}; @@ -123,7 +124,7 @@ amnezia::XrayServerConfig XrayConfigsModel::applyConfig(int index) const return m_configs.at(index).serverConfig; } -void XrayConfigsModel::removeConfig(int index) +void XrayConfigSnapshotsModel::removeConfig(int index) { if (index < 0 || index >= m_configs.size()) { return; @@ -137,7 +138,7 @@ void XrayConfigsModel::removeConfig(int index) emit configRemoved(index); } -QString XrayConfigsModel::exportToJson(int index) const +QString XrayConfigSnapshotsModel::exportToJson(int index) const { if (index < 0 || index >= m_configs.size()) { return {}; @@ -145,7 +146,7 @@ QString XrayConfigsModel::exportToJson(int index) const return QString::fromUtf8(QJsonDocument(m_configs.at(index).toJson()).toJson(QJsonDocument::Indented)); } -bool XrayConfigsModel::importFromJson(const QString &jsonString) +bool XrayConfigSnapshotsModel::importFromJson(const QString &jsonString) { QJsonDocument doc = QJsonDocument::fromJson(jsonString.toUtf8()); if (!doc.isObject()) { @@ -170,7 +171,7 @@ bool XrayConfigsModel::importFromJson(const QString &jsonString) return true; } -QString XrayConfigsModel::buildDisplayName(const amnezia::XrayServerConfig &cfg) +QString XrayConfigSnapshotsModel::buildDisplayName(const amnezia::XrayServerConfig &cfg) { // Build a human-readable name: "XHTTP TLS Reality", "RAW Reality", etc. QString transport; @@ -194,22 +195,22 @@ QString XrayConfigsModel::buildDisplayName(const amnezia::XrayServerConfig &cfg) return QString("%1 %2").arg(transport, security).trimmed(); } -void XrayConfigsModel::createFromXrayModel(XrayConfigModel *model) +void XrayConfigSnapshotsModel::createFromCurrentModel() { - if (!model) { + if (!m_xrayConfigModel) { return; } - createFromCurrent(model->getProtocolConfig().serverConfig); + createFromCurrent(m_xrayConfigModel->getProtocolConfig().serverConfig); } -void XrayConfigsModel::applyConfigToXrayModel(int index, XrayConfigModel *model) +void XrayConfigSnapshotsModel::applyConfigToCurrentModel(int index) { - if (!model) { + if (!m_xrayConfigModel) { return; } amnezia::XrayServerConfig cfg = applyConfig(index); if (cfg.port.isEmpty()) { return; // guard against invalid index } - model->applyServerConfig(cfg); + m_xrayConfigModel->applyServerConfig(cfg); } diff --git a/client/ui/models/protocols/xrayConfigsModel.h b/client/ui/models/protocols/xrayConfigSnapshotsModel.h similarity index 82% rename from client/ui/models/protocols/xrayConfigsModel.h rename to client/ui/models/protocols/xrayConfigSnapshotsModel.h index a17f416c1..9688cd863 100644 --- a/client/ui/models/protocols/xrayConfigsModel.h +++ b/client/ui/models/protocols/xrayConfigSnapshotsModel.h @@ -24,7 +24,7 @@ struct XrayConfigSnapshot static XrayConfigSnapshot fromJson(const QJsonObject &json); }; -class XrayConfigsModel : public QAbstractListModel +class XrayConfigSnapshotsModel : public QAbstractListModel { Q_OBJECT @@ -35,7 +35,8 @@ public: CreatedAtRole, // "dd.MM.yyyy HH:mm" }; - explicit XrayConfigsModel(SecureAppSettingsRepository *appSettings, QObject *parent = nullptr); + explicit XrayConfigSnapshotsModel(SecureAppSettingsRepository *appSettings, XrayConfigModel *xrayConfigModel, + QObject *parent = nullptr); int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; @@ -51,8 +52,8 @@ public slots: Q_INVOKABLE bool importFromJson(const QString &jsonString); // Convenience: create snapshot from live model, apply snapshot back to model - Q_INVOKABLE void createFromXrayModel(XrayConfigModel *model); - Q_INVOKABLE void applyConfigToXrayModel(int index, XrayConfigModel *model); + Q_INVOKABLE void createFromCurrentModel(); + Q_INVOKABLE void applyConfigToCurrentModel(int index); signals: void configApplied(int index); @@ -64,6 +65,7 @@ protected: private: SecureAppSettingsRepository *m_appSettings; + XrayConfigModel *m_xrayConfigModel; QVector m_configs; void persistAll(); diff --git a/client/ui/qml/Pages2/PageProtocolXrayFlowSettings.qml b/client/ui/qml/Pages2/PageProtocolXrayFlowSettings.qml index 0a52311e2..6617b239f 100644 --- a/client/ui/qml/Pages2/PageProtocolXrayFlowSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXrayFlowSettings.qml @@ -25,7 +25,7 @@ PageType { ListViewType { id: listView anchors.top: backButton.bottom - anchors.bottom: saveButton.top + anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right @@ -86,20 +86,20 @@ PageType { } } - BasicButtonType { - id: saveButton - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin - anchors.leftMargin: 16 - anchors.rightMargin: 16 - text: qsTr("Save") - onClicked: { - forceActiveFocus() - PageController.closePage() - } - Keys.onEnterPressed: clicked() - Keys.onReturnPressed: clicked() - } + // BasicButtonType { + // id: saveButton + // anchors.bottom: parent.bottom + // anchors.left: parent.left + // anchors.right: parent.right + // anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin + // anchors.leftMargin: 16 + // anchors.rightMargin: 16 + // text: qsTr("Save") + // onClicked: { + // forceActiveFocus() + // PageController.closePage() + // } + // Keys.onEnterPressed: clicked() + // Keys.onReturnPressed: clicked() + // } } diff --git a/client/ui/qml/Pages2/PageProtocolXraySecuritySettings.qml b/client/ui/qml/Pages2/PageProtocolXraySecuritySettings.qml index efbc0aedf..a1dda29e4 100644 --- a/client/ui/qml/Pages2/PageProtocolXraySecuritySettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXraySecuritySettings.qml @@ -25,7 +25,7 @@ PageType { ListViewType { id: listView anchors.top: backButton.bottom - anchors.bottom: saveButton.top + anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right @@ -304,20 +304,21 @@ PageType { } } - BasicButtonType { - id: saveButton - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin - anchors.leftMargin: 16 - anchors.rightMargin: 16 - text: qsTr("Save") - onClicked: { - forceActiveFocus() - PageController.closePage() - } - Keys.onEnterPressed: clicked() - Keys.onReturnPressed: clicked() - } + // BasicButtonType { + // id: saveButton + // anchors.bottom: parent.bottom + // anchors.left: parent.left + // anchors.right: parent.right + // anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin + // anchors.leftMargin: 16 + // anchors.rightMargin: 16 + // text: qsTr("Save") + // onClicked: { + // forceActiveFocus() + // PageController.closePage() + // } + // Keys.onEnterPressed: clicked() + // Keys.onReturnPressed: clicked() + // } } + diff --git a/client/ui/qml/Pages2/PageProtocolXraySettings.qml b/client/ui/qml/Pages2/PageProtocolXraySettings.qml index bc35474c6..59d0a6d9f 100644 --- a/client/ui/qml/Pages2/PageProtocolXraySettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXraySettings.qml @@ -68,7 +68,7 @@ PageType { implicitHeight: 40 image: "qrc:/images/controls/more-vertical.svg" imageColor: AmneziaStyle.color.mutedGray - onClicked: PageController.goToPage(PageEnum.PageProtocolXrayConfigsSettings) + onClicked: PageController.goToPage(PageEnum.PageProtocolXraySnapshots) } } diff --git a/client/ui/qml/Pages2/PageProtocolXrayConfigsSettings.qml b/client/ui/qml/Pages2/PageProtocolXraySnapshots.qml similarity index 68% rename from client/ui/qml/Pages2/PageProtocolXrayConfigsSettings.qml rename to client/ui/qml/Pages2/PageProtocolXraySnapshots.qml index 514d699b9..525cb2308 100644 --- a/client/ui/qml/Pages2/PageProtocolXrayConfigsSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXraySnapshots.qml @@ -10,15 +10,38 @@ import "../Controls2" import "../Controls2/TextTypes" import "../Config" import "../Components" +import Qt.labs.platform 1.1 PageType { id: root - property string selectedConfigName: "" + property string selectedConfigName: "" property int selectedConfigIndex: -1 // Reload the list every time we open this page - Component.onCompleted: XrayConfigsModel.reload() + Component.onCompleted: XrayConfigSnapshotsModel.reload() + + // ── Save xray config snapshot to file ──────────────────────────── + function saveConfigToFile(json) { + var fileName = "" + if (GC.isMobile()) { + fileName = "amnezia_xray_config.json" + } else { + fileName = SystemController.getFileName( + qsTr("Save XRay configuration"), + qsTr("JSON files (*.json)"), + StandardPaths.standardLocations(StandardPaths.DocumentsLocation) + "/amnezia_xray_config", + true, + ".json") + } + if (fileName !== "") { + PageController.showBusyIndicator(true) + ExportController.setConfigFromString(json, fileName) + PageController.showBusyIndicator(false) + PageController.showNotificationMessage(qsTr("Configuration saved")) + } + } + BackButtonType { id: backButton @@ -35,7 +58,7 @@ PageType { anchors.left: parent.left anchors.right: parent.right - model: XrayConfigsModel + model: XrayConfigSnapshotsModel header: ColumnLayout { width: listView.width @@ -57,31 +80,30 @@ PageType { text: qsTr("Create configuration based on current settings") textMaximumLineCount: 2 rightImageSource: "qrc:/images/controls/chevron-right.svg" - clickedFunction: function() { - XrayConfigsModel.createFromXrayModel(XrayConfigModel) + clickedFunction: function () { + XrayConfigSnapshotsModel.createFromCurrentModel() } } - DividerType {} + DividerType { + } // ── Export ──────────────────────────────────────────────── LabelWithButtonType { Layout.fillWidth: true text: qsTr("Export settings") rightImageSource: "qrc:/images/controls/chevron-right.svg" - clickedFunction: function() { - if (root.selectedConfigIndex >= 0) { - var json = XrayConfigsModel.exportToJson(root.selectedConfigIndex) - ExportController.setConfigFromString(json, "xray_config.json") - } else if (XrayConfigsModel.rowCount() > 0) { - // Export the first one if none selected - var json = XrayConfigsModel.exportToJson(0) - ExportController.setConfigFromString(json, "xray_config.json") + clickedFunction: function () { + var idx = root.selectedConfigIndex >= 0 ? root.selectedConfigIndex : 0 + if (listView.count > 0) { + var json = XrayConfigSnapshotsModel.exportToJson(idx) + saveConfigToFile(json) } } } - DividerType {} + DividerType { + } // ── Import ──────────────────────────────────────────────── LabelWithButtonType { @@ -89,18 +111,25 @@ PageType { text: qsTr("Import settings") descriptionText: qsTr("In JSON format") rightImageSource: "qrc:/images/controls/chevron-right.svg" - clickedFunction: function() { - var filePath = SystemController.getFileName(qsTr("Open XRay config"), qsTr("JSON files (*.json)")) + clickedFunction: function () { + var filePath = SystemController.getFileName( + qsTr("Open XRay configuration"), + qsTr("JSON files (*.json)")) if (filePath !== "") { var jsonContent = ImportController.readTextFile(filePath) if (jsonContent !== "") { - XrayConfigsModel.importFromJson(jsonContent) + if (!XrayConfigSnapshotsModel.importFromJson(jsonContent)) { + PageController.showNotificationMessage(qsTr("Failed to import configuration")) + } else { + PageController.showNotificationMessage(qsTr("Configuration imported successfully")) + } } } } } - DividerType {} + DividerType { + } // ── Section label ───────────────────────────────────────── CaptionTextType { @@ -111,17 +140,19 @@ PageType { Layout.bottomMargin: 8 text: qsTr("Configurations") color: AmneziaStyle.color.mutedGray - visible: XrayConfigsModel.rowCount() > 0 + visible: listView.count > 0 } } // ── Empty state ─────────────────────────────────────────────── footer: ColumnLayout { width: listView.width - visible: XrayConfigsModel.rowCount() === 0 + visible: listView.count === 0 spacing: 0 - Item { Layout.preferredHeight: 32 } + Item { + Layout.preferredHeight: 32 + } ParagraphTextType { Layout.fillWidth: true @@ -144,20 +175,22 @@ PageType { text: configName descriptionText: configDate rightImageSource: "qrc:/images/controls/more-vertical.svg" - clickedFunction: function() { - root.selectedConfigName = configName + clickedFunction: function () { + root.selectedConfigName = configName root.selectedConfigIndex = index configActionsDrawer.openTriggered() } } - DividerType {} + DividerType { + } } } // ── Import result handler ───────────────────────────────────────── Connections { - target: XrayConfigsModel + target: XrayConfigSnapshotsModel + function onImportFailed(errorMessage) { PageController.showNotificationMessage(errorMessage) } @@ -184,7 +217,7 @@ PageType { BackButtonType { Layout.fillWidth: true Layout.topMargin: 16 - backButtonFunction: function() { + backButtonFunction: function () { configActionsDrawer.closeTriggered() } } @@ -204,51 +237,57 @@ PageType { Layout.fillWidth: true text: qsTr("Apply configuration") rightImageSource: "qrc:/images/controls/chevron-right.svg" - clickedFunction: function() { + clickedFunction: function () { configActionsDrawer.closeTriggered() - XrayConfigsModel.applyConfigToXrayModel(root.selectedConfigIndex, XrayConfigModel) + XrayConfigSnapshotsModel.applyConfigToCurrentModel(root.selectedConfigIndex) PageController.closePage() } } - DividerType {} + DividerType { + } // Export this config LabelWithButtonType { Layout.fillWidth: true text: qsTr("Export configuration") rightImageSource: "qrc:/images/controls/chevron-right.svg" - clickedFunction: function() { + clickedFunction: function () { configActionsDrawer.closeTriggered() - var json = XrayConfigsModel.exportToJson(root.selectedConfigIndex) - ExportController.setConfigFromString(json, "xray_config.json") + var json = XrayConfigSnapshotsModel.exportToJson(root.selectedConfigIndex) + saveConfigToFile(json) } } - DividerType {} + DividerType { + } // Delete LabelWithButtonType { Layout.fillWidth: true text: qsTr("Delete configuration") textColor: AmneziaStyle.color.vibrantRed - clickedFunction: function() { + clickedFunction: function () { configActionsDrawer.closeTriggered() - var yesButtonFunction = function() { - XrayConfigsModel.removeConfig(root.selectedConfigIndex) + var yesButtonFunction = function () { + XrayConfigSnapshotsModel.removeConfig(root.selectedConfigIndex) root.selectedConfigIndex = -1 - root.selectedConfigName = "" + root.selectedConfigName = "" } showQuestionDrawer( qsTr("Delete configuration?"), qsTr("This action cannot be undone."), qsTr("Delete"), qsTr("Cancel"), - yesButtonFunction, function() {}) + yesButtonFunction, function () { + }) } } - DividerType {} - Item { Layout.preferredHeight: 16 } + DividerType { + } + Item { + Layout.preferredHeight: 16 + } } } } diff --git a/client/ui/qml/Pages2/PageProtocolXrayTransportSettings.qml b/client/ui/qml/Pages2/PageProtocolXrayTransportSettings.qml index 8d711c337..8b78eb14d 100644 --- a/client/ui/qml/Pages2/PageProtocolXrayTransportSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXrayTransportSettings.qml @@ -25,7 +25,7 @@ PageType { ListViewType { id: listView anchors.top: backButton.bottom - anchors.bottom: saveButton.top + anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right @@ -735,20 +735,21 @@ PageType { } } - BasicButtonType { - id: saveButton - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin - anchors.leftMargin: 16 - anchors.rightMargin: 16 - text: qsTr("Save") - onClicked: { - forceActiveFocus() - PageController.closePage() - } - Keys.onEnterPressed: clicked() - Keys.onReturnPressed: clicked() - } + // BasicButtonType { + // id: saveButton + // anchors.bottom: parent.bottom + // anchors.left: parent.left + // anchors.right: parent.right + // anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin + // anchors.leftMargin: 16 + // anchors.rightMargin: 16 + // text: qsTr("Save") + // onClicked: { + // forceActiveFocus() + // PageController.closePage() + // } + // Keys.onEnterPressed: clicked() + // Keys.onReturnPressed: clicked() + // } } + diff --git a/client/ui/qml/Pages2/PageProtocolXrayXPaddingBytesSettings.qml b/client/ui/qml/Pages2/PageProtocolXrayXPaddingBytesSettings.qml index 303ccebc4..6590ad1ed 100644 --- a/client/ui/qml/Pages2/PageProtocolXrayXPaddingBytesSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXrayXPaddingBytesSettings.qml @@ -25,7 +25,7 @@ PageType { ListViewType { id: listView anchors.top: backButton.bottom - anchors.bottom: saveButton.top + anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right @@ -63,24 +63,26 @@ PageType { onMaxChanged: xPaddingBytesMax = val } - Item { Layout.preferredHeight: 16 } + Item { + Layout.preferredHeight: 16 + } } } - BasicButtonType { - id: saveButton - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin - anchors.leftMargin: 16 - anchors.rightMargin: 16 - text: qsTr("Save") - onClicked: { - forceActiveFocus() - PageController.closePage() - } - Keys.onEnterPressed: clicked() - Keys.onReturnPressed: clicked() - } + // BasicButtonType { + // id: saveButton + // anchors.bottom: parent.bottom + // anchors.left: parent.left + // anchors.right: parent.right + // anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin + // anchors.leftMargin: 16 + // anchors.rightMargin: 16 + // text: qsTr("Save") + // onClicked: { + // forceActiveFocus() + // PageController.closePage() + // } + // Keys.onEnterPressed: clicked() + // Keys.onReturnPressed: clicked() + // } } diff --git a/client/ui/qml/Pages2/PageProtocolXrayXPaddingSettings.qml b/client/ui/qml/Pages2/PageProtocolXrayXPaddingSettings.qml index b6eaa3f4a..d2d0ad70d 100644 --- a/client/ui/qml/Pages2/PageProtocolXrayXPaddingSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXrayXPaddingSettings.qml @@ -25,7 +25,7 @@ PageType { ListViewType { id: listView anchors.top: backButton.bottom - anchors.bottom: saveButton.top + anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right @@ -194,20 +194,20 @@ PageType { } } - BasicButtonType { - id: saveButton - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin - anchors.leftMargin: 16 - anchors.rightMargin: 16 - text: qsTr("Save") - onClicked: { - forceActiveFocus() - PageController.closePage() - } - Keys.onEnterPressed: clicked() - Keys.onReturnPressed: clicked() - } + // BasicButtonType { + // id: saveButton + // anchors.bottom: parent.bottom + // anchors.left: parent.left + // anchors.right: parent.right + // anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin + // anchors.leftMargin: 16 + // anchors.rightMargin: 16 + // text: qsTr("Save") + // onClicked: { + // forceActiveFocus() + // PageController.closePage() + // } + // Keys.onEnterPressed: clicked() + // Keys.onReturnPressed: clicked() + // } } diff --git a/client/ui/qml/Pages2/PageProtocolXrayXmuxSettings.qml b/client/ui/qml/Pages2/PageProtocolXrayXmuxSettings.qml index 58b9572b7..8376a5cc2 100644 --- a/client/ui/qml/Pages2/PageProtocolXrayXmuxSettings.qml +++ b/client/ui/qml/Pages2/PageProtocolXrayXmuxSettings.qml @@ -25,7 +25,7 @@ PageType { ListViewType { id: listView anchors.top: backButton.bottom - anchors.bottom: saveButton.top + anchors.bottom: parent.bottom anchors.left: parent.left anchors.right: parent.right @@ -182,20 +182,21 @@ PageType { } } - BasicButtonType { - id: saveButton - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin - anchors.leftMargin: 16 - anchors.rightMargin: 16 - text: qsTr("Save") - onClicked: { - forceActiveFocus() - PageController.closePage() - } - Keys.onEnterPressed: clicked() - Keys.onReturnPressed: clicked() - } + // BasicButtonType { + // id: saveButton + // anchors.bottom: parent.bottom + // anchors.left: parent.left + // anchors.right: parent.right + // anchors.bottomMargin: 16 + PageController.safeAreaBottomMargin + // anchors.leftMargin: 16 + // anchors.rightMargin: 16 + // text: qsTr("Save") + // onClicked: { + // forceActiveFocus() + // PageController.closePage() + // } + // Keys.onEnterPressed: clicked() + // Keys.onReturnPressed: clicked() + // } } + diff --git a/client/ui/qml/qml.qrc b/client/ui/qml/qml.qrc index cb84c94ac..bbd1d2e32 100644 --- a/client/ui/qml/qml.qrc +++ b/client/ui/qml/qml.qrc @@ -78,7 +78,7 @@ Pages2/PageProtocolWireGuardSettings.qml Pages2/PageProtocolXraySettings.qml - Pages2/PageProtocolXrayConfigsSettings.qml + Pages2/PageProtocolXraySnapshots.qml Pages2/PageProtocolXrayFlowSettings.qml Pages2/PageProtocolXraySecuritySettings.qml Pages2/PageProtocolXrayTransportSettings.qml