macOS: compact Instances row

This commit is contained in:
Peter Steinberger
2025-12-18 00:24:10 +01:00
parent d3f4db649f
commit 07c8fdffd1

View File

@@ -58,6 +58,8 @@ struct InstancesSettings: View {
@ViewBuilder @ViewBuilder
private func instanceRow(_ inst: InstanceInfo) -> some View { private func instanceRow(_ inst: InstanceInfo) -> some View {
let isGateway = (inst.mode ?? "").trimmingCharacters(in: .whitespacesAndNewlines).lowercased() == "gateway"
VStack(alignment: .leading, spacing: 4) { VStack(alignment: .leading, spacing: 4) {
HStack(spacing: 8) { HStack(spacing: 8) {
Text(inst.host ?? "unknown host").font(.subheadline.bold()) Text(inst.host ?? "unknown host").font(.subheadline.bold())
@@ -76,21 +78,21 @@ struct InstancesSettings: View {
{ {
self.label(icon: device.symbol, text: device.title) self.label(icon: device.symbol, text: device.title)
} }
self.label(icon: "clock", text: inst.lastInputDescription)
// Last local input is helpful for interactive nodes, but noisy/meaningless for the gateway.
if !isGateway, let secs = inst.lastInputSeconds {
self.label(icon: "clock", text: "\(secs)s ago")
}
if let mode = inst.mode { self.label(icon: "network", text: mode) } if let mode = inst.mode { self.label(icon: "network", text: mode) }
if let reason = inst.reason, !reason.isEmpty {
self.label( if let update = self.updateSummaryText(inst, isGateway: isGateway) {
icon: "info.circle", self.label(icon: "arrow.clockwise", text: update)
text: "Updated by: \(self.presenceUpdateSourceText(reason))") .help(self.presenceUpdateSourceHelp(inst.reason ?? ""))
.help(self.presenceUpdateSourceHelp(reason))
} }
} }
Text(inst.text) Text(inst.text)
.font(.footnote) .font(.footnote)
.foregroundStyle(.secondary) .foregroundStyle(.secondary)
Text(inst.ageDescription)
.font(.caption)
.foregroundStyle(.secondary)
} }
.padding(.vertical, 6) .padding(.vertical, 6)
} }
@@ -151,28 +153,45 @@ struct InstancesSettings: View {
return (prefix, versionToken) return (prefix, versionToken)
} }
private func presenceUpdateSourceText(_ reason: String) -> String { private func presenceUpdateSourceShortText(_ reason: String) -> String? {
let trimmed = reason.trimmingCharacters(in: .whitespacesAndNewlines) let trimmed = reason.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return nil }
switch trimmed { switch trimmed {
case "self": case "self":
return "Gateway (self)" return "Self"
case "connect": case "connect":
return "Client connected" return "Connect"
case "disconnect": case "disconnect":
return "Client disconnected" return "Disconnect"
case "launch": case "launch":
return "App launch" return "Launch"
case "periodic": case "periodic":
return "Heartbeat" return "Heartbeat"
case "instances-refresh": case "instances-refresh":
return "UI refresh (Instances tab)" return "Instances"
case "seq gap": case "seq gap":
return "Resynced after event gap" return "Resync"
default: default:
return trimmed.isEmpty ? "Unknown" : trimmed return trimmed
} }
} }
private func updateSummaryText(_ inst: InstanceInfo, isGateway: Bool) -> String? {
// For gateway rows, omit the "updated via/by" provenance entirely.
if isGateway {
return nil
}
let age = inst.ageDescription.trimmingCharacters(in: .whitespacesAndNewlines)
guard !age.isEmpty else { return nil }
let source = self.presenceUpdateSourceShortText(inst.reason ?? "")
if let source, !source.isEmpty {
return "\(age) · \(source)"
}
return age
}
private func presenceUpdateSourceHelp(_ reason: String) -> String { private func presenceUpdateSourceHelp(_ reason: String) -> String {
let trimmed = reason.trimmingCharacters(in: .whitespacesAndNewlines) let trimmed = reason.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty { if trimmed.isEmpty {