import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'core/config/app_config.dart'; import 'core/theme/app_theme.dart'; // import 'services/firebase_service.dart'; // Not needed for direct Firebase initialization import 'services/gemini_service.dart'; import 'services/dialog_service.dart'; // TODO: Import models when Hive adapters are generated import 'models/user_model.dart'; import 'models/menu_model.dart'; import 'models/recommendation_model.dart'; import 'screens/splash_screen.dart'; import 'core/constants/app_constants.dart'; import 'firebase_options.dart'; // Background message handler @pragma('vm:entry-point') Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { // Only initialize if not already initialized if (Firebase.apps.isEmpty) { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); } debugPrint('Handling a background message: ${message.messageId}'); } void main() async { WidgetsFlutterBinding.ensureInitialized(); // Set system UI overlay style SystemChrome.setSystemUIOverlayStyle( const SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: Brightness.dark, systemNavigationBarColor: Colors.white, systemNavigationBarIconBrightness: Brightness.dark, ), ); // Set preferred orientations await SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); try { // Initialize Hive await Hive.initFlutter(); // Register Hive adapters Hive.registerAdapter(UserModelAdapter()); Hive.registerAdapter(UserPreferencesAdapter()); Hive.registerAdapter(MenuModelAdapter()); Hive.registerAdapter(RecommendationModelAdapter()); Hive.registerAdapter(MenuRecommendationAdapter()); // Open Hive boxes await Future.wait([ Hive.openBox(AppConstants.userPreferencesBox), Hive.openBox(AppConstants.recommendationsBox), Hive.openBox(AppConstants.menusBox), ]); // Initialize Firebase (handle duplicate app error gracefully) try { if (Firebase.apps.isEmpty) { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); } debugPrint('✅ Firebase initialized'); } catch (e) { if (e.toString().contains('duplicate-app')) { debugPrint('⚠️ Firebase already initialized, using existing instance'); } else { rethrow; } } // Set up background message handler FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); // Initialize Gemini service try { await GeminiService().initialize(); debugPrint('✅ Gemini service initialized'); } catch (e) { debugPrint('⚠️ Gemini service initialization failed: $e'); debugPrint('💡 Users can set their own API key in settings'); } // Print configuration in debug mode AppConfig.printConfig(); runApp(const ProviderScope(child: AmoriMenuRecommenderApp())); } catch (e) { debugPrint('Initialization error: $e'); runApp( MaterialApp( home: Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 64, color: Colors.red), const SizedBox(height: 16), const Text( 'Gagal menginisialisasi aplikasi', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), Text( 'Error: $e', textAlign: TextAlign.center, style: const TextStyle(fontSize: 14, color: Colors.grey), ), const SizedBox(height: 24), ElevatedButton( onPressed: () { // Restart app main(); }, child: const Text('Coba Lagi'), ), ], ), ), ), ), ); } } class AmoriMenuRecommenderApp extends ConsumerWidget { const AmoriMenuRecommenderApp({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return MaterialApp( title: AppConstants.appName, debugShowCheckedModeBanner: false, theme: AppTheme.lightTheme, darkTheme: AppTheme.darkTheme, themeMode: ThemeMode.system, // Global Keys for DialogService navigatorKey: DialogService().navigatorKey, scaffoldMessengerKey: DialogService().scaffoldMessengerKey, home: const SplashScreen(), builder: (context, child) { // Handle global errors ErrorWidget.builder = (FlutterErrorDetails errorDetails) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(Icons.error_outline, size: 64, color: Colors.red), const SizedBox(height: 16), const Text( 'Terjadi kesalahan', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold), ), const SizedBox(height: 8), if (AppConfig.isDebugMode) Padding( padding: const EdgeInsets.all(16.0), child: Text( errorDetails.exception.toString(), textAlign: TextAlign.center, style: const TextStyle( fontSize: 12, color: Colors.grey, ), ), ), const SizedBox(height: 24), ElevatedButton( onPressed: () { // Navigate back or restart Navigator.of(context).pop(); }, child: const Text('Kembali'), ), ], ), ), ); }; return child!; }, ); } }