引导、通知栏计时

This commit is contained in:
ytc1012
2025-11-24 10:33:09 +08:00
parent 149d1ed6cd
commit 2c6ced5c14
7 changed files with 496 additions and 28 deletions

View File

@@ -24,21 +24,66 @@ class FocusScreen extends StatefulWidget {
State<FocusScreen> createState() => _FocusScreenState();
}
class _FocusScreenState extends State<FocusScreen> {
class _FocusScreenState extends State<FocusScreen> with WidgetsBindingObserver {
late Timer _timer;
late int _remainingSeconds;
late DateTime _startTime;
final List<String> _distractions = [];
bool _isPaused = false;
bool _isInBackground = false;
final NotificationService _notificationService = NotificationService();
@override
void initState() {
super.initState();
_remainingSeconds = widget.durationMinutes * 60;
_startTime = DateTime.now();
WidgetsBinding.instance.addObserver(this);
_startTimer();
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
_timer.cancel();
// Cancel ongoing notification when leaving the screen
_notificationService.cancelOngoingFocusNotification();
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
switch (state) {
case AppLifecycleState.paused:
case AppLifecycleState.inactive:
case AppLifecycleState.detached:
// App went to background
_isInBackground = true;
if (!_isPaused && _remainingSeconds > 0) {
_showBackgroundNotification();
}
break;
case AppLifecycleState.resumed:
// App came back to foreground
_isInBackground = false;
_notificationService.cancelOngoingFocusNotification();
break;
case AppLifecycleState.hidden:
break;
}
}
void _showBackgroundNotification() {
final minutes = _remainingSeconds ~/ 60;
final seconds = _remainingSeconds % 60;
_notificationService.showOngoingFocusNotification(
remainingMinutes: minutes,
remainingSeconds: seconds,
);
}
void _startTimer() {
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (!_isPaused && _remainingSeconds > 0) {
@@ -46,6 +91,18 @@ class _FocusScreenState extends State<FocusScreen> {
_remainingSeconds--;
});
// Update background notification every 30 seconds when in background
if (_isInBackground && _remainingSeconds > 0) {
if (_remainingSeconds % 30 == 0) {
final minutes = _remainingSeconds ~/ 60;
final seconds = _remainingSeconds % 60;
_notificationService.updateOngoingFocusNotification(
remainingMinutes: minutes,
remainingSeconds: seconds,
);
}
}
if (_remainingSeconds == 0) {
_onTimerComplete();
}
@@ -55,11 +112,14 @@ class _FocusScreenState extends State<FocusScreen> {
void _onTimerComplete() async {
_timer.cancel();
// Cancel ongoing notification and show completion notification
await _notificationService.cancelOngoingFocusNotification();
_saveFocusSession(completed: true);
// Send notification
final notificationService = NotificationService();
await notificationService.showFocusCompletedNotification(
// Send completion notification
await _notificationService.showFocusCompletedNotification(
minutes: widget.durationMinutes,
distractionCount: _distractions.length,
);
@@ -82,6 +142,13 @@ class _FocusScreenState extends State<FocusScreen> {
setState(() {
_isPaused = !_isPaused;
});
// Update notification when paused
if (_isPaused && _isInBackground) {
_notificationService.cancelOngoingFocusNotification();
} else if (!_isPaused && _isInBackground) {
_showBackgroundNotification();
}
}
void _stopEarly() {
@@ -257,12 +324,6 @@ class _FocusScreenState extends State<FocusScreen> {
return '${minutes.toString().padLeft(2, '0')}:${secs.toString().padLeft(2, '0')}';
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(