// Auto dark/bright from the tablet's light sensor. The Redmi Pad SE has no separate one: // Xiaomi derives it from the front camera ("camera_light_Sensor") and offers it as // Android's ordinary light sensor, the one auto-brightness reads. No camera permission. import 'package:flutter/services.dart'; /// Light levels in lux, about once a second, from MainActivity. Ends at once (an error, /// which [Themes.followLight] ignores) where there is no sensor or no Android side. Stream lightLevels() => const EventChannel('yukart/light') .receiveBroadcastStream() .map((e) => (e as num).toDouble()); /// Dark or bright from light levels, with a gap and a hold so dusk, shade and /// passing lights do not flicker it. class LightSwitch { /// Dark at or below this. static const darkAt = 15.0; /// Bright at or above this; in between, whatever it was. static const brightAt = 60.0; /// How long a level must last before it switches. static const hold = Duration(seconds: 5); bool? _dark; DateTime? _since; bool? get isDark => _dark; /// A change is waiting out its hold. bool get pending => _since != null; /// The hold has passed with no reading against it (a sensor that reports only on /// change goes quiet): make the waiting change. void settle() { if (_since == null) return; _dark = !_dark!; _since = null; } /// Feed one reading; returns the verdict (null until a reading outside the gap). bool? feed(double lux, DateTime now) { final want = lux <= darkAt ? true : lux >= brightAt ? false : _dark; if (_dark == null) { // The first clear reading decides at once; one in the gap leaves it open. _dark = want; } else if (want == _dark) { _since = null; } else { _since ??= now; if (now.difference(_since!) >= hold) { _dark = want; _since = null; } } return _dark; } }