Files
jamshalat-diary/lib/app/app.dart
2026-03-18 00:07:10 +07:00

90 lines
2.6 KiB
Dart

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<App> createState() => _AppState();
}
class _AppState extends ConsumerState<App> 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,
);
}
}