You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.2 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. import 'dart:async';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter_bloc/flutter_bloc.dart';
  4. import 'package:flutter_svg/flutter_svg.dart';
  5. import 'package:my_flutter_puzzle/cubits/base_cubit_type.dart';
  6. import 'package:my_flutter_puzzle/cubits/count_down_timer_cubit.dart';
  7. import 'package:my_flutter_puzzle/utils/extensions/string_extensions.dart';
  8. class CountDownTimerWidget extends StatefulWidget {
  9. final int duration;
  10. final Function() finishCallback;
  11. const CountDownTimerWidget({Key? key, required this.duration, required this.finishCallback}) : super(key: key);
  12. @override
  13. State<CountDownTimerWidget> createState() => _CountDownTimerWidgetState();
  14. }
  15. class _CountDownTimerWidgetState extends State<CountDownTimerWidget> {
  16. Timer? _countdownTimer;
  17. Duration? _duration;
  18. late final CountDownTimerCubit _cubit;
  19. @override
  20. void initState() {
  21. _cubit = BlocProvider.of<CountDownTimerCubit>(context);
  22. _duration = Duration(minutes: widget.duration);
  23. super.initState();
  24. }
  25. @override
  26. Widget build(BuildContext context) {
  27. String strDigits(int n) => n.toString().padLeft(2, '0');
  28. final minutes = strDigits(_duration!.inMinutes.remainder(60));
  29. final seconds = strDigits(_duration!.inSeconds.remainder(60));
  30. return BlocBuilder<CountDownTimerCubit, BaseCubitType<CountDownTimerState>>(
  31. builder: (context, state) {
  32. switch (state.eventName!) {
  33. case CountDownTimerState.empty:
  34. break;
  35. case CountDownTimerState.start:
  36. WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  37. _startTimer();
  38. _cubit.empty();
  39. });
  40. break;
  41. case CountDownTimerState.stop:
  42. WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  43. _stopTimer();
  44. _cubit.empty();
  45. });
  46. break;
  47. case CountDownTimerState.reset:
  48. WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
  49. _resetTimer();
  50. _cubit.empty();
  51. });
  52. break;
  53. }
  54. return Row(
  55. children: [
  56. Text(
  57. '$minutes:$seconds',
  58. style: const TextStyle(
  59. fontSize: 16,
  60. fontWeight: FontWeight.bold,
  61. color: Colors.white,
  62. ),
  63. ),
  64. const SizedBox(width: 8),
  65. SvgPicture.asset('timer'.svgPath),
  66. ],
  67. );
  68. },
  69. );
  70. }
  71. void _startTimer() {
  72. _duration = Duration(minutes: widget.duration);
  73. _countdownTimer = Timer.periodic(const Duration(seconds: 1), (_) => _setCountDown());
  74. }
  75. void _stopTimer() {
  76. if (_countdownTimer == null) {
  77. return;
  78. }
  79. setState(() => _countdownTimer!.cancel());
  80. }
  81. void _resetTimer() {
  82. _stopTimer();
  83. setState(() => _duration = Duration(minutes: widget.duration));
  84. _startTimer();
  85. }
  86. void _setCountDown() {
  87. const reduceSecondsBy = 1;
  88. setState(() {
  89. final seconds = _duration!.inSeconds - reduceSecondsBy;
  90. if (seconds < 0) {
  91. widget.finishCallback.call();
  92. _countdownTimer!.cancel();
  93. } else {
  94. _duration = Duration(seconds: seconds);
  95. _cubit.setDuration(_duration!);
  96. }
  97. });
  98. }
  99. }