throttled function

VoidCallback throttled(
  1. VoidCallback fn, {
  2. Duration window = const Duration(milliseconds: 600),
})

Wraps fn so repeated calls within window of the last one that ran are dropped — guards a button/action callback against rage-tap causing a double purchase, double navigation, double submit. Only blocks double-firing; a throw from fn still propagates (never swallowed).

Measures elapsed time with a single Stopwatch started on first call (BUG-28) rather than DateTime.now() — a monotonic clock can't be rewound by a system-clock change, so it can't get stuck dropping every call indefinitely the way a wall-clock diff would if the clock jumped backward mid-session.

Implementation

VoidCallback throttled(
  VoidCallback fn, {
  Duration window = const Duration(milliseconds: 600),
}) {
  if (window.isNegative) {
    throw ArgumentError.value(window, 'window', 'must not be negative');
  }
  final stopwatch = Stopwatch();
  Duration? lastRunAt;
  return () {
    if (!stopwatch.isRunning) stopwatch.start();
    final now = stopwatch.elapsed;
    if (lastRunAt != null && now - lastRunAt! < window) return;
    lastRunAt = now;
    fn();
  };
}