import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; final notifications = FlutterLocalNotificationsPlugin(); void main() async { WidgetsFlutterBinding.ensureInitialized(); const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher'); const settings = InitializationSettings(android: androidSettings); await notifications.initialize(settings); await notifications.resolvePlatformSpecificImplementation()?.requestNotificationsPermission(); runApp(const TimerApp()); } class TimerApp extends StatelessWidget { const TimerApp({super.key}); @override Widget build(BuildContext context) => MaterialApp( theme: ThemeData(useMaterial3: true, colorScheme: ColorScheme.fromSeed( seedColor: Colors.deepPurple, brightness: Brightness.light, )), home: const TimerScreen(), ); } class TimerScreen extends StatefulWidget { const TimerScreen({super.key}); @override State createState() => _TimerScreenState(); } class _TimerScreenState extends State { int duration = 60; int remaining = 60; Timer? timer; bool isRunning = false; void _showNotification() async { const androidDetails = AndroidNotificationDetails( 'timer_channel', 'Таймер', channelDescription: 'Уведомления таймера', importance: Importance.high, priority: Priority.high, ); const details = NotificationDetails(android: androidDetails); await notifications.show(0, 'Таймер завершён!', 'Время вышло.', details); } void _startTimer() { setState(() => isRunning = true); timer = Timer.periodic(const Duration(seconds: 1), (_) { if (remaining > 0) { setState(() => remaining--); } else { timer?.cancel(); _showNotification(); setState(() => isRunning = false); } }); } void _pauseTimer() { timer?.cancel(); setState(() => isRunning = false); } void _resetTimer() { timer?.cancel(); setState(() { isRunning = false; remaining = duration; }); } void _selectDuration() { showModalBottomSheet( context: context, builder: (_) => Column( mainAxisSize: MainAxisSize.min, children: [1, 5, 10, 15, 30, 60].map((m) { return ListTile( title: Text('$m мин'), onTap: () { setState(() { duration = m * 60; remaining = duration; }); Navigator.pop(context); }, ); }).toList(), ), ); } @override void dispose() { timer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { final minutes = (remaining / 60).floor(); final seconds = remaining % 60; final progress = duration > 0 ? (remaining / duration) as double : 0.0; return Scaffold( appBar: AppBar(title: const Text('Таймер')), body: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( onTap: _selectDuration, child: Stack( alignment: Alignment.center, children: [ SizedBox( width: 200, height: 200, child: CircularProgressIndicator( value: progress, strokeWidth: 8, ), ), Text( '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}', style: Theme.of(context).textTheme.displayMedium, ), ], ), ), const SizedBox(height: 40), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ FloatingActionButton( onPressed: isRunning ? _pauseTimer : _startTimer, child: Icon(isRunning ? Icons.pause : Icons.play_arrow), ), if (remaining != duration) ...[ const SizedBox(width: 16), OutlinedButton(onPressed: _resetTimer, child: const Text('Сброс')), ], ], ), ], ), ); } }