Files
MacMonitor/Sources/UI/MenuBar/MenuBarStatusView.swift
gronodandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> a7f13542ae feat(alerts): implement threshold alert engine and Notification Center integration (fixes #24)
Introduce Sources/Intelligence with an @Observable AlertEngine that evaluates
five configurable rules (CPU temperature, fan stall, low memory, low storage,
low battery) against a Sendable AlertEvaluationContext built after each
telemetry decode pass. Breached conditions dispatch through a mockable
AlertNotificationDispatching protocol to UNUserNotificationCenter with
per-alert cooldowns, edge-triggered resolve detection, and a capped
in-memory history log.

Add a macOS Settings scene (AlertsSettingsView) for thresholds, cooldown,
permission status, and test notifications; a new Alerts and Notifications
sidebar tab with active-alert cards and the history log; header and menu bar
warning indicators; and an AppNavigationBus so notification actions
(Open MacMonitor, View Processes) steer the main window.

Also fix the memory snapshot decode to read memoryPressureStatus so
pressureLevel is populated correctly.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-08 13:53:48 +01:00

37 lines
1.2 KiB
Swift

import SwiftUI
public struct MenuBarStatusView: View {
public let cpuLoad: Double
public let memoryPercent: Double
public let activeAlertCount: Int
public init(cpuLoad: Double, memoryPercent: Double, activeAlertCount: Int = 0) {
self.cpuLoad = cpuLoad
self.memoryPercent = memoryPercent
self.activeAlertCount = activeAlertCount
}
public var body: some View {
HStack(spacing: 5) {
if activeAlertCount > 0 {
Image(systemName: "exclamationmark.triangle.fill")
.font(.system(size: 11))
.foregroundStyle(.orange)
}
Image(systemName: "cpu")
.font(.system(size: 11))
Text(String(format: "%.0f%%", cpuLoad))
.font(.system(size: 11, weight: .medium, design: .monospaced))
Text("•")
.foregroundColor(.secondary)
Image(systemName: "memorychip")
.font(.system(size: 11))
Text(String(format: "%.0f%%", memoryPercent))
.font(.system(size: 11, weight: .medium, design: .monospaced))
}
}
}