import 'dart:async'; import 'package:flutter/material.dart'; import 'package:test_sa/extensions/context_extension.dart'; import 'package:test_sa/extensions/int_extensions.dart'; import 'package:test_sa/extensions/text_extensions.dart'; import 'package:test_sa/extensions/widget_extensions.dart'; import 'package:test_sa/models/timer_model.dart'; import 'package:test_sa/views/app_style/sizing.dart'; import '../../../new_views/app_style/app_color.dart'; class AppTimer extends StatefulWidget { final TimerModel timer; final Future Function(TimerModel) onChange; final TextStyle style; final BoxDecoration decoration; final bool enabled; final String label; final Function(bool) timerProgress; const AppTimer({ Key key, this.label, this.timer, this.onChange, this.style, this.decoration, this.timerProgress, this.enabled = true, }) : super(key: key); @override State createState() => _AppTimerState(); } class _AppTimerState extends State { Timer _timer; DateTime _startAt; DateTime _endAt; int _delay = 0; bool _running = false; bool _loading = false; final ValueNotifier _period = ValueNotifier("0:00:00"); _startTimer() async { if (!_running) { final time = DateTime.now(); bool result = await widget.onChange(TimerModel(startAt: time, endAt: null, durationInSecond: _delay)); if (!result) return; _running = true; if (_endAt != null) { _delay += _endAt.difference(_startAt).inSeconds; } _startAt = time.subtract(Duration(seconds: _delay)); _endAt = null; } _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (_loading == true) return; _period.value = (_endAt ?? DateTime.now()).difference(_startAt).toString().split(".").first; }); } _stopTimer() async { final time = DateTime.now(); final tempStartAt = _startAt.add(Duration(seconds: _delay)); bool result = await widget.onChange(TimerModel(startAt: tempStartAt, endAt: time, durationInSecond: _delay)); if (!result) return; _running = false; _endAt = time; _startAt = tempStartAt; _timer?.cancel(); } _onPressed() async { _loading = true; setState(() {}); if (!_running) { await _startTimer(); } else { await _stopTimer(); } _loading = false; setState(() {}); //widget.timerProgress(_running); } @override void initState() { _startAt = widget.timer?.startAt; _endAt = widget.timer?.endAt; _running = _startAt != null && _endAt == null; _delay = (widget.timer?.durationInSecond ?? 0); final difference = _startAt == null ? 0 : (_endAt ?? DateTime.now())?.difference(_startAt)?.inSeconds ?? 0; _period.value = Duration(seconds: _running ? difference : (difference != 0 ? difference : _delay)).toString().split(".").first; super.initState(); if (_running) { _startTimer(); } } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Container( width: 100 * AppStyle.getScaleFactor(context), height: 56.toScreenHeight, padding: EdgeInsets.symmetric(horizontal: 16.toScreenWidth), decoration:widget.decoration?? BoxDecoration( color: context.isDark && (widget.enabled == false) ? AppColor.neutral60 : (widget.enabled == false) ? AppColor.neutral40 : AppColor.background(context), borderRadius: BorderRadius.circular(10), boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)], ), child: _loading ? const SizedBox.square(dimension: 18, child: CircularProgressIndicator(color: Colors.white)) : Row( children: [ Expanded( child: ValueListenableBuilder( valueListenable: _period, builder: (context, value, _) { return Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ (widget.label ?? "Timer").tinyFont(context), value.bodyText(context).custom( color: widget.enabled ? context.isDark ? AppColor.neutral30 : AppColor.neutral50 : AppColor.neutral20, ), ], ); }, ), ), if (widget.enabled) Icon(_running ? Icons.pause : Icons.play_arrow), ], ), ).onPress(_loading || widget.enabled == false ? () {} : _onPressed); } }