Fix: Brightness and Volume Control

This commit is contained in:
Hariharan Mudaliar 2025-09-06 21:54:19 +05:30
commit 98c826aaae
11 changed files with 340 additions and 97 deletions

View file

@ -11,82 +11,102 @@ import Foundation
import Defaults
class SystemChangesObserver {
private var oldVolume: Float
private var oldMuted: Bool
private var oldVolume: Float = 0
private var oldMuted: Bool = false
private var oldBrightness: Float = 0
private weak var coordinator: DynamicIslandViewCoordinator?
private var timer: Timer?
// Backup timer for edge cases only
private var backupTimer: Timer?
init(coordinator: DynamicIslandViewCoordinator) {
self.coordinator = coordinator
// Initialize baseline values only once
oldVolume = SystemVolumeManager.getOutputVolume()
oldMuted = SystemVolumeManager.isMuted()
do {
oldBrightness = try SystemDisplayManager.getDisplayBrightness()
} catch {
NSLog("Failed to retrieve display brightness: \(error)")
NSLog("Failed to retrieve initial display brightness: \(error)")
}
}
func startObserving() {
guard Defaults[.enableSystemHUD] else { return }
createObservers()
createTimerForContinuousChangesCheck(with: 0.2)
}
private func createTimerForContinuousChangesCheck(with seconds: TimeInterval) {
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 Defaults[.enableSystemHUD] && Defaults[.enableVolumeHUD] else { return }
if oldVolume == 0.0 || oldVolume == 1.0 {
sendVolumeNotification(value: oldVolume)
}
print("Showing volume HUD")
startMinimalBackupTimer()
}
@objc func showBrightnessHUD() {
guard Defaults[.enableSystemHUD] && Defaults[.enableBrightnessHUD] else { return }
if oldBrightness == 0.0 || oldBrightness == 1.0 {
sendBrightnessNotification(value: oldBrightness)
private func startMinimalBackupTimer() {
// More frequent backup check (every 300ms) for better responsiveness
// This is a reasonable compromise between the original 200ms and the previous 5s
backupTimer = Timer.scheduledTimer(withTimeInterval: 0.3, repeats: true) { [weak self] _ in
guard Defaults[.enableSystemHUD] else { return }
self?.performBackupCheck()
}
print("Showing brightness HUD")
}
@objc func checkChanges() {
guard Defaults[.enableSystemHUD] else { return }
checkBrightnessChanges()
private func performBackupCheck() {
// Only check if we haven't had recent activity
checkVolumeChanges()
checkBrightnessChanges()
}
private func isAlmost(firstNumber: Float, secondNumber: Float) -> Bool {
let marginValue = 5 / 100.0
return (firstNumber + Float(marginValue) >= secondNumber && firstNumber - Float(marginValue) <= secondNumber)
// MARK: - Public Media Key Event Handlers (called from MediaKeyApplication)
func handleVolumeKeyEvent() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.handleVolumeKeyPress()
}
}
func handleBrightnessKeyEvent() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) {
self.handleBrightnessKeyPress()
}
}
// MARK: - Key Press Event Handlers
private func handleVolumeKeyPress() {
guard Defaults[.enableVolumeHUD] else { return }
let newVolume = SystemVolumeManager.getOutputVolume()
let newMuted = SystemVolumeManager.isMuted()
// Always show HUD for key press feedback, even if value doesn't change
print("🔊 Volume key pressed - showing HUD: volume=\(newVolume), muted=\(newMuted)")
if newMuted {
sendVolumeNotification(value: 0.0)
} else {
sendVolumeNotification(value: newVolume)
}
// Update stored values
oldVolume = newVolume
oldMuted = newMuted
}
private func handleBrightnessKeyPress() {
guard Defaults[.enableBrightnessHUD] else { return }
guard NSScreen.screens.count > 0 else { return }
do {
let newBrightness = try SystemDisplayManager.getDisplayBrightness()
// Always show HUD for key press feedback, even if value doesn't change
print("☀️ Brightness key pressed - showing HUD: brightness=\(newBrightness)")
sendBrightnessNotification(value: newBrightness)
// Update stored value
oldBrightness = newBrightness
} catch {
// Silently ignore brightness errors to reduce log spam
}
}
private func checkVolumeChanges() {
@ -95,7 +115,12 @@ class SystemChangesObserver {
let newVolume = SystemVolumeManager.getOutputVolume()
let newMuted = SystemVolumeManager.isMuted()
if !isAlmost(firstNumber: oldVolume, secondNumber: newVolume) || newMuted != oldMuted {
let volumeChanged = !isAlmost(firstNumber: oldVolume, secondNumber: newVolume)
let muteChanged = newMuted != oldMuted
if volumeChanged || muteChanged {
print("🔊 Volume change detected: \(oldVolume) → \(newVolume), muted: \(oldMuted) → \(newMuted)")
if newMuted {
sendVolumeNotification(value: 0.0)
} else {
@ -108,22 +133,30 @@ class SystemChangesObserver {
private func checkBrightnessChanges() {
guard Defaults[.enableBrightnessHUD] else { return }
if NSScreen.screens.count == 0 {
return
}
guard NSScreen.screens.count > 0 else { return }
do {
let newBrightness = try SystemDisplayManager.getDisplayBrightness()
if !isAlmost(firstNumber: oldBrightness, secondNumber: newBrightness) {
let brightnessChanged = !isAlmost(firstNumber: oldBrightness, secondNumber: newBrightness)
if brightnessChanged {
print("☀️ Brightness change detected: \(oldBrightness) → \(newBrightness)")
sendBrightnessNotification(value: newBrightness)
oldBrightness = newBrightness
}
} catch {
NSLog("Failed to retrieve display brightness: \(error)")
// Silently ignore brightness errors to reduce log spam
}
}
private func isAlmost(firstNumber: Float, secondNumber: Float) -> Bool {
// Convert sensitivity setting to a more responsive threshold
// Sensitivity 1-10 scale maps to 0.01-0.10 threshold range
let marginValue = Float(Defaults[.systemHUDSensitivity]) / 100.0
let threshold = max(0.01, marginValue) // Minimum threshold for responsiveness
return abs(firstNumber - secondNumber) <= threshold
}
// MARK: - Internal Notification Methods
private func sendVolumeNotification(value: Float) {
@ -149,8 +182,12 @@ class SystemChangesObserver {
}
func stopObserving() {
timer?.invalidate()
timer = nil
NotificationCenter.default.removeObserver(self)
// Clean up backup timer
backupTimer?.invalidate()
backupTimer = nil
print("🎹 Media key detection stopped")
}
}
}