diff --git a/backend/ride/firebase/send_fcm.php b/backend/ride/firebase/send_fcm.php index b1bce2c2..f2521aa1 100644 --- a/backend/ride/firebase/send_fcm.php +++ b/backend/ride/firebase/send_fcm.php @@ -16,15 +16,15 @@ function resolveServiceAccountPath(): string { if (!empty($envPath) && file_exists($envPath)) { return $envPath; } - if (file_exists('/keys/firebase_service_account.json')) { - return '/keys/firebase_service_account.json'; - } + // if (file_exists('/keys/firebase_service_account.json')) { + // return '/keys/firebase_service_account.json'; + // } if (file_exists('/keys/service-account.json')) { return '/keys/service-account.json'; } - if (file_exists(__DIR__ . '/../../keys/firebase_service_account.json')) { - return __DIR__ . '/../../keys/firebase_service_account.json'; - } + // if (file_exists(__DIR__ . '/../../keys/firebase_service_account.json')) { + // return __DIR__ . '/../../keys/firebase_service_account.json'; + // } return __DIR__ . '/service-account.json'; } diff --git a/siro_driver/lib/controller/firebase/firbase_messge.dart b/siro_driver/lib/controller/firebase/firbase_messge.dart index 0b72bbda..3a442ce6 100755 --- a/siro_driver/lib/controller/firebase/firbase_messge.dart +++ b/siro_driver/lib/controller/firebase/firbase_messge.dart @@ -134,10 +134,6 @@ class FirebaseMessagesController extends GetxController { switch (category) { case 'ORDER': case 'Order': // Handle both cases for backward compatibility - // if (Platform.isAndroid) { - // notificationController.showNotification(title, body, 'order', ''); - // } - // 🔥 [Fix FCM-Guard] منع إعاقة الرحلة النشطة بطلبات جديدة عبر FCM String currentRideStatus = box.read(BoxName.rideStatus) ?? ''; if (currentRideStatus == 'Begin' || @@ -150,6 +146,11 @@ class FirebaseMessagesController extends GetxController { var myListString = message.data['DriverList']; if (myListString != null) { + if (Platform.isAndroid) { + notificationController.showOrderNotification( + title, body, 'ding.wav', myListString); + } + var myList = jsonDecode(myListString) as List; driverToken = myList[14].toString(); Get.put(HomeCaptainController(), permanent: true).changeRideId(); diff --git a/siro_rider/lib/controller/firebase/firbase_messge.dart b/siro_rider/lib/controller/firebase/firbase_messge.dart index 6e8b2fe2..28edbeba 100644 --- a/siro_rider/lib/controller/firebase/firbase_messge.dart +++ b/siro_rider/lib/controller/firebase/firbase_messge.dart @@ -124,6 +124,11 @@ class FirebaseMessagesController extends GetxController { // ... داخل معالج الإشعارات في تطبيق الراكب ... else if (category == 'Accepted Ride') { + if (Platform.isAndroid) { + String notifTitle = 'Ride Accepted ✅'.tr; + String notifBody = 'The captain is on their way to you now.'.tr; + notificationController.showNotification(notifTitle, notifBody, 'ding'); + } if (mapCtrl != null) { Map? driverInfoMap; @@ -198,6 +203,11 @@ class FirebaseMessagesController extends GetxController { update(); } else if (category == 'Trip is Begin') { // <-- كان 'Trip is Begin' + if (Platform.isAndroid) { + String notifTitle = 'Trip Begun 🚀'.tr; + String notifBody = 'Have a safe and comfortable trip.'.tr; + notificationController.showNotification(notifTitle, notifBody, 'ding'); + } Log.print('[FCM] استقبل إشعار "TRIP_BEGUN".'); // استدعاء الحارس mapCtrl!.processRideBegin(source: "FCM"); @@ -208,9 +218,19 @@ class FirebaseMessagesController extends GetxController { } update(); } else if (category == "Arrive Ride") { + if (Platform.isAndroid) { + String notifTitle = 'Driver is outside 🚖'.tr; + String notifBody = 'The captain has arrived at your location.'.tr; + notificationController.showNotification(notifTitle, notifBody, 'ding'); + } // استدعاء الحارس mapCtrl!.processDriverArrival("FCM"); } else if (category == 'Driver Finish Trip') { + if (Platform.isAndroid) { + String notifTitle = 'Trip Finished 🏁'.tr; + String notifBody = 'Please pay and rate the driver.'.tr; + notificationController.showNotification(notifTitle, notifBody, 'ding'); + } List driverList = []; // ✅ معالجة آمنة للبيانات diff --git a/siro_rider/lib/controller/firebase/local_notification.dart b/siro_rider/lib/controller/firebase/local_notification.dart index be123e2c..3469975a 100644 --- a/siro_rider/lib/controller/firebase/local_notification.dart +++ b/siro_rider/lib/controller/firebase/local_notification.dart @@ -66,6 +66,27 @@ class NotificationController extends GetxController { id: 0, title: title, body: message, notificationDetails: details); Log.print('Notification shown: $title - $message'); } + + // 🆕 Static method for background isolates where GetX might not be initialized + static Future showBackgroundNotification(String title, String message, String tone) async { + final FlutterLocalNotificationsPlugin plugin = FlutterLocalNotificationsPlugin(); + const AndroidInitializationSettings android = AndroidInitializationSettings('@mipmap/launcher_icon'); + const DarwinInitializationSettings ios = DarwinInitializationSettings(); + await plugin.initialize(settings: const InitializationSettings(android: android, iOS: ios)); + + final AndroidNotificationDetails androidDetails = AndroidNotificationDetails( + 'high_importance_channel', + 'High Importance Notifications', + importance: Importance.max, + priority: Priority.high, + showWhen: false, + sound: RawResourceAndroidNotificationSound(tone), + ); + const DarwinNotificationDetails iosDetails = DarwinNotificationDetails(sound: 'default'); + + await plugin.show(id: 0, title: title, body: message, notificationDetails: NotificationDetails(android: androidDetails, iOS: iosDetails)); + Log.print('Background notification shown: $title - $message'); + } // /Users/hamzaaleghwairyeen/development/App/ride 2/lib/controller/firebase/local_notification.dart // Assume _flutterLocalNotificationsPlugin is initialized somewhere in your code diff --git a/siro_rider/lib/controller/local/ar_eg.dart b/siro_rider/lib/controller/local/ar_eg.dart index 169cf32e..945fbcda 100644 --- a/siro_rider/lib/controller/local/ar_eg.dart +++ b/siro_rider/lib/controller/local/ar_eg.dart @@ -21,7 +21,18 @@ final Map ar_eg = { "Stops": "محطات", "No bus running on this route right now": "لا يوجد باص يعمل على هذا الخط الآن", "Bus is delayed": "الباص متأخر", - "Missed the bus? Book a ride now": "فاتك الأتوبيس؟ احجز سيارة دلوقتي", + "Missed the bus? Book a ride now": "فاتك الباص؟ اطلب سيارة الآن", + + // ── FCM Notifications ── + "Ride Accepted ✅": "تم قبول رحلتك ✅", + "The captain is on their way to you now.": "الكابتن في طريقه إليك الآن.", + "Driver is outside 🚖": "السائق في الخارج 🚖", + "The captain has arrived at your location.": "الكابتن وصل إلى موقعك، الرجاء التوجه إليه.", + "Trip Begun 🚀": "بدأت الرحلة 🚀", + "Have a safe and comfortable trip.": "نتمنى لك رحلة آمنة ومريحة.", + "Trip Finished 🏁": "تم إنهاء الرحلة 🏁", + "Please pay and rate the driver.": "الرجاء الدفع وتقييم السائق.", + " ')[0]).toString()}.\\n\${' I am using": " ')[0]).toString()}.\\n\${' I am using", " I am currently located at ": " أنا حالياً في ", " I am using": " أنا استخدم", diff --git a/siro_rider/lib/controller/local/ar_jo.dart b/siro_rider/lib/controller/local/ar_jo.dart index 91b950ef..a6248bbf 100644 --- a/siro_rider/lib/controller/local/ar_jo.dart +++ b/siro_rider/lib/controller/local/ar_jo.dart @@ -22,6 +22,16 @@ final Map ar_jo = { "No bus running on this route right now": "لا يوجد باص يعمل على هذا الخط الآن", "Bus is delayed": "الباص متأخر", "Missed the bus? Book a ride now": "فاتك الباص؟ اطلب سيارة الآن", + + // ── FCM Notifications ── + "Ride Accepted ✅": "تم قبول رحلتك ✅", + "The captain is on their way to you now.": "الكابتن في طريقه إليك الآن.", + "Driver is outside 🚖": "السائق في الخارج 🚖", + "The captain has arrived at your location.": "الكابتن وصل إلى موقعك، الرجاء التوجه إليه.", + "Trip Begun 🚀": "بدأت الرحلة 🚀", + "Have a safe and comfortable trip.": "نتمنى لك رحلة آمنة ومريحة.", + "Trip Finished 🏁": "تم إنهاء الرحلة 🏁", + "Please pay and rate the driver.": "الرجاء الدفع وتقييم السائق.", " ')[0]).toString()}.\\n\${' I am using": " ')[0]).toString()}.\\n\${' I am using", " I am currently located at ": " أنا حالياً في ", " I am using": " أنا استخدم", diff --git a/siro_rider/lib/controller/local/ar_sy.dart b/siro_rider/lib/controller/local/ar_sy.dart index a48dca7f..7dbf5937 100644 --- a/siro_rider/lib/controller/local/ar_sy.dart +++ b/siro_rider/lib/controller/local/ar_sy.dart @@ -21,7 +21,18 @@ final Map ar_sy = { "Stops": "محطات", "No bus running on this route right now": "لا يوجد باص يعمل على هذا الخط الآن", "Bus is delayed": "الباص متأخر", - "Missed the bus? Book a ride now": "فاتك الباص؟ اطلب سيارة هلق", + "Missed the bus? Book a ride now": "فاتك الباص؟ اطلب سيارة الآن", + + // ── FCM Notifications ── + "Ride Accepted ✅": "تم قبول رحلتك ✅", + "The captain is on their way to you now.": "الكابتن في طريقه إليك الآن.", + "Driver is outside 🚖": "السائق في الخارج 🚖", + "The captain has arrived at your location.": "الكابتن وصل إلى موقعك، الرجاء التوجه إليه.", + "Trip Begun 🚀": "بدأت الرحلة 🚀", + "Have a safe and comfortable trip.": "نتمنى لك رحلة آمنة ومريحة.", + "Trip Finished 🏁": "تم إنهاء الرحلة 🏁", + "Please pay and rate the driver.": "الرجاء الدفع وتقييم السائق.", + " ')[0]).toString()}.\\n\${' I am using": " ')[0]).toString()}.\\n\${' I am using", " I am currently located at ": " أنا حالياً في ", " I am using": " أنا استخدم", diff --git a/siro_rider/lib/main.dart b/siro_rider/lib/main.dart index 0fcd532c..82a3d837 100644 --- a/siro_rider/lib/main.dart +++ b/siro_rider/lib/main.dart @@ -23,6 +23,7 @@ import 'controller/home/ios_live_activity_service.dart'; import 'services/android_live_update_service.dart'; import 'controller/local/local_controller.dart'; import 'controller/local/translations.dart'; +import 'controller/firebase/local_notification.dart'; import 'controller/themes/themes.dart'; import 'firebase_options.dart'; import 'models/db_sql.dart'; @@ -72,6 +73,48 @@ Future backgroundMessageHandler(RemoteMessage message) async { } catch (e) { Log.print("Silent push location update failed: $e"); } + + // 🆕 عرض الإشعارات المترجمة في الخلفية + try { + final category = message.data['category'] ?? ''; + if (category == 'Accepted Ride' || + category == 'Arrive Ride' || + category == 'Trip is Begin' || + category == 'Driver Finish Trip') { + final storage = GetStorage(); + final lang = storage.read(BoxName.lang) ?? 'ar'; + String titleKey = ''; + String bodyKey = ''; + + if (category == 'Accepted Ride') { + titleKey = 'Ride Accepted ✅'; + bodyKey = 'The captain is on their way to you now.'; + } else if (category == 'Arrive Ride') { + titleKey = 'Driver is outside 🚖'; + bodyKey = 'The captain has arrived at your location.'; + } else if (category == 'Trip is Begin') { + titleKey = 'Trip Begun 🚀'; + bodyKey = 'Have a safe and comfortable trip.'; + } else if (category == 'Driver Finish Trip') { + titleKey = 'Trip Finished 🏁'; + bodyKey = 'Please pay and rate the driver.'; + } + + // ترجمة باستخدام ملفات الترجمة حتى في الخلفية + String title = titleKey; + String body = bodyKey; + + if (lang.toString().startsWith('ar')) { + title = MyTranslation().keys['ar']?[titleKey] ?? titleKey; + body = MyTranslation().keys['ar']?[bodyKey] ?? bodyKey; + } + + // عرض الإشعار المحلي عبر الكلاس المخصص + await NotificationController.showBackgroundNotification(title, body, 'ding'); + } + } catch (e) { + Log.print("Background local notification failed: $e"); + } } } @@ -99,7 +142,8 @@ void main() { // Initialize Geofencing Service only if permission is already granted to avoid auto-prompt if (Platform.isAndroid || Platform.isIOS) { LocationPermission permission = await Geolocator.checkPermission(); - if (permission != LocationPermission.denied && permission != LocationPermission.deniedForever) { + if (permission != LocationPermission.denied && + permission != LocationPermission.deniedForever) { await SiroGeofencingService.initAndStart(); } }