import 'dart:async'; import 'dart:ui' show ViewFocusEvent, ViewFocusState; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../core/providers/theme_provider.dart'; import '../features/dashboard/data/prayer_times_provider.dart'; import 'router.dart'; import 'theme/app_theme.dart'; /// Root MaterialApp.router wired to GoRouter + ThemeMode from Riverpod. class App extends ConsumerStatefulWidget { const App({super.key}); @override ConsumerState createState() => _AppState(); } class _AppState extends ConsumerState with WidgetsBindingObserver { Timer? _midnightResyncTimer; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addPostFrameCallback((_) { HardwareKeyboard.instance.syncKeyboardState(); }); _scheduleMidnightResync(); } @override void dispose() { _midnightResyncTimer?.cancel(); WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { if (state == AppLifecycleState.resumed || state == AppLifecycleState.inactive) { // Resync stale pressed-key state to avoid repeated KeyDown assertions. HardwareKeyboard.instance.syncKeyboardState(); } if (state == AppLifecycleState.resumed) { ref.invalidate(prayerTimesProvider); unawaited(ref.read(prayerTimesProvider.future)); _scheduleMidnightResync(); } } @override void didChangeViewFocus(ViewFocusEvent event) { if (event.state == ViewFocusState.focused) { HardwareKeyboard.instance.syncKeyboardState(); } } void _scheduleMidnightResync() { _midnightResyncTimer?.cancel(); final now = DateTime.now(); final nextRun = DateTime(now.year, now.month, now.day, 0, 5).isAfter(now) ? DateTime(now.year, now.month, now.day, 0, 5) : DateTime(now.year, now.month, now.day + 1, 0, 5); final delay = nextRun.difference(now); _midnightResyncTimer = Timer(delay, () { ref.invalidate(prayerTimesProvider); unawaited(ref.read(prayerTimesProvider.future)); _scheduleMidnightResync(); }); } @override Widget build(BuildContext context) { final themeMode = ref.watch(themeProvider); return MaterialApp.router( title: 'Jamshalat Diary', debugShowCheckedModeBanner: false, theme: AppTheme.light, darkTheme: AppTheme.dark, themeMode: themeMode, routerConfig: appRouter, ); } }