mirror of
https://github.com/logos-storage/logos-storage-app-skeleton.git
synced 2026-06-13 20:09:28 +00:00
Add nice onboarding
This commit is contained in:
parent
16d16de3c7
commit
a7d1e092a3
@ -772,8 +772,6 @@ StorageBackend::StorageStatus StorageBackend::status() const { return m_status;
|
||||
|
||||
QString StorageBackend::cid() const { return m_cid; }
|
||||
|
||||
QString StorageBackend::configJson() const { return QString::fromUtf8(m_config.toJson(QJsonDocument::Compact)); }
|
||||
|
||||
int StorageBackend::uploadProgress() const { return m_uploadProgress; }
|
||||
|
||||
QString StorageBackend::uploadStatus() const { return m_uploadStatus; }
|
||||
@ -824,7 +822,7 @@ void StorageBackend::reloadIfChanged(const QString& configJson) {
|
||||
|
||||
void StorageBackend::saveCurrentConfig() {
|
||||
qDebug() << "StorageBackend::saveUserConfig";
|
||||
saveUserConfig(QString::fromUtf8(m_config.toJson(QJsonDocument::Compact)));
|
||||
saveUserConfig(QString::fromUtf8(m_config.toJson(QJsonDocument::Indented)));
|
||||
}
|
||||
|
||||
void StorageBackend::saveUserConfig(const QString& configJson) {
|
||||
@ -865,7 +863,7 @@ void StorageBackend::enableUpnpConfig() {
|
||||
|
||||
obj["nat"] = "upnp";
|
||||
|
||||
reloadIfChanged(QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Compact)));
|
||||
reloadIfChanged(QString::fromUtf8(QJsonDocument(obj).toJson(QJsonDocument::Indented)));
|
||||
}
|
||||
|
||||
void StorageBackend::enableNatExtConfig(int tcpPort) {
|
||||
@ -1013,7 +1011,7 @@ void StorageBackend::loadUserConfig() {
|
||||
result = init(QString::fromUtf8(file.readAll()));
|
||||
} else {
|
||||
qWarning() << "StorageBackend::loadUserConfig Failed to read the user config file, fallback to default config";
|
||||
result = init(QString::fromUtf8(defaultConfig().toJson(QJsonDocument::Compact)));
|
||||
result = init(QString::fromUtf8(defaultConfig().toJson(QJsonDocument::Indented)));
|
||||
}
|
||||
|
||||
if (!result.success) {
|
||||
|
||||
@ -62,7 +62,6 @@ class StorageBackend : public QObject {
|
||||
QString cid() const;
|
||||
QString debugLogs() const;
|
||||
StorageStatus status() const;
|
||||
QString configJson() const;
|
||||
int uploadProgress() const;
|
||||
QString uploadStatus() const;
|
||||
QVariantList manifests() const;
|
||||
|
||||
@ -10,7 +10,7 @@ LogosStorageLayout {
|
||||
property var backend: null
|
||||
|
||||
signal back
|
||||
signal completed(string configJson)
|
||||
signal completed
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
@ -56,7 +56,8 @@ LogosStorageLayout {
|
||||
property bool isValid: true
|
||||
|
||||
Component.onCompleted: {
|
||||
text = (root.backend && root.backend.configJson) ? root.backend.configJson : "{}"
|
||||
text = (root.backend
|
||||
&& root.backend.configJson) ? root.backend.configJson : "{}"
|
||||
validate()
|
||||
}
|
||||
|
||||
@ -102,7 +103,11 @@ LogosStorageLayout {
|
||||
anchors.fill: parent
|
||||
enabled: jsonArea.isValid
|
||||
cursorShape: jsonArea.isValid ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: root.completed(jsonArea.text)
|
||||
onClicked: function () {
|
||||
root.backend.saveUserConfig(jsonArea.text)
|
||||
root.backend.reloadIfChanged(jsonArea.text)
|
||||
root.completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -136,6 +136,8 @@ qt_add_qml_module(appqml
|
||||
PortForwarding.qml
|
||||
ErrorToast.qml
|
||||
HealthIndicator.qml
|
||||
ModeSelector.qml
|
||||
AdvancedSetup.qml
|
||||
)
|
||||
|
||||
# Set up QML module directory for runtime
|
||||
|
||||
@ -33,12 +33,12 @@ Item {
|
||||
// and click on "Back",
|
||||
// In that case, we pop the navigation after
|
||||
// the node is stopped.
|
||||
function onStopCompleted() {
|
||||
if (!settings.onboardingCompleted) {
|
||||
// function onStopCompleted() {
|
||||
// if (!settings.onboardingCompleted) {
|
||||
|
||||
// stackView.pop()
|
||||
}
|
||||
}
|
||||
// // stackView.pop()
|
||||
// }
|
||||
// }
|
||||
|
||||
// When the onboarding is completed,
|
||||
// the user should have a config save in his
|
||||
@ -49,7 +49,6 @@ Item {
|
||||
function onReady() {
|
||||
if (settings.onboardingCompleted) {
|
||||
root.backend.loadUserConfig()
|
||||
root.backend.start()
|
||||
stackView.replace(storageComponent, StackView.Immediate)
|
||||
}
|
||||
}
|
||||
@ -70,7 +69,21 @@ Item {
|
||||
StackView {
|
||||
id: stackView
|
||||
anchors.fill: parent
|
||||
initialItem: onboardingComponent
|
||||
initialItem: modeSelectorComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: modeSelectorComponent
|
||||
|
||||
ModeSelector {
|
||||
onCompleted: function (isGuide) {
|
||||
if (isGuide) {
|
||||
stackView.push(onboardingComponent)
|
||||
} else {
|
||||
stackView.push(advancedSetupComponent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
@ -79,8 +92,8 @@ Item {
|
||||
OnBoarding {
|
||||
backend: root.backend
|
||||
|
||||
// The completed event means the user
|
||||
// selected upup or port forwarding.
|
||||
onBack: stackView.pop()
|
||||
|
||||
onCompleted: function (upnpEnabled) {
|
||||
if (upnpEnabled) {
|
||||
stackView.push(startNodeComponent)
|
||||
@ -91,6 +104,21 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: advancedSetupComponent
|
||||
|
||||
AdvancedSetup {
|
||||
backend: root.backend
|
||||
|
||||
onBack: stackView.pop()
|
||||
|
||||
onCompleted: function () {
|
||||
settings.onboardingCompleted = true
|
||||
stackView.replace(storageComponent, StackView.Immediate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: storageComponent
|
||||
|
||||
|
||||
@ -43,28 +43,25 @@ LogosStorageLayout {
|
||||
width: 190
|
||||
height: 230
|
||||
radius: 14
|
||||
color: root.selectedMode === 0 ? Qt.rgba(1, 1, 1, 0.08) : "transparent"
|
||||
border.color: root.selectedMode === 0 ? "white" : Qt.rgba(1, 1, 1, 0.2)
|
||||
color: root.selectedMode === 0 ? Qt.rgba(1, 1, 1,
|
||||
0.08) : "transparent"
|
||||
border.color: root.selectedMode === 0 ? "white" : Qt.rgba(1, 1,
|
||||
1,
|
||||
0.2)
|
||||
border.width: root.selectedMode === 0 ? 2 : 1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 14
|
||||
|
||||
// Nothing OS dot icon — crosshair/compass
|
||||
// Nothing OS dot icon like
|
||||
Grid {
|
||||
columns: 5
|
||||
spacing: 4
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 1, 0, 0,
|
||||
1, 1, 0, 1, 1,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 1, 0, 0
|
||||
]
|
||||
model: [0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0]
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
@ -106,28 +103,25 @@ LogosStorageLayout {
|
||||
width: 190
|
||||
height: 230
|
||||
radius: 14
|
||||
color: root.selectedMode === 1 ? Qt.rgba(1, 1, 1, 0.08) : "transparent"
|
||||
border.color: root.selectedMode === 1 ? "white" : Qt.rgba(1, 1, 1, 0.2)
|
||||
color: root.selectedMode === 1 ? Qt.rgba(1, 1, 1,
|
||||
0.08) : "transparent"
|
||||
border.color: root.selectedMode === 1 ? "white" : Qt.rgba(1, 1,
|
||||
1,
|
||||
0.2)
|
||||
border.width: root.selectedMode === 1 ? 2 : 1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 14
|
||||
|
||||
// Nothing OS dot icon — X pattern
|
||||
// Nothing OS dot icon like
|
||||
Grid {
|
||||
columns: 5
|
||||
spacing: 4
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
1, 0, 0, 0, 1,
|
||||
0, 1, 0, 1, 0,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 1, 0, 1, 0,
|
||||
1, 0, 0, 0, 1
|
||||
]
|
||||
model: [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1]
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import QtQuick
|
||||
import QtQuick.Dialogs
|
||||
import QtQuick.Layouts
|
||||
import Logos.Theme
|
||||
import Logos.Controls
|
||||
@ -9,49 +8,187 @@ LogosStorageLayout {
|
||||
|
||||
property var backend: mockBackend
|
||||
|
||||
signal completed(bool enabled)
|
||||
signal back
|
||||
signal completed(bool upnpEnabled)
|
||||
|
||||
property int selectedMode: -1 // 0 = upnp, 1 = port forwarding
|
||||
|
||||
ColumnLayout {
|
||||
spacing: Theme.spacing.medium
|
||||
Layout.fillWidth: true
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacing.medium
|
||||
width: 430
|
||||
|
||||
LogosText {
|
||||
id: titleText
|
||||
text: "Network Configuration"
|
||||
font.pixelSize: Theme.typography.titleText
|
||||
text: "Welcome to Logos Storage"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
LogosText {
|
||||
id: questionText
|
||||
font.pixelSize: Theme.typography.titleText
|
||||
text: "Is UPnP enabled on your router ?"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
}
|
||||
|
||||
LogosText {
|
||||
id: questionDescriptionText
|
||||
text: "How is your network configured?"
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
text: "UPnP simplifies configuration by handling port forwarding automatically."
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Item {
|
||||
height: Theme.spacing.medium
|
||||
}
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacing.medium
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
// ── UPnP card ────────────────────────────────────────────────
|
||||
Rectangle {
|
||||
width: 190
|
||||
height: 230
|
||||
radius: 14
|
||||
color: root.selectedMode === 0 ? Qt.rgba(1, 1, 1, 0.08) : "transparent"
|
||||
border.color: root.selectedMode === 0 ? "white" : Qt.rgba(1, 1, 1, 0.2)
|
||||
border.width: root.selectedMode === 0 ? 2 : 1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 14
|
||||
|
||||
// Nothing OS dot icon — diamond/network
|
||||
Grid {
|
||||
columns: 5
|
||||
spacing: 4
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
0, 0, 1, 0, 0,
|
||||
0, 1, 0, 1, 0,
|
||||
1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0,
|
||||
0, 0, 1, 0, 0
|
||||
]
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
radius: 2
|
||||
color: "white"
|
||||
opacity: modelData ? 0.9 : 0.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "UPnP"
|
||||
color: "white"
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Automatic port\nforwarding via\nUPnP router."
|
||||
color: Qt.rgba(1, 1, 1, 0.55)
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 150
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.selectedMode = 0
|
||||
}
|
||||
}
|
||||
|
||||
// ── Port Forwarding card ─────────────────────────────────────
|
||||
Rectangle {
|
||||
width: 190
|
||||
height: 230
|
||||
radius: 14
|
||||
color: root.selectedMode === 1 ? Qt.rgba(1, 1, 1, 0.08) : "transparent"
|
||||
border.color: root.selectedMode === 1 ? "white" : Qt.rgba(1, 1, 1, 0.2)
|
||||
border.width: root.selectedMode === 1 ? 2 : 1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 14
|
||||
|
||||
// Nothing OS dot icon — right arrow
|
||||
Grid {
|
||||
columns: 5
|
||||
spacing: 4
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
Repeater {
|
||||
model: [
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 0, 1, 0,
|
||||
1, 1, 1, 1, 1,
|
||||
0, 0, 0, 1, 0,
|
||||
0, 0, 1, 0, 0
|
||||
]
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
radius: 2
|
||||
color: "white"
|
||||
opacity: modelData ? 0.9 : 0.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Port Forwarding"
|
||||
color: "white"
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Manual TCP port\nconfiguration on\nyour router."
|
||||
color: Qt.rgba(1, 1, 1, 0.55)
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
Layout.preferredWidth: 150
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: root.selectedMode = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
height: Theme.spacing.small
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: Theme.spacing.medium
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
|
||||
LogosStorageButton {
|
||||
text: "No / I don't know"
|
||||
onClicked: root.completed(false)
|
||||
text: "Back"
|
||||
onClicked: root.back()
|
||||
}
|
||||
|
||||
LogosStorageButton {
|
||||
text: "Yes, I use UPnP"
|
||||
onClicked: function () {
|
||||
console.info("enableUpnpConfig")
|
||||
root.backend.enableUpnpConfig()
|
||||
root.completed(true)
|
||||
text: "Continue"
|
||||
enabled: root.selectedMode !== -1
|
||||
onClicked: {
|
||||
if (root.selectedMode === 0) {
|
||||
root.backend.enableUpnpConfig()
|
||||
}
|
||||
root.completed(root.selectedMode === 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,6 +53,8 @@ LogosStorageLayout {
|
||||
return backend.status == running
|
||||
}
|
||||
|
||||
Component.onCompleted: root.backend.start()
|
||||
|
||||
QtObject {
|
||||
id: mockBackend
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user