feat(ios): add native settings and storage controls

This commit is contained in:
chick
2026-09-09 02:06:34 +08:00
parent 9c3186252b
commit c568e496b2
8 changed files with 423 additions and 1 deletions
@@ -0,0 +1,87 @@
import Foundation
import Darwin
struct SettingsRuntime: Equatable {
let appName: String
let marketingVersion: String
let buildVersion: String
let platform: String
let deviceModel: String
}
struct ServerCapability: Equatable, Identifiable {
let id: String
let name: String
let detail: String
}
@MainActor
final class SettingsViewModel: ObservableObject {
@Published private(set) var runtime: SettingsRuntime?
@Published private(set) var serverCapabilities: [ServerCapability] = []
@Published private(set) var isLoading = false
@Published var storageLabel = "--"
@Published var serverCapabilitiesNotice = ""
@Published var notice: String?
@Published var errorMessage: String?
private let store: any LogStore
init(store: any LogStore) {
self.store = store
}
func refresh() async {
isLoading = true
errorMessage = nil
runtime = SettingsRuntime(
appName: AppMetadata.name,
marketingVersion: AppMetadata.marketingVersion,
buildVersion: AppMetadata.buildVersion,
platform: "iOS",
deviceModel: Self.deviceModel()
)
serverCapabilities = []
serverCapabilitiesNotice = "定时任务与后台刷新已在 iOS 版停用。"
await loadStorageLabel()
isLoading = false
}
func clearRuntimeLogs() async -> Int {
do {
let removed = try await store.clearRuntimeLogs()
notice = removed > 0 ? "已清除 \(removed) 条运行日志。" : "没有可清除的运行日志。"
errorMessage = nil
await loadStorageLabel()
return removed
} catch {
notice = nil
errorMessage = "清除运行日志失败。"
return 0
}
}
private func loadStorageLabel() async {
do {
let runtimeCount = try await store.runtimeLogs().count
let connectionCount = try await store.connectionLogs().count
storageLabel = "\(runtimeCount) 条运行日志 · \(connectionCount) 条连接日志"
} catch {
storageLabel = "--"
errorMessage = "无法读取本地数据状态。"
}
}
private static func deviceModel() -> String {
var systemInfo = utsname()
guard uname(&systemInfo) == 0 else { return "未知设备" }
let bytes = withUnsafeBytes(of: systemInfo.machine) { Data($0) }
let model = String(
decoding: bytes.prefix { $0 != 0 },
as: UTF8.self
)
return model.isEmpty ? "未知设备" : model
}
}