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
170 lines
6.0 KiB
QML
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()
|
|
}
|
|
}
|
|
}
|
|
}
|