Files
sendico/frontend/pweb/lib/controllers/common/cooldown.dart
2026-02-21 21:55:20 +03:00

86 lines
1.9 KiB
Dart

import 'dart:async';
class CooldownController {
CooldownController({void Function()? onTick}) : _onTick = onTick;
final void Function()? _onTick;
Timer? _timer;
DateTime? _until;
int _remainingSeconds = 0;
int get remainingSeconds => _remainingSeconds;
bool get isActive => _remainingSeconds > 0;
DateTime? get until => _until;
void start(Duration duration) {
startUntil(DateTime.now().add(duration));
}
void startUntil(DateTime until) {
_until = until;
_restartTimer();
_syncRemaining(notify: true);
}
void syncUntil(DateTime? until, {bool notify = true}) {
if (until == null) {
stop(notify: notify);
return;
}
_until = until;
_restartTimer();
_syncRemaining(notify: notify);
}
void stop({bool notify = false}) {
_timer?.cancel();
_timer = null;
_until = null;
final hadRemaining = _remainingSeconds != 0;
_remainingSeconds = 0;
if (notify && hadRemaining) {
_onTick?.call();
}
}
void dispose() {
_timer?.cancel();
_timer = null;
}
void _restartTimer() {
_timer?.cancel();
_timer = null;
if (_remaining() <= 0) return;
_timer = Timer.periodic(const Duration(seconds: 1), (_) {
final nextRemaining = _remaining();
if (nextRemaining <= 0) {
stop(notify: true);
return;
}
if (nextRemaining != _remainingSeconds) {
_remainingSeconds = nextRemaining;
_onTick?.call();
}
});
}
void _syncRemaining({required bool notify}) {
final nextRemaining = _remaining();
if (nextRemaining == _remainingSeconds) return;
_remainingSeconds = nextRemaining;
if (notify) {
_onTick?.call();
}
}
int _remaining() {
final until = _until;
if (until == null) return 0;
final remaining = until.difference(DateTime.now()).inSeconds;
return remaining < 0 ? 0 : remaining;
}
}