import 'dart:convert'; import 'dart:io'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_ringtone_player/flutter_ringtone_player.dart'; import 'package:generp/Models/hrmModels/leaveApplicationLIstResponse.dart'; import 'package:generp/Utils/app_colors.dart'; import 'package:generp/screens/AttendanceScreen.dart'; import 'package:generp/screens/crm/LeadDetailsByMode.dart'; import 'package:generp/screens/crm/ProspectListByMode.dart'; import 'package:generp/screens/crm/crmDashboard.dart'; import 'package:generp/screens/hrm/Attendancelist.dart'; import 'package:generp/screens/hrm/OrganizationStructureScreen.dart'; import 'package:generp/screens/hrm/TourExpensesListScreen.dart'; import 'Notifiers/hrmProvider/advanceProvider.dart'; import 'screens/notifierExports.dart'; import 'package:generp/Utils/SharedpreferencesService.dart'; import 'package:generp/screens/splash.dart'; import 'package:provider/provider.dart'; import 'Utils/commonWidgets.dart'; // Navigator Key for global navigation final GlobalKey navigatorKey = GlobalKey(); // Notification Channel const AndroidNotificationChannel channel = AndroidNotificationChannel( 'generp_channel', 'generp_channel_name', importance: Importance.max, playSound: true, ); final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); Future _firebaseMessagingBackgroundHandler(RemoteMessage message) async { await Firebase.initializeApp(); debugPrint("📩 Background notification received: ${message.data}"); } void handleNotificationTap(Map data) { debugPrint("👉 Handling notification tap: $data"); try { String type = data['type'] ?? ''; String? rollId = data['RoleID'] ?? data['rollId']; String? notificationId = data['notification_id'] ?? data['notificationId']; String? url = data['url']; String? mode = data['Parameter']; debugPrint("👉 Handling notification tap: $mode"); if (type.toLowerCase() == "app") { // 🔥 Navigation based on RoleID switch (rollId) { case "1": navigatorKey.currentState?.pushNamed('/crm_lead_list'); break; case "4": navigatorKey.currentState?.pushNamed('/crm_prospect_list'); break; case "5": navigatorKey.currentState?.pushNamed( '/crm_prospect_details', arguments: {"id": notificationId}, ); break; case "6": navigatorKey.currentState?.pushNamed( '/crm_lead_details', arguments: {"id": notificationId}, ); break; case "7": navigatorKey.currentState?.pushNamed('/dashboard'); break; case "8": navigatorKey.currentState?.pushNamed('/crm_new_customer_new_lead_register'); break; case "10": navigatorKey.currentState?.pushNamed('/crm_prospect_list_team'); break; case "11": navigatorKey.currentState?.pushNamed('/crm_prospect_list_admin'); break; case "15": navigatorKey.currentState?.pushNamed('/finance_list_employee'); break; case "16": navigatorKey.currentState?.pushNamed('/finance_list_admin'); break; case "17": navigatorKey.currentState?.pushNamed('/dispatch_list_executive'); break; case "312": navigatorKey.currentState?.pushNamed('/tour_bill_list'); break; case "601": navigatorKey.currentState?.pushNamed('/manual_attendance_request_list'); break; default: navigatorKey.currentState?.pushNamed('/home'); // fallback } } else if (type.toLowerCase() == "web" && url != null && url.isNotEmpty) { // Open in WebView or browser navigatorKey.currentState?.pushNamed( '/webview', arguments: {"url": url}, ); } else { // fallback navigatorKey.currentState?.pushNamed('/home'); } } catch (e) { debugPrint("❌ Error handling notification tap: $e"); } } // FlutterLocalNotificationsPlugin cannot auto-detect foreground taps void showInAppNotification(BuildContext context, Map data) { final snackBar = SnackBar( content: Text(data['type'] ?? "New Notification"), action: SnackBarAction( label: 'Open', onPressed: () { debugPrint("👉 Foreground notification tapped: $data"); handleNotificationTap(data); }, ), ); ScaffoldMessenger.of(context).showSnackBar(snackBar); } void main() async { WidgetsFlutterBinding.ensureInitialized(); // Firebase init if (Platform.isAndroid) { await Firebase.initializeApp( options: FirebaseOptions( apiKey: "AIzaSyBmkmKdYfBt2n5QRlmZJ9MV_Amh9xR3UOY", appId: "1:329382566569:android:26dc8519537b04deff67b8", messagingSenderId: "329382566569", projectId: "generp-fe09d", ), ); } else if (Platform.isIOS) { await Firebase.initializeApp(); } // 🔔 Local Notification Init const AndroidInitializationSettings initSettingsAndroid = AndroidInitializationSettings('@mipmap/ic_launcher'); const DarwinInitializationSettings initSettingsIOS = DarwinInitializationSettings(); const InitializationSettings initializationSettings = InitializationSettings( android: initSettingsAndroid, iOS: initSettingsIOS, ); flutterLocalNotificationsPlugin.initialize( initializationSettings, onDidReceiveNotificationResponse: (NotificationResponse notificationResponse) async { if (notificationResponse.payload != null) { handleNotificationTap(jsonDecode(notificationResponse.payload!)); debugPrint("📩 Notification clicked: $notificationResponse"); } } ); // Firebase Messaging FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler); FirebaseMessaging messaging = FirebaseMessaging.instance; await messaging.requestPermission(alert: true, badge: true, sound: true); // Foreground notification FirebaseMessaging.onMessage.listen((RemoteMessage message) { final notification = message.notification; final android = message.notification?.android; debugPrint("😊 Foreground msg received: ${message.data}"); if (notification != null && android != null) { // flutterLocalNotificationsPlugin.show( // notification.hashCode, // notification.title, // notification.body, // NotificationDetails( // android: AndroidNotificationDetails( // channel.id, // channel.name, // importance: Importance.max, // priority: Priority.high, // icon: '@mipmap/ic_launcher', // ), // ), // payload: jsonEncode({ // "type": message.data['type'], // "rollId": message.data['RoleID'], // "notificationId": message.data['notification_id'], // }), // ); } // ⚡ Foreground tap alternative: // Show an in-app banner or SnackBar with a tap action final context = navigatorKey.currentContext; if (context != null) { // Add haptic feedback HapticFeedback.mediumImpact(); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ SizedBox( child: Image.asset( "assets/images/ic_splash.jpg", height: 30, width: 30, ), ), SizedBox(width: 8), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( notification?.title ?? "New Notification", style: TextStyle( fontSize: 14, color: AppColors.app_blue, fontFamily: "JakartaMedium", ), ), if (notification?.body != null) SizedBox(height: 2), if (notification?.body != null) Text( notification!.body!, style: TextStyle( fontSize: 12, color: AppColors.semi_black, fontFamily: "JakartaMedium", ), ), ], ), ), ], ), action: SnackBarAction( label: "Open", textColor: AppColors.app_blue, onPressed: () { // Add haptic feedback for button press HapticFeedback.lightImpact(); debugPrint("👉 Foreground notification tapped: ${message.data}"); // Use the same payload structure as local notifications handleNotificationTap({ "type": message.data['type'], "rollId": message.data['RoleID'], "notificationId": message.data['notification_id'], }); }, ), backgroundColor: AppColors.white, behavior: SnackBarBehavior.floating, elevation: 6, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), margin: const EdgeInsets.all(16), duration: const Duration(seconds: 4), ), ); } }); await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(channel); await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions( alert: true, badge: true, sound: true, ); FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { String type = message.data['type'] ?? ''; String redirectUrl = message.data['redirect_url'] ?? ''; handleNotificationTap(message.data); // Navigator.push( // context, // MaterialPageRoute(builder: (context) => Dashboard()), // ); if (kDebugMode) { print('A new onMessageOpenedApp event was published!'); } }); // Save FCM Token await FirebaseMessaging.instance.getToken().then((value) { if (value != null) { SharedpreferencesService().saveString("fbstoken", value); debugPrint("🔑 FCM Token: $value"); } }); runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); // This widget is the root of your application. @override Widget build(BuildContext context) { // SystemChrome.setApplicationSwitcherDescription(ApplicationSwitcherDescription()); // SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge); // FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) { // String type = message.data['type'] ?? ''; // String redirectUrl = message.data['redirect_url'] ?? ''; // // // Navigator.push( // // context, // // MaterialPageRoute(builder: (context) => Dashboard()), // // ); // if (kDebugMode) { // print('A new onMessageOpenedApp event was published!'); // } // }); return MultiProvider( providers: [ ChangeNotifierProvider(create: (_) => SplashVersionNotifier()), ChangeNotifierProvider(create: (_) => UpdatePasswordProvider()), ChangeNotifierProvider(create: (_) => Scanloginprovider()), ChangeNotifierProvider(create: (_) => Loginnotifier()), ChangeNotifierProvider(create: (_) => Counter()), ChangeNotifierProvider(create: (_) => HomescreenNotifier()), ChangeNotifierProvider(create: (_) => ProfileNotifer()), ChangeNotifierProvider(create: (_) => LogoutNotifier()), ChangeNotifierProvider(create: (_) => AttendanceNotifier()), ChangeNotifierProvider(create: (_) => CheckInOutProvider()), ChangeNotifierProvider(create: (_) => InventoryProvider()), ChangeNotifierProvider( create: (_) => Serviceengineerdashboardprovider(), ), ChangeNotifierProvider(create: (_) => Pendingcomplaintsprovider()), ChangeNotifierProvider(create: (_) => Todaymontlyvisitsprovider()), ChangeNotifierProvider(create: (_) => Paymentcollectionprovider()), ChangeNotifierProvider(create: (_) => Visitdetailsprovider()), ChangeNotifierProvider(create: (_) => Pcwalletprovider()), ChangeNotifierProvider(create: (_) => Paymentdetailsprovider()), ChangeNotifierProvider(create: (_) => Generatordetailsprovider()), ChangeNotifierProvider(create: (_) => Nearbygeneratorsprovider()), ///finance ChangeNotifierProvider(create: (_) => Dashboardprovider()), ChangeNotifierProvider(create: (_) => Requestionlistprovider()), ChangeNotifierProvider(create: (_) => Requesitionlidtdetailsprovider()), ChangeNotifierProvider( create: (_) => Paymentrequisitionpaymentslistprovider(), ), ChangeNotifierProvider(create: (_) => Paymentreceiptsprovider()), ChangeNotifierProvider(create: (_) => Commonpagesprovider()), ChangeNotifierProvider(create: (_) => Accountslistprovider()), ChangeNotifierProvider(create: (_) => Accountdetailsprovider()), ChangeNotifierProvider(create: (_) => Accountledgerprovider()), ChangeNotifierProvider(create: (_) => Pagesdashboardprovider()), ChangeNotifierProvider(create: (_) => Paymentsprovider()), ChangeNotifierProvider(create: (_) => Tpcagentsprovider()), ChangeNotifierProvider(create: (_) => Addpaymentprovider()), ChangeNotifierProvider(create: (_) => Addorderprovider()), ChangeNotifierProvider(create: (_) => Editpaymentprovider()), ///crm ChangeNotifierProvider(create: (_) => Crmdashboardprovider()), ChangeNotifierProvider(create: (_) => Leadlistprovider()), ChangeNotifierProvider(create: (_) => crmLeadDetailsProvider()), ChangeNotifierProvider(create: (_) => Editcrmaccountdetailsprovider()), ChangeNotifierProvider(create: (_) => Editproductlistprovider()), ChangeNotifierProvider(create: (_) => ProspectListProvider()), ChangeNotifierProvider(create: (_) => crmProspectDetailsProvider()), ChangeNotifierProvider(create: (_) => crmNearbyOpenLeadsProvider()), ChangeNotifierProvider(create: (_) => Crmgeneratequotationprovider()), ChangeNotifierProvider(create: (_) => Crmeditprospectaccountprovider()), ChangeNotifierProvider(create: (_) => Addprospectleadsprovider()), ChangeNotifierProvider(create: (_) => Editorderprovider()), ChangeNotifierProvider(create: (_) => Dispatchorderprovider()), ChangeNotifierProvider(create: (_) => followUpUpdateProvider()), ChangeNotifierProvider(create: (_) => Appointmentcalendarprovider()), ChangeNotifierProvider(create: (_) => Addnewleadsandprospectsprovider()), ChangeNotifierProvider(create: (_) => HrmAccessiblePagesProvider()), ChangeNotifierProvider(create: (_) => Attendancelistprovider()), ChangeNotifierProvider(create: (_) => AttendanceDetailsProvider()), ChangeNotifierProvider(create: (_) => TourExpensesProvider()), ChangeNotifierProvider(create: (_) => TourExpensesDetailsProvider()), ChangeNotifierProvider(create: (_) => RewardListProvider()), ChangeNotifierProvider(create: (_) => LeaveApplicationListProvider()), ChangeNotifierProvider(create: (_) => Orgprovider()), ChangeNotifierProvider(create: (_) => AdvanceListProvider()), ChangeNotifierProvider(create: (_) => CasualLeaveHistoryProvider()), ], child: Builder( builder: (BuildContext context) { return MaterialApp( navigatorKey: navigatorKey, routes: { '/home': (context) => const AttendanceScreen(), '/chat': (context) => AttendanceScreen(), '/product_details': (context) => AttendanceScreen(), '/order_details': (context) => AttendanceScreen(), '/crm_lead_list': (context) => LeadDetailsByMode(mode: "", pageTitleName: "Lead Details", leadId: ""), '/crm_prospect_list': (context) => ProspectListByMode(), '/crm_prospect_details': (context) => AttendanceScreen(), '/crm_lead_details': (context) => AttendanceScreen(), '/dashboard': (context) => CrmdashboardScreen(), '/crm_new_customer_new_lead_register': (context) => AttendanceScreen(), '/crm_prospect_list_team': (context) => AttendanceScreen(), '/crm_prospect_list_admin': (context) => AttendanceScreen(), '/finance_list_employee': (context) => AttendanceScreen(), '/finance_list_admin': (context) => AttendanceScreen(), '/dispatch_list_executive': (context) => AttendanceScreen(), '/tour_bill_list': (context) => TourExpensesListScreen(), '/manual_attendance_request_list': (context) => AttendanceListScreen(mode: "",), }, scrollBehavior: const MaterialScrollBehavior().copyWith( dragDevices: {PointerDeviceKind.touch,PointerDeviceKind.mouse}, ), navigatorObservers: [MyNavigatorObserver()], builder: (BuildContext context, Widget? child) { final MediaQueryData data = MediaQuery.of(context); return MediaQuery( data: data.copyWith(textScaler: TextScaler.linear(1.0)), child: child ?? Container(), ); }, themeMode: ThemeMode.light, debugShowCheckedModeBanner: false, theme: ThemeData( fontFamily: 'JakartaRegular', splashColor: Colors.transparent, highlightColor: Colors.transparent, hoverColor: Colors.transparent, scaffoldBackgroundColor: Colors.white, dialogBackgroundColor: Colors.white, cardColor: Colors.white, shadowColor: Colors.white54, searchBarTheme: const SearchBarThemeData(), tabBarTheme: const TabBarThemeData(), textSelectionTheme: TextSelectionThemeData( cursorColor: AppColors.app_blue, ), dialogTheme: const DialogThemeData( shadowColor: Colors.white, surfaceTintColor: Colors.white, backgroundColor: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(5.0), ), // Set the border radius of the dialog ), ), buttonTheme: const ButtonThemeData(), appBarTheme: const AppBarTheme( shadowColor: Colors.white, surfaceTintColor: Colors.white, color: Colors.white, ), cardTheme: const CardThemeData( shadowColor: Colors.white, surfaceTintColor: Colors.white, color: Colors.white, //), ), textButtonTheme: TextButtonThemeData( style: ButtonStyle( // overlayColor: MaterialStateProperty.all(Colors.white), ), ), bottomSheetTheme: const BottomSheetThemeData( surfaceTintColor: Colors.white, backgroundColor: Colors.white, dragHandleColor: Color(0xFFe4e4e4), dragHandleSize: Size(60.0, 6.0), ), colorScheme: const ColorScheme.light( background: Colors.white, ).copyWith(background: Colors.white), scrollbarTheme: ScrollbarThemeData( minThumbLength: 20, interactive: true, radius: Radius.circular(6), thickness: WidgetStatePropertyAll(10), thumbColor: WidgetStateProperty.all( AppColors.grey_semi.withOpacity(0.6), ), ), checkboxTheme: CheckboxThemeData( side: BorderSide(width: 0.5), checkColor: WidgetStatePropertyAll(AppColors.white), ), useMaterial3: true, // inputDecorationTheme: InputDecorationTheme( // hintStyle: TextStyle( // fontWeight: FontWeight.w400, // color: Color(0xFFB4BEC0), // fontSize: 14, // ), // // enabledBorder: InputBorder.none, // focusedBorder: InputBorder.none, // ), ), home: const Splash(), ); }, ), ); } }