Files
Panama/config/dot/quickshell/modules/settings/HealthSummary.qml
T
Gabriel Brown 6042c0b1c0 Merge codex's System Health and recovery work
Brings in panama-doctor (a 25-check diagnostic with fixture-backed
contracts), a Health service, a System Health page replacing Startup &
Services, and a bar indicator that stays absent until something is
actually degraded. All seven of its contracts pass on the merge.

Three things needed resolving rather than accepting:

The branch predates the debranding, so its user-visible strings still
named the product -- "Panama desktop is healthy", "Restart Panama",
"Panama tools". Rewritten to say the same thing without the name, which
is what the rest of the app now does.

Its Fedora hand-off card was a single button calling openGnomePanel
("network") under a subtitle naming five subjects. Main had already
replaced that with a row per subject, each opening the panel that owns
it, so those rows are ported into HealthPage instead. Printers and
online accounts stay on Network & Devices with the rest of the network
hardware.

That broke its own assertion, which matched the literal
openGnomePanel("network") string. Rewritten rather than reverted: it now
checks the boundary card exists and that every panel named in HealthPage
is one openGnomePanel actually allows, since a name outside the
allow-list opens nothing at all. Verified it catches a plausible-looking
wrong name.

SettingsShell and SettingsSidebar conflicted because both sides added
pages; resolved as the union, keeping its System Health page and live
footer alongside main's Mouse & Touchpad, Privacy & Security, Region &
Language and Online Accounts.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
2026-08-18 11:20:06 -04:00

170 lines
6.0 KiB
QML

import QtQuick
import qs.config
import qs.services
SettingsCard {
id: root
objectName: "health-summary"
implicitHeight: 126
readonly property int observationCount: Health.summary.warnings + Health.summary.errors
readonly property string heroTitle: {
if (Health.diagnosticUnavailable)
return "Health check unavailable";
if (Health.checks.length === 0)
return "Checking the desktop";
if (Health.status === "error")
return "Action required";
if (Health.status === "warning")
return "Needs attention";
return "Healthy";
}
readonly property string heroDetail: {
if (Health.diagnosticUnavailable)
return Health.lastError || "The latest health check could not be completed.";
if (Health.checks.length === 0)
return "Checking the desktop services, tools, and integrations this app owns.";
if (Health.status === "error")
return root.observationCount === 1
? "One part of the desktop needs action."
: `${root.observationCount} parts of the desktop need action.`;
if (Health.status === "warning")
return root.observationCount === 1
? "Your desktop is working. One feature needs a decision."
: `Your desktop is working. ${root.observationCount} features need a decision.`;
return "Desktop services and tools are working normally.";
}
readonly property color statusColor: {
if (Health.diagnosticUnavailable || Health.status === "error")
return Theme.danger;
if (Health.status === "warning")
return Theme.warn;
if (Health.checks.length === 0)
return Theme.fgMuted;
return Theme.ok;
}
function scanTime(): string {
const generatedAt = String(Health.snapshot.generatedAt || "");
if (generatedAt === "")
return "No completed check yet";
const date = new Date(generatedAt);
if (Number.isNaN(date.getTime()))
return "Last check completed";
return `Last checked ${date.toLocaleTimeString(Qt.locale(), Locale.ShortFormat)}`;
}
Item {
width: parent.width
implicitHeight: 96
Column {
anchors.left: parent.left
anchors.right: actions.left
anchors.rightMargin: 22
anchors.verticalCenter: parent.verticalCenter
spacing: 4
Text {
width: parent.width
text: Health.diagnosticUnavailable
? "DIAGNOSTICS"
: root.observationCount > 0
? root.observationCount + (root.observationCount === 1 ? " OBSERVATION" : " OBSERVATIONS")
: "PANAMA DESKTOP"
color: root.statusColor
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
font.weight: Font.DemiBold
font.letterSpacing: 1.15
}
Text {
width: parent.width
text: root.heroTitle
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: 24
font.weight: Font.DemiBold
elide: Text.ElideRight
}
Text {
width: parent.width
text: root.heroDetail
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
elide: Text.ElideRight
}
Row {
spacing: 10
Text {
text: root.scanTime()
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
Text {
objectName: "health-checking-label"
visible: Health.busy
text: "Checking…"
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
Text {
visible: Health.lastCopyResult !== ""
text: Health.lastCopyResult
color: Health.lastCopyResult === "Report copied." ? Theme.ok : Theme.warn
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
}
}
}
Row {
id: actions
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: 8
SettingsButton {
id: copyButton
objectName: "health-copy-report-button"
visible: !Health.diagnosticUnavailable
text: "Copy report"
enabled: Health.checks.length > 0
activeFocusOnTab: enabled
border.width: activeFocus ? 2 : 1
border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08)
onClicked: Health.copyReport()
Keys.onReturnPressed: if (enabled) Health.copyReport()
Keys.onSpacePressed: if (enabled) Health.copyReport()
}
SettingsButton {
id: refreshButton
objectName: "health-refresh-button"
text: Health.diagnosticUnavailable ? "Retry" : "Refresh"
tone: Health.diagnosticUnavailable ? "normal" : "accent"
enabled: !Health.busy
activeFocusOnTab: enabled
border.width: activeFocus ? 2 : (tone === "accent" ? 0 : 1)
border.color: activeFocus ? Theme.accent : Theme.alpha(Theme.fg, 0.08)
onClicked: Health.refresh()
Keys.onReturnPressed: if (enabled) Health.refresh()
Keys.onSpacePressed: if (enabled) Health.refresh()
}
}
}
}