Add reachability (Auto) keep-awake mode + battery-floor safety - #49
Add reachability (Auto) keep-awake mode + battery-floor safety#49tomarai85 wants to merge 1 commit into
Conversation
On battery, release the keep-awake assertion at or below a user-chosen level so the Mac can sleep before the battery is fully drained. Off by default; nothing changes unless it is turned on. BatteryFloorPolicy.decide is a pure function with a recover margin so the decision cannot flap around the threshold, and it is covered by 10 unit tests. The IOKit power-source read is cached for 5s so the 250ms poll does not spin it. Unreadable power state stays awake, so the floor can never make behavior worse than today. Menu: Battery floor > Off / 10% / 15% / 20% / 30%. Localized EN/JA/KO/zh-Hans.
4ba23be to
7d90ff5
Compare
|
Rebased on current main. #41 landed the day after I opened this and overlapped with the keep-awake mode, so I dropped that half and kept only the battery floor. Now +294/−1 across 4 files, down from +501/−22 across 7. Off by default — with no configuration the app behaves exactly as it does today.
The UI is a menu submenu ( |
What
Two small, opt-in additions. Defaults are unchanged — with no configuration the app behaves exactly as it does today (Caps Lock keeps the Mac awake).
1. Keep-awake mode: Off / Caps Lock / Auto
Caps Lock stays the default and works exactly as today.
Autokeeps the Mac awake automatically, independent of Caps Lock — for the case of closing the lid and driving the machine remotely (e.g. SSH from a phone), where you want it to stay reachable without remembering to toggle a key.Offis an explicit no-op.2. Battery floor (opt-in, default 15%)
On battery, keep-awake is released at/below a threshold so the Mac can sleep before the battery fully drains — which, in the remote-use case, would also drop your access. It re-arms on AC, with hysteresis so it doesn't oscillate as the percentage jitters near the threshold.
Implementation notes:
BatteryReaderreads the power source via IOKit (IOPSCopyPowerSourcesInfo) — no subprocess.BatteryFloorPolicywith 10 unit tests covering the floor boundary, the hysteresis latch, and the fail-safe cases (unreadable power → stay awake/reachable; on AC → keep; unknown percentage → keep).Both are surfaced in the status menu (mode items + a Battery floor submenu) and the settings window, following the existing preference + localization patterns.
One small responsiveness change: the poll timer runs in
.defaultinstead of.common, so its periodicpmset -gverification never spawns a subprocess while a menu is being tracked.Testing
swift test— all 24 tests green (14 existing + 10 new).Notes