mirror of
https://github.com/logos-storage/logos-storage-app-skeleton.git
synced 2026-06-20 07:19:27 +00:00
Provide an error modal to display error
This commit is contained in:
parent
8c6bd2f4ef
commit
733a43a4f8
@ -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; }
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -134,6 +134,7 @@ qt_add_qml_module(appqml
|
||||
LogosStorageButton.qml
|
||||
LogosStorageLayout.qml
|
||||
PortForwarding.qml
|
||||
ErrorToast.qml
|
||||
)
|
||||
|
||||
# Set up QML module directory for runtime
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -8,5 +8,6 @@
|
||||
<file alias="LogosStorageButton.qml">qml/LogosStorageButton.qml</file>
|
||||
<file alias="LogosStorageLayout.qml">qml/LogosStorageLayout.qml</file>
|
||||
<file alias="PortForwarding.qml">qml/PortForwarding.qml</file>
|
||||
<file alias="ErrorToast.qml">qml/ErrorToast.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user