I am using Flutter and the Bloc Pattern with rxdart and would like to have a debug mode in my app similar like you enable the developer mode in Android the user should touch 5 times a logo in the UI. The UI part is pretty simple with:
Column _renderLogo(BuildContext context) => new Column(
children: <Widget>[
GestureDetector(
onTap: () => BlocProvider.of(context).debugEnabledSink.add(true),
child: Container( ...more logo rendering...
With that in mind, I am looking for an easy elegant way to enable the detection of 5 events in 10 seconds. The whole detection should reset when not enough events are detected in any 10 second time window.
You can use a pseudo-timer to achieve this:
const maxDebugTimerSeconds = 10;
const maxTapCount = 5;
DateTime firstTap;
int tapCount;
void doGestureOnTap() {
final now = DateTime.now();
if (firstTap != null && now.difference(firstTap).inSeconds < maxDebugTimerSeconds) {
tapCount++;
if (tapCount >= maxTapCount) {
BlocProvider.of(context).debugEnabledSink.add(true);
}
} else {
firstTap = now;
tapCount = 0;
}
}
...
GestureDetector(
onTap: doGestureOnTap,
...
),
This answer is based on the comment of @pskink above. I just post it here because it seems like a very elegant way of solving my problem. Thank you @pskink
DebugSwitcher might not be the best class Name it's more TimeWindowEventDetector but you get the idea.
class DebugSwitcher {
final Duration window;
final int cnt;
bool value = false;
var timeStamps = [];
DebugSwitcher({this.window = const Duration(seconds: 10), this.cnt = 5});
call(data, sink) {
var now = DateTime.now();
timeStamps.removeWhere((ts) => now.difference(ts) >= window);
timeStamps.add(now);
if (timeStamps.length >= cnt) {
timeStamps = [];
sink.add(value = !value);
}
}
}
Than u listen to the Sink Events this way:
_debugEnabledController.stream
.transform(StreamTransformer.fromHandlers(handleData: DebugSwitcher()))
.listen(
(_) {
_isDebugModeOn.value = true;
infoInternal.value = 'Enabled Debug Mode';
},
);
The Sink is defined like this:
final StreamController<bool> _debugEnabledController =
StreamController<bool>();
Sink<bool> get debugEnabledSink => _debugEnabledController.sink;
In the UI the code looks like this:
Column _renderLogo(BuildContext context) => new Column(
children: <Widget>[
GestureDetector(
onTap: () => BlocProvider.of(context).debugEnabledSink.add(true),
child: Container(
margin: const EdgeInsets.only(top: 10.0, right: 10.0),
height: 80.0,
child: Theme.of(context).primaryColorBrightness ==
Brightness.light
? new Image.asset('assets/app_icon_light.png', fit: BoxFit.contain)
: new Image.asset('assets/app_icon.png', fit: BoxFit.contain),
),
),
],
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.