From 07aad8787408d8ff2d28d8e3ace6413d5ca27623 Mon Sep 17 00:00:00 2001 From: dranik Date: Tue, 16 Jun 2026 13:58:22 +0300 Subject: [PATCH] fixed timeout & add message & fix disabled telemt|mtproxy --- .../selfhosted/installUiController.cpp | 15 ++++---- .../selfhosted/installUiController.h | 2 +- .../qml/Pages2/PageServiceMtProxySettings.qml | 36 +++++++++++++++++-- .../qml/Pages2/PageServiceTelemtSettings.qml | 34 +++++++++++++++++- 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/client/ui/controllers/selfhosted/installUiController.cpp b/client/ui/controllers/selfhosted/installUiController.cpp index c4c48e48b..b145f7c32 100644 --- a/client/ui/controllers/selfhosted/installUiController.cpp +++ b/client/ui/controllers/selfhosted/installUiController.cpp @@ -390,20 +390,21 @@ void InstallUiController::refreshContainerStatus(const QString &serverId, int co return; } + using StatusResult = std::pair; // {status, errorCode} InstallController *installController = m_installController; - auto *watcher = new QFutureWatcher(this); - QObject::connect(watcher, &QFutureWatcher::finished, this, [this, watcher]() { - const int status = watcher->result(); + auto *watcher = new QFutureWatcher(this); + QObject::connect(watcher, &QFutureWatcher::finished, this, [this, watcher]() { + const StatusResult result = watcher->result(); watcher->deleteLater(); - emit containerStatusRefreshed(status); + emit containerStatusRefreshed(result.first, result.second); }); - QFuture future = QtConcurrent::run([installController, serverId, container]() -> int { + QFuture future = QtConcurrent::run([installController, serverId, container]() -> StatusResult { int status = 3; const ErrorCode errorCode = installController->queryDockerContainerStatus(serverId, container, status); if (errorCode != ErrorCode::NoError) { - return 3; + return { 3, static_cast(errorCode) }; } - return status; + return { status, static_cast(ErrorCode::NoError) }; }); watcher->setFuture(future); } diff --git a/client/ui/controllers/selfhosted/installUiController.h b/client/ui/controllers/selfhosted/installUiController.h index 25c1fed4d..14d506b72 100644 --- a/client/ui/controllers/selfhosted/installUiController.h +++ b/client/ui/controllers/selfhosted/installUiController.h @@ -114,7 +114,7 @@ signals: void removeAllContainersFinished(const QString &finishedMessage); void removeContainerFinished(const QString &finishedMessage); void setContainerEnabledFinished(bool enabled); - void containerStatusRefreshed(int status); + void containerStatusRefreshed(int status, int errorCode); void containerDiagnosticsRefreshed(bool portReachable, bool upstreamReachable, int clientsConnected, const QString &lastConfigRefresh, const QString &statsEndpoint); void containerSecretFetched(const QString &secret); diff --git a/client/ui/qml/Pages2/PageServiceMtProxySettings.qml b/client/ui/qml/Pages2/PageServiceMtProxySettings.qml index 9fab37e07..a265734b7 100644 --- a/client/ui/qml/Pages2/PageServiceMtProxySettings.qml +++ b/client/ui/qml/Pages2/PageServiceMtProxySettings.qml @@ -21,6 +21,8 @@ PageType { id: root property int containerStatus: 1 + // Last status-query error code (0 = none). 305 = SshTimeoutError → server unreachable. + property int statusErrorCode: 0 property bool isUpdating: false property bool isCheckingStatus: false property bool isFetchingSecret: false @@ -261,6 +263,7 @@ PageType { isCheckingStatus = false isFetchingSecret = false busyIndicatorShown = false + statusErrorCode = 0 PageController.disableControls(false) PageController.showBusyIndicator(false) diagLoading = false @@ -348,13 +351,18 @@ PageType { enabled ? qsTr("MTProxy started") : qsTr("MTProxy stopped")) } - function onContainerStatusRefreshed(status) { + function onContainerStatusRefreshed(status, errorCode) { if (!root.visible) { isCheckingStatus = false isFetchingSecret = false return } containerStatus = status + root.statusErrorCode = errorCode + if (status === 3 && errorCode !== 0) { + PageController.showNotificationMessage( + qsTr("Settings locked: connection timed out (error code %1). Re-open the page to retry.").arg(errorCode)) + } root.savedTransportMode = MtProxyConfigModel.getTransportMode() root.savedTlsDomain = MtProxyConfigModel.getTlsDomain() @@ -842,6 +850,8 @@ PageType { width: settingsListView.width spacing: 0 + readonly property bool fieldsEditable: isEnabled && containerStatus === 1 && !root.pageBusy + function mtProxyActiveSecretForBaseHex(baseHex) { return root.mtProxyClientSecretForTabIndex(baseHex, root.syncedSecretTabIndex, root.savedTlsDomain, MtProxyConfigModel.defaultTlsDomain()) @@ -887,6 +897,21 @@ PageType { } } + CaptionTextType { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 8 + visible: !fieldsEditable && !root.pageBusy + text: (containerStatus === 1 || containerStatus === 2) + ? qsTr("Enable MTProxy to edit settings") + : (statusErrorCode !== 0 + ? qsTr("Settings locked: connection timed out (error code %1). Re-open the page to retry.").arg(statusErrorCode) + : qsTr("Cannot reach the server — settings are unavailable")) + color: AmneziaStyle.color.mutedGray + wrapMode: Text.WordWrap + } + ColumnLayout { Layout.fillWidth: true Layout.topMargin: 16 @@ -921,6 +946,7 @@ PageType { image: "qrc:/images/controls/refresh-cw.svg" imageColor: AmneziaStyle.color.paleGray visible: ServersUiController.isProcessedServerHasWriteAccess() + enabled: fieldsEditable onClicked: { var secretSnapshot = secret showQuestionDrawer( @@ -949,6 +975,7 @@ PageType { TextFieldWithHeaderType { id: publicHostTextField + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1010,6 +1037,7 @@ PageType { TextFieldWithHeaderType { id: portTextField + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1064,6 +1092,7 @@ PageType { TextFieldWithHeaderType { id: tagTextField + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1147,6 +1176,7 @@ PageType { DropDownType { id: transportModeDropDown + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1182,6 +1212,7 @@ PageType { TextFieldWithHeaderType { id: tlsDomainTextField + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1264,6 +1295,7 @@ PageType { Layout.fillWidth: true spacing: 0 visible: advancedHeader.expanded + enabled: fieldsEditable CaptionTextType { Layout.fillWidth: true @@ -1871,7 +1903,7 @@ PageType { Layout.rightMargin: 16 Layout.leftMargin: 16 visible: ServersUiController.isProcessedServerHasWriteAccess() - enabled: !root.mtProxyNetworkBlocked + enabled: fieldsEditable && !root.mtProxyNetworkBlocked text: qsTr("Save") clickedFunc: function () { if (root.mtProxyNetworkBlocked) { diff --git a/client/ui/qml/Pages2/PageServiceTelemtSettings.qml b/client/ui/qml/Pages2/PageServiceTelemtSettings.qml index e96edde5a..26fccc2e5 100644 --- a/client/ui/qml/Pages2/PageServiceTelemtSettings.qml +++ b/client/ui/qml/Pages2/PageServiceTelemtSettings.qml @@ -20,6 +20,7 @@ PageType { id: root property int containerStatus: 1 + property int statusErrorCode: 0 property bool isUpdating: false property bool isCheckingStatus: false property bool isFetchingSecret: false @@ -235,6 +236,7 @@ PageType { isCheckingStatus = false isFetchingSecret = false busyIndicatorShown = false + statusErrorCode = 0 PageController.disableControls(false) PageController.showBusyIndicator(false) diagLoading = false @@ -324,13 +326,18 @@ PageType { enabled ? qsTr("Telemt started") : qsTr("Telemt stopped")) } - function onContainerStatusRefreshed(status) { + function onContainerStatusRefreshed(status, errorCode) { if (!root.visible) { isCheckingStatus = false isFetchingSecret = false return } containerStatus = status + root.statusErrorCode = errorCode + if (status === 3 && errorCode !== 0) { + PageController.showNotificationMessage( + qsTr("Settings locked: connection timed out (error code %1). Re-open the page to retry.").arg(errorCode)) + } root.savedTransportMode = TelemtConfigModel.getTransportMode() root.savedTlsDomain = TelemtConfigModel.getTlsDomain() @@ -817,6 +824,8 @@ PageType { width: settingsListView.width spacing: 0 + readonly property bool fieldsEditable: isEnabled && containerStatus === 1 && !root.pageBusy + function telemtActiveSecretForBaseHex(baseHex) { return root.telemtClientSecretForTabIndex(baseHex, root.syncedSecretTabIndex, root.savedTlsDomain, TelemtConfigModel.defaultTlsDomain()) @@ -850,6 +859,21 @@ PageType { } } + CaptionTextType { + Layout.fillWidth: true + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.bottomMargin: 8 + visible: !fieldsEditable && !root.pageBusy + text: (containerStatus === 1 || containerStatus === 2) + ? qsTr("Enable Telemt to edit settings") + : (statusErrorCode !== 0 + ? qsTr("Settings locked: connection timed out (error code %1). Re-open the page to retry.").arg(statusErrorCode) + : qsTr("Cannot reach the server — settings are unavailable")) + color: AmneziaStyle.color.mutedGray + wrapMode: Text.WordWrap + } + ColumnLayout { Layout.fillWidth: true Layout.topMargin: 16 @@ -884,6 +908,7 @@ PageType { image: "qrc:/images/controls/refresh-cw.svg" imageColor: AmneziaStyle.color.paleGray visible: ServersUiController.isProcessedServerHasWriteAccess() + enabled: fieldsEditable onClicked: { var secretSnapshot = secret showQuestionDrawer( @@ -912,6 +937,7 @@ PageType { TextFieldWithHeaderType { id: publicHostTextField + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -973,6 +999,7 @@ PageType { TextFieldWithHeaderType { id: portTextField + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1021,6 +1048,7 @@ PageType { TextFieldWithHeaderType { id: tagTextField + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1104,6 +1132,7 @@ PageType { DropDownType { id: transportModeDropDown + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1139,6 +1168,7 @@ PageType { TextFieldWithHeaderType { id: tlsDomainTextField + enabled: fieldsEditable Layout.fillWidth: true Layout.leftMargin: 16 Layout.rightMargin: 16 @@ -1221,6 +1251,7 @@ PageType { Layout.fillWidth: true spacing: 0 visible: advancedHeader.expanded + enabled: fieldsEditable CaptionTextType { Layout.fillWidth: true @@ -1646,6 +1677,7 @@ PageType { Layout.rightMargin: 16 Layout.leftMargin: 16 visible: ServersUiController.isProcessedServerHasWriteAccess() + enabled: fieldsEditable text: qsTr("Save") clickedFunc: function () { var portValue = portTextField.textField.text === ""