Files
moltbot/apps/ios/Sources/Device/DeviceInfoHelper.swift
2026-03-02 04:36:49 +00:00

74 lines
2.4 KiB
Swift

import Foundation
import UIKit
import Darwin
/// Shared device and platform info for Settings, gateway node payloads, and device status.
enum DeviceInfoHelper {
/// e.g. "iOS 18.0.0" or "iPadOS 18.0.0" by interface idiom. Use for gateway/device payloads.
@MainActor
static func platformString() -> String {
let v = ProcessInfo.processInfo.operatingSystemVersion
let name = switch UIDevice.current.userInterfaceIdiom {
case .pad:
"iPadOS"
case .phone:
"iOS"
default:
"iOS"
}
return "\(name) \(v.majorVersion).\(v.minorVersion).\(v.patchVersion)"
}
/// Always "iOS X.Y.Z" for UI display (e.g. Settings), matching legacy behavior on iPad.
static func platformStringForDisplay() -> String {
let v = ProcessInfo.processInfo.operatingSystemVersion
return "iOS \(v.majorVersion).\(v.minorVersion).\(v.patchVersion)"
}
/// Device family for display: "iPad", "iPhone", or "iOS".
@MainActor
static func deviceFamily() -> String {
switch UIDevice.current.userInterfaceIdiom {
case .pad:
"iPad"
case .phone:
"iPhone"
default:
"iOS"
}
}
/// Machine model identifier from uname (e.g. "iPhone17,1").
static func modelIdentifier() -> String {
var systemInfo = utsname()
uname(&systemInfo)
let machine = withUnsafeBytes(of: &systemInfo.machine) { ptr in
String(bytes: ptr.prefix { $0 != 0 }, encoding: .utf8)
}
let trimmed = machine?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
return trimmed.isEmpty ? "unknown" : trimmed
}
/// App marketing version only, e.g. "2026.2.0" or "dev".
static func appVersion() -> String {
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev"
}
/// App build string, e.g. "123" or "".
static func appBuild() -> String {
let raw = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? ""
return raw.trimmingCharacters(in: .whitespacesAndNewlines)
}
/// Display string for Settings: "1.2.3" or "1.2.3 (456)" when build differs.
static func openClawVersionString() -> String {
let version = appVersion()
let build = appBuild()
if build.isEmpty || build == version {
return version
}
return "\(version) (\(build))"
}
}