Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion ChillMac/App/AppSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,10 @@ final class AppSettings: ObservableObject {
}

func syncLaunchAtLogin() {
launchAtLogin = (SMAppService.mainApp.status == .enabled)
let enabled = SMAppService.mainApp.status == .enabled
if launchAtLogin != enabled {
launchAtLogin = enabled
}
}

func setLaunchAtLogin(_ enabled: Bool) {
Expand Down
17 changes: 11 additions & 6 deletions ChillMac/App/StatusBarController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,9 @@ final class StatusBarController: NSObject {
fpsMonitor.stopMonitoring()
fanMonitor.isPopoverVisible = false
} else if let button = statusItem.button {
// Resume secondary monitors when popover opens
cpuInfo.startMonitoring()
memoryInfo.startMonitoring()
batteryInfo.startMonitoring()
systemInfo.startMonitoring()
fpsMonitor.startMonitoring()
// Sync settings and show the hosting view first, then start monitors on the
// next turn — otherwise their @Published writes land mid-body and spam
// "Publishing changes from within view updates".
fanMonitor.isPopoverVisible = true
AppSettings.shared.syncLaunchAtLogin()
NotificationCenter.default.post(name: .popoverDidClose, object: nil)
Expand All @@ -162,6 +159,14 @@ final class StatusBarController: NSObject {
NSApp.activate(ignoringOtherApps: true)
popover.contentViewController?.view.window?.makeKeyAndOrderFront(nil)
NotificationCenter.default.post(name: .popoverDidShow, object: nil)
DispatchQueue.main.async { [weak self] in
guard let self else { return }
self.cpuInfo.startMonitoring()
self.memoryInfo.startMonitoring()
self.batteryInfo.startMonitoring()
self.systemInfo.startMonitoring()
self.fpsMonitor.startMonitoring()
}
}
}

Expand Down
51 changes: 36 additions & 15 deletions ChillMac/Fan/CpuInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,26 +60,47 @@ final class CpuInfo: ObservableObject {

previousInfo = current

let newUser: Double
let newSystem: Double
let newIdle: Double
let newTotal: Double
if totalDiff > 0 {
userPercent = (userDiff + niceDiff) / totalDiff * 100
systemPercent = sysDiff / totalDiff * 100
idlePercent = idleDiff / totalDiff * 100
totalUsage = 100 - idlePercent
newUser = (userDiff + niceDiff) / totalDiff * 100
newSystem = sysDiff / totalDiff * 100
newIdle = idleDiff / totalDiff * 100
newTotal = 100 - newIdle
} else {
newUser = userPercent
newSystem = systemPercent
newIdle = idlePercent
newTotal = totalUsage
}

history.append(totalUsage)
if history.count > maxHistory {
history.removeFirst(history.count - maxHistory)
}
// Defer publishes so Timer callbacks don't write mid-body while the popover is rendering.
DispatchQueue.main.async { [weak self] in
guard let self else { return }
if abs(self.userPercent - newUser) >= 0.1 { self.userPercent = newUser }
if abs(self.systemPercent - newSystem) >= 0.1 { self.systemPercent = newSystem }
if abs(self.idlePercent - newIdle) >= 0.1 { self.idlePercent = newIdle }
if abs(self.totalUsage - newTotal) >= 0.1 { self.totalUsage = newTotal }

userHistory.append(userPercent)
if userHistory.count > maxHistory {
userHistory.removeFirst(userHistory.count - maxHistory)
}
// History charts only matter with the CPU detail panel open.
guard self.isDetailVisible else { return }

self.history.append(newTotal)
if self.history.count > self.maxHistory {
self.history.removeFirst(self.history.count - self.maxHistory)
}

systemHistory.append(systemPercent)
if systemHistory.count > maxHistory {
systemHistory.removeFirst(systemHistory.count - maxHistory)
self.userHistory.append(newUser)
if self.userHistory.count > self.maxHistory {
self.userHistory.removeFirst(self.userHistory.count - self.maxHistory)
}

self.systemHistory.append(newSystem)
if self.systemHistory.count > self.maxHistory {
self.systemHistory.removeFirst(self.systemHistory.count - self.maxHistory)
}
}

// Fetch top processes every 5th poll, only when detail panel is visible.
Expand Down