import Foundation import SwiftUI enum TaskSection: String, CaseIterable, Identifiable { case processes = "Processes" case performance = "Performance" case history = "App history" case startup = "Startup apps" case users = "Users" case details = "Details" case services = "Services" case settings = "Settings" var id: String { rawValue } var icon: String { switch self { case .processes: "square.stack.3d.up" case .performance: "waveform.path.ecg" case .history: "clock.arrow.circlepath" case .startup: "gauge.open.with.lines.needle.33percent" case .users: "person.2" case .details: "list.bullet.rectangle" case .services: "gearshape.2" case .settings: "gearshape" } } } enum UpdateSpeed: String, CaseIterable, Identifiable { case high = "High" case normal = "Normal" case low = "Low" case paused = "Paused" var id: String { rawValue } var interval: Duration { switch self { case .high: .seconds(1) case .normal: .seconds(2) case .low: .seconds(5) case .paused: .seconds(2) } } } struct ProcessRecord: Identifiable, Hashable, Sendable { let pid: Int32 let parentPID: Int32 let name: String let executablePath: String let user: String let cpu: Double let memoryPercent: Double let residentBytes: UInt64 let state: String let elapsed: String let cpuTime: TimeInterval let threadCount: Int let openFileCount: Int let architecture: String let priority: Int let nice: Int var id: Int32 { pid } var displayName: String { let cleaned = name.trimmingCharacters(in: .whitespacesAndNewlines) return cleaned.isEmpty ? "Process \(pid)" : cleaned } } struct AppUsageRecord: Identifiable, Codable, Hashable, Sendable { let id: String var name: String var executablePath: String var user: String var cpuSeconds: TimeInterval var networkReceivedBytes: UInt64 var networkSentBytes: UInt64 var lastSeen: Date var networkTotalBytes: UInt64 { networkReceivedBytes + networkSentBytes } } struct ProcessActivityRate: Hashable, Sendable { var diskRead = 0.0 var diskWrite = 0.0 var networkReceive = 0.0 var networkSend = 0.0 var diskTotal: Double { diskRead + diskWrite } var networkTotal: Double { networkReceive + networkSend } } enum ServiceDomain: String, CaseIterable, Identifiable, Sendable { case user = "User" case system = "System" var id: String { rawValue } var launchctlPrefix: String { self == .system ? "system" : "gui/\(getuid())" } } struct ServiceRecord: Identifiable, Hashable, Sendable { let label: String let pid: Int32? let lastExitStatus: Int32 let domain: ServiceDomain var id: String { "\(domain.rawValue):\(label)" } var isRunning: Bool { pid != nil } var isControllable: Bool { domain == .user } var configurationPath: String? { let roots = domain == .system ? ["/Library/LaunchDaemons", "/System/Library/LaunchDaemons"] : [NSHomeDirectory() + "/Library/LaunchAgents", "/Library/LaunchAgents", "/System/Library/LaunchAgents"] return roots.map { "\($0)/\(label).plist" }.first { FileManager.default.fileExists(atPath: $0) } } var displayName: String { let parts = label.split(separator: ".").map(String.init) let meaningful = parts.filter { part in let isNumber = part.allSatisfy(\.isNumber) let isUUID = UUID(uuidString: part) != nil return !isNumber && !isUUID } guard let last = meaningful.last else { return label } let generic = ["agent", "helper", "service", "xpcservice", "app"] if generic.contains(last.lowercased()), meaningful.count > 1 { return "\(meaningful[meaningful.count - 2]) \(last)" } return last } var publisher: String { let parts = label.split(separator: ".").map(String.init) guard let first = parts.first else { return "Unknown" } if label.hasPrefix("com.apple") { return "Apple" } if first == "application", parts.count > 2 { let vendorIndex = ["com", "org", "net", "io"].contains(parts[1].lowercased()) ? 2 : 1 let vendor = parts[vendorIndex] return vendor.prefix(1).uppercased() + vendor.dropFirst() } if ["com", "org", "net", "io", "us"].contains(first.lowercased()), parts.count > 1 { return parts[1].prefix(1).uppercased() + parts[1].dropFirst() } return first.prefix(1).uppercased() + first.dropFirst() } } struct MetricSample: Identifiable { let id = UUID() let date: Date let value: Double } struct VolumeSnapshot: Identifiable, Hashable, Sendable { let id: String let name: String let mountPath: String let fileSystem: String let capacity: UInt64 let available: UInt64 let isEjectable: Bool var used: UInt64 { capacity > available ? capacity - available : 0 } var usedPercent: Double { capacity > 0 ? Double(used) / Double(capacity) * 100 : 0 } } struct SystemSnapshot { var cpuPercent = 0.0 var memoryUsed: UInt64 = 0 var memoryTotal: UInt64 = ProcessInfo.processInfo.physicalMemory var memoryActive: UInt64 = 0 var memoryWired: UInt64 = 0 var memoryCompressed: UInt64 = 0 var memoryCached: UInt64 = 0 var swapUsed: UInt64 = 0 var swapTotal: UInt64 = 0 var memoryType = "Unified" var memorySpeed = "Not reported by macOS" var memoryManufacturer = "Apple unified memory" var diskFree: UInt64 = 0 var diskTotal: UInt64 = 0 var diskReadRate = 0.0 var diskWriteRate = 0.0 var diskOperationsPerSecond = 0.0 var diskLatencyMilliseconds = 0.0 var diskActivePercent = 0.0 var gpuPercent = 0.0 var gpuRendererPercent = 0.0 var gpuTilerPercent = 0.0 var gpuMemoryBytes: UInt64 = 0 var gpuAllocatedBytes: UInt64 = 0 var gpuCoreCount = 0 var processCount = 0 var threadCount = 0 var uptime: TimeInterval = ProcessInfo.processInfo.systemUptime var corePercents: [Double] = [] var networkReceiveRate = 0.0 var networkSendRate = 0.0 var networkInterface = "Network" var removableVolumes: [VolumeSnapshot] = [] var memoryPercent: Double { guard memoryTotal > 0 else { return 0 } return Double(memoryUsed) / Double(memoryTotal) * 100 } var diskPercent: Double { guard diskTotal > 0 else { return 0 } return Double(diskTotal - diskFree) / Double(diskTotal) * 100 } var diskThroughput: Double { diskReadRate + diskWriteRate } } @MainActor enum Formatters { static let bytes: ByteCountFormatter = { let formatter = ByteCountFormatter() formatter.countStyle = .memory formatter.allowedUnits = [.useKB, .useMB, .useGB, .useTB] return formatter }() static func percent(_ value: Double) -> String { value < 10 ? String(format: "%.1f%%", value) : String(format: "%.0f%%", value) } static func uptime(_ interval: TimeInterval) -> String { let total = Int(interval) let days = total / 86_400 let hours = (total % 86_400) / 3_600 let minutes = (total % 3_600) / 60 return days > 0 ? "\(days)d \(hours)h \(minutes)m" : "\(hours)h \(minutes)m" } static func rate(_ bytesPerSecond: Double) -> String { "\(bytes.string(fromByteCount: Int64(max(0, bytesPerSecond))))/s" } static func duration(_ interval: TimeInterval) -> String { let total = max(0, Int(interval.rounded())) let hours = total / 3_600 let minutes = (total % 3_600) / 60 let seconds = total % 60 return hours > 0 ? String(format: "%d:%02d:%02d", hours, minutes, seconds) : String(format: "%02d:%02d", minutes, seconds) } }