This commit is contained in:
2026-07-12 04:34:44 +08:00
parent e7ce0f7bae
commit 909fdf46d6
43 changed files with 4727 additions and 0 deletions

7
lib/vendor/countdown/countdown.dart vendored Normal file
View File

@@ -0,0 +1,7 @@
// Copyright (c) 2015, Benjamin NGUYEN. All rights reserved. Use of this source code
// is governed by a BSD-style license that can be found in the LICENSE file.
/// The countdown library.
library countdown;
export 'src/countdown_base.dart';

View File

@@ -0,0 +1,90 @@
// Copyright (c) 2015, Benjamin NGUYEN. All rights reserved. Use of this source code
// is governed by a BSD-style license that can be found in the LICENSE file.
library countdown.base;
import "dart:async";
class CountDown {
/// reference point for start and resume
DateTime? _begin;
Timer? _timer;
Duration? _duration;
Duration? remainingTime;
bool isPaused = false;
StreamController<Duration>? _controller;
Duration? _refresh;
/// provide a way to send less data to the client but keep the data of the timer up to date
int _everyTick = 0;
int counter = 0;
/// once you instantiate the CountDown you need to register to receive information
CountDown(Duration duration,
{Duration refresh = const Duration(milliseconds: 10), int everyTick = 1}) {
_refresh = refresh;
_everyTick = everyTick;
this._duration = duration;
_controller = StreamController<Duration>(
onListen: _onListen,
onPause: _onPause,
onResume: _onResume,
onCancel: _onCancel);
}
Stream<Duration> get stream => _controller!.stream;
/// _onListen
/// invoke when the first subscriber has subscribe and not before to avoid leak of memory
_onListen() {
// reference point
_begin = DateTime.now();
_timer = Timer.periodic(_refresh!, _tick);
}
/// the remaining time is set at '_refresh' ms accurate
_onPause() {
isPaused = true;
_timer?.cancel();
_timer = null;
}
/// ...restart the timer with the duration
_onResume() {
_begin = DateTime.now();
_duration = this.remainingTime;
isPaused = false;
// lance le timer
_timer = Timer.periodic(_refresh!, _tick);
}
_onCancel() {
// on pause we already cancel the _timer
if (!isPaused) {
_timer?.cancel();
_timer = null;
}
// _controller.close(); // close automatically the "pipe" when the sub close it by sub.cancel()
}
void _tick(Timer? timer) {
counter++;
Duration alreadyConsumed = DateTime.now().difference(_begin!);
this.remainingTime = this._duration! - alreadyConsumed;
if (this.remainingTime!.isNegative) {
timer?.cancel();
timer = null;
// tell the onDone's subscriber that it's finish
_controller?.close();
} else {
// here we can control the frequency of sending data
if (counter % _everyTick == 0) {
_controller?.add(this.remainingTime!);
counter = 0;
}
}
}
}