fix: stabilize Bluetooth polling and dedupe lid-cycle lock chimes

BluetoothAudioManager
- Replace Timer.scheduledTimer polling with DispatchSourceTimer on a
  utility queue so main-thread back-pressure no longer stalls the 3s
  connect-detection cadence.
- Distinguish "host controller unavailable" from "powered off" via a
  new bluetoothIsPoweredOn() helper, so transient IOBluetooth registry
  blips at launch no longer clear connectedDevices.
- Re-read device metadata (name, type, battery) at +500ms and +2s after
  IOBluetoothDeviceConnectedNotification to catch IORegistry's
  late-population window; the existing HUD wait-task then updates the
  shown battery in place.
- Declare BluetoothAudioDeviceType: Equatable to support the
  change-detection diff in the re-read pass.

LockSoundPlayer
- Add a 1.2s cross-type cooldown so a rapid lid close->open no longer
  plays lock-then-unlock chimes as a doubled sound (the per-type
  throttle never covered this case).
- Bump per-type throttle 0.25s -> 0.6s.
- Reset throttle state when enableLockSounds is toggled back on, so the
  first chime after re-enable is never suppressed by a stale timestamp.

StatsManager
- Shorten notchCloseStopDelay 3.0s -> 1.0s so the monitoring timer is
  invalidated sooner after the user closes the notch, freeing the
  main-thread tick budget for animation work.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
FBukovina 2026-05-21 21:33:41 +02:00
commit d139742660
3 changed files with 141 additions and 27 deletions

View file

@ -463,7 +463,9 @@ class StatsManager: ObservableObject {
private var cancellables = Set<AnyCancellable>()
private let minUpdateInterval: TimeInterval = 1.0
private let maxUpdateInterval: TimeInterval = 60.0
private let notchCloseStopDelay: TimeInterval = 3.0
// Shorter than the previous 3.0 s: keeps stats "warm" enough for fast open→close→open
// cycles while freeing the main-thread tick budget sooner after a deliberate close.
private let notchCloseStopDelay: TimeInterval = 1.0
private let tabSwitchStopDelay: TimeInterval = 0.1
// MARK: - Initialization