mirror of
https://github.com/logos-storage/logos-storage-app-skeleton.git
synced 2026-06-14 20:39:27 +00:00
Add more consistency using the theme variables
This commit is contained in:
parent
2049492519
commit
9ac02311df
35
README.md
35
README.md
@ -78,6 +78,41 @@ To restart the onboarding process, simply delete the prefences file and relaunch
|
||||
|
||||
The application also provides a JSON editor in the debug panel for runtime configuration tweaks. To apply changes, restart the Storage Module.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Node has no peers
|
||||
|
||||
**Symptom:**
|
||||
The node starts successfully but never connects to any peer.
|
||||
|
||||
**Cause:**
|
||||
Logos Storage uses a discovery port (default `8090`) to announce itself to the DHT and find peers. If this port is already use by another process, the DHT cannot work properly.
|
||||
|
||||
**Fix:**
|
||||
Ensure that no process is running on `8090` process or change the default port value in the advanced configuration.
|
||||
|
||||
### UPnP not working
|
||||
|
||||
**Symptom:**
|
||||
You selected UPnP during setup but the node remains unreachable.
|
||||
|
||||
**Cause:**
|
||||
UPnP relies on your router supporting and enabling the UPnP protocol. Many routers have it disabled by default for security reasons.
|
||||
|
||||
**Fix:**
|
||||
Make sure UPnP is enabled on your router or switch to port forwarding config.
|
||||
|
||||
### Manual port forwarding
|
||||
|
||||
**Symptom:**
|
||||
You configure the port forwarding with a TCP port but the node remains unreachable.
|
||||
|
||||
**Cause:**
|
||||
The port is not open on your router.
|
||||
|
||||
**Fix:**
|
||||
Make port forwarding is enabled for this port on your router.
|
||||
|
||||
#### Nix Organization
|
||||
|
||||
The nix build system is organized into modular files in the `/nix` directory:
|
||||
|
||||
@ -36,9 +36,9 @@ LogosStorageLayout {
|
||||
Rectangle {
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
color: "#1e1e1e"
|
||||
color: Theme.palette.backgroundElevated
|
||||
radius: 8
|
||||
border.color: jsonArea.isValid ? "#3a3a3a" : "#ff0000"
|
||||
border.color: jsonArea.isValid ? Theme.palette.borderSecondary : Theme.palette.error
|
||||
border.width: 1
|
||||
|
||||
ScrollView {
|
||||
@ -49,7 +49,7 @@ LogosStorageLayout {
|
||||
id: jsonArea
|
||||
font.family: "monospace"
|
||||
font.pixelSize: 12
|
||||
color: "#d4d4d4"
|
||||
color: Theme.palette.text
|
||||
wrapMode: Text.WrapAnywhere
|
||||
background: Item {}
|
||||
|
||||
@ -85,29 +85,14 @@ LogosStorageLayout {
|
||||
onClicked: root.back()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 120
|
||||
height: 36
|
||||
radius: 8
|
||||
color: jsonArea.isValid ? "#4CAF50" : "#444444"
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: "Validate"
|
||||
color: "white"
|
||||
font.pixelSize: 14
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
enabled: jsonArea.isValid
|
||||
cursorShape: jsonArea.isValid ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
onClicked: function () {
|
||||
root.backend.saveUserConfig(jsonArea.text)
|
||||
root.backend.reloadIfChanged(jsonArea.text)
|
||||
root.completed()
|
||||
}
|
||||
LogosStorageButton {
|
||||
text: "Validate"
|
||||
variant: "success"
|
||||
enabled: jsonArea.isValid
|
||||
onClicked: {
|
||||
root.backend.saveUserConfig(jsonArea.text)
|
||||
root.backend.reloadIfChanged(jsonArea.text)
|
||||
root.completed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,6 +138,12 @@ qt_add_qml_module(appqml
|
||||
HealthIndicator.qml
|
||||
ModeSelector.qml
|
||||
AdvancedSetup.qml
|
||||
DotIcon.qml
|
||||
NodeStatusIcon.qml
|
||||
GuideIcon.qml
|
||||
AdvancedIcon.qml
|
||||
UpnpIcon.qml
|
||||
PortIcon.qml
|
||||
)
|
||||
|
||||
# Set up QML module directory for runtime
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import QtQuick
|
||||
import Logos.Theme
|
||||
|
||||
Item {
|
||||
id: root
|
||||
@ -57,14 +58,14 @@ Item {
|
||||
height: 10
|
||||
radius: 5
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
color: root.nodeIsUp ? "#4CAF50" : "#f44336"
|
||||
color: root.nodeIsUp ? Theme.palette.success : Theme.palette.error
|
||||
opacity: root.blinkOn ? 1.0 : 0.15
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root.nodeIsUp ? "Node reachable" : "Node unreachable"
|
||||
color: root.nodeIsUp ? "#4CAF50" : "#f44336"
|
||||
color: root.nodeIsUp ? Theme.palette.success : Theme.palette.error
|
||||
font.pixelSize: 12
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,10 +6,21 @@ Button {
|
||||
id: control
|
||||
padding: Theme.spacing.small
|
||||
|
||||
// "default" | "success"
|
||||
property string variant: "default"
|
||||
|
||||
readonly property bool isSuccess: variant === "success"
|
||||
|
||||
contentItem: Text {
|
||||
text: control.text
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
color: control.enabled ? Theme.palette.text : Theme.palette.textMuted
|
||||
color: {
|
||||
if (!control.enabled)
|
||||
return Theme.palette.textMuted
|
||||
if (control.isSuccess)
|
||||
return Theme.palette.background
|
||||
return Theme.palette.text
|
||||
}
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
}
|
||||
@ -18,10 +29,18 @@ Button {
|
||||
color: {
|
||||
if (!control.enabled)
|
||||
return Theme.palette.backgroundElevated
|
||||
if (control.isSuccess)
|
||||
return Theme.palette.success
|
||||
return Theme.palette.backgroundSecondary
|
||||
}
|
||||
border.width: 1
|
||||
border.color: Theme.palette.border
|
||||
border.color: {
|
||||
if (!control.enabled)
|
||||
return Theme.palette.border
|
||||
if (control.isSuccess)
|
||||
return Theme.palette.success
|
||||
return Theme.palette.border
|
||||
}
|
||||
radius: Theme.spacing.tiny
|
||||
|
||||
Behavior on color {
|
||||
|
||||
@ -8,7 +8,7 @@ LogosStorageLayout {
|
||||
|
||||
signal completed(bool isGuide)
|
||||
|
||||
property int selectedMode: -1 // 0 = guide, 1 = advanced
|
||||
property int selectedMode: -1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
@ -30,9 +30,7 @@ LogosStorageLayout {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Item {
|
||||
height: Theme.spacing.medium
|
||||
}
|
||||
Item { height: Theme.spacing.medium }
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacing.medium
|
||||
@ -43,38 +41,22 @@ 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 ? Theme.palette.overlayLight : "transparent"
|
||||
border.color: root.selectedMode === 0 ? Theme.palette.text : Theme.palette.borderTertiaryMuted
|
||||
border.width: root.selectedMode === 0 ? 2 : 1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 14
|
||||
|
||||
// Nothing OS dot icon like
|
||||
Grid {
|
||||
columns: 5
|
||||
spacing: 4
|
||||
GuideIcon {
|
||||
dotColor: Theme.palette.text
|
||||
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]
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
radius: 2
|
||||
color: "white"
|
||||
opacity: modelData ? 0.9 : 0.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Guide"
|
||||
color: "white"
|
||||
color: Theme.palette.text
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@ -82,7 +64,7 @@ LogosStorageLayout {
|
||||
|
||||
Text {
|
||||
text: "Step-by-step setup.\nRecommended for\nmost users."
|
||||
color: Qt.rgba(1, 1, 1, 0.55)
|
||||
color: Theme.palette.textSecondary
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@ -103,38 +85,22 @@ 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 ? Theme.palette.overlayLight : "transparent"
|
||||
border.color: root.selectedMode === 1 ? Theme.palette.text : Theme.palette.borderTertiaryMuted
|
||||
border.width: root.selectedMode === 1 ? 2 : 1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 14
|
||||
|
||||
// Nothing OS dot icon like
|
||||
Grid {
|
||||
columns: 5
|
||||
spacing: 4
|
||||
AdvancedIcon {
|
||||
dotColor: Theme.palette.text
|
||||
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]
|
||||
Rectangle {
|
||||
width: 6
|
||||
height: 6
|
||||
radius: 2
|
||||
color: "white"
|
||||
opacity: modelData ? 0.9 : 0.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
text: "Advanced"
|
||||
color: "white"
|
||||
color: Theme.palette.text
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@ -142,7 +108,7 @@ LogosStorageLayout {
|
||||
|
||||
Text {
|
||||
text: "Manual JSON\nconfiguration for\nexperienced users."
|
||||
color: Qt.rgba(1, 1, 1, 0.55)
|
||||
color: Theme.palette.textSecondary
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@ -159,9 +125,7 @@ LogosStorageLayout {
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
height: Theme.spacing.small
|
||||
}
|
||||
Item { height: Theme.spacing.small }
|
||||
|
||||
LogosStorageButton {
|
||||
text: "Continue"
|
||||
|
||||
@ -11,7 +11,7 @@ LogosStorageLayout {
|
||||
signal back
|
||||
signal completed(bool upnpEnabled)
|
||||
|
||||
property int selectedMode: -1 // 0 = upnp, 1 = port forwarding
|
||||
property int selectedMode: -1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
@ -33,9 +33,7 @@ LogosStorageLayout {
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
Item {
|
||||
height: Theme.spacing.medium
|
||||
}
|
||||
Item { height: Theme.spacing.medium }
|
||||
|
||||
Row {
|
||||
spacing: Theme.spacing.medium
|
||||
@ -46,41 +44,22 @@ 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 ? Theme.palette.overlayLight : "transparent"
|
||||
border.color: root.selectedMode === 0 ? Theme.palette.text : Theme.palette.borderTertiaryMuted
|
||||
border.width: root.selectedMode === 0 ? 2 : 1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 14
|
||||
|
||||
// Nothing OS dot icon — diamond/network
|
||||
Grid {
|
||||
columns: 5
|
||||
spacing: 4
|
||||
UpnpIcon {
|
||||
dotColor: Theme.palette.text
|
||||
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"
|
||||
color: Theme.palette.text
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@ -88,7 +67,7 @@ LogosStorageLayout {
|
||||
|
||||
Text {
|
||||
text: "Automatic port\nforwarding via\nUPnP router."
|
||||
color: Qt.rgba(1, 1, 1, 0.55)
|
||||
color: Theme.palette.textSecondary
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@ -109,41 +88,22 @@ 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 ? Theme.palette.overlayLight : "transparent"
|
||||
border.color: root.selectedMode === 1 ? Theme.palette.text : Theme.palette.borderTertiaryMuted
|
||||
border.width: root.selectedMode === 1 ? 2 : 1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: 14
|
||||
|
||||
// Nothing OS dot icon — right arrow
|
||||
Grid {
|
||||
columns: 5
|
||||
spacing: 4
|
||||
PortIcon {
|
||||
dotColor: Theme.palette.text
|
||||
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"
|
||||
color: Theme.palette.text
|
||||
font.pixelSize: 16
|
||||
font.bold: true
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@ -151,7 +111,7 @@ LogosStorageLayout {
|
||||
|
||||
Text {
|
||||
text: "Manual TCP port\nconfiguration on\nyour router."
|
||||
color: Qt.rgba(1, 1, 1, 0.55)
|
||||
color: Theme.palette.textSecondary
|
||||
font.pixelSize: 12
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
@ -168,9 +128,7 @@ LogosStorageLayout {
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
height: Theme.spacing.small
|
||||
}
|
||||
Item { height: Theme.spacing.small }
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
|
||||
@ -16,10 +16,6 @@ LogosStorageLayout {
|
||||
Connections {
|
||||
target: root.backend
|
||||
|
||||
// The nat ext checking needs a bit of
|
||||
// time because the Storage backend retrieves
|
||||
// the public IP by making a call to the echo service.
|
||||
// When the config is done, just push the startNodeComponent.
|
||||
function onNatExtConfigCompleted() {
|
||||
root.loading = false
|
||||
root.completed(root.tcpPort)
|
||||
@ -30,20 +26,26 @@ LogosStorageLayout {
|
||||
anchors.centerIn: parent
|
||||
spacing: Theme.spacing.medium
|
||||
width: 400
|
||||
Layout.fillWidth: true
|
||||
|
||||
LogosText {
|
||||
id: questionText
|
||||
font.pixelSize: Theme.typography.titleText
|
||||
text: "Choose your TCP port"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
PortIcon {
|
||||
animated: root.loading
|
||||
dotColor: Theme.palette.text
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
LogosText {
|
||||
font.pixelSize: Theme.typography.titleText
|
||||
text: "Port Configuration"
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
LogosText {
|
||||
id: questionDescriptionText
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
text: "The TCP port has to be open to connect with other remote peers."
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
text: "The TCP port must be open to connect with remote peers."
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
LogosTextField {
|
||||
@ -64,14 +66,14 @@ LogosStorageLayout {
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
spacing: Theme.spacing.small
|
||||
|
||||
LogosStorageButton {
|
||||
text: "Back"
|
||||
onClicked: {
|
||||
root.back()
|
||||
}
|
||||
enabled: !root.loading
|
||||
onClicked: root.back()
|
||||
}
|
||||
|
||||
LogosStorageButton {
|
||||
@ -83,6 +85,14 @@ LogosStorageLayout {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LogosText {
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
text: "Retrieving your public IP..."
|
||||
color: Theme.palette.textTertiary
|
||||
visible: root.loading
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
|
||||
@ -9,7 +9,7 @@ LogosStorageLayout {
|
||||
|
||||
property var backend: mockBackend
|
||||
property string status: ""
|
||||
property string title: "Starting your node...."
|
||||
property string title: "Starting your node"
|
||||
property string resolution: ""
|
||||
property bool starting: true
|
||||
property bool success: false
|
||||
@ -19,15 +19,13 @@ LogosStorageLayout {
|
||||
|
||||
function onNodeStarted() {
|
||||
root.starting = false
|
||||
root.status = "Logos Storage started successfully."
|
||||
root.title = "Success"
|
||||
root.status = "Your node is up and reachable."
|
||||
root.title = "Node is ready"
|
||||
root.success = true
|
||||
}
|
||||
|
||||
Component.onCompleted: root.backend.start()
|
||||
|
||||
// Wait after startCompleted before calling checkNodeIs to
|
||||
// make sure the the node is started and ready.
|
||||
Timer {
|
||||
id: nodeCheckTimer
|
||||
interval: 500
|
||||
@ -39,9 +37,8 @@ LogosStorageLayout {
|
||||
target: root.backend
|
||||
|
||||
function onStartCompleted() {
|
||||
console.info("startCompleted")
|
||||
root.title = "Checking.."
|
||||
root.status = "Your node is started, checking everything is up."
|
||||
root.title = "Checking connectivity"
|
||||
root.status = "Node started, verifying reachability..."
|
||||
nodeCheckTimer.start()
|
||||
}
|
||||
|
||||
@ -57,7 +54,7 @@ LogosStorageLayout {
|
||||
|
||||
function onNodeIsntUp(reason) {
|
||||
root.starting = false
|
||||
root.title = "Node not reachable"
|
||||
root.title = "Node unreachable"
|
||||
root.status = ""
|
||||
root.resolution = reason
|
||||
}
|
||||
@ -69,28 +66,35 @@ LogosStorageLayout {
|
||||
spacing: Theme.spacing.medium
|
||||
|
||||
LogosText {
|
||||
id: titleText
|
||||
font.pixelSize: Theme.typography.titleText
|
||||
text: root.title
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
|
||||
LogosText {
|
||||
id: statusText
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
text: root.status
|
||||
NodeStatusIcon {
|
||||
starting: root.starting
|
||||
success: root.success
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
LogosText {
|
||||
id: resolutionText
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
text: root.status
|
||||
visible: root.status !== ""
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
}
|
||||
|
||||
LogosText {
|
||||
font.pixelSize: Theme.typography.primaryText
|
||||
text: root.resolution
|
||||
visible: root.resolution !== ""
|
||||
color: Theme.palette.error
|
||||
wrapMode: Text.WordWrap
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
Layout.alignment: Qt.AlignHCenter
|
||||
}
|
||||
}
|
||||
@ -101,12 +105,11 @@ LogosStorageLayout {
|
||||
anchors.bottomMargin: 10
|
||||
anchors.leftMargin: 10
|
||||
text: "Back"
|
||||
onClicked: function () {
|
||||
enabled: !root.starting
|
||||
onClicked: {
|
||||
root.backend.stop()
|
||||
root.back()
|
||||
}
|
||||
|
||||
enabled: root.starting == false
|
||||
}
|
||||
|
||||
LogosStorageButton {
|
||||
@ -115,40 +118,33 @@ LogosStorageLayout {
|
||||
anchors.bottomMargin: 10
|
||||
anchors.rightMargin: 10
|
||||
text: "Next"
|
||||
onClicked: function () {
|
||||
enabled: root.success
|
||||
onClicked: {
|
||||
root.backend.saveCurrentConfig()
|
||||
root.next()
|
||||
}
|
||||
enabled: root.success == true
|
||||
}
|
||||
|
||||
// In preview/mock mode, simulate a successful node start after 2 seconds
|
||||
Timer {
|
||||
interval: 2000
|
||||
running: root.backend && root.backend.isMock === true
|
||||
onTriggered: root.onNodeStarted()
|
||||
repeat: false
|
||||
onTriggered: root.onNodeStarted()
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: mockBackend
|
||||
|
||||
readonly property bool isMock: true
|
||||
property string configJson: "{}"
|
||||
|
||||
signal startCompleted
|
||||
signal startFailed(string error)
|
||||
signal nodeIsUp
|
||||
signal nodeIsntUp(string reason)
|
||||
|
||||
function guessResolution() {
|
||||
return ""
|
||||
}
|
||||
|
||||
function checkNodeIsUp() {}
|
||||
|
||||
function stop() {}
|
||||
|
||||
function saveCurrentConfig() {}
|
||||
function start() {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,5 +10,13 @@
|
||||
<file alias="PortForwarding.qml">qml/PortForwarding.qml</file>
|
||||
<file alias="ErrorToast.qml">qml/ErrorToast.qml</file>
|
||||
<file alias="HealthIndicator.qml">qml/HealthIndicator.qml</file>
|
||||
<file alias="ModeSelector.qml">qml/ModeSelector.qml</file>
|
||||
<file alias="AdvancedSetup.qml">qml/AdvancedSetup.qml</file>
|
||||
<file alias="DotIcon.qml">qml/DotIcon.qml</file>
|
||||
<file alias="NodeStatusIcon.qml">qml/NodeStatusIcon.qml</file>
|
||||
<file alias="GuideIcon.qml">qml/GuideIcon.qml</file>
|
||||
<file alias="AdvancedIcon.qml">qml/AdvancedIcon.qml</file>
|
||||
<file alias="UpnpIcon.qml">qml/UpnpIcon.qml</file>
|
||||
<file alias="PortIcon.qml">qml/PortIcon.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user