26-1-21/1

This commit is contained in:
Hamza-Ayed
2026-01-21 17:01:45 +03:00
parent 11dfe94bbb
commit 3e89e1f1f0
32 changed files with 101957 additions and 12193 deletions

View File

@@ -105,6 +105,9 @@ class FirebaseMessagesController extends GetxController {
// اقرأ "النوع" من حمولة البيانات، وليس من العنوان
String category = message.data['category'] ?? '';
final mapCtrl = Get.isRegistered<MapPassengerController>()
? Get.find<MapPassengerController>()
: null;
// اقرأ العنوان (للعرض)
String title = message.notification?.title ?? '';
String body = message.notification?.body ?? '';
@@ -119,17 +122,25 @@ class FirebaseMessagesController extends GetxController {
// ... داخل معالج الإشعارات في تطبيق الراكب ...
else if (category == 'Accepted Ride') {
// <-- كان 'Accepted Ride'
var driverListJson = message.data['driverList'];
if (driverListJson != null) {
var myList = jsonDecode(driverListJson) as List<dynamic>;
final controller = Get.find<MapPassengerController>();
// controller.currentRideState.value = RideState.driverApplied;
await controller.processRideAcceptance(
driverIdFromFCM: myList[0].toString(),
rideIdFromFCM: myList[3].toString());
} else {
Log.print('❌ خطأ: RIDE_ACCEPTED وصل بدون driverList');
if (mapCtrl != null) {
Map<String, dynamic>? driverInfoMap;
// 2. معالجة driver_info (تأتي كـ String JSON من PHP)
if (message.data['driver_info'] != null) {
try {
String rawJson = message.data['driver_info'];
// 🔥 فك التشفير: تحويل الـ String إلى Map
driverInfoMap = jsonDecode(rawJson);
} catch (e) {
print("❌ Error decoding FCM driver_info: $e");
}
}
// 3. تمرير البيانات الجاهزة للكنترولر
await mapCtrl.processRideAcceptance(
driverData: driverInfoMap,
source: "FCM",
);
}
} else if (category == 'Promo') {
// <-- كان 'Promo'.tr
@@ -142,7 +153,7 @@ class FirebaseMessagesController extends GetxController {
if (Platform.isAndroid) {
notificationController.showNotification(title, body, 'iphone_ringtone');
}
var myListString = message.data['DriverList'];
var myListString = message.data['passengerList'];
var myList = jsonDecode(myListString) as List<dynamic>;
Get.to(() => TripMonitor(), arguments: {
'rideId': myList[0].toString(),
@@ -161,7 +172,7 @@ class FirebaseMessagesController extends GetxController {
if (Platform.isAndroid) {
notificationController.showNotification(title, body, 'tone1');
}
} else if (category == 'message From passenger') {
} else if (category == 'MSG_FROM_PASSENGER') {
// <-- كان 'message From passenger'
if (Platform.isAndroid) {
notificationController.showNotification(title, body, 'ding');
@@ -178,78 +189,33 @@ class FirebaseMessagesController extends GetxController {
} else if (category == 'Trip is Begin') {
// <-- كان 'Trip is Begin'
Log.print('[FCM] استقبل إشعار "TRIP_BEGUN".');
final controller = Get.find<MapPassengerController>();
controller.processRideBegin();
// استدعاء الحارس
mapCtrl!.processRideBegin(source: "FCM");
} else if (category == 'Hi ,I will go now') {
// <-- كان 'Hi ,I will go now'.tr
if (Platform.isAndroid) {
notificationController.showNotification(title, body, 'ding');
}
update();
} else if (category == 'Hi ,I Arrive your site') {
// <-- كان 'Hi ,I Arrive your site'.tr
final controller = Get.find<MapPassengerController>();
// if (controller.currentRideState.value == RideState.driverApplied) {
Log.print('[FCM] السائق وصل. تغيير الحالة إلى driverArrived');
controller.currentRideState.value = RideState.driverArrived;
// }
} else if (category == 'Cancel Trip from driver') {
// <-- كان "Cancel Trip from driver"
Get.back();
if (Platform.isAndroid) {
notificationController.showNotification(title, body, 'cancel');
}
Get.defaultDialog(
title: "The driver canceled your ride.".tr, // العنوان المترجم للعرض
middleText: "We will look for a new driver.\nPlease wait.".tr,
confirm: MyElevatedButton(
kolor: AppColor.greenColor,
title: 'Ok'.tr,
onPressed: () async {
Get.back();
await Get.find<MapPassengerController>()
.reSearchAfterCanceledFromDriver();
},
),
cancel: MyElevatedButton(
title: 'Cancel'.tr,
kolor: AppColor.redColor,
onPressed: () {
Get.offAll(() => const MapPagePassenger());
},
));
} else if (category == "Arrive Ride") {
// استدعاء الحارس
mapCtrl!.processDriverArrival("FCM");
} else if (category == 'Driver Finish Trip') {
// <-- كان 'Driver Finish Trip'.tr
final rawData = message.data['DriverList'];
List<dynamic> driverList = [];
if (rawData != null && rawData is String) {
// ✅ معالجة آمنة للبيانات
var rawData = message.data['DriverList'];
if (rawData != null && rawData.isNotEmpty) {
try {
driverList = jsonDecode(rawData);
driverList = jsonDecode(rawData) as List<dynamic>;
} catch (e) {
Log.print('Error decoding DriverList JSON: $e');
print("Error decoding DriverList: $e");
}
} else {
Log.print('Error: DriverList data is null or not a String.');
}
if (driverList.length >= 3) {
if (Platform.isAndroid) {
notificationController.showNotification(
title,
'${'you will pay to Driver'.tr} ${driverList[3].toString()} \$',
'tone1');
}
Get.find<AudioRecorderController>().stopRecording();
// ... (باقي كود المحفظة) ...
Get.find<MapPassengerController>().tripFinishedFromDriver();
// ... (إشعار "لا تنسى متعلقاتك") ...
Get.to(() => RateDriverFromPassenger(), arguments: {
'driverId': driverList[0].toString(),
'rideId': driverList[1].toString(),
'price': driverList[3].toString()
});
} else {
Log.print('Error: TRIP_FINISHED decoded list error.');
if (driverList.isNotEmpty) {
Get.find<MapPassengerController>()
.processRideFinished(driverList, source: "FCM");
}
} else if (category == 'Finish Monitor') {
// <-- كان "Finish Monitor".tr
@@ -262,19 +228,21 @@ class FirebaseMessagesController extends GetxController {
onPressed: () {
Get.offAll(() => const MapPagePassenger());
}));
} else if (category == 'Driver Cancelled Your Trip') {
} else if (category == 'Cancel Trip from driver') {
Log.print("🔔 FCM: Ride Cancelled by Driver received.");
// لا داعي لكتابة منطق التنظيف هنا، الكنترولر يتكفل بكل شيء
if (Get.isRegistered<MapPassengerController>()) {
// استدعاء الحارس (سيتجاهل الأمر إذا كان السوكيت قد سبقه)
Get.find<MapPassengerController>()
.processRideCancelledByDriver(message.data, source: "FCM");
}
// إشعار محلي (اختياري، لأن الديالوج سيظهر)
if (Platform.isAndroid) {
notificationController.showNotification(
'Driver Cancelled Your Trip'.tr,
'you will pay to Driver you will be pay the cost of driver time look to your Intaleq Wallet'
.tr,
'cancel');
'Trip Cancelled'.tr, 'The driver cancelled the trip.'.tr, 'cancel');
}
box.write(BoxName.parentTripSelected, false);
box.remove(BoxName.tokenParent);
Get.find<MapPassengerController>().restCounter();
Get.offAll(() => const MapPagePassenger());
}
// ... (باقي الحالات مثل Call Income, Call End, إلخ) ...
// ... بنفس الطريقة ...
@@ -617,7 +585,7 @@ class FirebaseMessagesController extends GetxController {
Future<dynamic> passengerDialog(String message) {
return Get.defaultDialog(
barrierDismissible: false,
title: 'message From Driver'.tr,
title: message.tr,
titleStyle: AppStyle.title,
middleTextStyle: AppStyle.title,
middleText: message.tr,

View File

@@ -1,41 +1,44 @@
import 'package:Intaleq/print.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:get/get.dart'; // للترجمة .tr
class NotificationService {
// استبدل هذا الرابط بالرابط الصحيح لملف PHP على السيرفر الخاص بك
static const String _serverUrl =
'https://syria.intaleq.xyz/intaleq/fcm/send_fcm.php';
static const String _batchServerUrl =
'https://syria.intaleq.xyz/intaleq/fcm/send_fcm_batch.php';
'https://api.intaleq.xyz/intaleq/ride/firebase/send_fcm.php';
static Future<void> sendNotification({
required String target,
required String title,
required String body,
required String? category, // <-- [الإضافة الأولى]
required String category, // إلزامي للتصنيف
String? tone,
List<String>? driverList, // <-- [تعديل 1] : إضافة المتغير الجديد
List<String>? driverList,
bool isTopic = false,
}) async {
try {
final Map<String, dynamic> payload = {
// 1. تجهيز البيانات المخصصة (Data Payload)
Map<String, dynamic> customData = {};
customData['category'] = category;
// إذا كان هناك قائمة سائقين/ركاب، نضعها هنا
if (driverList != null && driverList.isNotEmpty) {
// نرسلها كـ JSON String لأن FCM v1 يدعم String Values فقط في الـ data
customData['driverList'] = jsonEncode(driverList);
}
// 2. تجهيز الطلب الرئيسي للسيرفر
final Map<String, dynamic> requestPayload = {
'target': target,
'title': title,
'body': body,
'isTopic': isTopic,
'data':
customData, // 🔥🔥 التغيير الجوهري: وضعنا البيانات داخل "data" 🔥🔥
};
if (category != null) {
payload['category'] =
category; // <-- [الإضافة الثانية] (النص الثابت للتحكم)
}
// نضيف النغمة فقط إذا لم تكن فارغة
if (tone != null) {
payload['tone'] = tone;
}
// <-- [تعديل 2] : نضيف قائمة البيانات بعد تشفيرها إلى JSON
if (driverList != null) {
payload['driverList'] = jsonEncode(driverList);
if (tone != null) {
requestPayload['tone'] = tone;
}
final response = await http.post(
@@ -43,71 +46,18 @@ class NotificationService {
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(payload),
body: jsonEncode(requestPayload),
);
if (response.statusCode == 200) {
print('✅ Notification sent successfully.');
print('Server Response: ${response.body}');
// print('Response: ${response.body}');
} else {
print(
'❌ Failed to send notification. Status code: ${response.statusCode}');
print('Server Error: ${response.body}');
print('❌ Failed to send notification. Code: ${response.statusCode}');
print('Error Body: ${response.body}');
}
} catch (e) {
print('An error occurred while sending notification: $e');
}
}
/// [4] !! دالة جديدة مضافة !!
/// ترسل إشعاراً "مجمعاً" إلى قائمة من السائقين
static Future<void> sendBatchNotification({
required List<String> targets, // <-- قائمة التوكينز
required String title,
required String body,
String? tone,
List<String>? driverList, // <-- بيانات الرحلة (نفسها للجميع)
}) async {
// لا ترسل شيئاً إذا كانت القائمة فارغة
if (targets.isEmpty) {
Log.print('⚠️ [Batch] No targets to send to. Skipped.');
return;
}
try {
final Map<String, dynamic> payload = {
// "targets" بدلاً من "target"
'targets': jsonEncode(targets), // تشفير قائمة التوكينز
'title': title,
'body': body,
};
if (tone != null) {
payload['tone'] = tone;
}
// بيانات الرحلة (DriverList)
if (driverList != null) {
payload['driverList'] = jsonEncode(driverList);
}
final response = await http.post(
Uri.parse(_batchServerUrl), // <-- !! تستخدم الرابط الجديد
headers: {
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(payload),
);
if (response.statusCode == 200) {
Log.print('✅ [Batch] Notifications sent successfully.');
Log.print('Server Response: ${response.body}');
} else {
Log.print('❌ [Batch] Failed to send. Status: ${response.statusCode}');
Log.print('Server Error: ${response.body}');
}
} catch (e) {
Log.print('❌ [Batch] An error occurred: $e');
print('Error sending notification: $e');
}
}
}