Atoll/DynamicIsland/managers/SystemChangesObserver.swift
Hariharan Mudaliar 1a45d4e7f4 Working Indicators
2025-09-06 19:28:38 +05:30

153 lines
No EOL
4.5 KiB
Swift

//
// SystemChangesObserver.swift
// DynamicIsland
//
// Adapted from TheBoringWorker-HUD ChangesObserver.swift
// Created by GitHub Copilot on 06/09/25.
//
import Cocoa
import Foundation
import Defaults
class SystemChangesObserver: ObservableObject {
private var oldVolume: Float
private var oldMuted: Bool
private var oldBrightness: Float = 0
private weak var coordinator: DynamicIslandViewCoordinator?
@Default(.enableSystemHUD) var enableSystemHUD
@Default(.enableVolumeHUD) var enableVolumeHUD
@Default(.enableBrightnessHUD) var enableBrightnessHUD
init(coordinator: DynamicIslandViewCoordinator) {
self.coordinator = coordinator
oldVolume = SystemVolumeManager.getOutputVolume()
oldMuted = SystemVolumeManager.isMuted()
do {
oldBrightness = try SystemDisplayManager.getDisplayBrightness()
} catch {
NSLog("Failed to retrieve display brightness: \(error)")
}
}
func startObserving() {
guard enableSystemHUD else { return }
createObservers()
createTimerForContinuousChangesCheck(with: 0.2)
}
private func createTimerForContinuousChangesCheck(with seconds: TimeInterval) {
let timer = Timer(
timeInterval: seconds, target: self, selector: #selector(checkChanges), userInfo: nil,
repeats: true)
let mainLoop = RunLoop.main
mainLoop.add(timer, forMode: .common)
}
private func createObservers() {
NotificationCenter.default.addObserver(
self,
selector: #selector(showVolumeHUD),
name: SystemKeyObserver.volumeChanged,
object: nil)
NotificationCenter.default.addObserver(
self,
selector: #selector(showBrightnessHUD),
name: SystemKeyObserver.brightnessChanged,
object: nil)
}
@objc func showVolumeHUD() {
guard enableSystemHUD && enableVolumeHUD else { return }
if oldVolume == 0.0 || oldVolume == 1.0 {
sendVolumeNotification(value: oldVolume)
}
print("Showing volume HUD")
}
@objc func showBrightnessHUD() {
guard enableSystemHUD && enableBrightnessHUD else { return }
if oldBrightness == 0.0 || oldBrightness == 1.0 {
sendBrightnessNotification(value: oldBrightness)
}
print("Showing brightness HUD")
}
@objc func checkChanges() {
guard enableSystemHUD else { return }
checkBrightnessChanges()
checkVolumeChanges()
}
private func isAlmost(firstNumber: Float, secondNumber: Float) -> Bool {
let marginValue = 5 / 100.0
return (firstNumber + Float(marginValue) >= secondNumber && firstNumber - Float(marginValue) <= secondNumber)
}
private func checkVolumeChanges() {
guard enableVolumeHUD else { return }
let newVolume = SystemVolumeManager.getOutputVolume()
let newMuted = SystemVolumeManager.isMuted()
if !isAlmost(firstNumber: oldVolume, secondNumber: newVolume) || newMuted != oldMuted {
if newMuted {
sendVolumeNotification(value: 0.0)
} else {
sendVolumeNotification(value: newVolume)
}
oldVolume = newVolume
oldMuted = newMuted
}
}
private func checkBrightnessChanges() {
guard enableBrightnessHUD else { return }
if NSScreen.screens.count == 0 {
return
}
do {
let newBrightness = try SystemDisplayManager.getDisplayBrightness()
if !isAlmost(firstNumber: oldBrightness, secondNumber: newBrightness) {
sendBrightnessNotification(value: newBrightness)
oldBrightness = newBrightness
}
} catch {
NSLog("Failed to retrieve display brightness: \(error)")
}
}
// MARK: - Internal Notification Methods
private func sendVolumeNotification(value: Float) {
coordinator?.toggleSneakPeek(
status: true,
type: .volume,
value: CGFloat(value),
icon: ""
)
}
private func sendBrightnessNotification(value: Float) {
coordinator?.toggleSneakPeek(
status: true,
type: .brightness,
value: CGFloat(value),
icon: ""
)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
}