From 08a8eadb49f94edf59ab6b0f28307bc90fa1eaa0 Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Sun, 1 Jan 2023 21:48:20 +0300 Subject: [PATCH 1/3] added display of a notification that the server is busy installing third-party software - refactoring doInstallAction functions --- client/CMakeLists.txt | 4 +- client/core/scripts_registry.cpp | 1 + client/core/scripts_registry.h | 3 +- client/core/servercontroller.cpp | 34 ++- client/core/servercontroller.h | 3 + client/resources.qrc | 1 + client/server_scripts/check_server_is_busy.sh | 4 + client/server_scripts/install_docker.sh | 2 +- .../ServerConfiguringProgressLogic.cpp | 68 +++-- .../ServerConfiguringProgressLogic.h | 27 +- .../ui/pages_logic/protocols/CloakLogic.cpp | 58 +++-- client/ui/pages_logic/protocols/CloakLogic.h | 4 + .../ui/pages_logic/protocols/OpenVpnLogic.cpp | 58 +++-- .../ui/pages_logic/protocols/OpenVpnLogic.h | 5 + .../protocols/ShadowSocksLogic.cpp | 74 ++++-- .../pages_logic/protocols/ShadowSocksLogic.h | 10 +- .../Pages/PageServerConfiguringProgress.qml | 16 ++ .../ui/qml/Pages/Protocols/PageProtoCloak.qml | 30 ++- .../qml/Pages/Protocols/PageProtoOpenVPN.qml | 32 ++- .../Pages/Protocols/PageProtoShadowSocks.qml | 46 +++- client/ui/uilogic.cpp | 232 +++--------------- client/ui/uilogic.h | 32 --- 22 files changed, 398 insertions(+), 346 deletions(-) create mode 100644 client/server_scripts/check_server_is_busy.sh diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 8aeddc32a..82b3b4fd5 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -21,13 +21,13 @@ set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "Autogen") find_package(Qt6 REQUIRED COMPONENTS Widgets Core Gui Network Xml RemoteObjects Quick Svg QuickControls2 - Core5Compat + Core5Compat Concurrent ) set(LIBS ${LIBS} Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Network Qt6::Xml Qt6::RemoteObjects Qt6::Quick Qt6::Svg Qt6::QuickControls2 - Qt6::Core5Compat + Qt6::Core5Compat Qt6::Concurrent ) qt_standard_project_setup() diff --git a/client/core/scripts_registry.cpp b/client/core/scripts_registry.cpp index 77c056bdb..d33881a24 100644 --- a/client/core/scripts_registry.cpp +++ b/client/core/scripts_registry.cpp @@ -31,6 +31,7 @@ QString amnezia::scriptName(SharedScriptType type) case SharedScriptType::remove_all_containers: return QLatin1String("remove_all_containers.sh"); case SharedScriptType::setup_host_firewall: return QLatin1String("setup_host_firewall.sh"); case SharedScriptType::check_connection: return QLatin1String("check_connection.sh"); + case SharedScriptType::check_server_is_busy: return QLatin1String("check_server_is_busy.sh"); } } diff --git a/client/core/scripts_registry.h b/client/core/scripts_registry.h index 3d69d95ae..9528d763c 100644 --- a/client/core/scripts_registry.h +++ b/client/core/scripts_registry.h @@ -15,7 +15,8 @@ enum SharedScriptType { remove_container, remove_all_containers, setup_host_firewall, - check_connection + check_connection, + check_server_is_busy }; enum ProtocolScriptType { // Protocol scripts diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index c7336b621..ef1511b2f 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include "sftpchannel.h" #include "sshconnectionmanager.h" @@ -528,14 +530,36 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent stdOut += data + "\n"; }; - ErrorCode e = runScript(credentials, - replaceVars(amnezia::scriptData(SharedScriptType::install_docker), - genVarsForScript(credentials)), - cbReadStdOut, cbReadStdErr); + QFutureWatcher watcher; + + QFuture future = QtConcurrent::run([this, &stdOut, &cbReadStdOut, &cbReadStdErr, &credentials]() { + do { + stdOut.clear(); + runScript(credentials, + replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), + genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); + if (!stdOut.isEmpty() || stdOut.contains("Unable to acquire the dpkg frontend lock")) { + emit serverIsBusy(true); + QThread::msleep(1000); + } + } while (!stdOut.isEmpty()); + }); + + watcher.setFuture(future); + + QEventLoop wait; + QObject::connect(&watcher, &QFutureWatcher::finished, &wait, &QEventLoop::quit); + wait.exec(); + + emit serverIsBusy(false); + + ErrorCode error = runScript(credentials, + replaceVars(amnezia::scriptData(SharedScriptType::install_docker), + genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); if (stdOut.contains("command not found")) return ErrorCode::ServerDockerFailedError; - return e; + return error; } ErrorCode ServerController::prepareHostWorker(const ServerCredentials &credentials, DockerContainer container, const QJsonObject &config) diff --git a/client/core/servercontroller.h b/client/core/servercontroller.h index 091eaa524..b151dc548 100644 --- a/client/core/servercontroller.h +++ b/client/core/servercontroller.h @@ -84,6 +84,9 @@ private: std::shared_ptr m_settings; std::shared_ptr m_configurator; + +signals: + void serverIsBusy(const bool isBusy); }; #endif // SERVERCONTROLLER_H diff --git a/client/resources.qrc b/client/resources.qrc index a7e67e398..75a410d01 100644 --- a/client/resources.qrc +++ b/client/resources.qrc @@ -160,5 +160,6 @@ ui/qml/Pages/PageQrDecoderIos.qml server_scripts/website_tor/Dockerfile ui/qml/Pages/PageViewConfig.qml + server_scripts/check_server_is_busy.sh diff --git a/client/server_scripts/check_server_is_busy.sh b/client/server_scripts/check_server_is_busy.sh new file mode 100644 index 000000000..17c278641 --- /dev/null +++ b/client/server_scripts/check_server_is_busy.sh @@ -0,0 +1,4 @@ +pm_apt="/usr/bin/apt-get";\ +if [[ -f "$pm_apt" ]]; then pm=$pm_apt; else exit; fi;\ +if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi;\ +sudo fuser /var/lib/dpkg/lock-frontend \ No newline at end of file diff --git a/client/server_scripts/install_docker.sh b/client/server_scripts/install_docker.sh index baff7cb61..e12ab2c13 100644 --- a/client/server_scripts/install_docker.sh +++ b/client/server_scripts/install_docker.sh @@ -3,7 +3,7 @@ if [[ -f "$pm_apt" ]]; then pm=$pm_apt; docker_pkg="docker.io"; else pm=$pm_yum; if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi;\ docker_service=$(systemctl list-units --full -all | grep docker.service | grep -v inactive | grep -v dead | grep -v failed);\ if [[ -f "$pm_apt" ]]; then export DEBIAN_FRONTEND=noninteractive; fi;\ -if [[ -z "$docker_service" ]]; then sudo $pm update -y -q; sudo $pm install -y -q curl $docker_pkg; fi;\ +if [[ -z "$docker_service" ]]; then sudo $pm update -y -q; sudo $pm install -y -q curl $docker_pkg; fi;\ docker_service=$(systemctl list-units --full -all | grep docker.service | grep -v inactive | grep -v dead | grep -v failed);\ if [[ -z "$docker_service" ]]; then sleep 5 && sudo systemctl start docker && sleep 5; fi;\ docker --version diff --git a/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp b/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp index 32ae366d0..236971811 100644 --- a/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp +++ b/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp @@ -5,6 +5,8 @@ #include #include +#include "core/servercontroller.h" + ServerConfiguringProgressLogic::ServerConfiguringProgressLogic(UiLogic *logic, QObject *parent): PageLogicBase(logic, parent), m_progressBarValue{0}, @@ -13,7 +15,9 @@ ServerConfiguringProgressLogic::ServerConfiguringProgressLogic(UiLogic *logic, Q m_progressBarVisible{true}, m_progressBarMaximium{100}, m_progressBarTextVisible{true}, - m_progressBarText{tr("Configuring...")} + m_progressBarText{tr("Configuring...")}, + m_labelServerBusyVisible{false}, + m_labelServerBusyText{""} { } @@ -30,14 +34,14 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function void { set_pageEnabled(enabled); }; - ButtonFunc button; - LabelFunc info; + ButtonFunc noButton; + LabelFunc noWaitInfo; ProgressFunc progress; - progress.setVisibleFunc = [this] (bool visible) ->void { + progress.setVisibleFunc = [this] (bool visible) -> void { set_progressBarVisible(visible); }; - progress.setValueFunc = [this] (int value) ->void { + progress.setValueFunc = [this] (int value) -> void { set_progressBarValue(value); }; progress.getValueFunc = [this] (void) -> int { @@ -47,8 +51,24 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function void { + set_labelServerBusyText(text); + }; + busyInfo.setVisibleFunc = [this] (bool visible) -> void { + set_labelServerBusyVisible(visible); + }; + return doInstallAction(action, page, progress, noButton, noWaitInfo, busyInfo); +} +ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function &action, + const PageFunc &page, + const ProgressFunc &progress, + const ButtonFunc &button, + const LabelFunc &waitInfo, + const LabelFunc &serverBusyInfo) +{ progress.setVisibleFunc(true); if (page.setEnabledFunc) { page.setEnabledFunc(false); @@ -56,11 +76,11 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function 0) { + if (remainingVal > 0) { QTimer timer1; QEventLoop loop1; @@ -120,8 +158,8 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function &action); + AUTO_PROPERTY(bool, labelServerBusyVisible) + AUTO_PROPERTY(QString, labelServerBusyText) private: struct ProgressFunc { @@ -48,5 +43,23 @@ private: std::function setTextFunc; }; +public: + explicit ServerConfiguringProgressLogic(UiLogic *uiLogic, QObject *parent = nullptr); + ~ServerConfiguringProgressLogic() = default; + + friend class OpenVpnLogic; + friend class ShadowSocksLogic; + friend class CloakLogic; + friend class UiLogic; + + void onUpdatePage() override; + ErrorCode doInstallAction(const std::function &action); + ErrorCode doInstallAction(const std::function &action, + const PageFunc &page, + const ProgressFunc &progress, + const ButtonFunc &button, + const LabelFunc &waitInfo, + const LabelFunc &serverBusyInfo); + }; #endif // SERVER_CONFIGURING_PROGRESS_LOGIC_H diff --git a/client/ui/pages_logic/protocols/CloakLogic.cpp b/client/ui/pages_logic/protocols/CloakLogic.cpp index 590199901..1456e457f 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.cpp +++ b/client/ui/pages_logic/protocols/CloakLogic.cpp @@ -1,7 +1,10 @@ #include "CloakLogic.h" -#include "core/servercontroller.h" + #include -#include "../../uilogic.h" + +#include "core/servercontroller.h" +#include "ui/uilogic.h" +#include "ui/pages_logic/ServerConfiguringProgressLogic.h" using namespace amnezia; using namespace PageEnumNS; @@ -59,40 +62,59 @@ void CloakLogic::onPushButtonSaveClicked() QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::Cloak), protocolConfig); - UiLogic::PageFunc page_func; - page_func.setEnabledFunc = [this] (bool enabled) -> void { + ServerConfiguringProgressLogic::PageFunc pageFunc; + pageFunc.setEnabledFunc = [this] (bool enabled) -> void { set_pageEnabled(enabled); }; - UiLogic::ButtonFunc pushButton_save_func; - pushButton_save_func.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ButtonFunc saveButtonFunc; + saveButtonFunc.setVisibleFunc = [this] (bool visible) -> void { set_pushButtonSaveVisible(visible); }; - UiLogic::LabelFunc label_info_func; - label_info_func.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::LabelFunc waitInfoFunc; + waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void { set_labelInfoVisible(visible); }; - label_info_func.setTextFunc = [this] (const QString& text) ->void { + waitInfoFunc.setTextFunc = [this] (const QString& text) -> void { set_labelInfoText(text); }; - UiLogic::ProgressFunc progressBar_reset; - progressBar_reset.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ProgressFunc progressBarFunc; + progressBarFunc.setVisibleFunc = [this] (bool visible) -> void { set_progressBarResetVisible(visible); }; - progressBar_reset.setValueFunc = [this] (int value) ->void { + progressBarFunc.setValueFunc = [this] (int value) -> void { set_progressBarResetValue(value); }; - progressBar_reset.getValueFunc = [this] (void) -> int { + progressBarFunc.getValueFunc = [this] (void) -> int { return progressBarResetValue(); }; - progressBar_reset.getMaximiumFunc = [this] (void) -> int { + progressBarFunc.getMaximiumFunc = [this] (void) -> int { return progressBarResetMaximium(); }; + progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void { + set_progressBarTextVisible(visible); + }; + progressBarFunc.setTextFunc = [this] (const QString& text) -> void { + set_progressBarText(text); + }; - ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + ServerConfiguringProgressLogic::LabelFunc busyInfoFuncy; + busyInfoFuncy.setTextFunc = [this] (const QString& text) -> void { + set_labelServerBusyText(text); + }; + busyInfoFuncy.setVisibleFunc = [this] (bool visible) -> void { + set_labelServerBusyVisible(visible); + }; + + progressBarFunc.setTextVisibleFunc(true); + progressBarFunc.setTextFunc(QString("Configuring...")); + ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), + uiLogic()->selectedDockerContainer, + containerConfig, + newContainerConfig); }, - page_func, progressBar_reset, - pushButton_save_func, label_info_func); + pageFunc, progressBarFunc, + saveButtonFunc, waitInfoFunc, busyInfoFuncy); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); diff --git a/client/ui/pages_logic/protocols/CloakLogic.h b/client/ui/pages_logic/protocols/CloakLogic.h index d88252c8f..57afb5b0f 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.h +++ b/client/ui/pages_logic/protocols/CloakLogic.h @@ -20,7 +20,11 @@ class CloakLogic : public PageProtocolLogicBase AUTO_PROPERTY(QString, labelInfoText) AUTO_PROPERTY(int, progressBarResetValue) AUTO_PROPERTY(int, progressBarResetMaximium) + AUTO_PROPERTY(bool, progressBarTextVisible) + AUTO_PROPERTY(QString, progressBarText) + AUTO_PROPERTY(bool, labelServerBusyVisible) + AUTO_PROPERTY(QString, labelServerBusyText) public: Q_INVOKABLE void onPushButtonSaveClicked(); diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp index 91f211511..a25fd1342 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp @@ -1,7 +1,10 @@ #include "OpenVpnLogic.h" -#include "core/servercontroller.h" + #include -#include "../../uilogic.h" + +#include "core/servercontroller.h" +#include "ui/uilogic.h" +#include "ui/pages_logic/ServerConfiguringProgressLogic.h" using namespace amnezia; using namespace PageEnumNS; @@ -98,40 +101,59 @@ void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::OpenVpn), protocolConfig); - UiLogic::PageFunc page_proto_openvpn; - page_proto_openvpn.setEnabledFunc = [this] (bool enabled) -> void { + ServerConfiguringProgressLogic::PageFunc pageFunc; + pageFunc.setEnabledFunc = [this] (bool enabled) -> void { set_pageEnabled(enabled); }; - UiLogic::ButtonFunc pushButton_proto_openvpn_save; - pushButton_proto_openvpn_save.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ButtonFunc saveButtonFunc; + saveButtonFunc.setVisibleFunc = [this] (bool visible) -> void { set_pushButtonSaveVisible(visible); }; - UiLogic::LabelFunc label_proto_openvpn_info; - label_proto_openvpn_info.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::LabelFunc waitInfoFunc; + waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void { set_labelProtoOpenVpnInfoVisible(visible); }; - label_proto_openvpn_info.setTextFunc = [this] (const QString& text) ->void { + waitInfoFunc.setTextFunc = [this] (const QString& text) -> void { set_labelProtoOpenVpnInfoText(text); }; - UiLogic::ProgressFunc progressBar_proto_openvpn_reset; - progressBar_proto_openvpn_reset.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ProgressFunc progressBarFunc; + progressBarFunc.setVisibleFunc = [this] (bool visible) -> void { set_progressBarResetVisible(visible); }; - progressBar_proto_openvpn_reset.setValueFunc = [this] (int value) ->void { + progressBarFunc.setValueFunc = [this] (int value) -> void { set_progressBarResetValue(value); }; - progressBar_proto_openvpn_reset.getValueFunc = [this] (void) -> int { + progressBarFunc.getValueFunc = [this] (void) -> int { return progressBarResetValue(); }; - progressBar_proto_openvpn_reset.getMaximiumFunc = [this] (void) -> int { + progressBarFunc.getMaximiumFunc = [this] (void) -> int { return progressBarResetMaximium(); }; + progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void { + set_progressBarTextVisible(visible); + }; + progressBarFunc.setTextFunc = [this] (const QString& text) -> void { + set_progressBarText(text); + }; - ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + ServerConfiguringProgressLogic::LabelFunc busyInfoFuncy; + busyInfoFuncy.setTextFunc = [this] (const QString& text) -> void { + set_labelServerBusyText(text); + }; + busyInfoFuncy.setVisibleFunc = [this] (bool visible) -> void { + set_labelServerBusyVisible(visible); + }; + + progressBarFunc.setTextVisibleFunc(true); + progressBarFunc.setTextFunc(QString("Configuring...")); + ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), + uiLogic()->selectedDockerContainer, + containerConfig, + newContainerConfig); }, - page_proto_openvpn, progressBar_proto_openvpn_reset, - pushButton_proto_openvpn_save, label_proto_openvpn_info); + pageFunc, progressBarFunc, + saveButtonFunc, waitInfoFunc, busyInfoFuncy); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.h b/client/ui/pages_logic/protocols/OpenVpnLogic.h index 23c2dd4d7..1dafe5ee2 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.h +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.h @@ -34,6 +34,11 @@ class OpenVpnLogic : public PageProtocolLogicBase AUTO_PROPERTY(QString, labelProtoOpenVpnInfoText) AUTO_PROPERTY(int, progressBarResetValue) AUTO_PROPERTY(int, progressBarResetMaximium) + AUTO_PROPERTY(bool, progressBarTextVisible) + AUTO_PROPERTY(QString, progressBarText) + + AUTO_PROPERTY(bool, labelServerBusyVisible) + AUTO_PROPERTY(QString, labelServerBusyText) public: Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked(); diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp index 1d5da9366..c2575a4d2 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp @@ -1,7 +1,10 @@ #include "ShadowSocksLogic.h" -#include "core/servercontroller.h" + #include -#include "../../uilogic.h" + +#include "core/servercontroller.h" +#include "ui/pages_logic/ServerConfiguringProgressLogic.h" +#include "ui/uilogic.h" using namespace amnezia; using namespace PageEnumNS; @@ -11,12 +14,12 @@ ShadowSocksLogic::ShadowSocksLogic(UiLogic *logic, QObject *parent): m_comboBoxCipherText{"chacha20-poly1305"}, m_lineEditPortText{}, m_pushButtonSaveVisible{false}, - m_progressBaResetVisible{false}, + m_progressBarResetVisible{false}, m_lineEditPortEnabled{false}, m_labelInfoVisible{true}, m_labelInfoText{}, - m_progressBaResetValue{0}, - m_progressBaResetMaximium{100} + m_progressBarResetValue{0}, + m_progressBarResetMaximium{100} { } @@ -25,7 +28,7 @@ void ShadowSocksLogic::updateProtocolPage(const QJsonObject &ssConfig, DockerCon { set_pageEnabled(haveAuthData); set_pushButtonSaveVisible(haveAuthData); - set_progressBaResetVisible(haveAuthData); + set_progressBarResetVisible(haveAuthData); set_comboBoxCipherText(ssConfig.value(config_key::cipher). toString(protocols::shadowsocks::defaultCipher)); @@ -51,40 +54,59 @@ void ShadowSocksLogic::onPushButtonSaveClicked() QJsonObject containerConfig = m_settings->containerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer); QJsonObject newContainerConfig = containerConfig; newContainerConfig.insert(ProtocolProps::protoToString(Proto::ShadowSocks), protocolConfig); - UiLogic::PageFunc page_proto_shadowsocks; - page_proto_shadowsocks.setEnabledFunc = [this] (bool enabled) -> void { + ServerConfiguringProgressLogic::PageFunc pageFunc; + pageFunc.setEnabledFunc = [this] (bool enabled) -> void { set_pageEnabled(enabled); }; - UiLogic::ButtonFunc pushButton_proto_shadowsocks_save; - pushButton_proto_shadowsocks_save.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::ButtonFunc saveButtonFunc; + saveButtonFunc.setVisibleFunc = [this] (bool visible) -> void { set_pushButtonSaveVisible(visible); }; - UiLogic::LabelFunc label_proto_shadowsocks_info; - label_proto_shadowsocks_info.setVisibleFunc = [this] (bool visible) ->void { + ServerConfiguringProgressLogic::LabelFunc waitInfoFunc; + waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void { set_labelInfoVisible(visible); }; - label_proto_shadowsocks_info.setTextFunc = [this] (const QString& text) ->void { + waitInfoFunc.setTextFunc = [this] (const QString& text) -> void { set_labelInfoText(text); }; - UiLogic::ProgressFunc progressBar_reset; - progressBar_reset.setVisibleFunc = [this] (bool visible) ->void { - set_progressBaResetVisible(visible); + ServerConfiguringProgressLogic::ProgressFunc progressBarFunc; + progressBarFunc.setVisibleFunc = [this] (bool visible) -> void { + set_progressBarResetVisible(visible); }; - progressBar_reset.setValueFunc = [this] (int value) ->void { - set_progressBaResetValue(value); + progressBarFunc.setValueFunc = [this] (int value) -> void { + set_progressBarResetValue(value); }; - progressBar_reset.getValueFunc = [this] (void) -> int { - return progressBaResetValue(); + progressBarFunc.getValueFunc = [this] (void) -> int { + return progressBarResetValue(); }; - progressBar_reset.getMaximiumFunc = [this] (void) -> int { - return progressBaResetMaximium(); + progressBarFunc.getMaximiumFunc = [this] (void) -> int { + return progressBarResetMaximium(); + }; + progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void { + set_progressBarTextVisible(visible); + }; + progressBarFunc.setTextFunc = [this] (const QString& text) -> void { + set_progressBarText(text); }; - ErrorCode e = uiLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ - return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), uiLogic()->selectedDockerContainer, containerConfig, newContainerConfig); + ServerConfiguringProgressLogic::LabelFunc busyInfoFuncy; + busyInfoFuncy.setTextFunc = [this] (const QString& text) -> void { + set_labelServerBusyText(text); + }; + busyInfoFuncy.setVisibleFunc = [this] (bool visible) -> void { + set_labelServerBusyVisible(visible); + }; + + progressBarFunc.setTextVisibleFunc(true); + progressBarFunc.setTextFunc(QString("Configuring...")); + ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ + return m_serverController->updateContainer(m_settings->serverCredentials(uiLogic()->selectedServerIndex), + uiLogic()->selectedDockerContainer, + containerConfig, + newContainerConfig); }, - page_proto_shadowsocks, progressBar_reset, - pushButton_proto_shadowsocks_save, label_proto_shadowsocks_info); + pageFunc, progressBarFunc, + saveButtonFunc, waitInfoFunc, busyInfoFuncy); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.h b/client/ui/pages_logic/protocols/ShadowSocksLogic.h index 4e5668254..1300511f5 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.h +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.h @@ -12,13 +12,17 @@ class ShadowSocksLogic : public PageProtocolLogicBase AUTO_PROPERTY(QString, comboBoxCipherText) AUTO_PROPERTY(QString, lineEditPortText) AUTO_PROPERTY(bool, pushButtonSaveVisible) - AUTO_PROPERTY(bool, progressBaResetVisible) + AUTO_PROPERTY(bool, progressBarResetVisible) AUTO_PROPERTY(bool, lineEditPortEnabled) AUTO_PROPERTY(bool, labelInfoVisible) AUTO_PROPERTY(QString, labelInfoText) - AUTO_PROPERTY(int, progressBaResetValue) - AUTO_PROPERTY(int, progressBaResetMaximium) + AUTO_PROPERTY(int, progressBarResetValue) + AUTO_PROPERTY(int, progressBarResetMaximium) + AUTO_PROPERTY(bool, progressBarTextVisible) + AUTO_PROPERTY(QString, progressBarText) + AUTO_PROPERTY(bool, labelServerBusyVisible) + AUTO_PROPERTY(QString, labelServerBusyText) public: Q_INVOKABLE void onPushButtonSaveClicked(); diff --git a/client/ui/qml/Pages/PageServerConfiguringProgress.qml b/client/ui/qml/Pages/PageServerConfiguringProgress.qml index 1cd154caf..e481dbfe7 100644 --- a/client/ui/qml/Pages/PageServerConfiguringProgress.qml +++ b/client/ui/qml/Pages/PageServerConfiguringProgress.qml @@ -27,6 +27,22 @@ PageBase { horizontalAlignment: Text.AlignHCenter } + LabelType { + id: labelServerBusy + x: 0 + anchors.top: label.bottom + anchors.topMargin: 30 + + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + + width: parent.width - 40 + height: 41 + + text: ServerConfiguringProgressLogic.labelServerBusyText + visible: ServerConfiguringProgressLogic.labelServerBusyVisible + } + LabelType { anchors.bottom: pr.top anchors.bottomMargin: 20 diff --git a/client/ui/qml/Pages/Protocols/PageProtoCloak.qml b/client/ui/qml/Pages/Protocols/PageProtoCloak.qml index 01ad4f81f..17dc829a8 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoCloak.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoCloak.qml @@ -14,6 +14,7 @@ PageProtocolBase { enabled: logic.pageEnabled BackButton { id: back + enabled: logic.pageEnabled } Caption { @@ -110,12 +111,20 @@ PageProtocolBase { } } + LabelType { + id: label_server_busy + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true + visible: logic.labelServerBusyVisible + text: logic.labelServerBusyText + } + LabelType { id: label_proto_cloak_info - x: 30 - anchors.bottom: pb_save.top - anchors.bottomMargin: 10 - width: parent.width - 40 + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true visible: logic.labelInfoVisible text: logic.labelInfoText } @@ -146,6 +155,19 @@ PageProtocolBase { } } visible: logic.progressBarResetVisible + LabelType { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: logic.progressBarText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.styleName: "normal" + font.pixelSize: 16 + color: "#D4D4D4" + visible: logic.progressBarTextVisible + } } BlueButtonType { id: pb_save diff --git a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml index 8387b9fe8..a644bf596 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml @@ -13,6 +13,7 @@ PageProtocolBase { BackButton { id: back + enabled: logic.pageEnabled } Caption { id: caption @@ -345,9 +346,19 @@ PageProtocolBase { } LabelType { - id: label_proto_openvpn_info + id: label_server_busy + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true + visible: logic.labelServerBusyVisible + text: logic.labelServerBusyText + } - height: 41 + LabelType { + id: label_proto_openvpn_info + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true visible: logic.labelProtoOpenVpnInfoVisible text: logic.labelProtoOpenVpnInfoText } @@ -395,11 +406,20 @@ PageProtocolBase { } } } - + LabelType { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: logic.progressBarText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.styleName: "normal" + font.pixelSize: 16 + color: "#D4D4D4" + visible: logic.progressBarTextVisible + } } - } - } - } diff --git a/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml b/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml index e2726106e..3fe0df26d 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml @@ -13,6 +13,7 @@ PageProtocolBase { BackButton { id: back + enabled: logic.pageEnabled } Caption { @@ -88,27 +89,33 @@ PageProtocolBase { Item { Layout.fillHeight: true } - } + LabelType { + id: label_server_busy + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true + visible: logic.labelServerBusyVisible + text: logic.labelServerBusyText + } - LabelType { - id: label_proto_shadowsocks_info - x: 30 - anchors.bottom: pb_save.top - anchors.bottomMargin: 10 - width: parent.width - 40 - height: 41 - visible: logic.labelInfoVisible - text: logic.labelInfoText + LabelType { + id: label_proto_shadowsocks_info + horizontalAlignment: Text.AlignHCenter + Layout.maximumWidth: parent.width + Layout.fillWidth: true + visible: logic.labelInfoVisible + text: logic.labelInfoText + } } ProgressBar { id: progressBar_reset anchors.fill: pb_save from: 0 - to: logic.progressBaResetMaximium - value: logic.progressBaResetValue - visible: logic.progressBaResetVisible + to: logic.progressBarResetMaximium + value: logic.progressBarResetValue + visible: logic.progressBarResetVisible background: Rectangle { implicitWidth: parent.width implicitHeight: parent.height @@ -126,6 +133,19 @@ PageProtocolBase { color: Qt.rgba(255, 255, 255, 0.15); } } + LabelType { + anchors.left: parent.left + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + text: logic.progressBarText + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + font.family: "Lato" + font.styleName: "normal" + font.pixelSize: 16 + color: "#D4D4D4" + visible: logic.progressBarTextVisible + } } BlueButtonType { diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index e336fa768..9d43f4140 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -303,44 +303,62 @@ void UiLogic::installServer(QMap &containers) loop.exec(); qApp->processEvents(); - PageFunc page_new_server_configuring; - page_new_server_configuring.setEnabledFunc = [this] (bool enabled) -> void { + ServerConfiguringProgressLogic::PageFunc pageFunc; + pageFunc.setEnabledFunc = [this] (bool enabled) -> void { pageLogic()->set_pageEnabled(enabled); }; - ButtonFunc no_button; - LabelFunc label_new_server_configuring_wait_info; - label_new_server_configuring_wait_info.setTextFunc = [this] (const QString& text) -> void { + + ServerConfiguringProgressLogic::ButtonFunc noButton; + + ServerConfiguringProgressLogic::LabelFunc waitInfoFunc; + waitInfoFunc.setTextFunc = [this] (const QString& text) -> void { pageLogic()->set_labelWaitInfoText(text); }; - label_new_server_configuring_wait_info.setVisibleFunc = [this] (bool visible) ->void { + waitInfoFunc.setVisibleFunc = [this] (bool visible) -> void { pageLogic()->set_labelWaitInfoVisible(visible); }; - ProgressFunc progressBar_new_server_configuring; - progressBar_new_server_configuring.setVisibleFunc = [this] (bool visible) ->void { + + ServerConfiguringProgressLogic::ProgressFunc progressBarFunc; + progressBarFunc.setVisibleFunc = [this] (bool visible) -> void { pageLogic()->set_progressBarVisible(visible); }; - progressBar_new_server_configuring.setValueFunc = [this] (int value) ->void { + progressBarFunc.setValueFunc = [this] (int value) -> void { pageLogic()->set_progressBarValue(value); }; - progressBar_new_server_configuring.getValueFunc = [this] (void) -> int { + progressBarFunc.getValueFunc = [this] (void) -> int { return pageLogic()->progressBarValue(); }; - progressBar_new_server_configuring.getMaximiumFunc = [this] (void) -> int { + progressBarFunc.getMaximiumFunc = [this] (void) -> int { return pageLogic()->progressBarMaximium(); }; - progressBar_new_server_configuring.setTextVisibleFunc = [this] (bool visible) ->void { + progressBarFunc.setTextVisibleFunc = [this] (bool visible) -> void { pageLogic()->set_progressBarTextVisible(visible); }; - progressBar_new_server_configuring.setTextFunc = [this] (const QString& text) ->void { + progressBarFunc.setTextFunc = [this] (const QString& text) -> void { pageLogic()->set_progressBarText(text); }; - bool ok = installContainers(installCredentials, containers, - page_new_server_configuring, - progressBar_new_server_configuring, - no_button, - label_new_server_configuring_wait_info); - if (ok) { + ServerConfiguringProgressLogic::LabelFunc busyInfoFunc; + busyInfoFunc.setTextFunc = [this] (const QString& text) -> void { + pageLogic()->set_labelServerBusyText(text); + }; + busyInfoFunc.setVisibleFunc = [this] (bool visible) -> void { + pageLogic()->set_labelServerBusyVisible(visible); + }; + + int count = 0; + ErrorCode error; + for (QMap::iterator i = containers.begin(); i != containers.end(); i++, count++) { + progressBarFunc.setTextFunc(QString("Installing %1 %2 %3").arg(count+1).arg(tr("of")).arg(containers.size())); + + error = pageLogic()->doInstallAction([&] () { + return m_serverController->setupContainer(installCredentials, i.key(), i.value()); + }, pageFunc, progressBarFunc, noButton, waitInfoFunc, busyInfoFunc); + + m_serverController->disconnectFromHost(installCredentials); + } + + if (error == ErrorCode::NoError) { QJsonObject server; server.insert(config_key::hostName, installCredentials.hostName); server.insert(config_key::userName, installCredentials.userName); @@ -367,182 +385,6 @@ void UiLogic::installServer(QMap &containers) } } -bool UiLogic::installContainers(ServerCredentials credentials, - QMap &containers, - const PageFunc &page, - const ProgressFunc &progress, - const ButtonFunc &button, - const LabelFunc &info) -{ - if (!progress.setValueFunc) return false; - - if (page.setEnabledFunc) { - page.setEnabledFunc(false); - } - if (button.setVisibleFunc) { - button.setVisibleFunc(false); - } - - if (info.setVisibleFunc) { - info.setVisibleFunc(true); - } - if (info.setTextFunc) { - info.setTextFunc(tr("Please wait, configuring process may take up to 5 minutes")); - } - - int cnt = 0; - for (QMap::iterator i = containers.begin(); i != containers.end(); i++, cnt++) { - QTimer timer; - connect(&timer, &QTimer::timeout, [progress](){ - progress.setValueFunc(progress.getValueFunc() + 1); - }); - - progress.setValueFunc(0); - timer.start(1000); - - progress.setTextVisibleFunc(true); - progress.setTextFunc(QString("Installing %1 %2 %3").arg(cnt+1).arg(tr("of")).arg(containers.size())); - - ErrorCode e = m_serverController->setupContainer(credentials, i.key(), i.value()); - qDebug() << "Setup server finished with code" << e; - m_serverController->disconnectFromHost(credentials); - - if (e) { - if (page.setEnabledFunc) { - page.setEnabledFunc(true); - } - if (button.setVisibleFunc) { - button.setVisibleFunc(true); - } - if (info.setVisibleFunc) { - info.setVisibleFunc(false); - } - - QMessageBox::warning(nullptr, APPLICATION_NAME, - tr("Error occurred while configuring server.") + "\n" + - errorString(e)); - - return false; - } - - // just ui progressbar tweak - timer.stop(); - - int remaining_val = progress.getMaximiumFunc() - progress.getValueFunc(); - - if (remaining_val > 0) { - QTimer timer1; - QEventLoop loop1; - - connect(&timer1, &QTimer::timeout, [&](){ - progress.setValueFunc(progress.getValueFunc() + 1); - if (progress.getValueFunc() >= progress.getMaximiumFunc()) { - loop1.quit(); - } - }); - - timer1.start(5); - loop1.exec(); - } - } - - - if (button.setVisibleFunc) { - button.setVisibleFunc(true); - } - if (page.setEnabledFunc) { - page.setEnabledFunc(true); - } - if (info.setTextFunc) { - info.setTextFunc(tr("Amnezia server installed")); - } - - return true; -} - -ErrorCode UiLogic::doInstallAction(const std::function &action, - const PageFunc &page, - const ProgressFunc &progress, - const ButtonFunc &button, - const LabelFunc &info) -{ - progress.setVisibleFunc(true); - if (page.setEnabledFunc) { - page.setEnabledFunc(false); - } - if (button.setVisibleFunc) { - button.setVisibleFunc(false); - } - if (info.setVisibleFunc) { - info.setVisibleFunc(true); - } - if (info.setTextFunc) { - info.setTextFunc(tr("Please wait, configuring process may take up to 5 minutes")); - } - - QTimer timer; - connect(&timer, &QTimer::timeout, [progress](){ - progress.setValueFunc(progress.getValueFunc() + 1); - }); - - progress.setValueFunc(0); - timer.start(1000); - - ErrorCode e = action(); - qDebug() << "doInstallAction finished with code" << e; - - if (e) { - if (page.setEnabledFunc) { - page.setEnabledFunc(true); - } - if (button.setVisibleFunc) { - button.setVisibleFunc(true); - } - if (info.setVisibleFunc) { - info.setVisibleFunc(false); - } - QMessageBox::warning(nullptr, APPLICATION_NAME, - tr("Error occurred while configuring server.") + "\n" + - errorString(e)); - - progress.setVisibleFunc(false); - return e; - } - - // just ui progressbar tweak - timer.stop(); - - int remaining_val = progress.getMaximiumFunc() - progress.getValueFunc(); - - if (remaining_val > 0) { - QTimer timer1; - QEventLoop loop1; - - connect(&timer1, &QTimer::timeout, [&](){ - progress.setValueFunc(progress.getValueFunc() + 1); - if (progress.getValueFunc() >= progress.getMaximiumFunc()) { - loop1.quit(); - } - }); - - timer1.start(5); - loop1.exec(); - } - - - progress.setVisibleFunc(false); - if (button.setVisibleFunc) { - button.setVisibleFunc(true); - } - if (page.setEnabledFunc) { - page.setEnabledFunc(true); - } - if (info.setTextFunc) { - info.setTextFunc(tr("Operation finished")); - } - return ErrorCode::NoError; -} - PageProtocolLogicBase *UiLogic::protocolLogic(Proto p) { PageProtocolLogicBase *logic = m_protocolLogicMap.value(p); diff --git a/client/ui/uilogic.h b/client/ui/uilogic.h index 82f2d6ea0..4cc006dd4 100644 --- a/client/ui/uilogic.h +++ b/client/ui/uilogic.h @@ -136,38 +136,6 @@ private slots: private: PageEnumNS::Page currentPage(); - struct ProgressFunc { - std::function setVisibleFunc; - std::function setValueFunc; - std::function getValueFunc; - std::function getMaximiumFunc; - std::function setTextVisibleFunc; - std::function setTextFunc; - }; - struct PageFunc { - std::function setEnabledFunc; - }; - struct ButtonFunc { - std::function setVisibleFunc; - }; - struct LabelFunc { - std::function setVisibleFunc; - std::function setTextFunc; - }; - - bool installContainers(ServerCredentials credentials, - QMap &containers, - const PageFunc& page, - const ProgressFunc& progress, - const ButtonFunc& button, - const LabelFunc& info); - - ErrorCode doInstallAction(const std::function &action, - const PageFunc& page, - const ProgressFunc& progress, - const ButtonFunc& button, - const LabelFunc& info); - public: Q_INVOKABLE PageProtocolLogicBase *protocolLogic(Proto p); From 6ec090ea0dd5037e25de3af39d5e45df9d57511a Mon Sep 17 00:00:00 2001 From: "vladimir.kuznetsov" Date: Mon, 2 Jan 2023 17:32:27 +0300 Subject: [PATCH 2/3] added a "Cancel" button to interrupt the server configuration process when it is found that it is busy installing other software --- client/core/defs.h | 1 + client/core/errorstrings.cpp | 1 + client/core/servercontroller.cpp | 20 ++++++- client/core/servercontroller.h | 2 + .../ServerConfiguringProgressLogic.cpp | 55 ++++++++++++++----- .../ServerConfiguringProgressLogic.h | 12 +++- .../ui/pages_logic/protocols/CloakLogic.cpp | 13 ++++- client/ui/pages_logic/protocols/CloakLogic.h | 4 ++ .../ui/pages_logic/protocols/OpenVpnLogic.cpp | 15 ++++- .../ui/pages_logic/protocols/OpenVpnLogic.h | 5 +- .../protocols/ShadowSocksLogic.cpp | 13 ++++- .../pages_logic/protocols/ShadowSocksLogic.h | 4 ++ .../Pages/PageServerConfiguringProgress.qml | 20 +++++-- .../ui/qml/Pages/Protocols/PageProtoCloak.qml | 10 +++- .../qml/Pages/Protocols/PageProtoOpenVPN.qml | 49 +++++++++++------ .../Pages/Protocols/PageProtoShadowSocks.qml | 10 ++++ client/ui/uilogic.cpp | 7 ++- 17 files changed, 193 insertions(+), 48 deletions(-) diff --git a/client/core/defs.h b/client/core/defs.h index 5845fd3c4..3f8614012 100644 --- a/client/core/defs.h +++ b/client/core/defs.h @@ -31,6 +31,7 @@ enum ErrorCode ServerPortAlreadyAllocatedError, ServerContainerMissingError, ServerDockerFailedError, + ServerCancelInstallation, // Ssh connection errors SshSocketError, SshTimeoutError, SshProtocolError, diff --git a/client/core/errorstrings.cpp b/client/core/errorstrings.cpp index 722dd4b40..1e7eb3958 100644 --- a/client/core/errorstrings.cpp +++ b/client/core/errorstrings.cpp @@ -15,6 +15,7 @@ QString errorString(ErrorCode code){ case(ServerPortAlreadyAllocatedError): return QObject::tr("Server port already used. Check for another software"); case(ServerContainerMissingError): return QObject::tr("Server error: Docker container missing"); case(ServerDockerFailedError): return QObject::tr("Server error: Docker failed"); + case(ServerCancelInstallation): return QObject::tr("Installation canceled by user"); // Ssh connection errors case(SshSocketError): return QObject::tr("Ssh connection error"); diff --git a/client/core/servercontroller.cpp b/client/core/servercontroller.cpp index ef1511b2f..c9d4f0deb 100644 --- a/client/core/servercontroller.cpp +++ b/client/core/servercontroller.cpp @@ -530,10 +530,13 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent stdOut += data + "\n"; }; - QFutureWatcher watcher; + QFutureWatcher watcher; - QFuture future = QtConcurrent::run([this, &stdOut, &cbReadStdOut, &cbReadStdErr, &credentials]() { + QFuture future = QtConcurrent::run([this, &stdOut, &cbReadStdOut, &cbReadStdErr, &credentials]() { do { + if (m_cancelInstallation) { + return ErrorCode::ServerCancelInstallation; + } stdOut.clear(); runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::check_server_is_busy), @@ -543,16 +546,22 @@ ErrorCode ServerController::installDockerWorker(const ServerCredentials &credent QThread::msleep(1000); } } while (!stdOut.isEmpty()); + return ErrorCode::NoError; }); watcher.setFuture(future); QEventLoop wait; - QObject::connect(&watcher, &QFutureWatcher::finished, &wait, &QEventLoop::quit); + QObject::connect(&watcher, &QFutureWatcher::finished, &wait, &QEventLoop::quit); wait.exec(); + m_cancelInstallation = false; emit serverIsBusy(false); + if (future.result() != ErrorCode::NoError) { + return future.result(); + } + ErrorCode error = runScript(credentials, replaceVars(amnezia::scriptData(SharedScriptType::install_docker), genVarsForScript(credentials)), cbReadStdOut, cbReadStdErr); @@ -820,6 +829,11 @@ SshConnection *ServerController::connectToHost(const SshConnectionParameters &ss return client; } +void ServerController::setCancelInstallation(const bool cancel) +{ + m_cancelInstallation = cancel; +} + void ServerController::disconnectFromHost(const ServerCredentials &credentials) { SshConnection *client = acquireConnection(sshParams(credentials)); diff --git a/client/core/servercontroller.h b/client/core/servercontroller.h index b151dc548..c64401daf 100644 --- a/client/core/servercontroller.h +++ b/client/core/servercontroller.h @@ -73,6 +73,7 @@ public: QString checkSshConnection(const ServerCredentials &credentials, ErrorCode *errorCode = nullptr); QSsh::SshConnection *connectToHost(const QSsh::SshConnectionParameters &sshParams); + void setCancelInstallation(const bool cancel); private: ErrorCode installDockerWorker(const ServerCredentials &credentials, DockerContainer container); @@ -85,6 +86,7 @@ private: std::shared_ptr m_settings; std::shared_ptr m_configurator; + bool m_cancelInstallation = false; signals: void serverIsBusy(const bool isBusy); }; diff --git a/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp b/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp index 236971811..c6e7085b4 100644 --- a/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp +++ b/client/ui/pages_logic/ServerConfiguringProgressLogic.cpp @@ -59,22 +59,28 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function void { + set_pushButtonCancelVisible(visible); + }; + + return doInstallAction(action, page, progress, noButton, noWaitInfo, busyInfo, cancelButton); } ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function &action, const PageFunc &page, const ProgressFunc &progress, - const ButtonFunc &button, + const ButtonFunc &saveButton, const LabelFunc &waitInfo, - const LabelFunc &serverBusyInfo) + const LabelFunc &serverBusyInfo, + const ButtonFunc &cancelButton) { progress.setVisibleFunc(true); if (page.setEnabledFunc) { page.setEnabledFunc(false); } - if (button.setVisibleFunc) { - button.setVisibleFunc(false); + if (saveButton.setVisibleFunc) { + saveButton.setVisibleFunc(false); } if (waitInfo.setVisibleFunc) { waitInfo.setVisibleFunc(true); @@ -91,33 +97,47 @@ ErrorCode ServerConfiguringProgressLogic::doInstallAction(const std::function &action, const PageFunc &page, const ProgressFunc &progress, - const ButtonFunc &button, + const ButtonFunc &saveButton, const LabelFunc &waitInfo, - const LabelFunc &serverBusyInfo); + const LabelFunc &serverBusyInfo, + const ButtonFunc &cancelButton); + +signals: + void cancelDoInstallAction(const bool cancel); }; #endif // SERVER_CONFIGURING_PROGRESS_LOGIC_H diff --git a/client/ui/pages_logic/protocols/CloakLogic.cpp b/client/ui/pages_logic/protocols/CloakLogic.cpp index 1456e457f..6e1790132 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.cpp +++ b/client/ui/pages_logic/protocols/CloakLogic.cpp @@ -105,6 +105,11 @@ void CloakLogic::onPushButtonSaveClicked() set_labelServerBusyVisible(visible); }; + ServerConfiguringProgressLogic::ButtonFunc cancelButtonFunc; + cancelButtonFunc.setVisibleFunc = [this] (bool visible) -> void { + set_pushButtonCancelVisible(visible); + }; + progressBarFunc.setTextVisibleFunc(true); progressBarFunc.setTextFunc(QString("Configuring...")); ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ @@ -114,7 +119,8 @@ void CloakLogic::onPushButtonSaveClicked() newContainerConfig); }, pageFunc, progressBarFunc, - saveButtonFunc, waitInfoFunc, busyInfoFuncy); + saveButtonFunc, waitInfoFunc, + busyInfoFuncy, cancelButtonFunc); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); @@ -123,3 +129,8 @@ void CloakLogic::onPushButtonSaveClicked() qDebug() << "Protocol saved with code:" << e << "for" << uiLogic()->selectedServerIndex << uiLogic()->selectedDockerContainer; } + +void CloakLogic::onPushButtonCancelClicked() +{ + emit uiLogic()->pageLogic()->cancelDoInstallAction(true); +} diff --git a/client/ui/pages_logic/protocols/CloakLogic.h b/client/ui/pages_logic/protocols/CloakLogic.h index 57afb5b0f..5c39e8ac7 100644 --- a/client/ui/pages_logic/protocols/CloakLogic.h +++ b/client/ui/pages_logic/protocols/CloakLogic.h @@ -25,8 +25,12 @@ class CloakLogic : public PageProtocolLogicBase AUTO_PROPERTY(bool, labelServerBusyVisible) AUTO_PROPERTY(QString, labelServerBusyText) + + AUTO_PROPERTY(bool, pushButtonCancelVisible) + public: Q_INVOKABLE void onPushButtonSaveClicked(); + Q_INVOKABLE void onPushButtonCancelClicked(); public: explicit CloakLogic(UiLogic *uiLogic, QObject *parent = nullptr); diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp index a25fd1342..a37b365be 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.cpp +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.cpp @@ -92,7 +92,7 @@ void OpenVpnLogic::updateProtocolPage(const QJsonObject &openvpnConfig, DockerCo set_lineEditPortEnabled(container == DockerContainer::OpenVpn); } -void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() +void OpenVpnLogic::onPushButtonSaveClicked() { QJsonObject protocolConfig = m_settings->protocolConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, Proto::OpenVpn); protocolConfig = getProtocolConfigFromPage(protocolConfig); @@ -144,6 +144,11 @@ void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() set_labelServerBusyVisible(visible); }; + ServerConfiguringProgressLogic::ButtonFunc cancelButtonFunc; + cancelButtonFunc.setVisibleFunc = [this] (bool visible) -> void { + set_pushButtonCancelVisible(visible); + }; + progressBarFunc.setTextVisibleFunc(true); progressBarFunc.setTextFunc(QString("Configuring...")); ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ @@ -153,7 +158,8 @@ void OpenVpnLogic::onPushButtonProtoOpenVpnSaveClicked() newContainerConfig); }, pageFunc, progressBarFunc, - saveButtonFunc, waitInfoFunc, busyInfoFuncy); + saveButtonFunc, waitInfoFunc, + busyInfoFuncy, cancelButtonFunc); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); @@ -178,3 +184,8 @@ QJsonObject OpenVpnLogic::getProtocolConfigFromPage(QJsonObject oldConfig) oldConfig.insert(config_key::additional_server_config, textAreaAdditionalServerConfig()); return oldConfig; } + +void OpenVpnLogic::onPushButtonCancelClicked() +{ + emit uiLogic()->pageLogic()->cancelDoInstallAction(true); +} diff --git a/client/ui/pages_logic/protocols/OpenVpnLogic.h b/client/ui/pages_logic/protocols/OpenVpnLogic.h index 1dafe5ee2..dd8612381 100644 --- a/client/ui/pages_logic/protocols/OpenVpnLogic.h +++ b/client/ui/pages_logic/protocols/OpenVpnLogic.h @@ -40,8 +40,11 @@ class OpenVpnLogic : public PageProtocolLogicBase AUTO_PROPERTY(bool, labelServerBusyVisible) AUTO_PROPERTY(QString, labelServerBusyText) + AUTO_PROPERTY(bool, pushButtonCancelVisible) + public: - Q_INVOKABLE void onPushButtonProtoOpenVpnSaveClicked(); + Q_INVOKABLE void onPushButtonSaveClicked(); + Q_INVOKABLE void onPushButtonCancelClicked(); public: explicit OpenVpnLogic(UiLogic *uiLogic, QObject *parent = nullptr); diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp index c2575a4d2..94a8ee044 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.cpp @@ -97,6 +97,11 @@ void ShadowSocksLogic::onPushButtonSaveClicked() set_labelServerBusyVisible(visible); }; + ServerConfiguringProgressLogic::ButtonFunc cancelButtonFunc; + cancelButtonFunc.setVisibleFunc = [this] (bool visible) -> void { + set_pushButtonCancelVisible(visible); + }; + progressBarFunc.setTextVisibleFunc(true); progressBarFunc.setTextFunc(QString("Configuring...")); ErrorCode e = uiLogic()->pageLogic()->doInstallAction([this, containerConfig, &newContainerConfig](){ @@ -106,7 +111,8 @@ void ShadowSocksLogic::onPushButtonSaveClicked() newContainerConfig); }, pageFunc, progressBarFunc, - saveButtonFunc, waitInfoFunc, busyInfoFuncy); + saveButtonFunc, waitInfoFunc, + busyInfoFuncy, cancelButtonFunc); if (!e) { m_settings->setContainerConfig(uiLogic()->selectedServerIndex, uiLogic()->selectedDockerContainer, newContainerConfig); @@ -114,3 +120,8 @@ void ShadowSocksLogic::onPushButtonSaveClicked() } qDebug() << "Protocol saved with code:" << e << "for" << uiLogic()->selectedServerIndex << uiLogic()->selectedDockerContainer; } + +void ShadowSocksLogic::onPushButtonCancelClicked() +{ + emit uiLogic()->pageLogic()->cancelDoInstallAction(true); +} diff --git a/client/ui/pages_logic/protocols/ShadowSocksLogic.h b/client/ui/pages_logic/protocols/ShadowSocksLogic.h index 1300511f5..da8599596 100644 --- a/client/ui/pages_logic/protocols/ShadowSocksLogic.h +++ b/client/ui/pages_logic/protocols/ShadowSocksLogic.h @@ -23,8 +23,12 @@ class ShadowSocksLogic : public PageProtocolLogicBase AUTO_PROPERTY(bool, labelServerBusyVisible) AUTO_PROPERTY(QString, labelServerBusyText) + + AUTO_PROPERTY(bool, pushButtonCancelVisible) + public: Q_INVOKABLE void onPushButtonSaveClicked(); + Q_INVOKABLE void onPushButtonCancelClicked(); public: explicit ShadowSocksLogic(UiLogic *uiLogic, QObject *parent = nullptr); diff --git a/client/ui/qml/Pages/PageServerConfiguringProgress.qml b/client/ui/qml/Pages/PageServerConfiguringProgress.qml index e481dbfe7..87c602c3c 100644 --- a/client/ui/qml/Pages/PageServerConfiguringProgress.qml +++ b/client/ui/qml/Pages/PageServerConfiguringProgress.qml @@ -10,7 +10,6 @@ PageBase { page: PageEnum.ServerConfiguringProgress logic: ServerConfiguringProgressLogic - enabled: ServerConfiguringProgressLogic.pageEnabled Caption { id: caption text: qsTr("Configuring...") @@ -56,14 +55,27 @@ PageBase { visible: ServerConfiguringProgressLogic.labelWaitInfoVisible } - ProgressBar { - id: pr + + BlueButtonType { + id: pb_cancel + z: 1 anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: logo.bottom anchors.bottomMargin: 40 - width: parent.width - 40 + width: root.width - 60 height: 40 + text: qsTr("Cancel") + visible: ServerConfiguringProgressLogic.pushButtonCancelVisible + enabled: ServerConfiguringProgressLogic.pushButtonCancelVisible + onClicked: { + ServerConfiguringProgressLogic.onPushButtonCancelClicked() + } + } + ProgressBar { + id: pr + enabled: ServerConfiguringProgressLogic.pageEnabled + anchors.fill: pb_cancel from: 0 to: ServerConfiguringProgressLogic.progressBarMaximium value: ServerConfiguringProgressLogic.progressBarValue diff --git a/client/ui/qml/Pages/Protocols/PageProtoCloak.qml b/client/ui/qml/Pages/Protocols/PageProtoCloak.qml index 17dc829a8..86a2584a1 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoCloak.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoCloak.qml @@ -129,7 +129,6 @@ PageProtocolBase { text: logic.labelInfoText } - ProgressBar { id: progressBar_proto_cloak_reset anchors.horizontalCenter: parent.horizontalCenter @@ -184,4 +183,13 @@ PageProtocolBase { } } + BlueButtonType { + anchors.fill: pb_save + text: qsTr("Cancel") + visible: logic.pushButtonCancelVisible + enabled: logic.pushButtonCancelVisible + onClicked: { + logic.onPushButtonCancelClicked() + } + } } diff --git a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml index a644bf596..19dad8e6a 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoOpenVPN.qml @@ -37,7 +37,6 @@ PageProtocolBase { ColumnLayout { id: content - enabled: logic.pageEnabled anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right @@ -45,12 +44,13 @@ PageProtocolBase { LabelType { id: lb_subnet + enabled: logic.pageEnabled height: 21 text: qsTr("VPN Addresses Subnet") } TextFieldType { id: tf_subnet - + enabled: logic.pageEnabled implicitWidth: parent.width height: 31 text: logic.lineEditSubnetText @@ -59,15 +59,16 @@ PageProtocolBase { } } - // LabelType { id: lb_proto + enabled: logic.pageEnabled Layout.topMargin: 20 height: 21 text: qsTr("Network protocol") } Rectangle { id: rect_proto + enabled: logic.pageEnabled implicitWidth: root.width - 60 height: 71 border.width: 1 @@ -99,8 +100,8 @@ PageProtocolBase { } } - // RowLayout { + enabled: logic.pageEnabled Layout.topMargin: 10 Layout.fillWidth: true LabelType { @@ -122,12 +123,9 @@ PageProtocolBase { } } - - - // CheckBoxType { id: check_auto_enc - + enabled: logic.pageEnabled implicitWidth: parent.width height: 21 text: qsTr("Auto-negotiate encryption") @@ -140,15 +138,16 @@ PageProtocolBase { } } - // LabelType { id: lb_cipher + enabled: logic.pageEnabled height: 21 text: qsTr("Cipher") } ComboBoxType { id: cb_cipher + enabled: logic.pageEnabled && !check_auto_enc.checked implicitWidth: parent.width height: 31 @@ -175,18 +174,18 @@ PageProtocolBase { onCurrentTextChanged: { logic.comboBoxVpnCipherText = currentText } - enabled: !check_auto_enc.checked } - // LabelType { id: lb_hash + enabled: logic.pageEnabled height: 21 Layout.topMargin: 20 text: qsTr("Hash") } ComboBoxType { id: cb_hash + enabled: logic.pageEnabled && !check_auto_enc.checked height: 31 implicitWidth: parent.width model: [ @@ -212,11 +211,11 @@ PageProtocolBase { onCurrentTextChanged: { logic.comboBoxVpnHashText = currentText } - enabled: !check_auto_enc.checked } CheckBoxType { id: check_tls + enabled: logic.pageEnabled implicitWidth: parent.width Layout.topMargin: 20 height: 21 @@ -230,6 +229,7 @@ PageProtocolBase { CheckBoxType { id: check_block_dns + enabled: logic.pageEnabled implicitWidth: parent.width height: 21 text: qsTr("Block DNS requests outside of VPN") @@ -242,7 +242,7 @@ PageProtocolBase { BasicButtonType { id: pb_client_config - + enabled: logic.pageEnabled implicitWidth: parent.width height: 21 text: qsTr("Additional client config commands →") @@ -267,6 +267,7 @@ PageProtocolBase { Rectangle { id: rect_client_conf + enabled: logic.pageEnabled implicitWidth: root.width - 60 height: 101 border.width: 1 @@ -288,14 +289,12 @@ PageProtocolBase { } } } - - } BasicButtonType { id: pb_server_config - + enabled: logic.pageEnabled implicitWidth: parent.width height: 21 text: qsTr("Additional server config commands →") @@ -320,6 +319,7 @@ PageProtocolBase { Rectangle { id: rect_server_conf + enabled: logic.pageEnabled implicitWidth: root.width - 60 height: 101 border.width: 1 @@ -347,6 +347,7 @@ PageProtocolBase { LabelType { id: label_server_busy + enabled: logic.pageEnabled horizontalAlignment: Text.AlignHCenter Layout.maximumWidth: parent.width Layout.fillWidth: true @@ -356,6 +357,7 @@ PageProtocolBase { LabelType { id: label_proto_openvpn_info + enabled: logic.pageEnabled horizontalAlignment: Text.AlignHCenter Layout.maximumWidth: parent.width Layout.fillWidth: true @@ -371,18 +373,31 @@ PageProtocolBase { BlueButtonType { id: pb_save + enabled: logic.pageEnabled z: 1 height: 40 text: qsTr("Save and restart VPN") width: parent.width visible: logic.pushButtonSaveVisible onClicked: { - logic.onPushButtonProtoOpenVpnSaveClicked() + logic.onPushButtonSaveClicked() + } + } + + BlueButtonType { + z: 1 + anchors.fill: pb_save + text: qsTr("Cancel") + visible: logic.pushButtonCancelVisible + enabled: logic.pushButtonCancelVisible + onClicked: { + logic.onPushButtonCancelClicked() } } ProgressBar { id: progress_save + enabled: logic.pageEnabled anchors.fill: pb_save from: 0 to: logic.progressBarResetMaximium diff --git a/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml b/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml index 3fe0df26d..4d627fe27 100644 --- a/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml +++ b/client/ui/qml/Pages/Protocols/PageProtoShadowSocks.qml @@ -162,4 +162,14 @@ PageProtocolBase { logic.onPushButtonSaveClicked() } } + + BlueButtonType { + anchors.fill: pb_save + text: qsTr("Cancel") + visible: logic.pushButtonCancelVisible + enabled: logic.pushButtonCancelVisible + onClicked: { + logic.onPushButtonCancelClicked() + } + } } diff --git a/client/ui/uilogic.cpp b/client/ui/uilogic.cpp index 9d43f4140..ef50c4645 100644 --- a/client/ui/uilogic.cpp +++ b/client/ui/uilogic.cpp @@ -346,6 +346,11 @@ void UiLogic::installServer(QMap &containers) pageLogic()->set_labelServerBusyVisible(visible); }; + ServerConfiguringProgressLogic::ButtonFunc cancelButtonFunc; + cancelButtonFunc.setVisibleFunc = [this] (bool visible) -> void { + pageLogic()->set_pushButtonCancelVisible(visible); + }; + int count = 0; ErrorCode error; for (QMap::iterator i = containers.begin(); i != containers.end(); i++, count++) { @@ -353,7 +358,7 @@ void UiLogic::installServer(QMap &containers) error = pageLogic()->doInstallAction([&] () { return m_serverController->setupContainer(installCredentials, i.key(), i.value()); - }, pageFunc, progressBarFunc, noButton, waitInfoFunc, busyInfoFunc); + }, pageFunc, progressBarFunc, noButton, waitInfoFunc, busyInfoFunc, cancelButtonFunc); m_serverController->disconnectFromHost(installCredentials); } From 9f114a1dad1354c9b2d63cc7816fbc7d03cbdcc1 Mon Sep 17 00:00:00 2001 From: pokamest Date: Mon, 16 Jan 2023 18:12:30 +0000 Subject: [PATCH 3/3] Tiny fix [no ci] --- client/server_scripts/install_docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/server_scripts/install_docker.sh b/client/server_scripts/install_docker.sh index e12ab2c13..baff7cb61 100644 --- a/client/server_scripts/install_docker.sh +++ b/client/server_scripts/install_docker.sh @@ -3,7 +3,7 @@ if [[ -f "$pm_apt" ]]; then pm=$pm_apt; docker_pkg="docker.io"; else pm=$pm_yum; if [[ ! -f "/usr/bin/sudo" ]]; then $pm update -y -q; $pm install -y -q sudo; fi;\ docker_service=$(systemctl list-units --full -all | grep docker.service | grep -v inactive | grep -v dead | grep -v failed);\ if [[ -f "$pm_apt" ]]; then export DEBIAN_FRONTEND=noninteractive; fi;\ -if [[ -z "$docker_service" ]]; then sudo $pm update -y -q; sudo $pm install -y -q curl $docker_pkg; fi;\ +if [[ -z "$docker_service" ]]; then sudo $pm update -y -q; sudo $pm install -y -q curl $docker_pkg; fi;\ docker_service=$(systemctl list-units --full -all | grep docker.service | grep -v inactive | grep -v dead | grep -v failed);\ if [[ -z "$docker_service" ]]; then sleep 5 && sudo systemctl start docker && sleep 5; fi;\ docker --version