feat(instances): show OS version

This commit is contained in:
Peter Steinberger
2025-12-13 23:46:07 +00:00
parent 755e329b01
commit a53d8ed4e4
6 changed files with 81 additions and 0 deletions

View File

@@ -67,6 +67,9 @@ struct InstancesSettings: View {
if let version = inst.version {
self.label(icon: "shippingbox", text: version)
}
if let platform = inst.platform, let prettyPlatform = self.prettyPlatform(platform) {
self.label(icon: self.platformIcon(platform), text: prettyPlatform)
}
self.label(icon: "clock", text: inst.lastInputDescription)
if let mode = inst.mode { self.label(icon: "network", text: mode) }
if let reason = inst.reason, !reason.isEmpty {
@@ -94,6 +97,52 @@ struct InstancesSettings: View {
.font(.footnote)
}
private func platformIcon(_ raw: String) -> String {
let (prefix, _) = self.parsePlatform(raw)
switch prefix {
case "macos":
return "laptopcomputer"
case "ios":
return "iphone"
case "ipados":
return "ipad"
case "tvos":
return "appletv"
case "watchos":
return "applewatch"
default:
return "cpu"
}
}
private func prettyPlatform(_ raw: String) -> String? {
let (prefix, version) = self.parsePlatform(raw)
if prefix.isEmpty { return nil }
let name: String = switch prefix {
case "macos": "macOS"
case "ios": "iOS"
case "ipados": "iPadOS"
case "tvos": "tvOS"
case "watchos": "watchOS"
default: prefix.prefix(1).uppercased() + prefix.dropFirst()
}
guard let version, !version.isEmpty else { return name }
let parts = version.split(separator: ".").map(String.init)
if parts.count >= 2 {
return "\(name) \(parts[0]).\(parts[1])"
}
return "\(name) \(version)"
}
private func parsePlatform(_ raw: String) -> (prefix: String, version: String?) {
let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty { return ("", nil) }
let parts = trimmed.split(whereSeparator: { $0 == " " || $0 == "\t" }).map(String.init)
let prefix = parts.first?.lowercased() ?? ""
let versionToken = parts.dropFirst().first
return (prefix, versionToken)
}
private func presenceUpdateSourceText(_ reason: String) -> String {
let trimmed = reason.trimmingCharacters(in: .whitespacesAndNewlines)
switch trimmed {

View File

@@ -8,6 +8,7 @@ struct InstanceInfo: Identifiable, Codable {
let host: String?
let ip: String?
let version: String?
let platform: String?
let lastInputSeconds: Int?
let mode: String?
let reason: String?
@@ -145,6 +146,8 @@ final class InstancesStore: ObservableObject {
let host = Host.current().localizedName ?? "this-mac"
let ip = Self.primaryIPv4Address()
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
let osVersion = ProcessInfo.processInfo.operatingSystemVersion
let platform = "macos \(osVersion.majorVersion).\(osVersion.minorVersion).\(osVersion.patchVersion)"
let text = "Local node: \(host)\(ip.map { " (\($0))" } ?? "") · app \(version ?? "dev")"
let ts = Date().timeIntervalSince1970 * 1000
return InstanceInfo(
@@ -152,6 +155,7 @@ final class InstancesStore: ObservableObject {
host: host,
ip: ip,
version: version,
platform: platform,
lastInputSeconds: Self.lastInputSeconds(),
mode: "local",
reason: reason,
@@ -228,6 +232,7 @@ final class InstancesStore: ObservableObject {
host: "gateway (health)",
ip: nil,
version: nil,
platform: nil,
lastInputSeconds: nil,
mode: "health",
reason: "health probe",
@@ -276,6 +281,7 @@ final class InstancesStore: ObservableObject {
host: entry.host,
ip: entry.ip,
version: entry.version,
platform: entry.platform,
lastInputSeconds: entry.lastinputseconds,
mode: entry.mode,
reason: entry.reason,
@@ -299,6 +305,7 @@ extension InstancesStore {
host: "steipete-mac",
ip: "10.0.0.12",
version: "1.2.3",
platform: "macos 26.2.0",
lastInputSeconds: 12,
mode: "local",
reason: "preview",
@@ -309,6 +316,7 @@ extension InstancesStore {
host: "gateway",
ip: "100.64.0.2",
version: "1.2.3",
platform: "linux 6.6.0",
lastInputSeconds: 45,
mode: "remote",
reason: "preview",

View File

@@ -167,6 +167,7 @@ public struct PresenceEntry: Codable {
public let host: String?
public let ip: String?
public let version: String?
public let platform: String?
public let mode: String?
public let lastinputseconds: Int?
public let reason: String?
@@ -179,6 +180,7 @@ public struct PresenceEntry: Codable {
host: String?,
ip: String?,
version: String?,
platform: String?,
mode: String?,
lastinputseconds: Int?,
reason: String?,
@@ -190,6 +192,7 @@ public struct PresenceEntry: Codable {
self.host = host
self.ip = ip
self.version = version
self.platform = platform
self.mode = mode
self.lastinputseconds = lastinputseconds
self.reason = reason
@@ -202,6 +205,7 @@ public struct PresenceEntry: Codable {
case host
case ip
case version
case platform
case mode
case lastinputseconds = "lastInputSeconds"
case reason