import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:firebase_database/firebase_database.dart'; import 'package:in_app_notification/in_app_notification.dart'; import 'firebase_options.dart'; import 'service/notification_service.dart'; // IMPORT PAGE import 'screen/welcome.dart'; import 'screen/login.dart'; import 'screen/register.dart'; import 'screen/dashboard.dart'; import 'screen/pesan.dart'; import 'screen/history.dart'; import 'screen/akun.dart'; final GlobalKey navigatorKey = GlobalKey(); /// 🔔 HANDLER NOTIFIKASI BACKGROUND @pragma('vm:entry-point') Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { // Inisialisasi Firebase di background await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); if (message.notification != null) { String body = message.notification!.body ?? ""; body = body .replaceAll(RegExp(r'Proses Optimal', caseSensitive: false), 'Belum Matang') .replaceAll(RegExp(r'Proses Awal', caseSensitive: false), 'Belum Matang') .replaceAll(RegExp(r'Menjelang Matang', caseSensitive: false), 'Belum Matang'); await NotificationService.showNotification( message.notification!.title ?? "Notifikasi", body, ); } } Future main() async { // 1. Pastikan binding sudah siap WidgetsFlutterBinding.ensureInitialized(); // 2. Inisialisasi Firebase (Gunakan Try-Catch agar aman) try { await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); } catch (e) { debugPrint("Firebase init error: $e"); } // 3. Register Background Handler FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); // 4. Init Local Notification await NotificationService.init(); // 5. Jalankan Aplikasi Dulu (SANGAT PENTING agar tidak layar hitam) runApp(const GoTapeApp()); // 6. Jalankan konfigurasi tambahan setelah runApp agar tidak menghambat startup _initNotification(); } /// Fungsi tambahan untuk setup notifikasi tanpa menghambat UI void _initNotification() async { try { FirebaseMessaging messaging = FirebaseMessaging.instance; // Minta Izin await messaging.requestPermission(); // Ambil & Simpan Token String? token = await messaging.getToken(); if (token != null) { // Simpan ke database tanpa await agar tidak nunggu lama FirebaseDatabase.instance.ref("fcm_token").set(token); debugPrint("🔥 FCM TOKEN: $token"); } // Listener Foreground FirebaseMessaging.onMessage.listen((RemoteMessage message) { if (message.notification != null) { String title = message.notification!.title ?? "Notifikasi"; String body = message.notification!.body ?? ""; body = body .replaceAll(RegExp(r'Proses Optimal', caseSensitive: false), 'Belum Matang') .replaceAll(RegExp(r'Proses Awal', caseSensitive: false), 'Belum Matang') .replaceAll(RegExp(r'Menjelang Matang', caseSensitive: false), 'Belum Matang'); NotificationService.showNotification(title, body); // Tampilkan In-App Notification (Seperti WhatsApp) final context = navigatorKey.currentContext; if (context != null) { InAppNotification.show( child: _buildWhatsAppStyleNotification(title, body), context: context, duration: const Duration(seconds: 4), curve: Curves.easeOutCubic, ); } } }); // Listener saat notif diklik FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { debugPrint("🔔 User membuka notifikasi"); }); } catch (e) { debugPrint("Notification Setup Error: $e"); } } Widget _buildWhatsAppStyleNotification(String title, String body) { bool isAlert = title.toLowerCase().contains('berbahaya') || title.toLowerCase().contains('matang'); return SafeArea( child: Container( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), padding: const EdgeInsets.all(16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.15), blurRadius: 15, offset: const Offset(0, 5), ), ], ), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( color: isAlert ? Colors.redAccent : const Color(0xFF5B35D5), shape: BoxShape.circle, ), child: Icon( isAlert ? Icons.warning_rounded : Icons.notifications_active, color: Colors.white, size: 24, ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( title, style: TextStyle( fontWeight: FontWeight.bold, fontSize: 16, color: isAlert ? Colors.redAccent : Colors.black87, ), ), const SizedBox(height: 4), Text( body, style: const TextStyle( color: Colors.black54, fontSize: 14, ), maxLines: 2, overflow: TextOverflow.ellipsis, ), ], ), ), ], ), ), ); } class GoTapeApp extends StatelessWidget { const GoTapeApp({super.key}); @override Widget build(BuildContext context) { return InAppNotification( child: MaterialApp( navigatorKey: navigatorKey, debugShowCheckedModeBanner: false, title: 'GoTape', theme: ThemeData( useMaterial3: true, colorSchemeSeed: const Color(0xFF4DB6AC), scaffoldBackgroundColor: const Color(0xFFF2F6F6), appBarTheme: const AppBarTheme( centerTitle: true, elevation: 0, backgroundColor: Colors.transparent, ), ), // Halaman Utama menggunakan AuthGate home: const AuthGate(), // Daftar Route routes: { '/welcome': (_) => const WelcomeScreen(), '/login': (_) => const LoginPage(), '/register': (_) => const RegisterScreen(), '/dashboard': (_) => const DashboardPage(), '/pesan': (_) => const NotificationPage(), '/riwayat': (_) => const HistoryPage(), '/akun': (_) => const AkunScreen(), }, ), ); } } class AuthGate extends StatelessWidget { const AuthGate({super.key}); @override Widget build(BuildContext context) { return StreamBuilder( stream: FirebaseAuth.instance.authStateChanges(), builder: (context, snapshot) { // Jika sedang mengecek status login if (snapshot.connectionState == ConnectionState.waiting) { return const Scaffold( body: Center( child: CircularProgressIndicator(color: Color(0xFF4DB6AC)), ), ); } // Jika terjadi error pada Firebase Auth if (snapshot.hasError) { return const Scaffold( body: Center( child: Text( 'Terjadi kesalahan autentikasi', style: TextStyle(color: Colors.red), ), ), ); } // Jika user sudah login, lempar ke Dashboard if (snapshot.hasData && snapshot.data != null) { return const DashboardPage(); } // Jika belum login, tampilkan Welcome Screen return const WelcomeScreen(); }, ); } }