mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 23:24:32 +00:00
141 lines
4.5 KiB
Swift
141 lines
4.5 KiB
Swift
import Foundation
|
|
import CoreGraphics
|
|
import Defaults
|
|
|
|
final class SystemChangesObserver: MediaKeyInterceptorDelegate {
|
|
private weak var coordinator: DynamicIslandViewCoordinator?
|
|
private let volumeController = SystemVolumeController.shared
|
|
private let brightnessController = SystemBrightnessController.shared
|
|
private let mediaKeyInterceptor = MediaKeyInterceptor.shared
|
|
|
|
private let standardVolumeStep: Float = 1.0 / 16.0
|
|
private let standardBrightnessStep: Float = 1.0 / 16.0
|
|
private let fineStepDivisor: Float = 4.0
|
|
|
|
private var volumeEnabled = false
|
|
private var brightnessEnabled = false
|
|
|
|
init(coordinator: DynamicIslandViewCoordinator) {
|
|
self.coordinator = coordinator
|
|
}
|
|
|
|
func startObserving(volumeEnabled: Bool, brightnessEnabled: Bool) {
|
|
self.volumeEnabled = volumeEnabled
|
|
self.brightnessEnabled = brightnessEnabled
|
|
|
|
volumeController.onVolumeChange = { [weak self] volume, muted in
|
|
guard let self, self.volumeEnabled else { return }
|
|
let value = muted ? 0 : volume
|
|
self.sendVolumeNotification(value: value)
|
|
}
|
|
volumeController.onRouteChange = { [weak self] in
|
|
guard let self, self.volumeEnabled else { return }
|
|
self.sendVolumeNotification(value: self.volumeController.isMuted ? 0 : self.volumeController.currentVolume)
|
|
}
|
|
volumeController.start()
|
|
|
|
brightnessController.onBrightnessChange = { [weak self] brightness in
|
|
guard let self, self.brightnessEnabled else { return }
|
|
self.sendBrightnessNotification(value: brightness)
|
|
}
|
|
brightnessController.start()
|
|
|
|
mediaKeyInterceptor.delegate = self
|
|
let tapStarted = mediaKeyInterceptor.start()
|
|
if !tapStarted {
|
|
NSLog("⚠️ Media key interception unavailable; system HUD will remain visible")
|
|
}
|
|
mediaKeyInterceptor.configuration = MediaKeyConfiguration(
|
|
interceptVolume: volumeEnabled,
|
|
interceptBrightness: brightnessEnabled
|
|
)
|
|
}
|
|
|
|
func update(volumeEnabled: Bool, brightnessEnabled: Bool) {
|
|
self.volumeEnabled = volumeEnabled
|
|
self.brightnessEnabled = brightnessEnabled
|
|
mediaKeyInterceptor.configuration = MediaKeyConfiguration(
|
|
interceptVolume: volumeEnabled,
|
|
interceptBrightness: brightnessEnabled
|
|
)
|
|
}
|
|
|
|
func stopObserving() {
|
|
mediaKeyInterceptor.stop()
|
|
mediaKeyInterceptor.delegate = nil
|
|
|
|
volumeController.stop()
|
|
volumeController.onVolumeChange = nil
|
|
volumeController.onRouteChange = nil
|
|
|
|
brightnessController.stop()
|
|
brightnessController.onBrightnessChange = nil
|
|
}
|
|
|
|
// MARK: - MediaKeyInterceptorDelegate
|
|
|
|
func mediaKeyInterceptor(
|
|
_ interceptor: MediaKeyInterceptor,
|
|
didReceiveVolumeCommand direction: MediaKeyDirection,
|
|
step: MediaKeyStep,
|
|
isRepeat: Bool
|
|
) {
|
|
guard volumeEnabled else { return }
|
|
let baseStep = stepSize(for: step, base: standardVolumeStep)
|
|
let delta = direction == .up ? baseStep : -baseStep
|
|
volumeController.adjust(by: delta)
|
|
}
|
|
|
|
func mediaKeyInterceptorDidToggleMute(_ interceptor: MediaKeyInterceptor) {
|
|
guard volumeEnabled else { return }
|
|
volumeController.toggleMute()
|
|
}
|
|
|
|
func mediaKeyInterceptor(
|
|
_ interceptor: MediaKeyInterceptor,
|
|
didReceiveBrightnessCommand direction: MediaKeyDirection,
|
|
step: MediaKeyStep,
|
|
isRepeat: Bool
|
|
) {
|
|
guard brightnessEnabled else { return }
|
|
let baseStep = stepSize(for: step, base: standardBrightnessStep)
|
|
let delta = direction == .up ? baseStep : -baseStep
|
|
brightnessController.adjust(by: delta)
|
|
}
|
|
|
|
// MARK: - HUD Dispatch
|
|
|
|
private func sendVolumeNotification(value: Float) {
|
|
if HUDSuppressionCoordinator.shared.shouldSuppressVolumeHUD {
|
|
return
|
|
}
|
|
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: ""
|
|
)
|
|
}
|
|
}
|
|
|
|
private extension SystemChangesObserver {
|
|
func stepSize(for step: MediaKeyStep, base: Float) -> Float {
|
|
switch step {
|
|
case .standard:
|
|
return base
|
|
case .fine:
|
|
return base / fineStepDivisor
|
|
}
|
|
}
|
|
}
|
|
|
|
|