Add components

This commit is contained in:
Arnaud 2026-02-22 16:26:21 +04:00
parent e8c524dc41
commit 9b85c68aaf
No known key found for this signature in database
GPG Key ID: 20E40A5D3110766F
3 changed files with 393 additions and 0 deletions

91
src/qml/DebugPanel.qml Normal file
View File

@ -0,0 +1,91 @@
import QtQuick
import QtQuick.Layouts
import Logos.Theme
import Logos.Controls
// qmllint disable unqualified
Rectangle {
id: root
property var backend
property bool running: false
color: Theme.palette.backgroundElevated
border.color: Theme.palette.borderSecondary
border.width: 1
ColumnLayout {
anchors.fill: parent
spacing: 0
RowLayout {
Layout.fillWidth: true
Layout.leftMargin: 10
Layout.topMargin: 6
Layout.bottomMargin: 4
spacing: 6
LogosStorageButton {
text: "Debug"
enabled: root.running
onClicked: root.backend.tryDebug()
}
LogosStorageButton {
text: "Peer ID"
enabled: root.running
onClicked: root.backend.showPeerId()
}
LogosStorageButton {
text: "Data dir"
enabled: root.running
onClicked: root.backend.dataDir()
}
LogosStorageButton {
text: "SPR"
enabled: root.running
onClicked: root.backend.spr()
}
LogosStorageButton {
text: "Version"
enabled: root.running
onClicked: root.backend.version()
}
Item {
Layout.fillWidth: true
}
}
Rectangle {
Layout.fillWidth: true
Layout.preferredHeight: 1
color: Theme.palette.borderSecondary
}
Flickable {
id: logFlick
Layout.fillWidth: true
Layout.fillHeight: true
clip: true
contentWidth: width
contentHeight: debugText.paintedHeight
TextEdit {
id: debugText
width: logFlick.width
text: root.backend.debugLogs
color: Theme.palette.textSecondary
font.family: "monospace"
font.pixelSize: 11
wrapMode: Text.WrapAnywhere
readOnly: true
padding: 8
bottomPadding: 20
onTextChanged: Qt.callLater(function () {
logFlick.contentY = Math.max(0, logFlick.contentHeight - logFlick.height)
})
}
}
}
}

147
src/qml/NodeHeader.qml Normal file
View File

@ -0,0 +1,147 @@
import QtQuick
import QtQuick.Layouts
import Logos.Theme
import Logos.Controls
// qmllint disable unqualified
RowLayout {
id: root
property var backend
property bool nodeIsUp: false
property bool blinkOn: false
readonly property int stopped: 0
readonly property int starting: 1
readonly property int running: 2
readonly property int stopping: 3
readonly property int destroyed: 4
signal settingsRequested()
spacing: Theme.spacing.medium
StorageIcon {
animated: root.backend.status === root.starting
|| root.backend.status === root.stopping
dotColor: {
if (root.backend.status === root.starting)
return Theme.palette.warning
if (root.backend.status !== root.running)
return Theme.palette.textMuted
return root.nodeIsUp ? Theme.palette.success : Theme.palette.error
}
}
ColumnLayout {
spacing: 6
LogosText {
text: "Logos Storage"
font.pixelSize: Theme.typography.titleText
}
RowLayout {
spacing: 7
Rectangle {
Layout.preferredWidth: 7
Layout.preferredHeight: 7
radius: 3.5
Layout.alignment: Qt.AlignVCenter
color: {
if (root.backend.status === root.starting)
return Theme.palette.warning
if (root.backend.status !== root.running)
return Theme.palette.textMuted
return root.nodeIsUp ? Theme.palette.success : Theme.palette.error
}
opacity: root.backend.status === root.running
? (root.blinkOn ? 1.0 : 0.15) : 1.0
}
LogosText {
text: {
switch (root.backend.status) {
case root.stopped: return "Stopped"
case root.starting: return "Starting…"
case root.running: return "Running"
case root.stopping: return "Stopping…"
case root.destroyed: return "Not initialised"
default: return ""
}
}
font.pixelSize: Theme.typography.primaryText
color: Theme.palette.textSecondary
Layout.alignment: Qt.AlignVCenter
}
}
}
Item {
Layout.fillWidth: true
}
Rectangle {
Layout.preferredWidth: 44
Layout.preferredHeight: 44
radius: 8
color: settingsHover.hovered ? Theme.palette.backgroundElevated : "transparent"
border.color: Theme.palette.borderSecondary
border.width: 1
SettingsIcon {
anchors.centerIn: parent
dotColor: Theme.palette.text
dotSize: 5
dotSpacing: 2
}
HoverHandler {
id: settingsHover
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: root.settingsRequested()
}
}
Rectangle {
Layout.preferredWidth: 44
Layout.preferredHeight: 44
radius: 8
color: startStopHover.hovered ? Theme.palette.backgroundElevated : "transparent"
border.color: Theme.palette.borderSecondary
border.width: 1
opacity: (root.backend.status === root.running
|| root.backend.status === root.stopped) ? 1.0 : 0.4
PlayIcon {
anchors.centerIn: parent
dotColor: Theme.palette.text
dotSize: 5
dotSpacing: 2
visible: root.backend.status !== root.running
}
StopIcon {
anchors.centerIn: parent
dotColor: Theme.palette.text
dotSize: 5
dotSpacing: 2
visible: root.backend.status === root.running
}
HoverHandler {
id: startStopHover
}
MouseArea {
anchors.fill: parent
enabled: root.backend.status === root.running
|| root.backend.status === root.stopped
cursorShape: Qt.PointingHandCursor
onClicked: root.backend.status === root.running
? root.backend.stop() : root.backend.start()
}
}
}

155
src/qml/StatusWidgets.qml Normal file
View File

@ -0,0 +1,155 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Dialogs
import QtQuick.Layouts
import Logos.Theme
import Logos.Controls
// qmllint disable unqualified
ColumnLayout {
id: root
property var backend
property bool running: false
spacing: 0
TextEdit {
id: clipHelper
visible: false
function copyText(str) {
clipHelper.text = str
clipHelper.selectAll()
clipHelper.copy()
}
}
FileDialog {
id: uploadDialog
onAccepted: root.backend.tryUploadFile(selectedFile)
}
Connections {
target: root.backend
function onUploadCompleted(cid) { root._lastCid = cid }
function onDownloadCompleted(cid) { root._lastCid = cid }
}
property string _lastCid: ""
RowLayout {
Layout.fillWidth: true
spacing: Theme.spacing.medium
UploadWidget {
uploadProgress: root.backend.uploadProgress
running: root.running
onUploadRequested: uploadDialog.open()
}
DiskWidget {
backend: root.backend
}
PeersWidget {
backend: root.backend
}
Item {
Layout.fillWidth: true
}
}
Item {
Layout.fillWidth: true
Layout.topMargin: 10
Layout.bottomMargin: 10
Layout.preferredHeight: 36
opacity: root._lastCid.length > 0 ? 1.0 : 0.0
Behavior on opacity {
NumberAnimation {
duration: 200
}
}
Rectangle {
height: 36
width: cidBadgeRow.implicitWidth + 28
radius: 6
color: Theme.palette.backgroundSecondary
border.color: Theme.palette.borderSecondary
border.width: 1
RowLayout {
id: cidBadgeRow
anchors.centerIn: parent
spacing: 8
LogosText {
text: "CID"
font.pixelSize: 10
color: Theme.palette.textTertiary
}
LogosText {
text: {
var c = root._lastCid
return c.length > 20 ? c.substring(0, 8) + "…" + c.slice(-6) : c
}
font.pixelSize: 11
font.family: "monospace"
color: Theme.palette.text
}
LogosText {
text: "COPY"
font.pixelSize: 9
color: Theme.palette.textTertiary
font.letterSpacing: 0.8
}
}
Rectangle {
id: copyFlash
anchors.fill: parent
radius: parent.radius
color: Theme.palette.success
opacity: 0
SequentialAnimation on opacity {
id: copyFlashAnim
running: false
NumberAnimation {
to: 0.18
duration: 80
}
NumberAnimation {
to: 0
duration: 500
}
}
}
HoverHandler {
id: cidBadgeHover
}
Rectangle {
anchors.fill: parent
radius: parent.radius
color: cidBadgeHover.hovered ? Qt.rgba(1, 1, 1, 0.04) : "transparent"
}
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
clipHelper.copyText(root._lastCid)
copyFlashAnim.restart()
}
}
}
}
}