diff --git a/src/StorageBackend.cpp b/src/StorageBackend.cpp index 34393e9..d534e7c 100644 --- a/src/StorageBackend.cpp +++ b/src/StorageBackend.cpp @@ -47,7 +47,7 @@ LogosResult StorageBackend::init(const QString& configJson) { m_config = QJsonDocument::fromJson(configJson.toUtf8()); if (m_config.isNull()) { qDebug() << "StorageBackend::initStorage invalid json config" << configJson; - emit initFailed(); + reportError("Failed to create the storage: invalid JSON config"); return {false, "", "Failed to create the storage, invalid json config"}; } @@ -57,9 +57,8 @@ LogosResult StorageBackend::init(const QString& configJson) { if (!result) { setStatus(Destroyed); - debug("Failed to init storage"); - emit initFailed(); - return {false, "", "Filed to init storage"}; + reportError("Failed to init storage"); + return {false, "", "Failed to init storage"}; } setStatus(Stopped); @@ -72,6 +71,7 @@ LogosResult StorageBackend::init(const QString& configJson) { setStatus(Stopped); debug("Failed to start Storage module:" + message); emit startFailed(message); + reportError("Failed to start: " + message); } else { setStatus(Running); debug("Storage module started."); @@ -237,6 +237,8 @@ LogosResult StorageBackend::start(const QString& newConfigJson) { setStatus(Starting); debug("Starting Storage module..."); + // TODO trach the start attempts in a file + auto result = m_logos->storage_module.start(); if (!result) { @@ -295,6 +297,11 @@ void StorageBackend::destroy() { QString StorageBackend::debugLogs() const { return m_debugLogs; }; +void StorageBackend::reportError(const QString& message) { + debug(message); + emit error(message); +} + void StorageBackend::debug(const QString& log) { if (!m_debugLogs.isEmpty()) { m_debugLogs += "\n"; @@ -866,36 +873,38 @@ void StorageBackend::enableNatExtConfig(int tcpPort) { QJsonArray listenAddrs = {QString("/ip4/0.0.0.0/tcp/%1").arg(tcpPort)}; obj["listen-addrs"] = listenAddrs; + reloadIfChanged(QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact))); + qDebug() << "StorageBackend::enableNatExtConfig Retrieving the public IP"; - + emit natExtConfigCompleted(); // Create the network manager - QNetworkAccessManager* manager = new QNetworkAccessManager(this); - QNetworkRequest request(QUrl("https://echo.codex.storage/")); - request.setRawHeader("Accept", "text/plain"); - QNetworkReply* reply = manager->get(request); + // QNetworkAccessManager* manager = new QNetworkAccessManager(this); + // QNetworkRequest request(QUrl("https://echo.codex.storage/")); + // request.setRawHeader("Accept", "text/plain"); + // QNetworkReply* reply = manager->get(request); - connect(reply, &QNetworkReply::finished, this, [this, reply, manager, obj]() { - reply->deleteLater(); - manager->deleteLater(); + // connect(reply, &QNetworkReply::finished, this, [this, reply, manager, obj]() { + // reply->deleteLater(); + // manager->deleteLater(); - if (reply->error() != QNetworkReply::NoError) { - emit natExtConfigFailed(reply->errorString()); - return; - } + // if (reply->error() != QNetworkReply::NoError) { + // reportError("NAT config failed: " + reply->errorString()); + // return; + // } - QString ip = reply->readAll().trimmed(); + // QString ip = reply->readAll().trimmed(); - qDebug() << "StorageBackend::enableNatExtConfig ip=" << ip; + // qDebug() << "StorageBackend::enableNatExtConfig ip=" << ip; - obj["nat"] = "extip:" + ip; + // obj["nat"] = "extip:" + ip; - qDebug() << "StorageBackend::enableNatExtConfig config=" - << QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact)); + // qDebug() << "StorageBackend::enableNatExtConfig config=" + // << QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact)); - reloadIfChanged(QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact))); + // reloadIfChanged(QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact))); - emit natExtConfigCompleted(); - }); + // emit natExtConfigCompleted(); + // }); } void StorageBackend::status(StorageStatus status) { m_status = status; } diff --git a/src/StorageBackend.h b/src/StorageBackend.h index 39db7f7..8442ea1 100644 --- a/src/StorageBackend.h +++ b/src/StorageBackend.h @@ -133,6 +133,25 @@ class StorageBackend : public QObject { // and re-create a context with the new configuration void enableNatExtConfig(int tcpPort); + // This method try to get guidance about the resolution + // of the misconfiguration for the node. + // The idea is to check if: + // + // 1- upnp is enabled. In this case, the user should go back + // and try to configure the port forwarding + // 2- port forwarning is enabled. Indicate that the port has to + // be free and open to remote connection. + void guessResolution(); + + // This method will ensure that the node is ready to be used. + // 1- Make a call to debug function in the storage module and + // make sure that the node has peer. If not, the UI should suggest + // to modifiy the discovery port (8090) in the advance settings (to come). + // 2- Ensure that the tcp port is open to remote connection. If not, + // the UI should suggest to change go back and try another port and double + // check that the port forwarding is enabled on the router. + void checkNodeIsUp(); + signals: void ready(); void startCompleted(); @@ -146,9 +165,8 @@ class StorageBackend : public QObject { void manifestsChanged(); void quotaChanged(); void initCompleted(); - void initFailed(); - void natExtConfigFailed(const QString& error); void natExtConfigCompleted(); + void error(const QString& message); private slots: @@ -156,6 +174,7 @@ class StorageBackend : public QObject { void setStatus(StorageStatus newStatus); void peerConnect(const QString& peerId); void debug(const QString& log); + void reportError(const QString& message); LogosAPI* m_logosAPI; LogosModules* m_logos; diff --git a/src/StorageUIPlugin.cpp b/src/StorageUIPlugin.cpp index 622a6a3..0513c92 100644 --- a/src/StorageUIPlugin.cpp +++ b/src/StorageUIPlugin.cpp @@ -102,13 +102,13 @@ void StorageUIPlugin::destroyWidget(QWidget* widget) { return; } - if (backend->status() != StorageBackend::StorageStatus::Destroyed) { - qDebug() << "StorageUIPlugin::destroyWidget: backend is not initialised so let's detroy it."; + if (backend->status() == StorageBackend::StorageStatus::Destroyed) { + qDebug() << "StorageUIPlugin::destroyWidget: backend is not initialised so let's delete the widget."; quickWidget->deleteLater(); return; } - if (backend->status() == StorageBackend::StorageStatus::Running) { + if (backend->status() != StorageBackend::StorageStatus::Running) { qDebug() << "StorageUIPlugin::destroyWidget: backend is not running so let's detroy it."; backend->destroy(); diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt index a373110..b7e8697 100644 --- a/src/qml/CMakeLists.txt +++ b/src/qml/CMakeLists.txt @@ -134,6 +134,7 @@ qt_add_qml_module(appqml LogosStorageButton.qml LogosStorageLayout.qml PortForwarding.qml + ErrorToast.qml ) # Set up QML module directory for runtime diff --git a/src/qml/ErrorToast.qml b/src/qml/ErrorToast.qml index 7b996e2..0a5c30f 100644 --- a/src/qml/ErrorToast.qml +++ b/src/qml/ErrorToast.qml @@ -9,26 +9,53 @@ Rectangle { property alias title: titleText.text property alias message: messageText.text - function show(t, msg) { - root.title = t - root.message = msg + function show(title, message) { + root.title = title + root.message = message root.visible = true slideAnim.restart() } function hide() { - root.visible = false + hideAnim.restart() } visible: false opacity: 0 width: 500 radius: Theme.spacing.tiny - color: "#1e1e1e" + color: "#3D2020" implicitHeight: content.implicitHeight + Theme.spacing.medium * 2 - transform: Translate { id: slideTranslate; y: 20 } + transform: Translate { + id: slideTranslate + y: 20 + } + + ParallelAnimation { + id: hideAnim + + NumberAnimation { + target: slideTranslate + property: "y" + from: 0 + to: 20 + duration: 300 + easing.type: Easing.InCubic + } + + NumberAnimation { + target: root + property: "opacity" + from: 1 + to: 0 + duration: 300 + easing.type: Easing.InCubic + } + + onFinished: root.visible = false + } ParallelAnimation { id: slideAnim @@ -52,6 +79,23 @@ Rectangle { } } + // Close button top right + LogosText { + text: "x" + font.pixelSize: Theme.typography.primaryText + anchors.top: parent.top + anchors.right: parent.right + anchors.margins: Theme.spacing.small + z: 1 + color: Theme.palette.text + + MouseArea { + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: root.hide() + } + } + ColumnLayout { id: content anchors { @@ -62,28 +106,12 @@ Rectangle { } spacing: Theme.spacing.tiny - RowLayout { + LogosText { + id: titleText Layout.fillWidth: true - - LogosText { - id: titleText - Layout.fillWidth: true - color: Theme.palette.error - font.pixelSize: Theme.typography.primaryText - font.bold: true - } - - LogosText { - text: "✕" - color: Theme.palette.textMuted - font.pixelSize: Theme.typography.primaryText - - MouseArea { - anchors.fill: parent - cursorShape: Qt.PointingHandCursor - onClicked: root.hide() - } - } + color: Theme.palette.error + font.pixelSize: Theme.typography.primaryText + font.bold: true } LogosText { diff --git a/src/qml/Main.qml b/src/qml/Main.qml index 83fa598..bdef8bc 100644 --- a/src/qml/Main.qml +++ b/src/qml/Main.qml @@ -1,6 +1,7 @@ import QtQuick import QtQuick.Controls import QtCore +import Logos.Theme // qmllint disable unqualified Item { @@ -20,6 +21,9 @@ Item { signal startFailed signal stopCompleted signal initCompleted + signal ready + signal error + signal natExtConfigCompleted function start() { console.log("mock start called") @@ -38,6 +42,8 @@ Item { function saveCurrentConfig() {} function stop() {} + + function guessResolution() {} } Settings { @@ -61,13 +67,23 @@ Item { initialItem: onboardingComponent } + ErrorToast { + id: errorToast + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: Theme.spacing.medium + } + Component { id: onboardingComponent OnBoarding { onCompleted: function (upnpEnabled) { + console.info("onboarding completed") if (upnpEnabled) { root.backend.enableUpnpConfig() + root.backend.start() + stackView.push(startNodeComponent) } else { stackView.push(portForwardingComponent) } @@ -122,16 +138,16 @@ Item { function onInitCompleted() {} function onReady() { - console.info("i am ready") if (settings.onboardingCompleted) { - console.info("onboardingCompleted completed") root.backend.loadUserConfig() root.backend.start() stackView.replace(storageComponent, StackView.Immediate) } } - function onNatExtConfigFailed(error) {} + function onError(message) { + errorToast.show("Error", message) + } function onNatExtConfigCompleted(error) { root.backend.start() diff --git a/src/qml/StartNode.qml b/src/qml/StartNode.qml index 2ee5499..c92d345 100644 --- a/src/qml/StartNode.qml +++ b/src/qml/StartNode.qml @@ -10,6 +10,7 @@ LogosStorageLayout { property var backend: mockBackend property string status: "" property string title: "Starting your node...." + property string resolution: "" property bool starting: true property bool success: false @@ -56,6 +57,8 @@ LogosStorageLayout { root.title = "Error" root.status = "Failed to start: " + error } + + function guessResolution() {} } ColumnLayout { @@ -76,6 +79,13 @@ LogosStorageLayout { text: root.status Layout.alignment: Qt.AlignHCenter } + + LogosText { + id: suggestionText + font.pixelSize: Theme.typography.primaryText + text: root.suggestion + Layout.alignment: Qt.AlignHCenter + } } LogosStorageButton { @@ -97,4 +107,14 @@ LogosStorageLayout { onClicked: root.next() enabled: root.success == true } + + Connections { + target: root.backend + + function onStartFailed(error) { + root.title = "Erreur" + root.status = "Your node failed to start with this error: " + error + root.method = root.backend.guessResolution() + } + } } diff --git a/src/qml/main.cpp b/src/qml/main.cpp index 5666f0b..6c9f90a 100644 --- a/src/qml/main.cpp +++ b/src/qml/main.cpp @@ -19,7 +19,7 @@ int main(int argc, char* argv[]) { Qt::QueuedConnection); engine.addImportPath(QCoreApplication::applicationDirPath() + "/qml"); - engine.loadFromModule("StorageBackend", "OnBoarding"); + engine.loadFromModule("StorageBackend", "Main"); return app.exec(); } diff --git a/src/storage_resources.qrc b/src/storage_resources.qrc index fff4020..a43bd09 100644 --- a/src/storage_resources.qrc +++ b/src/storage_resources.qrc @@ -8,5 +8,6 @@ qml/LogosStorageButton.qml qml/LogosStorageLayout.qml qml/PortForwarding.qml + qml/ErrorToast.qml