88 lines
2.6 KiB
Swift
88 lines
2.6 KiB
Swift
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
|
|
}
|
|
}
|