mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-08 06:54:24 +00:00
iOS: extract device/platform info into DeviceInfoHelper, keep Settings platform string as iOS X.Y.Z
This commit is contained in:
committed by
Peter Steinberger
parent
e3ac491da3
commit
32d7756d8c
71
apps/ios/Sources/Device/DeviceInfoHelper.swift
Normal file
71
apps/ios/Sources/Device/DeviceInfoHelper.swift
Normal file
@@ -0,0 +1,71 @@
|
||||
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.
|
||||
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".
|
||||
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))"
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,12 @@ final class DeviceStatusService: DeviceStatusServicing {
|
||||
|
||||
func info() -> OpenClawDeviceInfoPayload {
|
||||
let device = UIDevice.current
|
||||
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev"
|
||||
let appBuild = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? "0"
|
||||
let appVersion = DeviceInfoHelper.appVersion()
|
||||
let appBuild = DeviceStatusService.fallbackAppBuild(DeviceInfoHelper.appBuild())
|
||||
let locale = Locale.preferredLanguages.first ?? Locale.current.identifier
|
||||
return OpenClawDeviceInfoPayload(
|
||||
deviceName: device.name,
|
||||
modelIdentifier: Self.modelIdentifier(),
|
||||
modelIdentifier: DeviceInfoHelper.modelIdentifier(),
|
||||
systemName: device.systemName,
|
||||
systemVersion: device.systemVersion,
|
||||
appVersion: appVersion,
|
||||
@@ -75,13 +75,8 @@ final class DeviceStatusService: DeviceStatusServicing {
|
||||
return OpenClawStorageStatusPayload(totalBytes: total, freeBytes: free, usedBytes: used)
|
||||
}
|
||||
|
||||
private 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
|
||||
/// Fallback for payloads that require a non-empty build (e.g. "0").
|
||||
private static func fallbackAppBuild(_ build: String) -> String {
|
||||
build.isEmpty ? "0" : build
|
||||
}
|
||||
}
|
||||
|
||||
@@ -921,44 +921,6 @@ final class GatewayConnectionController {
|
||||
private static func motionAvailable() -> Bool {
|
||||
CMMotionActivityManager.isActivityAvailable() || CMPedometer.isStepCountingAvailable()
|
||||
}
|
||||
|
||||
private 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)"
|
||||
}
|
||||
|
||||
private func deviceFamily() -> String {
|
||||
switch UIDevice.current.userInterfaceIdiom {
|
||||
case .pad:
|
||||
"iPad"
|
||||
case .phone:
|
||||
"iPhone"
|
||||
default:
|
||||
"iOS"
|
||||
}
|
||||
}
|
||||
|
||||
private 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
|
||||
}
|
||||
|
||||
private func appVersion() -> String {
|
||||
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev"
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
@@ -980,19 +942,19 @@ extension GatewayConnectionController {
|
||||
}
|
||||
|
||||
func _test_platformString() -> String {
|
||||
self.platformString()
|
||||
DeviceInfoHelper.platformString()
|
||||
}
|
||||
|
||||
func _test_deviceFamily() -> String {
|
||||
self.deviceFamily()
|
||||
DeviceInfoHelper.deviceFamily()
|
||||
}
|
||||
|
||||
func _test_modelIdentifier() -> String {
|
||||
self.modelIdentifier()
|
||||
DeviceInfoHelper.modelIdentifier()
|
||||
}
|
||||
|
||||
func _test_appVersion() -> String {
|
||||
self.appVersion()
|
||||
DeviceInfoHelper.appVersion()
|
||||
}
|
||||
|
||||
func _test_setGateways(_ gateways: [GatewayDiscoveryModel.DiscoveredGateway]) {
|
||||
|
||||
@@ -374,9 +374,9 @@ struct SettingsTab: View {
|
||||
.foregroundStyle(.secondary)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.middle)
|
||||
LabeledContent("Device", value: self.deviceFamily())
|
||||
LabeledContent("Platform", value: self.platformString())
|
||||
LabeledContent("OpenClaw", value: self.openClawVersionString())
|
||||
LabeledContent("Device", value: DeviceInfoHelper.deviceFamily())
|
||||
LabeledContent("Platform", value: DeviceInfoHelper.platformStringForDisplay())
|
||||
LabeledContent("OpenClaw", value: DeviceInfoHelper.openClawVersionString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -584,32 +584,6 @@ struct SettingsTab: View {
|
||||
return trimmed.isEmpty ? "Not connected" : trimmed
|
||||
}
|
||||
|
||||
private func platformString() -> String {
|
||||
let v = ProcessInfo.processInfo.operatingSystemVersion
|
||||
return "iOS \(v.majorVersion).\(v.minorVersion).\(v.patchVersion)"
|
||||
}
|
||||
|
||||
private func deviceFamily() -> String {
|
||||
switch UIDevice.current.userInterfaceIdiom {
|
||||
case .pad:
|
||||
"iPad"
|
||||
case .phone:
|
||||
"iPhone"
|
||||
default:
|
||||
"iOS"
|
||||
}
|
||||
}
|
||||
|
||||
private func openClawVersionString() -> String {
|
||||
let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "dev"
|
||||
let build = Bundle.main.infoDictionary?["CFBundleVersion"] as? String ?? ""
|
||||
let trimmedBuild = build.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if trimmedBuild.isEmpty || trimmedBuild == version {
|
||||
return version
|
||||
}
|
||||
return "\(version) (\(trimmedBuild))"
|
||||
}
|
||||
|
||||
private func featureToggle(
|
||||
_ title: String,
|
||||
isOn: Binding<Bool>,
|
||||
|
||||
@@ -4,6 +4,9 @@ Sources/Gateway/GatewayDiscoveryModel.swift
|
||||
Sources/Gateway/GatewaySettingsStore.swift
|
||||
Sources/Gateway/KeychainStore.swift
|
||||
Sources/Camera/CameraController.swift
|
||||
Sources/Device/DeviceInfoHelper.swift
|
||||
Sources/Device/DeviceStatusService.swift
|
||||
Sources/Device/NetworkStatusService.swift
|
||||
Sources/Chat/ChatSheet.swift
|
||||
Sources/Chat/IOSGatewayChatTransport.swift
|
||||
Sources/OpenClawApp.swift
|
||||
|
||||
Reference in New Issue
Block a user