import 'dart:async'; import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; class IntervalTimerPage extends StatefulWidget { const IntervalTimerPage({Key? key}) : super(key: key); @override _IntervalTimerPageState createState() => _IntervalTimerPageState(); } class _IntervalTimerPageState extends State { final Duration _warmupDuration = const Duration(seconds: 5); final Duration _cooldownDuration = const Duration(seconds: 5); final Duration _highIntensityDuration = const Duration(seconds: 3); final Duration _lowIntensityDuration = const Duration(seconds: 2); late Duration _totalDuration = const Duration(minutes: 35); final highIntensityPlayer = AudioPlayer(); final lowIntensityPlayer = AudioPlayer(); final coolDownPlayer = AudioPlayer(); final int _numHighIntensityBlocks = 4; final int _numLowIntensityBlocks = 3; Timer? _timer; int _currentBlock = 0; Duration _currentDuration = const Duration(); bool _isPaused = true; @override void initState() { _currentDuration = _warmupDuration; super.initState(); } @override void dispose() { _timer?.cancel(); super.dispose(); } void _startTimer() { _isPaused = false; () async { await AudioPlayer().play(UrlSource('assets/go.mp3')); }(); _timer = Timer.periodic(const Duration(seconds: 1), (_) => _tick()); Future.delayed(const Duration(seconds: 1)).then((value) { _playHighIntensityMusic(); }); } void _resetTimer() { coolDownPlayer.stop(); highIntensityPlayer.stop(); lowIntensityPlayer.stop(); _isPaused = true; _timer?.cancel(); _currentBlock = 0; _currentDuration = _warmupDuration; _totalDuration = const Duration(minutes: 35); setState(() {}); } Future _playHighIntensityMusic() async { await highIntensityPlayer.setReleaseMode(ReleaseMode.loop); await highIntensityPlayer.play(UrlSource('assets/warmUp.mp3')); } Future _playLowIntensityMusic() async { await highIntensityPlayer.stop(); Future.delayed(const Duration(microseconds: 600)).then((value) async { await lowIntensityPlayer.play(UrlSource('assets/workout.mp3')); }); } Future _intervalChange() async { await AudioPlayer().play(UrlSource('assets/beep.mp3')); } void _tick() { setState(() { _currentDuration = Duration( seconds: _currentDuration.inSeconds - 1, ); _totalDuration = Duration( seconds: _totalDuration.inSeconds - 1, ); if (_currentDuration.inSeconds < 1) { if (_currentBlock < _numHighIntensityBlocks + _numLowIntensityBlocks) { _intervalChange(); if (_currentBlock == 0) { _playLowIntensityMusic(); } _currentBlock++; if (_currentBlock % 2 == 1) { _currentDuration = _highIntensityDuration; } else { _currentDuration = _lowIntensityDuration; } } else if (_currentBlock < _numHighIntensityBlocks * 2) { _intervalChange(); _currentBlock++; _currentDuration = _cooldownDuration; () async { await lowIntensityPlayer.stop(); await coolDownPlayer.play(UrlSource('assets/cool_down.mp3')); }(); } else { () async { Future.delayed(const Duration(microseconds: 900)) .then((value) async { await AudioPlayer().play(UrlSource('assets/finish.mp3')); }); }(); _resetTimer(); } } }); } String _formatDuration(Duration duration) { String twoDigits(int n) => n.toString().padLeft(2, '0'); final minutes = twoDigits(duration.inMinutes.remainder(60)); final seconds = twoDigits(duration.inSeconds.remainder(60)); return '$minutes:$seconds'; } String _formatTotalDuration(Duration duration) { final minutes = duration.inMinutes; final seconds = duration.inSeconds.remainder(60); return _formatDuration(Duration(minutes: minutes, seconds: seconds)); } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( _currentBlock == 0 ? 'Warm-up' : _currentBlock % 2 == 1 ? 'High Intensity' : _currentBlock < _numHighIntensityBlocks * 2 ? 'Low Intensity' : 'Cool-down', style: const TextStyle(fontSize: 32.0), ), const SizedBox(height: 16.0), Text( _formatDuration(_currentDuration), style: const TextStyle(fontSize: 80.0), ), const SizedBox(height: 32.0), Text( 'Total: ${_formatTotalDuration(_totalDuration)}', style: const TextStyle(fontSize: 24.0), ), const SizedBox(height: 32.0), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ IconButton( icon: Icon( _isPaused ? Icons.play_arrow_rounded : Icons.stop_rounded), iconSize: 48.0, onPressed: () { if (_isPaused) { _startTimer(); } else { _resetTimer(); } }, ), // ), ], ), ], ))); } }