import Foundation import SwiftUI /// 单个指标的展示样式 enum GaugeDisplayStyle: String, CaseIterable, Identifiable, Codable { case bar // 条状百分比 case ring // 圆环进度 case text // 纯文本百分比 case pie // 扇形小圆盘 case compact // 紧凑横条 + 文字 var id: String { rawValue } var displayName: String { switch self { case .bar: return "条状百分比" case .ring: return "圆环进度" case .text: return "纯文本" case .pie: return "扇形圆盘" case .compact: return "紧凑横条" } } var iconName: String { switch self { case .bar: return "rectangle.split.1x2" case .ring: return "circle.dotted" case .text: return "textformat" case .pie: return "chart.pie" case .compact: return "rectangle.compress.vertical" } } } /// 模块在窗口中的排列位置 enum ModulePosition: String, CaseIterable, Identifiable, Codable { case left // 左列 case right // 右列 case full // 全宽(独占一行) var id: String { rawValue } var displayName: String { switch self { case .left: return "左" case .right: return "右" case .full: return "全宽" } } } /// 配置管理者:所有用户偏好通过 UserDefaults 持久化 final class Configuration: ObservableObject { static let shared = Configuration() @Published var cpuStyle: GaugeDisplayStyle { didSet { save("cpuStyle", cpuStyle.rawValue) } } @Published var gpuStyle: GaugeDisplayStyle { didSet { save("gpuStyle", gpuStyle.rawValue) } } @Published var memoryStyle: GaugeDisplayStyle { didSet { save("memoryStyle", memoryStyle.rawValue) } } @Published var swapStyle: GaugeDisplayStyle { didSet { save("swapStyle", swapStyle.rawValue) } } @Published var showCPU: Bool { didSet { save("showCPU", showCPU) } } @Published var showGPU: Bool { didSet { save("showGPU", showGPU) } } @Published var showMemory: Bool { didSet { save("showMemory", showMemory) } } @Published var showSwap: Bool { didSet { save("showSwap", showSwap) } } @Published var showTopProcesses: Bool { didSet { save("showTopProcesses", showTopProcesses) } } @Published var processCount: Int { didSet { save("processCount", processCount) } } @Published var refreshInterval: Double { didSet { save("refreshInterval", refreshInterval) } } @Published var opacity: Double { didSet { save("opacity", opacity) } } @Published var fontSize: Double { didSet { save("fontSize", fontSize) } } @Published var windowWidth: Double { didSet { save("windowWidth", windowWidth) } } @Published var windowHeight: Double { didSet { save("windowHeight", windowHeight) } } @Published var cpuPos: ModulePosition { didSet { save("cpuPos", cpuPos.rawValue) } } @Published var gpuPos: ModulePosition { didSet { save("gpuPos", gpuPos.rawValue) } } @Published var memoryPos: ModulePosition { didSet { save("memoryPos", memoryPos.rawValue) } } @Published var swapPos: ModulePosition { didSet { save("swapPos", swapPos.rawValue) } } @Published var processesPos: ModulePosition { didSet { save("processesPos", processesPos.rawValue) } } // 行号:决定模块在垂直方向上的排列顺序(1-10) @Published var cpuRow: Int { didSet { save("cpuRow", cpuRow) } } @Published var gpuRow: Int { didSet { save("gpuRow", gpuRow) } } @Published var memoryRow: Int { didSet { save("memoryRow", memoryRow) } } @Published var swapRow: Int { didSet { save("swapRow", swapRow) } } @Published var processesRow: Int { didSet { save("processesRow", processesRow) } } private init() { let defaults = UserDefaults.standard cpuStyle = GaugeDisplayStyle(rawValue: defaults.string(forKey: "cpuStyle") ?? "ring") ?? .ring gpuStyle = GaugeDisplayStyle(rawValue: defaults.string(forKey: "gpuStyle") ?? "ring") ?? .ring memoryStyle = GaugeDisplayStyle(rawValue: defaults.string(forKey: "memoryStyle") ?? "bar") ?? .bar swapStyle = GaugeDisplayStyle(rawValue: defaults.string(forKey: "swapStyle") ?? "bar") ?? .bar showCPU = defaults.object(forKey: "showCPU") as? Bool ?? true showGPU = defaults.object(forKey: "showGPU") as? Bool ?? true showMemory = defaults.object(forKey: "showMemory") as? Bool ?? true showSwap = defaults.object(forKey: "showSwap") as? Bool ?? true showTopProcesses = defaults.object(forKey: "showTopProcesses") as? Bool ?? true processCount = defaults.object(forKey: "processCount") as? Int ?? 5 refreshInterval = defaults.object(forKey: "refreshInterval") as? Double ?? 1.5 opacity = defaults.object(forKey: "opacity") as? Double ?? 1.0 fontSize = defaults.object(forKey: "fontSize") as? Double ?? 12 windowWidth = defaults.object(forKey: "windowWidth") as? Double ?? 250 windowHeight = defaults.object(forKey: "windowHeight") as? Double ?? 300 cpuPos = ModulePosition(rawValue: defaults.string(forKey: "cpuPos") ?? "full") ?? .full gpuPos = ModulePosition(rawValue: defaults.string(forKey: "gpuPos") ?? "full") ?? .full memoryPos = ModulePosition(rawValue: defaults.string(forKey: "memoryPos") ?? "full") ?? .full swapPos = ModulePosition(rawValue: defaults.string(forKey: "swapPos") ?? "full") ?? .full processesPos = ModulePosition(rawValue: defaults.string(forKey: "processesPos") ?? "full") ?? .full cpuRow = defaults.object(forKey: "cpuRow") as? Int ?? 1 gpuRow = defaults.object(forKey: "gpuRow") as? Int ?? 2 memoryRow = defaults.object(forKey: "memoryRow") as? Int ?? 3 swapRow = defaults.object(forKey: "swapRow") as? Int ?? 4 processesRow = defaults.object(forKey: "processesRow") as? Int ?? 5 } private func save(_ key: String, _ value: Any) { UserDefaults.standard.set(value, forKey: key) } }