diff --git a/client/amnezia_application.cpp b/client/amnezia_application.cpp index f0a7769a..58e6b543 100644 --- a/client/amnezia_application.cpp +++ b/client/amnezia_application.cpp @@ -91,12 +91,11 @@ void AmneziaApplication::init() initControllers(); #ifdef Q_OS_ANDROID - if(!AndroidController::initLogging()) { + if (!AndroidController::initLogging()) { qFatal("Android logging initialization failed"); } AndroidController::instance()->setSaveLogs(m_settings->isSaveLogs()); - connect(m_settings.get(), &Settings::saveLogsChanged, - AndroidController::instance(), &AndroidController::setSaveLogs); + connect(m_settings.get(), &Settings::saveLogsChanged, AndroidController::instance(), &AndroidController::setSaveLogs); connect(AndroidController::instance(), &AndroidController::initConnectionState, this, [this](Vpn::ConnectionState state) { @@ -331,8 +330,8 @@ void AmneziaApplication::initModels() m_clientManagementModel.reset(new ClientManagementModel(m_settings, this)); m_engine->rootContext()->setContextProperty("ClientManagementModel", m_clientManagementModel.get()); - connect(m_clientManagementModel.get(), &ClientManagementModel::adminConfigRevoked, - m_serversModel.get(), &ServersModel::clearCachedProfile); + connect(m_clientManagementModel.get(), &ClientManagementModel::adminConfigRevoked, m_serversModel.get(), + &ServersModel::clearCachedProfile); connect(m_configurator.get(), &VpnConfigurator::newVpnConfigCreated, this, [this](const QString &clientId, const QString &clientName, const DockerContainer container, @@ -370,12 +369,13 @@ void AmneziaApplication::initControllers() m_settings, m_configurator)); m_engine->rootContext()->setContextProperty("ExportController", m_exportController.get()); - m_settingsController.reset(new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_settings)); + m_settingsController.reset( + new SettingsController(m_serversModel, m_containersModel, m_languageModel, m_sitesModel, m_settings)); m_engine->rootContext()->setContextProperty("SettingsController", m_settingsController.get()); if (m_settingsController->isAutoConnectEnabled() && m_serversModel->getDefaultServerIndex() >= 0) { QTimer::singleShot(1000, this, [this]() { m_connectionController->openConnection(); }); } - connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled , m_serversModel.get(), + connect(m_settingsController.get(), &SettingsController::amneziaDnsToggled, m_serversModel.get(), &ServersModel::toggleAmneziaDns); m_sitesController.reset(new SitesController(m_settings, m_vpnConnection, m_sitesModel)); @@ -384,6 +384,11 @@ void AmneziaApplication::initControllers() m_systemController.reset(new SystemController(m_settings)); m_engine->rootContext()->setContextProperty("SystemController", m_systemController.get()); - m_cloudController.reset(new ApiController(m_serversModel, m_containersModel)); - m_engine->rootContext()->setContextProperty("ApiController", m_cloudController.get()); + m_apiController.reset(new ApiController(m_serversModel, m_containersModel)); + m_engine->rootContext()->setContextProperty("ApiController", m_apiController.get()); + connect(m_apiController.get(), &ApiController::updateStarted, this, + [this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Connecting); }); + connect(m_apiController.get(), &ApiController::errorOccurred, this, + [this]() { emit m_vpnConnection->connectionStateChanged(Vpn::ConnectionState::Disconnected); }); + connect(m_apiController.get(), &ApiController::updateFinished, m_connectionController.get(), &ConnectionController::toggleConnection); } diff --git a/client/amnezia_application.h b/client/amnezia_application.h index 52427281..0161cd3a 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -121,7 +121,7 @@ private: QScopedPointer m_settingsController; QScopedPointer m_sitesController; QScopedPointer m_systemController; - QScopedPointer m_cloudController; + QScopedPointer m_apiController; }; #endif // AMNEZIA_APPLICATION_H diff --git a/client/core/defs.h b/client/core/defs.h index 8c96e571..6d1f1a34 100644 --- a/client/core/defs.h +++ b/client/core/defs.h @@ -88,7 +88,11 @@ namespace amnezia ImportInvalidConfigError = 900, // Android errors - AndroidError = 1000 + AndroidError = 1000, + + // Api errors + ApiConfigDownloadError = 1100, + ApiConfigAlreadyAdded = 1101 }; } // namespace amnezia diff --git a/client/core/errorstrings.cpp b/client/core/errorstrings.cpp index 880dfa0e..48cba3c5 100644 --- a/client/core/errorstrings.cpp +++ b/client/core/errorstrings.cpp @@ -64,6 +64,10 @@ QString errorString(ErrorCode code) { // Android errors case (AndroidError): errorMessage = QObject::tr("VPN connection error"); break; + // Api errors + case (ApiConfigDownloadError): errorMessage = QObject::tr("Error when retrieving configuration from API"); break; + case (ApiConfigAlreadyAdded): errorMessage = QObject::tr("This config has already been added to the application"); break; + case(InternalError): default: errorMessage = QObject::tr("Internal error"); break; diff --git a/client/protocols/protocols_defs.h b/client/protocols/protocols_defs.h index 8d7d9bfb..f83a0067 100644 --- a/client/protocols/protocols_defs.h +++ b/client/protocols/protocols_defs.h @@ -85,6 +85,8 @@ namespace amnezia constexpr char splitTunnelSites[] = "splitTunnelSites"; constexpr char splitTunnelType[] = "splitTunnelType"; + constexpr char crc[] = "crc"; + } namespace protocols diff --git a/client/ui/controllers/apiController.cpp b/client/ui/controllers/apiController.cpp index d4142751..43bea9fc 100644 --- a/client/ui/controllers/apiController.cpp +++ b/client/ui/controllers/apiController.cpp @@ -3,9 +3,11 @@ #include #include #include +#include #include "configurators/openvpn_configurator.h" #include "configurators/wireguard_configurator.h" +#include "core/errorstrings.h" namespace { @@ -28,7 +30,8 @@ ApiController::ApiController(const QSharedPointer &serversModel, { } -void ApiController::processCloudConfig(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData, QString &config) +void ApiController::processApiConfig(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData, + QString &config) { if (protocol == configKey::cloak) { config.replace("", "\n"); @@ -64,73 +67,91 @@ QJsonObject ApiController::fillApiPayload(const QString &protocol, const ApiCont return obj; } -bool ApiController::updateServerConfigFromApi() +void ApiController::updateServerConfigFromApi() +{ + QtConcurrent::run([this]() { + auto serverConfig = m_serversModel->getDefaultServerConfig(); + auto containerConfig = serverConfig.value(config_key::containers).toArray(); + + bool isConfigUpdateStarted = false; + + if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) { + emit updateStarted(); + isConfigUpdateStarted = true; + + QNetworkAccessManager manager; + + QNetworkRequest request; + request.setTransferTimeout(7000); + request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); + request.setRawHeader("Authorization", + "Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8()); + QString endpoint = serverConfig.value(configKey::apiEdnpoint).toString(); + request.setUrl(endpoint.replace("https", "http")); // todo remove + + QString protocol = serverConfig.value(configKey::protocol).toString(); + + auto apiPayloadData = generateApiPayloadData(protocol); + + QByteArray requestBody = QJsonDocument(fillApiPayload(protocol, apiPayloadData)).toJson(); + + QScopedPointer reply; + reply.reset(manager.post(request, requestBody)); + + QEventLoop wait; + QObject::connect(reply.get(), &QNetworkReply::finished, &wait, &QEventLoop::quit); + wait.exec(); + + if (reply->error() == QNetworkReply::NoError) { + QString contents = QString::fromUtf8(reply->readAll()); + auto data = QJsonDocument::fromJson(contents.toUtf8()).object().value(config_key::config).toString(); + + data.replace("vpn://", ""); + QByteArray ba = QByteArray::fromBase64(data.toUtf8(), + QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); + + QByteArray ba_uncompressed = qUncompress(ba); + if (!ba_uncompressed.isEmpty()) { + ba = ba_uncompressed; + } + + QString configStr = ba; + processApiConfig(protocol, apiPayloadData, configStr); + + QJsonObject apiConfig = QJsonDocument::fromJson(configStr.toUtf8()).object(); + + serverConfig.insert(config_key::dns1, apiConfig.value(config_key::dns1)); + serverConfig.insert(config_key::dns2, apiConfig.value(config_key::dns2)); + serverConfig.insert(config_key::containers, apiConfig.value(config_key::containers)); + serverConfig.insert(config_key::hostName, apiConfig.value(config_key::hostName)); + + auto defaultContainer = apiConfig.value(config_key::defaultContainer).toString(); + serverConfig.insert(config_key::defaultContainer, defaultContainer); + m_serversModel->editServer(serverConfig); + emit m_serversModel->defaultContainerChanged(ContainerProps::containerFromString(defaultContainer)); + } else { + qDebug() << reply->error(); + qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); + emit errorOccurred(errorString(ApiConfigDownloadError)); + return; + } + } + + emit updateFinished(isConfigUpdateStarted); + return; + }); +} + +void ApiController::clearApiConfig() { auto serverConfig = m_serversModel->getDefaultServerConfig(); - auto containerConfig = serverConfig.value(config_key::containers).toArray(); + serverConfig.remove(config_key::dns1); + serverConfig.remove(config_key::dns2); + serverConfig.remove(config_key::containers); + serverConfig.remove(config_key::hostName); - if (serverConfig.value(config_key::configVersion).toInt() && containerConfig.isEmpty()) { - QNetworkAccessManager manager; + serverConfig.insert(config_key::defaultContainer, ContainerProps::containerToString(DockerContainer::None)); - QNetworkRequest request; - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); - request.setRawHeader("Authorization", - "Api-Key " + serverConfig.value(configKey::accessToken).toString().toUtf8()); - QString endpoint = serverConfig.value(configKey::apiEdnpoint).toString(); - request.setUrl(endpoint.replace("https", "http")); // todo remove - - QString protocol = serverConfig.value(configKey::protocol).toString(); - - auto apiPayloadData = generateApiPayloadData(protocol); - - QByteArray requestBody = QJsonDocument(fillApiPayload(protocol, apiPayloadData)).toJson(); - - QScopedPointer reply; - reply.reset(manager.post(request, requestBody)); - - QEventLoop wait; - QObject::connect(reply.get(), &QNetworkReply::finished, &wait, &QEventLoop::quit); - wait.exec(); - - if (reply->error() == QNetworkReply::NoError) { - QString contents = QString::fromUtf8(reply->readAll()); - auto data = QJsonDocument::fromJson(contents.toUtf8()).object().value(config_key::config).toString(); - - data.replace("vpn://", ""); - QByteArray ba = QByteArray::fromBase64(data.toUtf8(), - QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); - - QByteArray ba_uncompressed = qUncompress(ba); - if (!ba_uncompressed.isEmpty()) { - ba = ba_uncompressed; - } - - QString configStr = ba; - processCloudConfig(protocol, apiPayloadData, configStr); - - QJsonObject cloudConfig = QJsonDocument::fromJson(configStr.toUtf8()).object(); - - serverConfig.insert("cloudConfig", cloudConfig); - serverConfig.insert(config_key::dns1, cloudConfig.value(config_key::dns1)); - serverConfig.insert(config_key::dns2, cloudConfig.value(config_key::dns2)); - serverConfig.insert(config_key::containers, cloudConfig.value(config_key::containers)); - serverConfig.insert(config_key::hostName, cloudConfig.value(config_key::hostName)); - - auto defaultContainer = cloudConfig.value(config_key::defaultContainer).toString(); - serverConfig.insert(config_key::defaultContainer, defaultContainer); - m_serversModel->editServer(serverConfig); - emit m_serversModel->defaultContainerChanged(ContainerProps::containerFromString(defaultContainer)); - } else { - QString err = reply->errorString(); - qDebug() << QString::fromUtf8(reply->readAll()); //todo remove debug output - qDebug() << reply->error(); - qDebug() << err; - qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); - emit errorOccurred(tr("Error when retrieving configuration from cloud server")); - return false; - } - } - - return true; + m_serversModel->editServer(serverConfig); } diff --git a/client/ui/controllers/apiController.h b/client/ui/controllers/apiController.h index ed7db533..c5d79ded 100644 --- a/client/ui/controllers/apiController.h +++ b/client/ui/controllers/apiController.h @@ -16,9 +16,13 @@ public: const QSharedPointer &containersModel, QObject *parent = nullptr); public slots: - bool updateServerConfigFromApi(); + void updateServerConfigFromApi(); + + void clearApiConfig(); signals: + void updateStarted(); + void updateFinished(bool isConfigUpdateStarted); void errorOccurred(const QString &errorMessage); private: @@ -31,7 +35,7 @@ private: ApiPayloadData generateApiPayloadData(const QString &protocol); QJsonObject fillApiPayload(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData); - void processCloudConfig(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData, QString &config); + void processApiConfig(const QString &protocol, const ApiController::ApiPayloadData &apiPayloadData, QString &config); QSharedPointer m_serversModel; QSharedPointer m_containersModel; diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp index 25bebfb1..12a16367 100644 --- a/client/ui/controllers/connectionController.cpp +++ b/client/ui/controllers/connectionController.cpp @@ -25,6 +25,11 @@ ConnectionController::ConnectionController(const QSharedPointer &s void ConnectionController::openConnection() { + if (!m_containersModel->isAnyContainerInstalled()) { + emit noInstalledContainers(); + return; + } + int serverIndex = m_serversModel->getDefaultServerIndex(); ServerCredentials credentials = m_serversModel->getServerCredentials(serverIndex); @@ -129,6 +134,17 @@ QString ConnectionController::connectionStateText() const return m_connectionStateText; } +void ConnectionController::toggleConnection(bool skipConnectionInProgressCheck) +{ + if (!skipConnectionInProgressCheck && isConnectionInProgress()) { + closeConnection(); + } else if (isConnected()) { + closeConnection(); + } else { + openConnection(); + } +} + bool ConnectionController::isConnectionInProgress() const { return m_isConnectionInProgress; diff --git a/client/ui/controllers/connectionController.h b/client/ui/controllers/connectionController.h index 74a3f600..9972a118 100644 --- a/client/ui/controllers/connectionController.h +++ b/client/ui/controllers/connectionController.h @@ -26,6 +26,8 @@ public: QString connectionStateText() const; public slots: + void toggleConnection(bool skipConnectionInProgressCheck); + void openConnection(); void closeConnection(); @@ -45,6 +47,8 @@ signals: void connectionErrorOccurred(const QString &errorMessage); void reconnectWithUpdatedContainer(const QString &message); + void noInstalledContainers(); + private: Vpn::ConnectionState getCurrentConnectionState(); diff --git a/client/ui/controllers/importController.cpp b/client/ui/controllers/importController.cpp index 59aab046..f7c1ea20 100644 --- a/client/ui/controllers/importController.cpp +++ b/client/ui/controllers/importController.cpp @@ -123,12 +123,19 @@ void ImportController::importConfig() credentials.userName = m_config.value(config_key::userName).toString(); credentials.secretData = m_config.value(config_key::password).toString(); - if (credentials.isValid() - || m_config.contains(config_key::containers) - || m_config.contains(config_key::configVersion)) { // todo + if (credentials.isValid() || m_config.contains(config_key::containers)) { m_serversModel->addServer(m_config); - emit importFinished(); + } else if (m_config.contains(config_key::configVersion)) { + quint16 crc = qChecksum(QJsonDocument(m_config).toJson()); + if (m_serversModel->isServerFromApiAlreadyExists(crc)) { + emit importErrorOccurred(errorString(ErrorCode::ApiConfigAlreadyAdded), true); + } else { + m_config.insert(config_key::crc, crc); + + m_serversModel->addServer(m_config); + emit importFinished(); + } } else { qDebug() << "Failed to import profile"; qDebug().noquote() << QJsonDocument(m_config).toJson(); diff --git a/client/ui/controllers/importController.h b/client/ui/controllers/importController.h index c1d0b2ab..5731cae8 100644 --- a/client/ui/controllers/importController.h +++ b/client/ui/controllers/importController.h @@ -39,7 +39,7 @@ public slots: signals: void importFinished(); - void importErrorOccurred(const QString &errorMessage); + void importErrorOccurred(const QString &errorMessage, bool goToPageHome = false); void qrDecodingFinished(); diff --git a/client/ui/models/containers_model.cpp b/client/ui/models/containers_model.cpp index 7e73b2e9..55ee5b28 100644 --- a/client/ui/models/containers_model.cpp +++ b/client/ui/models/containers_model.cpp @@ -53,7 +53,7 @@ QVariant ContainersModel::data(const int index, int role) const return data(modelIndex, role); } -void ContainersModel::updateModel(QJsonArray &containers) +void ContainersModel::updateModel(const QJsonArray &containers) { beginResetModel(); m_containers.clear(); diff --git a/client/ui/models/containers_model.h b/client/ui/models/containers_model.h index 23a91ea5..0deb0f4e 100644 --- a/client/ui/models/containers_model.h +++ b/client/ui/models/containers_model.h @@ -40,7 +40,7 @@ public: QVariant data(const int index, int role) const; public slots: - void updateModel(QJsonArray &containers); + void updateModel(const QJsonArray &containers); DockerContainer getDefaultContainer(); void setDefaultContainer(const int containerIndex); diff --git a/client/ui/models/servers_model.cpp b/client/ui/models/servers_model.cpp index 85410293..36b3d574 100644 --- a/client/ui/models/servers_model.cpp +++ b/client/ui/models/servers_model.cpp @@ -331,6 +331,11 @@ QJsonObject ServersModel::getDefaultServerConfig() return m_servers.at(m_defaultServerIndex).toObject(); } +QJsonObject ServersModel::getCurrentlyProcessedServerConfig() +{ + return m_servers.at(m_currentlyProcessedServerIndex).toObject(); +} + void ServersModel::reloadContainerConfig() { QJsonObject server = m_servers.at(m_currentlyProcessedServerIndex).toObject(); @@ -544,3 +549,18 @@ bool ServersModel::isDefaultServerFromApi() return m_settings->server(m_defaultServerIndex).value(config_key::configVersion).toInt(); } +bool ServersModel::isCurrentlyProcessedServerFromApi() +{ + return m_settings->server(m_currentlyProcessedServerIndex).value(config_key::configVersion).toInt(); +} + +bool ServersModel::isServerFromApiAlreadyExists(const quint16 crc) +{ + for (const auto &server : qAsConst(m_servers)) { + if (static_cast(server.toObject().value(config_key::crc).toInt()) == crc) { + return true; + } + } + return false; +} + diff --git a/client/ui/models/servers_model.h b/client/ui/models/servers_model.h index 5ea590eb..ce2ca7de 100644 --- a/client/ui/models/servers_model.h +++ b/client/ui/models/servers_model.h @@ -78,6 +78,7 @@ public slots: bool isAmneziaDnsContainerInstalled(const int serverIndex); QJsonObject getDefaultServerConfig(); + QJsonObject getCurrentlyProcessedServerConfig(); void reloadContainerConfig(); void updateContainerConfig(const int containerIndex, const QJsonObject config); @@ -99,6 +100,9 @@ public slots: void toggleAmneziaDns(bool enabled); bool isDefaultServerFromApi(); + bool isCurrentlyProcessedServerFromApi(); + + bool isServerFromApiAlreadyExists(const quint16 crc); protected: QHash roleNames() const override; @@ -109,7 +113,7 @@ signals: void defaultServerNameChanged(); void defaultServerDescriptionChanged(); - void containersUpdated(QJsonArray &containers); + void containersUpdated(const QJsonArray &containers); void defaultContainerChanged(const int containerIndex); private: diff --git a/client/ui/qml/Components/ConnectButton.qml b/client/ui/qml/Components/ConnectButton.qml index a0a57e6a..f628b6a5 100644 --- a/client/ui/qml/Components/ConnectButton.qml +++ b/client/ui/qml/Components/ConnectButton.qml @@ -138,26 +138,8 @@ Button { } onClicked: { - if (!ApiController.updateServerConfigFromApi()) { - return - } - - if (!ContainersModel.isAnyContainerInstalled()) { - PageController.setTriggeredBtConnectButton(true) - - ServersModel.currentlyProcessedIndex = ServersModel.getDefaultServerIndex() - InstallController.setShouldCreateServer(false) - PageController.goToPage(PageEnum.PageSetupWizardEasy) - - return - } - - if (ConnectionController.isConnectionInProgress) { - ConnectionController.closeConnection() - } else if (ConnectionController.isConnected) { - ConnectionController.closeConnection() - } else { - ConnectionController.openConnection() + if (!ConnectionController.isConnectionInProgress) { + ApiController.updateServerConfigFromApi() } } } diff --git a/client/ui/qml/Pages2/PageHome.qml b/client/ui/qml/Pages2/PageHome.qml index 5b44bc7c..db6ec11c 100644 --- a/client/ui/qml/Pages2/PageHome.qml +++ b/client/ui/qml/Pages2/PageHome.qml @@ -401,6 +401,13 @@ PageType { model: ServersModel currentIndex: ServersModel.defaultIndex + Connections { + target: ServersModel + function onDefaultServerIndexChanged(serverIndex) { + serversMenuContent.currentIndex = serverIndex + } + } + clip: true interactive: false @@ -429,19 +436,19 @@ PageType { text: name descriptionText: { - var description = "" + var fullDescription = "" if (hasWriteAccess) { if (SettingsController.isAmneziaDnsEnabled() && ServersModel.isAmneziaDnsContainerInstalled(index)) { - description += "Amnezia DNS | " + fullDescription += "Amnezia DNS | " } } else { if (containsAmneziaDns) { - description += "Amnezia DNS | " + fullDescription += "Amnezia DNS | " } } - return description += hostName + return fullDescription += serverDescription } checked: index === serversMenuContent.currentIndex diff --git a/client/ui/qml/Pages2/PageSettingsServerData.qml b/client/ui/qml/Pages2/PageSettingsServerData.qml index e3bb370f..a9365af4 100644 --- a/client/ui/qml/Pages2/PageSettingsServerData.qml +++ b/client/ui/qml/Pages2/PageSettingsServerData.qml @@ -225,7 +225,69 @@ PageType { DividerType { visible: content.isServerWithWriteAccess - } + } + + LabelWithButtonType { + visible: content.isServerWithWriteAccess + Layout.fillWidth: true + + text: qsTr("Clear server from Amnezia software") + textColor: "#EB5757" + + clickedFunction: function() { + questionDrawer.headerText = qsTr("Do you want to clear server from Amnezia software?") + questionDrawer.descriptionText = qsTr("All containers will be deleted on the server. This means that configuration files, keys and certificates will be deleted.") + questionDrawer.yesButtonText = qsTr("Continue") + questionDrawer.noButtonText = qsTr("Cancel") + + questionDrawer.yesButtonFunction = function() { + questionDrawer.visible = false + PageController.goToPage(PageEnum.PageDeinstalling) + if (ServersModel.isDefaultServerCurrentlyProcessed() && ConnectionController.isConnected) { + ConnectionController.closeConnection() + } + InstallController.removeAllContainers() + } + questionDrawer.noButtonFunction = function() { + questionDrawer.visible = false + } + questionDrawer.visible = true + } + } + + DividerType { + visible: content.isServerWithWriteAccess + } + + LabelWithButtonType { + visible: ServersModel.isCurrentlyProcessedServerFromApi() + Layout.fillWidth: true + + text: qsTr("Reset API config") + textColor: "#EB5757" + + clickedFunction: function() { + questionDrawer.headerText = qsTr("Do you want to reset API config?") + questionDrawer.descriptionText = "" + questionDrawer.yesButtonText = qsTr("Continue") + questionDrawer.noButtonText = qsTr("Cancel") + + questionDrawer.yesButtonFunction = function() { + questionDrawer.visible = false + PageController.showBusyIndicator(true) + ApiController.clearApiConfig() + PageController.showBusyIndicator(false) + } + questionDrawer.noButtonFunction = function() { + questionDrawer.visible = false + } + questionDrawer.visible = true + } + } + + DividerType { + visible: ServersModel.isCurrentlyProcessedServerFromApi() + } QuestionDrawer { id: questionDrawer diff --git a/client/ui/qml/Pages2/PageSetupWizardViewConfig.qml b/client/ui/qml/Pages2/PageSetupWizardViewConfig.qml index 6df26fc0..79b51bdb 100644 --- a/client/ui/qml/Pages2/PageSetupWizardViewConfig.qml +++ b/client/ui/qml/Pages2/PageSetupWizardViewConfig.qml @@ -18,8 +18,12 @@ PageType { Connections { target: ImportController - function onImportErrorOccurred(errorMessage) { - PageController.closePage() + function onImportErrorOccurred(errorMessage, goToPageHome) { + if (goToPageHome) { + PageController.goToStartPage() + } else { + PageController.closePage() + } PageController.showErrorMessage(errorMessage) } diff --git a/client/ui/qml/Pages2/PageStart.qml b/client/ui/qml/Pages2/PageStart.qml index 3afdf73a..3ade9af8 100644 --- a/client/ui/qml/Pages2/PageStart.qml +++ b/client/ui/qml/Pages2/PageStart.qml @@ -111,6 +111,22 @@ PageType { PageController.showNotificationMessage(message) PageController.closePage() } + + function onNoInstalledContainers() { + PageController.setTriggeredBtConnectButton(true) + + ServersModel.currentlyProcessedIndex = ServersModel.getDefaultServerIndex() + InstallController.setShouldCreateServer(false) + PageController.goToPage(PageEnum.PageSetupWizardEasy) + } + } + + Connections { + target: ApiController + + function onErrorOccurred(errorMessage) { + PageController.showErrorMessage(errorMessage) + } } StackViewType {