Files
intaleq/lib/views/widgets/my_circular_indicator_timer.dart

160 lines
4.4 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../constant/colors.dart';
class MyCircularProgressIndicatorWithTimer extends StatefulWidget {
final Color backgroundColor;
final bool isLoading;
const MyCircularProgressIndicatorWithTimer({
Key? key,
this.backgroundColor = Colors.transparent,
required this.isLoading,
}) : super(key: key);
@override
State<MyCircularProgressIndicatorWithTimer> createState() =>
_MyCircularProgressIndicatorWithTimerState();
}
class _MyCircularProgressIndicatorWithTimerState
extends State<MyCircularProgressIndicatorWithTimer> {
Timer? _timer;
int _timeLeft = 60;
bool _isLowTime = false;
@override
void initState() {
super.initState();
if (widget.isLoading) _startTimer();
}
@override
void didUpdateWidget(
covariant MyCircularProgressIndicatorWithTimer oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.isLoading && !oldWidget.isLoading) {
_resetTimer();
_startTimer();
} else if (!widget.isLoading && oldWidget.isLoading) {
_cancelTimer();
}
}
void _startTimer() {
_cancelTimer(); // Ensure no duplicate timers
_timer = Timer.periodic(const Duration(seconds: 1), (_) {
if (!mounted) return;
setState(() {
if (_timeLeft > 0) {
_timeLeft--;
_isLowTime = _timeLeft <= 10;
} else {
_cancelTimer();
}
});
});
}
void _resetTimer() {
_cancelTimer();
setState(() {
_timeLeft = 60;
_isLowTime = false;
});
}
void _cancelTimer() {
_timer?.cancel();
_timer = null;
}
@override
void dispose() {
_cancelTimer();
super.dispose();
}
@override
Widget build(BuildContext context) {
if (!widget.isLoading) return const SizedBox.shrink();
final progress = _timeLeft / 60.0;
final timerColor = _isLowTime ? Colors.orangeAccent : Colors.blueAccent;
return Center(
child: Container(
width: 200,
height: 200,
decoration: BoxDecoration(
color: widget.backgroundColor == Colors.transparent
? AppColor.secondaryColor.withOpacity(0.96)
: widget.backgroundColor,
shape: BoxShape.circle,
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.08),
blurRadius: 24,
spreadRadius: 2,
offset: const Offset(0, 8),
),
],
),
child: Stack(
alignment: Alignment.center,
children: [
// Elegant circular progress ring
SizedBox(
width: 184,
height: 184,
child: CircularProgressIndicator(
value: progress,
strokeWidth: 6,
backgroundColor: Get.isDarkMode
? Colors.grey.shade800
: Colors.grey.shade100,
valueColor: AlwaysStoppedAnimation<Color>(timerColor),
strokeCap: StrokeCap.round,
),
),
// Center content
Column(
mainAxisSize: MainAxisSize.min,
children: [
// Subtle scale animation when time is low
AnimatedContainer(
duration: const Duration(milliseconds: 400),
curve: Curves.easeOutCubic,
transform: Matrix4.identity()..scale(_isLowTime ? 1.08 : 1.0),
child: Image.asset(
'assets/images/logo.gif',
width: 96,
height: 96,
fit: BoxFit.contain,
),
),
const SizedBox(height: 14),
// Clean, modern timer text
AnimatedDefaultTextStyle(
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
style: TextStyle(
fontSize: 22,
fontWeight: FontWeight.w600,
color:
_isLowTime ? Colors.orangeAccent : AppColor.writeColor,
letterSpacing: 1.2,
fontFeatures: const [FontFeature.tabularFigures()],
),
child: Text('${_timeLeft}s'),
),
],
),
],
),
),
);
}
}