Resolve all lints and deprecation warnings
This commit is contained in:
153
lib/app_startup.dart
Normal file
153
lib/app_startup.dart
Normal file
@@ -0,0 +1,153 @@
|
||||
import 'dart:async';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hive_flutter/hive_flutter.dart';
|
||||
import 'main.dart'; // Import ChristianPeriodTrackerApp
|
||||
import 'models/cycle_entry.dart';
|
||||
import 'models/scripture.dart';
|
||||
import 'models/user_profile.dart';
|
||||
import 'screens/splash_screen.dart';
|
||||
import 'services/notification_service.dart';
|
||||
|
||||
class AppStartupWidget extends StatefulWidget {
|
||||
const AppStartupWidget({super.key});
|
||||
|
||||
@override
|
||||
State<AppStartupWidget> createState() => _AppStartupWidgetState();
|
||||
}
|
||||
|
||||
class _AppStartupWidgetState extends State<AppStartupWidget> {
|
||||
bool _isInitialized = false;
|
||||
String _status = 'Initializing...';
|
||||
bool _showSkipButton = false;
|
||||
final Duration _minSplashDuration = const Duration(milliseconds: 2000);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeApp();
|
||||
|
||||
// Show skip button if loading takes too long (e.g., 5 seconds)
|
||||
Future.delayed(const Duration(seconds: 5), () {
|
||||
if (mounted && !_isInitialized) {
|
||||
setState(() => _showSkipButton = true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _initializeApp() async {
|
||||
final stopwatch = Stopwatch()..start();
|
||||
|
||||
try {
|
||||
setState(() => _status = 'Loading user profile...');
|
||||
// Add timeout to prevent indefinite hanging
|
||||
await Hive.openBox<UserProfile>('user_profile')
|
||||
.timeout(const Duration(seconds: 5));
|
||||
|
||||
setState(() => _status = 'Loading cycle data...');
|
||||
await Hive.openBox<CycleEntry>('cycle_entries')
|
||||
.timeout(const Duration(seconds: 5));
|
||||
|
||||
setState(() => _status = 'Loading scriptures...');
|
||||
// Wrap scripture loading in a try-catch specifically to allow app to start even if assets fail
|
||||
try {
|
||||
await ScriptureDatabase()
|
||||
.loadScriptures()
|
||||
.timeout(const Duration(seconds: 5));
|
||||
} catch (e) {
|
||||
debugPrint('Scripture loading failed (non-critical): $e');
|
||||
setState(() => _status = 'Scripture loading skipped...');
|
||||
}
|
||||
|
||||
setState(() => _status = 'Setting up notifications...');
|
||||
try {
|
||||
await NotificationService()
|
||||
.initialize()
|
||||
.timeout(const Duration(seconds: 3));
|
||||
} catch (e) {
|
||||
debugPrint('Notification init failed: $e');
|
||||
}
|
||||
} catch (e, stack) {
|
||||
debugPrint('Initialization error: $e');
|
||||
debugPrint(stack.toString());
|
||||
setState(() => _status = 'Error: $e');
|
||||
// On critical error, allow user to proceed manually via skip button
|
||||
setState(() => _showSkipButton = true);
|
||||
return;
|
||||
}
|
||||
|
||||
final elapsed = stopwatch.elapsed;
|
||||
if (elapsed < _minSplashDuration) {
|
||||
await Future.delayed(_minSplashDuration - elapsed);
|
||||
}
|
||||
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isInitialized = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _skipInitialization() {
|
||||
setState(() => _isInitialized = true);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!_isInitialized) {
|
||||
return MaterialApp(
|
||||
home: Scaffold(
|
||||
body: Stack(
|
||||
children: [
|
||||
const SplashScreen(isStartup: true),
|
||||
|
||||
// Status Message (High Visibility)
|
||||
Positioned(
|
||||
bottom: 80,
|
||||
left: 20,
|
||||
right: 20,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.9),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
_status,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: Colors.black87,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
decoration: TextDecoration.none,
|
||||
fontFamily: 'SansSerif'),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// Skip Button
|
||||
if (_showSkipButton)
|
||||
Positioned(
|
||||
bottom: 30,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Center(
|
||||
child: ElevatedButton(
|
||||
onPressed: _skipInitialization,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.redAccent,
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
child: const Text('Skip Loading (Force Start)'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
debugShowCheckedModeBanner: false,
|
||||
);
|
||||
}
|
||||
|
||||
return const ChristianPeriodTrackerApp();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user