2022-08-19 07:30:37 +00:00
|
|
|
import 'dart:async';
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
2023-06-26 06:45:43 +00:00
|
|
|
import "package:photos/models/typedefs.dart";
|
2022-08-19 07:30:37 +00:00
|
|
|
|
|
|
|
class Debouncer {
|
2022-08-19 09:06:25 +00:00
|
|
|
final Duration _duration;
|
2023-11-11 02:17:40 +00:00
|
|
|
|
|
|
|
///in milliseconds
|
2022-08-22 08:26:01 +00:00
|
|
|
final ValueNotifier<bool> _debounceActiveNotifier = ValueNotifier(false);
|
2023-06-26 06:45:43 +00:00
|
|
|
|
2023-11-28 06:57:15 +00:00
|
|
|
/// If executionIntervalInSeconds is not null, then the debouncer will execute the
|
2023-06-26 06:45:43 +00:00
|
|
|
/// current callback it has in run() method repeatedly in the given interval.
|
2023-11-28 06:57:15 +00:00
|
|
|
/// This is useful for example when you want to execute a callback every 5 seconds
|
2023-11-28 07:30:35 +00:00
|
|
|
final int? executionIntervalInMilliSeconds;
|
2022-09-20 12:13:15 +00:00
|
|
|
Timer? _debounceTimer;
|
2022-08-22 09:14:52 +00:00
|
|
|
|
2023-11-28 07:30:35 +00:00
|
|
|
Debouncer(this._duration, {this.executionIntervalInMilliSeconds});
|
2023-06-26 06:45:43 +00:00
|
|
|
|
|
|
|
final Stopwatch _stopwatch = Stopwatch();
|
|
|
|
|
|
|
|
void run(FutureVoidCallback fn) {
|
2023-11-28 07:30:35 +00:00
|
|
|
bool shouldRunImmediately = false;
|
|
|
|
if (executionIntervalInMilliSeconds != null) {
|
|
|
|
// ensure the stop watch is running
|
|
|
|
_stopwatch.start();
|
|
|
|
if (_stopwatch.elapsedMilliseconds > executionIntervalInMilliSeconds!) {
|
|
|
|
shouldRunImmediately = true;
|
|
|
|
_stopwatch.stop();
|
|
|
|
_stopwatch.reset();
|
|
|
|
}
|
2023-06-26 06:45:43 +00:00
|
|
|
}
|
2022-08-19 07:30:37 +00:00
|
|
|
|
2022-08-22 08:26:01 +00:00
|
|
|
if (isActive()) {
|
2022-09-20 12:13:15 +00:00
|
|
|
_debounceTimer!.cancel();
|
2022-08-19 07:30:37 +00:00
|
|
|
}
|
2023-11-28 07:30:35 +00:00
|
|
|
_debounceTimer =
|
|
|
|
Timer(shouldRunImmediately ? Duration.zero : _duration, () async {
|
|
|
|
_stopwatch.stop();
|
|
|
|
_stopwatch.reset();
|
2022-08-22 08:26:01 +00:00
|
|
|
await fn();
|
|
|
|
_debounceActiveNotifier.value = false;
|
|
|
|
});
|
|
|
|
_debounceActiveNotifier.value = true;
|
2022-08-19 07:30:37 +00:00
|
|
|
}
|
|
|
|
|
2022-08-22 09:14:52 +00:00
|
|
|
void cancelDebounce() {
|
2022-08-19 09:16:26 +00:00
|
|
|
if (_debounceTimer != null) {
|
2022-09-20 12:13:15 +00:00
|
|
|
_debounceTimer!.cancel();
|
2022-08-19 07:30:37 +00:00
|
|
|
}
|
|
|
|
}
|
2022-08-19 09:06:25 +00:00
|
|
|
|
2022-09-20 12:13:15 +00:00
|
|
|
bool isActive() => _debounceTimer != null && _debounceTimer!.isActive;
|
2022-08-19 09:16:26 +00:00
|
|
|
|
2022-08-22 08:26:01 +00:00
|
|
|
ValueNotifier<bool> get debounceActiveNotifier {
|
|
|
|
return _debounceActiveNotifier;
|
2022-08-20 10:08:36 +00:00
|
|
|
}
|
2022-08-19 07:30:37 +00:00
|
|
|
}
|