Make 'auto-disable after fade' optional (default off) — keeps tracking on - #5
Make 'auto-disable after fade' optional (default off) — keeps tracking on#5chunzhi716 wants to merge 1 commit into
Conversation
Previously, after the screen faded for fadeTimeoutDuration (6s) without a blink, eye tracking was fully disabled (eyeTrackingEnabled = false), silently stopping the app's eye-strain protection until manually re-enabled. This adds an 'Auto-disable after fade' preference (default off). When off, the fade remains a blink reminder but tracking stays on. Addresses issue oxremy#4.
|
Hey — this is awesome, thank you so much. A bit of design context from my side, since I think it’ll make the last tweak before merge feel obvious: Why auto-disable existed in the first placeThe core BlinkMore loop was always meant to be simple:
That “fade stays up until you blink” behavior is the heart of the reminder. The fade timeout ( Your catch in #4 is totally fair though: for people who want always-on protection, that safety valve can quietly defeat the whole point. Making it optional (default off) is the right product call, and the prefs/menu wiring here looks clean and consistent with how the rest of the app is set up. Love it. One gap before mergeRight now That fixes the “tracking silently turns off” bug — which is huge — but with the new default it creates a hole in the reminder loop:
For the deep-focus case you described, you’d get one reminder and then a quiet gap with the camera still on. That wasn’t a problem when timeout always disabled tracking; once “keep tracking on” is the default, this becomes the main path and we should make it feel right. Suggested fixLean into the original design for the default case: if auto-disable is off, timeout should do nothing — leave the fade up until a blink. In private func handleFadeTimeout() {
print("Fade timeout reached after \(fadeTimeoutInterval)s")
// Auto-disable off: keep fade up as the reminder until they blink.
// (Original BlinkMore loop — fade persists until eyes close.)
guard preferencesService.autoDisableOnFade else { return }
// Auto-disable on: safety valve — clear stuck fade and release the camera.
removeFade()
DispatchQueue.main.async {
self.preferencesService.eyeTrackingEnabled = false
print("Disabled eye tracking after fade timeout (auto-disable enabled)")
}
}That gives:
Also worth updating the comment on (If you’d rather timeout still dismiss the fade when auto-disable is off, you’d need to re-arm the blink-threshold timer afterward while eyes are still open — doable, but leaving the fade up is simpler and matches the original reminder design better.) Quick checks
Again — thank you. You spotted something that was easy for me to take for granted as the person who added that timeout, and this PR makes the free app better for the always-on use case I know a lot of people want. Push that small tweak and I’ll be happy to get this merged. Really appreciate you building this with me ❤️ |
Summary
Closes the root cause discussed in #4.
Previously, after the screen faded for
fadeTimeoutDuration(6s) without a blink,handleFadeTimeout()seteyeTrackingEnabled = false, which fully disabled eye tracking until the user manually re-enabled it from the menu bar. For users who want the app to always track their eyes, this silently stops the eye-strain protection exactly when they're most at risk (deep focus / not blinking), and they may forget to turn it back on.Changes
Constants.swift: adddefaultAutoDisableOnFade = falseand theautoDisableOnFadeUserDefaults key.PreferencesService.swift: add@Published var autoDisableOnFade, load it from UserDefaults, and persist changes.FadeService.swift:handleFadeTimeout()now only disables tracking whenautoDisableOnFadeis enabled (guard). When off, the fade is purely a reminder and tracking stays on.StatusBarController.swift: add an "Auto-disable after fade" checkbox to the menu (default unchecked), wired to the new preference.Behavior
Note on verification
No problem

Addresses #4.