yoga_timer/lib/universal_page.dart

280 lines
9.2 KiB
Dart

import 'dart:async';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:wakelock/wakelock.dart';
class UniversalPage extends StatefulWidget {
const UniversalPage({super.key});
@override
State<UniversalPage> createState() => _UniversalPageState();
}
class _UniversalPageState extends State<UniversalPage> {
Duration exerciseDuration = const Duration(minutes: 4);
Duration shavasanaDuration = const Duration(minutes: 10);
late int exNumber = 5;
late int totalDuration =
exerciseDuration.inSeconds * exNumber + shavasanaDuration.inSeconds;
late Timer _timer;
late String startText = 'Старт';
final player = AudioPlayer();
bool isStarted() {
if (totalDuration ==
exerciseDuration.inSeconds * exNumber + shavasanaDuration.inSeconds) {
return false;
}
return true;
}
void startTimer() {
Wakelock.enable();
if (startText == 'Пауза') {
setState(() {
player.dispose();
startText = 'Возобновить';
_timer.cancel();
});
} else {
startText = 'Пауза';
const oneSec = Duration(seconds: 1);
_timer = Timer.periodic(
oneSec,
(Timer timer) {
if (totalDuration == 0) {
player.play(AssetSource('audio/finish.mp3'));
stopTimer();
} else if (totalDuration == shavasanaDuration.inSeconds) {
player.play(AssetSource('audio/relax.mp3'));
setState(() {
totalDuration--;
});
} else if ((totalDuration - shavasanaDuration.inSeconds) %
exerciseDuration.inSeconds ==
0 &&
(totalDuration - shavasanaDuration.inSeconds) > 0) {
player.play(AssetSource('audio/start.mp3'));
setState(() {
totalDuration--;
});
} else {
setState(() {
totalDuration--;
});
}
},
);
}
}
void stopTimer() {
setState(() {
Wakelock.disable();
player.dispose();
_timer.cancel();
startText = 'Старт';
totalDuration =
exerciseDuration.inSeconds * exNumber + shavasanaDuration.inSeconds;
});
}
void setTotalDuration(value) {
setState(() {
exNumber = value!;
totalDuration =
exerciseDuration.inSeconds * exNumber + shavasanaDuration.inSeconds;
});
}
void _showDialog(Widget child) {
showCupertinoModalPopup<void>(
context: context,
builder: (BuildContext context) => Container(
height: 216,
padding: const EdgeInsets.only(top: 6.0),
margin: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
color: CupertinoColors.systemBackground.resolveFrom(context),
child: SafeArea(
top: false,
child: child,
),
));
}
format(Duration duration) {
final splitDuration = duration.toString().split(":");
final hours = splitDuration[0];
final minutes = splitDuration[1];
final seconds = splitDuration[2].split('.')[0];
return [hours, minutes, seconds];
}
@override
void dispose() {
_timer.cancel();
player.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Универсальный таймер'),
),
body: ListView(
padding: const EdgeInsets.all(16.0),
children: [
const Center(
child: Text(
"Количество упражнений",
style: TextStyle(fontSize: 22.0),
)),
const Divider(),
CupertinoButton(
onPressed: isStarted()
? null
: () => _showDialog(
CupertinoPicker(
backgroundColor: Colors.white,
itemExtent: 30,
scrollController:
FixedExtentScrollController(initialItem: 1),
children: [
Text('0'),
Text('1'),
Text('2'),
Text('3'),
Text('4'),
Text('5'),
Text('6'),
Text('7'),
Text('8'),
Text('9'),
Text('10'),
Text('11'),
Text('12'),
Text('13'),
Text('14'),
Text('15'),
Text('16'),
Text('17'),
Text('18'),
Text('19'),
Text('20'),
Text('21'),
Text('22'),
Text('23'),
Text('24'),
Text('25')
],
onSelectedItemChanged: isStarted()
? null
: (value) => setTotalDuration(value),
),
),
child: Text(
exNumber.toString(),
style: const TextStyle(
fontSize: 22.0,
),
),
),
const Divider(),
const Center(
child: Text(
"Продолжительность каждого упражнения",
style: TextStyle(fontSize: 22.0),
)),
CupertinoButton(
onPressed: isStarted()
? null
: () => _showDialog(
CupertinoTimerPicker(
mode: CupertinoTimerPickerMode.ms,
initialTimerDuration: exerciseDuration,
onTimerDurationChanged: (Duration newDuration) {
setState(() {
exerciseDuration = newDuration;
totalDuration =
exerciseDuration.inSeconds * exNumber +
shavasanaDuration.inSeconds;
});
},
),
),
child: Text(
format(exerciseDuration)[1] +
":" +
format(exerciseDuration)[2],
style: const TextStyle(
fontSize: 22.0,
),
),
),
const Divider(),
const Center(
child: Text(
"Продолжительность шавасаны",
style: TextStyle(fontSize: 22.0),
)),
CupertinoButton(
onPressed: isStarted()
? null
: () => _showDialog(
CupertinoTimerPicker(
mode: CupertinoTimerPickerMode.ms,
initialTimerDuration: shavasanaDuration,
onTimerDurationChanged: (Duration newDuration) {
setState(() {
shavasanaDuration = newDuration;
totalDuration =
exerciseDuration.inSeconds * exNumber +
shavasanaDuration.inSeconds;
});
},
),
),
child: Text(
format(shavasanaDuration)[1] +
":" +
format(shavasanaDuration)[2],
style: const TextStyle(
fontSize: 22.0,
),
),
),
const Divider(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () => startTimer(), child: Text(startText)),
const SizedBox(width: 50),
ElevatedButton(
onPressed: isStarted() ? () => stopTimer() : null,
child: const Text('Стоп'))
]),
const Divider(),
const Center(
child: Text(
"Осталось практиковать:",
style: TextStyle(fontSize: 22.0),
)),
const Divider(),
Center(
child: Text(
"${format(Duration(seconds: totalDuration)).join(':')}",
style: const TextStyle(fontSize: 22.0)))
],
));
}
}