systemd: fetch remotes via busctl --host, applet-open gating, error states (step 4)

This commit is contained in:
Damocles 2026-05-07 20:24:25 +02:00
parent 6224d86965
commit 2ab2af8a23
4 changed files with 302 additions and 34 deletions

View file

@ -13,6 +13,9 @@ Column {
onHeightChanged: root.contentResized()
Component.onCompleted: NS.SystemdService.setAppletOpen(true)
Component.onDestruction: NS.SystemdService.setAppletOpen(false)
Repeater {
model: S.SystemdService.machines
@ -37,6 +40,9 @@ Column {
totalCount: _row.modelData.totalCount ?? 0
failedUnits: _row.modelData.failedUnits ?? []
runningUnits: _row.modelData.runningUnits ?? []
errorKind: _row.modelData.errorKind ?? ""
errorReason: _row.modelData.errorReason ?? ""
lastSeen: _row.modelData.lastSeen ?? 0
onContentResized: root.contentResized()
}
}

View file

@ -19,6 +19,9 @@ Column {
required property int totalCount
required property var failedUnits
required property var runningUnits
property string errorKind: ""
property string errorReason: ""
property int lastSeen: 0
signal contentResized
onHeightChanged: root.contentResized()
@ -87,12 +90,18 @@ Column {
visible: root.systemState !== "unknown"
color: {
const st = root.systemState;
if (root.errorKind === "permanent")
return NS.ThemeService.base08;
if (root.errorKind === "transient")
return NS.ThemeService.base04;
if (st === "running")
return NS.ThemeService.base0B;
if (st === "degraded")
return NS.ThemeService.base0A;
if (st === "pending")
return NS.ThemeService.base04;
if (st === "unreachable")
return NS.ThemeService.base04;
return NS.ThemeService.base08;
}
opacity: 0.85
@ -111,6 +120,44 @@ Column {
}
}
// Error / last-seen line for remote machines. Hidden when there's no
// error and the machine is reachable (lastSeen > 0 with no errorKind).
Item {
visible: root.errorKind !== "" || (root.lastSeen > 0 && root.systemState === "unreachable")
width: root.width
height: visible ? 22 : 0
Text {
anchors.left: parent.left
anchors.leftMargin: 24
anchors.right: parent.right
anchors.rightMargin: 12
anchors.verticalCenter: parent.verticalCenter
text: {
const ago = root.lastSeen > 0 ? " (last seen " + _agoString(root.lastSeen) + ")" : "";
if (root.errorReason !== "")
return root.errorReason + ago;
return ago.replace(/^\s+/, "");
}
color: root.errorKind === "permanent" ? NS.ThemeService.base08 : NS.ThemeService.base03
font.pixelSize: NS.ThemeService.fontSize - 3
font.family: NS.ThemeService.fontFamily
elide: Text.ElideRight
}
}
function _agoString(unix) {
const now = Math.floor(Date.now() / 1000);
const d = Math.max(0, now - unix);
if (d < 60)
return d + "s ago";
if (d < 3600)
return Math.floor(d / 60) + "m ago";
if (d < 86400)
return Math.floor(d / 3600) + "h ago";
return Math.floor(d / 86400) + "d ago";
}
// Failed units (auto-expanded; entire block hidden when there are none).
Repeater {
model: root._failedCount > 0 ? root.failedUnits : []