TempoFlow/lib/pages/breathe_page.dart

158 lines
4.6 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../theme/app_theme.dart';
import '../models/app_settings.dart';
class BreathePage extends StatefulWidget {
const BreathePage({super.key});
@override
State<BreathePage> createState() => _BreathePageState();
}
class _BreathePageState extends State<BreathePage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _scaleAnimation;
String _instruction = "Inhale";
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 19),
);
_scaleAnimation = TweenSequence<double>([
TweenSequenceItem(
tween: Tween(begin: 1.0, end: 1.5)
.chain(CurveTween(curve: Curves.easeOut)),
weight: 4,
),
TweenSequenceItem(tween: ConstantTween(1.5), weight: 7),
TweenSequenceItem(
tween: Tween(begin: 1.5, end: 1.0)
.chain(CurveTween(curve: Curves.easeIn)),
weight: 8,
),
]).animate(_controller);
_controller.addListener(() {
final val = _controller.value;
String newText;
if (val < 0.21) {
newText = "Inhale (4s)";
} else if (val < 0.58) {
newText = "Hold (7s)";
} else {
newText = "Exhale (8s)";
}
if (newText != _instruction) {
setState(() => _instruction = newText);
if (AppSettings.enableHaptics) HapticFeedback.mediumImpact();
}
});
_controller.repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFE3F2FD),
appBar: AppBar(
leading: const CloseButton(color: AppTheme.primary),
backgroundColor: Colors.transparent,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
"B R E A T H E",
style: TextStyle(
letterSpacing: 4,
fontSize: 24,
fontWeight: FontWeight.w900,
color: AppTheme.primary,
),
),
const SizedBox(height: 10),
const Text(
"4-7-8 Technique",
style: TextStyle(
color: AppTheme.textSub,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 60),
AnimatedBuilder(
animation: _scaleAnimation,
builder: (context, child) {
return Container(
width: 200 * _scaleAnimation.value,
height: 200 * _scaleAnimation.value,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppTheme.accent.withOpacity(0.4),
AppTheme.accent.withOpacity(0.1),
],
),
boxShadow: [
BoxShadow(
color: AppTheme.accent.withOpacity(0.2),
blurRadius: 30 * _scaleAnimation.value,
spreadRadius: 10,
)
],
),
child: Center(
child: Container(
width: 150,
height: 150,
decoration: const BoxDecoration(
color: Colors.white,
shape: BoxShape.circle,
),
child: Center(
child: Text(
_instruction.split(" ")[0],
style: const TextStyle(
fontSize: 32,
fontWeight: FontWeight.w800,
color: AppTheme.primary,
),
),
),
),
),
);
},
),
const SizedBox(height: 80),
Text(
_instruction,
style: const TextStyle(
fontSize: 24,
color: AppTheme.primary,
fontWeight: FontWeight.w800,
),
),
],
),
),
);
}
}