25-10-5/1
This commit is contained in:
@@ -44,8 +44,8 @@ android {
|
|||||||
applicationId = "com.intaleq_driver"
|
applicationId = "com.intaleq_driver"
|
||||||
minSdk = 29
|
minSdk = 29
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 17 // I've used the higher version number from your first file
|
versionCode = 18
|
||||||
versionName = '1.0.17' // I've used the higher version name
|
versionName = '1.0.18' // I've used the higher version name
|
||||||
multiDexEnabled = true
|
multiDexEnabled = true
|
||||||
|
|
||||||
ndk {
|
ndk {
|
||||||
|
|||||||
@@ -1,31 +1,31 @@
|
|||||||
List<String> syrianDriverMessages = [
|
List<String> syrianDriverMessages = [
|
||||||
// --- رسائل وقت الذروة والطلبات المستعجلة ---
|
// --- أوقات الذروة والطلبات الكتيرة ---
|
||||||
"البلد ولعانة هلأ! 🌃 هاد وقت الذروة، فرصة ذهبية لتدبّل أرباحك. انطلق معنا!",
|
"وقت الذروة: البلد مولّعة مشاوير! 🌃 افتح التطبيق بسرعة وبلّش أرباحك تدبّل.",
|
||||||
"انتبه: الطلبات كتيرة بمنطقتك! ⚠️ خليك أول واحد بياخد مشوار واكسب أكتر. جاهز تطلع؟",
|
"طلبات كتير حواليك: ⚠️ خليك أول كابتن بيلتقط الطلب وخلّي يومك رابح.",
|
||||||
"لا تروح عليك ساعة الذروة! ⏳ زباين أكتر يعني مصاري أكتر. فوت عالبرنامج هلأ!",
|
"الناس طالعة من الشغل: 🌇 الكل راجع عالبيت، خليك جاهز لرحلات كتيرة!",
|
||||||
"خلص الدوام عند كتير عالم، وصار وقت يرجعوا عالبيت! 🌇 خليك بطلن ووصلن بأمان.",
|
"زحمة المساء: ⏳ الزباين عم تزيد بهالوقت، لا تضيّع الفرصة واشتغل معنا!",
|
||||||
|
|
||||||
// --- رسائل للتركيز عالربح والمصاري ---
|
// --- التركيز عالربح والمصاري ---
|
||||||
"هدف اليوم صار قريب! 💪 كل مشوار بيقربك أكتر. بلّش مشوارك الجاي هلأ.",
|
"ضاعف ربحك: 💰 كل مشوار بيقربك من هدفك اليومي. جاهز تنطلق؟",
|
||||||
"جزدانك ناطر مصاري زيادة! 💰 فوت عالبرنامج وحوّل وقتك لمصاري عنجد ومضمونة.",
|
"مصاري أكتر: جزدانك ناطر تعبك، كل دقيقة شغل هي ربح مضمون. 💪",
|
||||||
"كبسة زر بتجيبلك ربح زيادة. جاهز للطلب الجاي؟ 🤔",
|
"خليك بالواجهة: الطلب الجاي ممكن يكون إلك، كبسة زر بتجيبلك رزقة اليوم.",
|
||||||
"لا تترك المصاري عالأرض! 💸 زباين انطلق عم يدوروا على كابتن شاطر متلك هلأ.",
|
"رزقتك جاهزة: 💸 لا تخلّي الزباين يستنّوا، افتح التطبيق وخليك متأهّب.",
|
||||||
|
|
||||||
// --- رسائل تقدير وشكر ---
|
// --- التقدير والشكر ---
|
||||||
"أنت مو بس شوفير، أنت شريكنا بالنجاح. 🙏 زباينّا ناطرينك. يسلم إيديك!",
|
"شكراً إلك: 🙏 إنت مو بس سائق، إنت أساس نجاح تطبيق انطلق.",
|
||||||
"نحنا عم نكبر فيك! 🌟 خليك فاتح واستقبل مشاوير جديدة من زباينّا الكويسين.",
|
"نفتخر فيك: 🌟 الكباتن متلك هنن يلي رافعين اسمنا بالعالي.",
|
||||||
"كباتنّا هنن الأحسن! 👍 ضل عم تقدّم هالخدمة الحلوة اللي بيعرفوها زباينا عن تطبيق انطلق.",
|
"أداء ممتاز: 👍 استمر بنفس الروح الحلوة، زباينك مبسوطين منك.",
|
||||||
"كل توصيلة ناجحة هي قصة نجاح لإلك وإلنا. خلينا نعمل قصص نجاح أكتر اليوم! 🗺️",
|
"نجاح مشترك: 🗺️ كل توصيلة بتعملها بتكبر فيها شركتنا وانت كمان.",
|
||||||
|
|
||||||
// --- رسائل تحفيز وتشجيع ---
|
// --- التحفيز والتشجيع ---
|
||||||
"يوم جديد، فرصة جديدة للنجاح! ☀️ فوت عالبرنامج وخلينا ننطلق سوا لأهدافك.",
|
"صباح النشاط: ☀️ بلّش نهارك بطاقة إيجابية وانطلق لتكسب أكتر.",
|
||||||
"طريق النجاح ببلّش بمشوار. 🏁 خود مشوارك الجاي واعمل إنجازات أكتر.",
|
"كل مشوار فرصة: 🏁 لا توقف، الطريق لإلك والنجاح ناطرك.",
|
||||||
"فيك تعمل دخل كتير منيح اليوم. نحنا واثقين فيك! انطلق هلأ. 💼",
|
"يوم مربح: 💼 السوق ناشط اليوم، لا تفوّت الفرصة!",
|
||||||
"الطلب الجاي يمكن يكون الأحسن! لا تضيّع فرصتك. فوت عالبرنامج وخليك جاهز. 🔔",
|
"جاهز للطلب الجاي: 🔔 الزبون الجاي ممكن يكون أوفر ممتاز، خليك مستعد.",
|
||||||
|
|
||||||
// --- رسائل نصايح ومعلومات ---
|
// --- نصايح ومعلومات ---
|
||||||
"نصيحة اليوم: روح عالأسواق والمطاعم هلأ بتزيد فرصة يجيك مشاوير. 🏙️",
|
"نصيحة اليوم: روح صوب الأسواق والمطاعم، الطلب هناك عالي هالفترة. 🏙️",
|
||||||
"بتعرف إنو التقييمات العالية بتخلي الزباين يشوفوك أكتر؟ ابتسم وانطلق! 😊",
|
"حافظ على تقييمك: 😊 الزبون بينجذب للكابتن يلي عنده تقييم عالي وابتسامة.",
|
||||||
"يمكن تشتّي بعد شوي! 🌧️ الطلب بيزيد بهيك جو، فرصة ممتازة تزود مصاريك.",
|
"جو ممطر: 🌧️ المطر يعني طلبات أكتر، خليك شغّال بهالوقت!",
|
||||||
"في حفلة كبيرة بقلب البلد اليوم. 🎆 جهّز حالك للمشاوير الكتيرة بهديك المنطقة."
|
"حدث اليوم: 🎆 في فعالية بالبلد، المشاوير كتيرة بهالمنطقة، استغلها!"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -356,8 +356,8 @@ Download the Intaleq app now and enjoy your ride!
|
|||||||
'${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n'
|
'${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n'
|
||||||
'_*${d['message']['inviteCode'].toString()}*_\n\n'
|
'_*${d['message']['inviteCode'].toString()}*_\n\n'
|
||||||
'${"Install our app:".tr}\n'
|
'${"Install our app:".tr}\n'
|
||||||
'*Android:* https://play.google.com/store/apps/details?id=com.sefer_driver\n\n\n'
|
'*Android:* https://play.google.com/store/apps/details?id=com.intaleq_driver\n\n\n'
|
||||||
'*iOS:* https://apps.apple.com/ae/app/sefer-driver/id6502189302';
|
'*iOS:* https://apps.apple.com/st/app/intaleq-driver/id6482995159';
|
||||||
|
|
||||||
launchCommunication('whatsapp', formattedPhoneNumber, message);
|
launchCommunication('whatsapp', formattedPhoneNumber, message);
|
||||||
invitePhoneController.clear();
|
invitePhoneController.clear();
|
||||||
@@ -395,8 +395,8 @@ Download the Intaleq app now and enjoy your ride!
|
|||||||
'${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n'
|
'${'before'.tr} *${d['message']['expirationTime'].toString()}*\n\n'
|
||||||
'_*${d['message']['inviteCode'].toString()}*_\n\n'
|
'_*${d['message']['inviteCode'].toString()}*_\n\n'
|
||||||
'${"Install our app:".tr}\n'
|
'${"Install our app:".tr}\n'
|
||||||
'*Android:* https://play.google.com/store/apps/details?id=com.mobileapp.store.ride\n\n\n'
|
'*Android:* https://play.google.com/store/apps/details?id=com.Intaleq.intaleq\n\n\n'
|
||||||
'*iOS:* https://apps.apple.com/us/app/sefer/id6458734951';
|
'*iOS:* https://apps.apple.com/st/app/intaleq-rider/id6748075179';
|
||||||
|
|
||||||
launchCommunication('whatsapp', formattedPhoneNumber, message);
|
launchCommunication('whatsapp', formattedPhoneNumber, message);
|
||||||
invitePhoneController.clear();
|
invitePhoneController.clear();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import '../../../views/auth/captin/otp_page.dart';
|
|||||||
import '../../../views/auth/captin/otp_token_page.dart';
|
import '../../../views/auth/captin/otp_token_page.dart';
|
||||||
import '../../../views/auth/syria/pending_driver_page.dart';
|
import '../../../views/auth/syria/pending_driver_page.dart';
|
||||||
import '../../firebase/firbase_messge.dart';
|
import '../../firebase/firbase_messge.dart';
|
||||||
|
import '../../firebase/notification_service.dart';
|
||||||
import '../../functions/encrypt_decrypt.dart';
|
import '../../functions/encrypt_decrypt.dart';
|
||||||
import '../../functions/package_info.dart';
|
import '../../functions/package_info.dart';
|
||||||
import '../../functions/secure_storage.dart';
|
import '../../functions/secure_storage.dart';
|
||||||
@@ -258,7 +259,7 @@ class LoginDriverController extends GetxController {
|
|||||||
update();
|
update();
|
||||||
await SecurityHelper.performSecurityChecks();
|
await SecurityHelper.performSecurityChecks();
|
||||||
// Log.print('(BoxName.emailDriver): ${box.read(BoxName.emailDriver)}');
|
// Log.print('(BoxName.emailDriver): ${box.read(BoxName.emailDriver)}');
|
||||||
|
// await getJWT();
|
||||||
var res = await CRUD().get(link: AppLink.loginFromGoogleCaptin, payload: {
|
var res = await CRUD().get(link: AppLink.loginFromGoogleCaptin, payload: {
|
||||||
'email': email ?? 'yet',
|
'email': email ?? 'yet',
|
||||||
'id': driverID,
|
'id': driverID,
|
||||||
@@ -328,8 +329,11 @@ class LoginDriverController extends GetxController {
|
|||||||
// if (box.read(BoxName.emailDriver).toString() !=
|
// if (box.read(BoxName.emailDriver).toString() !=
|
||||||
// '963992952235@intaleqapp.com') {
|
// '963992952235@intaleqapp.com') {
|
||||||
if (token != 'failure') {
|
if (token != 'failure') {
|
||||||
if ((jsonDecode(token)['data'][0]['token'].toString()) !=
|
var serverData = jsonDecode(token);
|
||||||
box.read(BoxName.tokenDriver).toString()) {
|
if ((serverData['data'][0]['token'].toString()) !=
|
||||||
|
box.read(BoxName.tokenDriver).toString() ||
|
||||||
|
serverData['data'][0]['fingerPrint'].toString() !=
|
||||||
|
fingerPrint.toString()) {
|
||||||
await Get.defaultDialog(
|
await Get.defaultDialog(
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
title: 'Device Change Detected'.tr,
|
title: 'Device Change Detected'.tr,
|
||||||
@@ -534,12 +538,20 @@ class LoginDriverController extends GetxController {
|
|||||||
if (token != 'failure') {
|
if (token != 'failure') {
|
||||||
if ((jsonDecode(token)['data'][0]['token']) !=
|
if ((jsonDecode(token)['data'][0]['token']) !=
|
||||||
(box.read(BoxName.tokenDriver))) {
|
(box.read(BoxName.tokenDriver))) {
|
||||||
Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
|
// Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
|
||||||
'token change'.tr,
|
// 'token change'.tr,
|
||||||
'change device'.tr,
|
// 'change device'.tr,
|
||||||
(jsonDecode(token)['data'][0]['token']).toString(),
|
// (jsonDecode(token)['data'][0]['token']).toString(),
|
||||||
[],
|
// [],
|
||||||
'ding.wav');
|
// 'ding.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: (jsonDecode(token)['data'][0]['token']).toString(),
|
||||||
|
title: 'token change',
|
||||||
|
body: 'token change'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'cancel',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
Get.defaultDialog(
|
Get.defaultDialog(
|
||||||
title: 'you will use this device?'.tr,
|
title: 'you will use this device?'.tr,
|
||||||
middleText: '',
|
middleText: '',
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import '../../../constant/box_name.dart';
|
|||||||
import '../../../constant/links.dart';
|
import '../../../constant/links.dart';
|
||||||
import '../../../main.dart';
|
import '../../../main.dart';
|
||||||
import '../../firebase/firbase_messge.dart';
|
import '../../firebase/firbase_messge.dart';
|
||||||
|
import '../../firebase/notification_service.dart';
|
||||||
import '../../functions/crud.dart';
|
import '../../functions/crud.dart';
|
||||||
|
|
||||||
class OtpVerificationController extends GetxController {
|
class OtpVerificationController extends GetxController {
|
||||||
@@ -101,12 +102,20 @@ class OtpVerificationController extends GetxController {
|
|||||||
? Get.find<FirebaseMessagesController>()
|
? Get.find<FirebaseMessagesController>()
|
||||||
: Get.put(FirebaseMessagesController());
|
: Get.put(FirebaseMessagesController());
|
||||||
|
|
||||||
await fcm.sendNotificationToDriverMAP(
|
// await fcm.sendNotificationToDriverMAP(
|
||||||
'token change',
|
// 'token change',
|
||||||
'change device'.tr,
|
// 'change device'.tr,
|
||||||
ptoken.toString(),
|
// ptoken.toString(),
|
||||||
[],
|
// [],
|
||||||
'cancel.wav',
|
// 'cancel.wav',
|
||||||
|
// );
|
||||||
|
await NotificationService.sendNotification(
|
||||||
|
target: ptoken.toString(),
|
||||||
|
title: 'token change',
|
||||||
|
body: 'token change'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'cancel',
|
||||||
|
driverList: [],
|
||||||
);
|
);
|
||||||
|
|
||||||
Get.offAll(() => HomeCaptain());
|
Get.offAll(() => HomeCaptain());
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import '../functions/encrypt_decrypt.dart';
|
|||||||
import '../functions/face_detect.dart';
|
import '../functions/face_detect.dart';
|
||||||
import 'access_token.dart';
|
import 'access_token.dart';
|
||||||
import 'local_notification.dart';
|
import 'local_notification.dart';
|
||||||
|
import 'notification_service.dart';
|
||||||
|
|
||||||
class FirebaseMessagesController extends GetxController {
|
class FirebaseMessagesController extends GetxController {
|
||||||
final fcmToken = FirebaseMessaging.instance;
|
final fcmToken = FirebaseMessaging.instance;
|
||||||
@@ -154,12 +155,20 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
'VIP Order'.tr, '', 'order', '');
|
'VIP Order'.tr, '', 'order', '');
|
||||||
}
|
}
|
||||||
MyDialog().getDialog('VIP Order'.tr, 'midTitle', () {
|
MyDialog().getDialog('VIP Order'.tr, 'midTitle', () {
|
||||||
sendNotificationToPassengerToken(
|
// sendNotificationToPassengerToken(
|
||||||
'VIP Order Accepted'.tr,
|
// 'VIP Order Accepted'.tr,
|
||||||
'The driver accepted your trip'.tr,
|
// 'The driver accepted your trip'.tr,
|
||||||
driverList[0],
|
// driverList[0],
|
||||||
[driverList[1]],
|
// [driverList[1]],
|
||||||
'order');
|
// 'order');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: driverList[0].toString(),
|
||||||
|
title: 'VIP Order Accepted'.tr,
|
||||||
|
body: 'The driver accepted your trip'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'order',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get.to(const VipOrderPage());
|
// Get.to(const VipOrderPage());
|
||||||
@@ -387,360 +396,360 @@ class FirebaseMessagesController extends GetxController {
|
|||||||
// }));
|
// }));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
late String serviceAccountKeyJson;
|
// late String serviceAccountKeyJson;
|
||||||
@override
|
// @override
|
||||||
Future<void> onInit() async {
|
// Future<void> onInit() async {
|
||||||
super.onInit();
|
// super.onInit();
|
||||||
try {
|
// try {
|
||||||
// getToken();
|
// // getToken();
|
||||||
var encryptedKey = Env.privateKeyFCM;
|
// var encryptedKey = Env.privateKeyFCM;
|
||||||
// Log.print('encryptedKey: ${encryptedKey}');
|
// // Log.print('encryptedKey: ${encryptedKey}');
|
||||||
serviceAccountKeyJson =
|
// serviceAccountKeyJson =
|
||||||
EncryptionHelper.instance.decryptData(encryptedKey);
|
// EncryptionHelper.instance.decryptData(encryptedKey);
|
||||||
// Log.print('serviceAccountKeyJson: ${serviceAccountKeyJson}');
|
// // Log.print('serviceAccountKeyJson: ${serviceAccountKeyJson}');
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
print('🔴 Error decrypting FCM key: $e');
|
// print('🔴 Error decrypting FCM key: $e');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void sendNotificationAll(String title, body, tone) async {
|
// void sendNotificationAll(String title, body, tone) async {
|
||||||
// توكني الحالي (لا أرسل لنفسي)
|
// // توكني الحالي (لا أرسل لنفسي)
|
||||||
final String myToken = box.read(BoxName.tokenFCM) ?? '';
|
// final String myToken = box.read(BoxName.tokenFCM) ?? '';
|
||||||
// اقرأ قائمة كل التوكنات
|
// // اقرأ قائمة كل التوكنات
|
||||||
final List<String> all =
|
// final List<String> all =
|
||||||
List<String>.from(box.read(BoxName.tokens) ?? const []);
|
// List<String>.from(box.read(BoxName.tokens) ?? const []);
|
||||||
|
|
||||||
// استبعد توكنك واحذف الفارغ
|
// // استبعد توكنك واحذف الفارغ
|
||||||
final targets = all.where((t) => t.isNotEmpty && t != myToken).toList();
|
// final targets = all.where((t) => t.isNotEmpty && t != myToken).toList();
|
||||||
|
|
||||||
if (serviceAccountKeyJson.isEmpty) {
|
// if (serviceAccountKeyJson.isEmpty) {
|
||||||
print("🔴 Error: Service Account Key is empty");
|
// print("🔴 Error: Service Account Key is empty");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
// final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
||||||
final accessToken = await accessTokenManager.getAccessToken();
|
// final accessToken = await accessTokenManager.getAccessToken();
|
||||||
|
|
||||||
for (final t in targets) {
|
// for (final t in targets) {
|
||||||
// ⚠️ المهم: استخدم t (توكن الهدف)، وليس المتغير myToken
|
// // ⚠️ المهم: استخدم t (توكن الهدف)، وليس المتغير myToken
|
||||||
final response = await http.post(
|
// final response = await http.post(
|
||||||
Uri.parse(
|
// Uri.parse(
|
||||||
'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
|
// 'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
|
||||||
headers: {
|
// headers: {
|
||||||
'Content-Type': 'application/json',
|
// 'Content-Type': 'application/json',
|
||||||
'Authorization': 'Bearer $accessToken',
|
// 'Authorization': 'Bearer $accessToken',
|
||||||
},
|
// },
|
||||||
body: jsonEncode({
|
// body: jsonEncode({
|
||||||
'message': {
|
// 'message': {
|
||||||
'token': t,
|
// 'token': t,
|
||||||
'notification': {'title': title, 'body': body},
|
// 'notification': {'title': title, 'body': body},
|
||||||
'android': {
|
// 'android': {
|
||||||
'priority': 'HIGH', // القيم الصحيحة: HIGH/NORMAL
|
// 'priority': 'HIGH', // القيم الصحيحة: HIGH/NORMAL
|
||||||
'notification': {'sound': tone},
|
// 'notification': {'sound': tone},
|
||||||
// (اختياري) TTL لتجنّب رسائل قديمة
|
// // (اختياري) TTL لتجنّب رسائل قديمة
|
||||||
'ttl': '30s',
|
// 'ttl': '30s',
|
||||||
},
|
// },
|
||||||
'apns': {
|
// 'apns': {
|
||||||
'headers': {
|
// 'headers': {
|
||||||
'apns-priority': '10',
|
// 'apns-priority': '10',
|
||||||
// لو iOS: حدد نوع الدفع
|
// // لو iOS: حدد نوع الدفع
|
||||||
'apns-push-type': 'alert',
|
// 'apns-push-type': 'alert',
|
||||||
},
|
// },
|
||||||
'payload': {
|
// 'payload': {
|
||||||
'aps': {'sound': tone}
|
// 'aps': {'sound': tone}
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (response.statusCode != 200) {
|
// if (response.statusCode != 200) {
|
||||||
// حاول تقرأ الخطأ وتشيل التوكنات التالفة
|
// // حاول تقرأ الخطأ وتشيل التوكنات التالفة
|
||||||
_handleV1Error(response, badToken: t);
|
// _handleV1Error(response, badToken: t);
|
||||||
await Future.delayed(const Duration(milliseconds: 50)); // تخفيف ضغط
|
// await Future.delayed(const Duration(milliseconds: 50)); // تخفيف ضغط
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void _handleV1Error(http.Response res, {required String badToken}) {
|
// void _handleV1Error(http.Response res, {required String badToken}) {
|
||||||
try {
|
// try {
|
||||||
final body = jsonDecode(res.body);
|
// final body = jsonDecode(res.body);
|
||||||
final err = body['error']?['status']?.toString() ?? '';
|
// final err = body['error']?['status']?.toString() ?? '';
|
||||||
// أمثلة شائعة:
|
// // أمثلة شائعة:
|
||||||
if (err.contains('UNREGISTERED') || err.contains('NOT_FOUND')) {
|
// if (err.contains('UNREGISTERED') || err.contains('NOT_FOUND')) {
|
||||||
removeInvalidToken(badToken);
|
// removeInvalidToken(badToken);
|
||||||
} else if (err.contains('INVALID_ARGUMENT')) {
|
// } else if (err.contains('INVALID_ARGUMENT')) {
|
||||||
// payload غير صحيح
|
// // payload غير صحيح
|
||||||
print(
|
// print(
|
||||||
'⚠️ INVALID_ARGUMENT for $badToken: ${body['error']?['message']}');
|
// '⚠️ INVALID_ARGUMENT for $badToken: ${body['error']?['message']}');
|
||||||
} else if (err.contains('RESOURCE_EXHAUSTED') ||
|
// } else if (err.contains('RESOURCE_EXHAUSTED') ||
|
||||||
err.contains('QUOTA_EXCEEDED')) {
|
// err.contains('QUOTA_EXCEEDED')) {
|
||||||
// تجاوزت الحصة—خفّف السرعة/قسّم الإرسال (FCM v1 له حصة/دقيقة)
|
// // تجاوزت الحصة—خفّف السرعة/قسّم الإرسال (FCM v1 له حصة/دقيقة)
|
||||||
// https docs: 600k req/min per project (token bucket)
|
// // https docs: 600k req/min per project (token bucket)
|
||||||
print('⏳ Throttled by FCM: slow down sending rate.');
|
// print('⏳ Throttled by FCM: slow down sending rate.');
|
||||||
} else {
|
// } else {
|
||||||
print('FCM v1 error: ${res.statusCode} ${res.body}');
|
// print('FCM v1 error: ${res.statusCode} ${res.body}');
|
||||||
}
|
// }
|
||||||
} catch (_) {
|
// } catch (_) {
|
||||||
print('FCM v1 error: ${res.statusCode} ${res.body}');
|
// print('FCM v1 error: ${res.statusCode} ${res.body}');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void sendNotificationToPassengerToken(
|
// void sendNotificationToPassengerToken(
|
||||||
String title, body, token, List<String> map, String tone,
|
// String title, body, token, List<String> map, String tone,
|
||||||
{int retryCount = 2}) async {
|
// {int retryCount = 2}) async {
|
||||||
try {
|
// try {
|
||||||
if (serviceAccountKeyJson.isEmpty) {
|
// if (serviceAccountKeyJson.isEmpty) {
|
||||||
print("🔴 Error: Service Account Key is empty");
|
// print("🔴 Error: Service Account Key is empty");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
// Initialize AccessTokenManager
|
// // Initialize AccessTokenManager
|
||||||
final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
// final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
||||||
|
|
||||||
// Obtain an OAuth 2.0 access token
|
// // Obtain an OAuth 2.0 access token
|
||||||
final accessToken = await accessTokenManager.getAccessToken();
|
// final accessToken = await accessTokenManager.getAccessToken();
|
||||||
// Log.print('accessToken: ${accessToken}');
|
// // Log.print('accessToken: ${accessToken}');
|
||||||
|
|
||||||
// Send the notification
|
// // Send the notification
|
||||||
final response = await http.post(
|
// final response = await http.post(
|
||||||
Uri.parse(
|
// Uri.parse(
|
||||||
'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
|
// 'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
|
||||||
headers: <String, String>{
|
// headers: <String, String>{
|
||||||
'Content-Type': 'application/json',
|
// 'Content-Type': 'application/json',
|
||||||
'Authorization': 'Bearer $accessToken',
|
// 'Authorization': 'Bearer $accessToken',
|
||||||
},
|
// },
|
||||||
body: jsonEncode({
|
// body: jsonEncode({
|
||||||
'message': {
|
// 'message': {
|
||||||
'token': token,
|
// 'token': token,
|
||||||
'notification': {
|
// 'notification': {
|
||||||
'title': title,
|
// 'title': title,
|
||||||
'body': body,
|
// 'body': body,
|
||||||
},
|
// },
|
||||||
'data': {
|
// 'data': {
|
||||||
'passengerList': jsonEncode(map),
|
// 'passengerList': jsonEncode(map),
|
||||||
},
|
// },
|
||||||
'android': {
|
// 'android': {
|
||||||
'priority': 'HIGH ', // Set priority to high
|
// 'priority': 'HIGH ', // Set priority to high
|
||||||
'notification': {
|
// 'notification': {
|
||||||
'sound': tone,
|
// 'sound': tone,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
'apns': {
|
// 'apns': {
|
||||||
'headers': {
|
// 'headers': {
|
||||||
'apns-priority': '10', // Set APNs priority to 10
|
// 'apns-priority': '10', // Set APNs priority to 10
|
||||||
},
|
// },
|
||||||
'payload': {
|
// 'payload': {
|
||||||
'aps': {
|
// 'aps': {
|
||||||
'sound': tone,
|
// 'sound': tone,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
// if (response.statusCode == 200) {
|
||||||
print(
|
// print(
|
||||||
'Notification sent successfully. Status code: ${response.statusCode}');
|
// 'Notification sent successfully. Status code: ${response.statusCode}');
|
||||||
print('Response body: ${response.body}');
|
// print('Response body: ${response.body}');
|
||||||
} else {
|
// } else {
|
||||||
print(
|
// print(
|
||||||
'Failed to send notification. Status code: ${response.statusCode}');
|
// 'Failed to send notification. Status code: ${response.statusCode}');
|
||||||
|
|
||||||
print('Response body: ${response.body}');
|
// print('Response body: ${response.body}');
|
||||||
if (retryCount > 0) {
|
// if (retryCount > 0) {
|
||||||
print('Retrying... Attempts remaining: $retryCount');
|
// print('Retrying... Attempts remaining: $retryCount');
|
||||||
await Future.delayed(
|
// await Future.delayed(
|
||||||
const Duration(seconds: 2)); // Optional delay before retrying
|
// const Duration(seconds: 2)); // Optional delay before retrying
|
||||||
return sendNotificationToPassengerToken(title, body, token, map, tone,
|
// return sendNotificationToPassengerToken(title, body, token, map, tone,
|
||||||
retryCount: retryCount - 1);
|
// retryCount: retryCount - 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
print('Error sending notification: $e');
|
// print('Error sending notification: $e');
|
||||||
if (retryCount > 0) {
|
// if (retryCount > 0) {
|
||||||
print('Retrying... Attempts remaining: $retryCount');
|
// print('Retrying... Attempts remaining: $retryCount');
|
||||||
await Future.delayed(
|
// await Future.delayed(
|
||||||
const Duration(seconds: 2)); // Optional delay before retrying
|
// const Duration(seconds: 2)); // Optional delay before retrying
|
||||||
return sendNotificationToPassengerToken(title, body, token, map, tone,
|
// return sendNotificationToPassengerToken(title, body, token, map, tone,
|
||||||
retryCount: retryCount - 1);
|
// retryCount: retryCount - 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
void sendNotificationToPassengerTokenCALL(
|
// void sendNotificationToPassengerTokenCALL(
|
||||||
String title, body, token, List<String> map, String tone,
|
// String title, body, token, List<String> map, String tone,
|
||||||
{int retryCount = 2}) async {
|
// {int retryCount = 2}) async {
|
||||||
try {
|
// try {
|
||||||
if (serviceAccountKeyJson.isEmpty) {
|
// if (serviceAccountKeyJson.isEmpty) {
|
||||||
print("🔴 Error: Service Account Key is empty");
|
// print("🔴 Error: Service Account Key is empty");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
// Initialize AccessTokenManager
|
// // Initialize AccessTokenManager
|
||||||
final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
// final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
||||||
|
|
||||||
// Obtain an OAuth 2.0 access token
|
// // Obtain an OAuth 2.0 access token
|
||||||
final accessToken = await accessTokenManager.getAccessToken();
|
// final accessToken = await accessTokenManager.getAccessToken();
|
||||||
// Log.print('accessToken: ${accessToken}');
|
// // Log.print('accessToken: ${accessToken}');
|
||||||
|
|
||||||
// Send the notification
|
// // Send the notification
|
||||||
final response = await http.post(
|
// final response = await http.post(
|
||||||
Uri.parse(
|
// Uri.parse(
|
||||||
'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
|
// 'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
|
||||||
headers: <String, String>{
|
// headers: <String, String>{
|
||||||
'Content-Type': 'application/json',
|
// 'Content-Type': 'application/json',
|
||||||
'Authorization': 'Bearer $accessToken',
|
// 'Authorization': 'Bearer $accessToken',
|
||||||
},
|
// },
|
||||||
body: jsonEncode({
|
// body: jsonEncode({
|
||||||
'message': {
|
// 'message': {
|
||||||
'token': token,
|
// 'token': token,
|
||||||
'notification': {
|
// 'notification': {
|
||||||
'title': title,
|
// 'title': title,
|
||||||
'body': body,
|
// 'body': body,
|
||||||
},
|
// },
|
||||||
'data': {
|
// 'data': {
|
||||||
'passengerList': jsonEncode(map),
|
// 'passengerList': jsonEncode(map),
|
||||||
},
|
// },
|
||||||
'android': {
|
// 'android': {
|
||||||
'priority': 'HIGH ', // Set priority to high
|
// 'priority': 'HIGH ', // Set priority to high
|
||||||
'notification': {
|
// 'notification': {
|
||||||
'sound': tone,
|
// 'sound': tone,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
'apns': {
|
// 'apns': {
|
||||||
'headers': {
|
// 'headers': {
|
||||||
'apns-priority': '10', // Set APNs priority to 10
|
// 'apns-priority': '10', // Set APNs priority to 10
|
||||||
},
|
// },
|
||||||
'payload': {
|
// 'payload': {
|
||||||
'aps': {
|
// 'aps': {
|
||||||
'sound': tone,
|
// 'sound': tone,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
// if (response.statusCode == 200) {
|
||||||
print(
|
// print(
|
||||||
'Notification sent successfully. Status code: ${response.statusCode}');
|
// 'Notification sent successfully. Status code: ${response.statusCode}');
|
||||||
print('Response body: ${response.body}');
|
// print('Response body: ${response.body}');
|
||||||
} else {
|
// } else {
|
||||||
print(
|
// print(
|
||||||
'Failed to send notification. Status code: ${response.statusCode}');
|
// 'Failed to send notification. Status code: ${response.statusCode}');
|
||||||
|
|
||||||
print('Response body: ${response.body}');
|
// print('Response body: ${response.body}');
|
||||||
if (retryCount > 0) {
|
// if (retryCount > 0) {
|
||||||
print('Retrying... Attempts remaining: $retryCount');
|
// print('Retrying... Attempts remaining: $retryCount');
|
||||||
await Future.delayed(
|
// await Future.delayed(
|
||||||
const Duration(seconds: 2)); // Optional delay before retrying
|
// const Duration(seconds: 2)); // Optional delay before retrying
|
||||||
return sendNotificationToPassengerTokenCALL(
|
// return sendNotificationToPassengerTokenCALL(
|
||||||
title, body, token, map, tone,
|
// title, body, token, map, tone,
|
||||||
retryCount: retryCount - 1);
|
// retryCount: retryCount - 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
print('Error sending notification: $e');
|
// print('Error sending notification: $e');
|
||||||
if (retryCount > 0) {
|
// if (retryCount > 0) {
|
||||||
print('Retrying... Attempts remaining: $retryCount');
|
// print('Retrying... Attempts remaining: $retryCount');
|
||||||
await Future.delayed(
|
// await Future.delayed(
|
||||||
const Duration(seconds: 2)); // Optional delay before retrying
|
// const Duration(seconds: 2)); // Optional delay before retrying
|
||||||
return sendNotificationToPassengerTokenCALL(
|
// return sendNotificationToPassengerTokenCALL(
|
||||||
title, body, token, map, tone,
|
// title, body, token, map, tone,
|
||||||
retryCount: retryCount - 1);
|
// retryCount: retryCount - 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
Future<void> sendNotificationToDriverMAP(
|
// Future<void> sendNotificationToDriverMAP(
|
||||||
String title, String body, String token, List<String> data, String tone,
|
// String title, String body, String token, List<String> data, String tone,
|
||||||
{int retryCount = 2}) async {
|
// {int retryCount = 2}) async {
|
||||||
try {
|
// try {
|
||||||
if (serviceAccountKeyJson.isEmpty) {
|
// if (serviceAccountKeyJson.isEmpty) {
|
||||||
print("🔴 Error: Service Account Key is empty");
|
// print("🔴 Error: Service Account Key is empty");
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Initialize AccessTokenManager
|
// // Initialize AccessTokenManager
|
||||||
final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
// final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
|
||||||
Log.print(
|
// Log.print(
|
||||||
'accessTokenManager: ${accessTokenManager.serviceAccountJsonKey}');
|
// 'accessTokenManager: ${accessTokenManager.serviceAccountJsonKey}');
|
||||||
|
|
||||||
// Obtain an OAuth 2.0 access token
|
// // Obtain an OAuth 2.0 access token
|
||||||
final accessToken = await accessTokenManager.getAccessToken();
|
// final accessToken = await accessTokenManager.getAccessToken();
|
||||||
// Log.print('accessToken: ${accessToken}');
|
// // Log.print('accessToken: ${accessToken}');
|
||||||
|
|
||||||
// Send the notification
|
// // Send the notification
|
||||||
final response = await http.post(
|
// final response = await http.post(
|
||||||
Uri.parse(
|
// Uri.parse(
|
||||||
'https://fcm.googleapis.com/v1/projects/intaleq-d48a7/messages:send'),
|
// 'https://fcm.googleapis.com/v1/projects/intaleq-d48a7/messages:send'),
|
||||||
headers: <String, String>{
|
// headers: <String, String>{
|
||||||
'Content-Type': 'application/json',
|
// 'Content-Type': 'application/json',
|
||||||
'Authorization': 'Bearer $accessToken',
|
// 'Authorization': 'Bearer $accessToken',
|
||||||
},
|
// },
|
||||||
body: jsonEncode({
|
// body: jsonEncode({
|
||||||
'message': {
|
// 'message': {
|
||||||
'token': token,
|
// 'token': token,
|
||||||
'notification': {
|
// 'notification': {
|
||||||
'title': title,
|
// 'title': title,
|
||||||
'body': body,
|
// 'body': body,
|
||||||
},
|
// },
|
||||||
'data': {
|
// 'data': {
|
||||||
'DriverList': jsonEncode(data),
|
// 'DriverList': jsonEncode(data),
|
||||||
},
|
// },
|
||||||
'android': {
|
// 'android': {
|
||||||
'priority': 'HIGH ', // Set priority to high
|
// 'priority': 'HIGH ', // Set priority to high
|
||||||
'notification': {
|
// 'notification': {
|
||||||
'sound': tone,
|
// 'sound': tone,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
'apns': {
|
// 'apns': {
|
||||||
'headers': {
|
// 'headers': {
|
||||||
'apns-priority': '10', // Set APNs priority to 10
|
// 'apns-priority': '10', // Set APNs priority to 10
|
||||||
},
|
// },
|
||||||
'payload': {
|
// 'payload': {
|
||||||
'aps': {
|
// 'aps': {
|
||||||
'sound': tone,
|
// 'sound': tone,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
// if (response.statusCode == 200) {
|
||||||
print(
|
// print(
|
||||||
'Notification sent successfully. Status code: ${response.statusCode}');
|
// 'Notification sent successfully. Status code: ${response.statusCode}');
|
||||||
// print('Response token: ${token}');
|
// // print('Response token: ${token}');
|
||||||
} else {
|
// } else {
|
||||||
print(
|
// print(
|
||||||
'Failed to send notification. Status code: ${response.statusCode}');
|
// 'Failed to send notification. Status code: ${response.statusCode}');
|
||||||
print('Response body: ${response.body}');
|
// print('Response body: ${response.body}');
|
||||||
if (retryCount > 0) {
|
// if (retryCount > 0) {
|
||||||
print('Retrying... Attempts remaining: $retryCount');
|
// print('Retrying... Attempts remaining: $retryCount');
|
||||||
await Future.delayed(
|
// await Future.delayed(
|
||||||
Duration(seconds: 2)); // Optional delay before retrying
|
// Duration(seconds: 2)); // Optional delay before retrying
|
||||||
return sendNotificationToDriverMAP(title, body, token, data, tone,
|
// return sendNotificationToDriverMAP(title, body, token, data, tone,
|
||||||
retryCount: retryCount - 1);
|
// retryCount: retryCount - 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} catch (e) {
|
// } catch (e) {
|
||||||
print('Error sending notification: $e');
|
// print('Error sending notification: $e');
|
||||||
if (retryCount > 0) {
|
// if (retryCount > 0) {
|
||||||
print('Retrying... Attempts remaining: $retryCount');
|
// print('Retrying... Attempts remaining: $retryCount');
|
||||||
await Future.delayed(
|
// await Future.delayed(
|
||||||
Duration(seconds: 2)); // Optional delay before retrying
|
// Duration(seconds: 2)); // Optional delay before retrying
|
||||||
return sendNotificationToDriverMAP(title, body, token, data, tone,
|
// return sendNotificationToDriverMAP(title, body, token, data, tone,
|
||||||
retryCount: retryCount - 1);
|
// retryCount: retryCount - 1);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
Future<void> removeInvalidToken(String token) async {
|
// Future<void> removeInvalidToken(String token) async {
|
||||||
// Remove token from your database/storage
|
// // Remove token from your database/storage
|
||||||
// This prevents future attempts to send to invalid tokens
|
// // This prevents future attempts to send to invalid tokens
|
||||||
print('Removing invalid token from database: $token');
|
// print('Removing invalid token from database: $token');
|
||||||
// Your database cleanup logic here
|
// // Your database cleanup logic here
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverlayContent extends StatelessWidget {
|
class OverlayContent extends StatelessWidget {
|
||||||
|
|||||||
@@ -6,66 +6,50 @@ class NotificationService {
|
|||||||
static const String _serverUrl =
|
static const String _serverUrl =
|
||||||
'https://syria.intaleq.xyz/intaleq/fcm/send_fcm.php';
|
'https://syria.intaleq.xyz/intaleq/fcm/send_fcm.php';
|
||||||
|
|
||||||
/// Sends a notification via your backend server.
|
|
||||||
///
|
|
||||||
/// [target]: The device token or the topic name.
|
|
||||||
/// [title]: The notification title.
|
|
||||||
/// [body]: The notification body.
|
|
||||||
/// [isTopic]: Set to true if the target is a topic, false if it's a device token.
|
|
||||||
static Future<void> sendNotification({
|
static Future<void> sendNotification({
|
||||||
required String target,
|
required String target,
|
||||||
required String title,
|
required String title,
|
||||||
required String body,
|
required String body,
|
||||||
|
String? tone,
|
||||||
|
List<String>? driverList, // <-- [تعديل 1] : إضافة المتغير الجديد
|
||||||
bool isTopic = false,
|
bool isTopic = false,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
|
final Map<String, dynamic> payload = {
|
||||||
|
'target': target,
|
||||||
|
'title': title,
|
||||||
|
'body': body,
|
||||||
|
'isTopic': isTopic,
|
||||||
|
};
|
||||||
|
|
||||||
|
// نضيف النغمة فقط إذا لم تكن فارغة
|
||||||
|
if (tone != null) {
|
||||||
|
payload['tone'] = tone;
|
||||||
|
}
|
||||||
|
|
||||||
|
// <-- [تعديل 2] : نضيف قائمة البيانات بعد تشفيرها إلى JSON
|
||||||
|
if (driverList != null) {
|
||||||
|
payload['driverList'] = jsonEncode(driverList);
|
||||||
|
}
|
||||||
|
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse(_serverUrl),
|
Uri.parse(_serverUrl),
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json; charset=UTF-8',
|
'Content-Type': 'application/json; charset=UTF-8',
|
||||||
},
|
},
|
||||||
body: jsonEncode({
|
body: jsonEncode(payload),
|
||||||
'target': target,
|
|
||||||
'title': title,
|
|
||||||
'body': body,
|
|
||||||
'isTopic': isTopic,
|
|
||||||
}),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
print('Notification sent successfully.');
|
print('✅ Notification sent successfully.');
|
||||||
print('Server Response: ${response.body}');
|
print('Server Response: ${response.body}');
|
||||||
} else {
|
} else {
|
||||||
print(
|
print(
|
||||||
'Failed to send notification. Status code: ${response.statusCode}');
|
'❌ Failed to send notification. Status code: ${response.statusCode}');
|
||||||
print('Server Error: ${response.body}');
|
print('Server Error: ${response.body}');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('An error occurred while sending notification: $e');
|
print('❌ An error occurred while sending notification: $e');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Example of how to use it ---
|
|
||||||
|
|
||||||
// To send to a specific driver (using their token)
|
|
||||||
void sendToSpecificDriver() {
|
|
||||||
String driverToken =
|
|
||||||
'bk3RNwTe3H0:CI2k_HHwgIpoDKCI5oT...'; // The driver's FCM token
|
|
||||||
NotificationService.sendNotification(
|
|
||||||
target: driverToken,
|
|
||||||
title: 'New Trip Request!',
|
|
||||||
body: 'A passenger is waiting for you.',
|
|
||||||
isTopic: false, // Important: this is a token
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// To send to all drivers (using a topic)
|
|
||||||
void sendToAllDrivers() {
|
|
||||||
NotificationService.sendNotification(
|
|
||||||
target: 'drivers', // The name of the topic
|
|
||||||
title: 'Important Announcement',
|
|
||||||
body: 'Please update your app to the latest version.',
|
|
||||||
isTopic: true, // Important: this is a topic
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import '../../constant/api_key.dart';
|
|||||||
import '../../constant/char_map.dart';
|
import '../../constant/char_map.dart';
|
||||||
import '../../constant/colors.dart';
|
import '../../constant/colors.dart';
|
||||||
import '../../print.dart';
|
import '../../print.dart';
|
||||||
|
import '../firebase/notification_service.dart';
|
||||||
import 'encrypt_decrypt.dart';
|
import 'encrypt_decrypt.dart';
|
||||||
import 'tts.dart';
|
import 'tts.dart';
|
||||||
import 'upload_image.dart';
|
import 'upload_image.dart';
|
||||||
@@ -105,12 +106,20 @@ class AI extends GetxController {
|
|||||||
NotificationController().showNotification(
|
NotificationController().showNotification(
|
||||||
"Code approved".tr, "Code approved".tr, 'tone2', '');
|
"Code approved".tr, "Code approved".tr, 'tone2', '');
|
||||||
// Notification text with dynamic token
|
// Notification text with dynamic token
|
||||||
Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
|
// Get.put(FirebaseMessagesController()).sendNotificationToDriverMAP(
|
||||||
'You have received a gift token!'.tr,
|
// 'You have received a gift token!'.tr,
|
||||||
'for '.tr + box.read(BoxName.phoneDriver).toString(),
|
// 'for '.tr + box.read(BoxName.phoneDriver).toString(),
|
||||||
jsonDecode(res)['message'][0]['token'].toString(),
|
// jsonDecode(res)['message'][0]['token'].toString(),
|
||||||
[],
|
// [],
|
||||||
'tone2', // Type of notification
|
// 'tone2', // Type of notification
|
||||||
|
// );
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: jsonDecode(res)['message'][0]['token'].toString(),
|
||||||
|
title: 'You have received a gift token!'.tr,
|
||||||
|
body: 'for '.tr + box.read(BoxName.phoneDriver).toString(),
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'tone2',
|
||||||
|
driverList: [],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// mySnackeBarError(
|
// mySnackeBarError(
|
||||||
|
|||||||
@@ -91,14 +91,16 @@ class DriverBehaviorController extends GetxController {
|
|||||||
final summary = await analyzeData();
|
final summary = await analyzeData();
|
||||||
if (summary.isEmpty) return;
|
if (summary.isEmpty) return;
|
||||||
|
|
||||||
final body = {
|
final Map<String, dynamic> body = {
|
||||||
'driver_id': driverId,
|
'driver_id': driverId,
|
||||||
'trip_id': tripId,
|
'trip_id': tripId,
|
||||||
...summary,
|
...summary, // فيه doubles
|
||||||
};
|
};
|
||||||
|
|
||||||
CRUD().post(link: AppLink.saveBehavior, payload: (body));
|
// اجبر كل القيم على String
|
||||||
|
final payload = body.map((k, v) => MapEntry(k, v?.toString() ?? ''));
|
||||||
|
|
||||||
|
await CRUD().post(link: AppLink.saveBehavior, payload: payload);
|
||||||
await clearData();
|
await clearData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import '../../../print.dart';
|
|||||||
import '../../../views/Rate/rate_passenger.dart';
|
import '../../../views/Rate/rate_passenger.dart';
|
||||||
import '../../../views/home/Captin/home_captain/home_captin.dart';
|
import '../../../views/home/Captin/home_captain/home_captin.dart';
|
||||||
import '../../firebase/firbase_messge.dart';
|
import '../../firebase/firbase_messge.dart';
|
||||||
|
import '../../firebase/notification_service.dart';
|
||||||
import '../../functions/crud.dart';
|
import '../../functions/crud.dart';
|
||||||
import '../../functions/encrypt_decrypt.dart';
|
import '../../functions/encrypt_decrypt.dart';
|
||||||
import '../../functions/location_controller.dart';
|
import '../../functions/location_controller.dart';
|
||||||
@@ -195,13 +196,23 @@ class MapDriverController extends GetxController {
|
|||||||
cancelTripFromDriverAfterApplied() async {
|
cancelTripFromDriverAfterApplied() async {
|
||||||
if (formKeyCancel.currentState!.validate()) {
|
if (formKeyCancel.currentState!.validate()) {
|
||||||
box.write(BoxName.statusDriverLocation, 'off');
|
box.write(BoxName.statusDriverLocation, 'off');
|
||||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
// Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||||
"Cancel Trip from driver",
|
// "Cancel Trip from driver",
|
||||||
"Trip Cancelled from driver. We are looking for a new driver. Please wait."
|
// "Trip Cancelled from driver. We are looking for a new driver. Please wait."
|
||||||
.tr,
|
// .tr,
|
||||||
tokenPassenger,
|
// tokenPassenger,
|
||||||
[],
|
// [],
|
||||||
'cancel.wav',
|
// 'cancel.wav',
|
||||||
|
// );
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: tokenPassenger.toString(),
|
||||||
|
title: "Cancel Trip from driver".tr,
|
||||||
|
body:
|
||||||
|
"Trip Cancelled from driver. We are looking for a new driver. Please wait."
|
||||||
|
.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'cancel',
|
||||||
|
driverList: [],
|
||||||
);
|
);
|
||||||
await CRUD().post(
|
await CRUD().post(
|
||||||
link: "${AppLink.seferCairoServer}/ride/rides/update.php",
|
link: "${AppLink.seferCairoServer}/ride/rides/update.php",
|
||||||
@@ -334,12 +345,20 @@ class MapDriverController extends GetxController {
|
|||||||
|
|
||||||
// Get.find<HomeCaptainController>().changeToAppliedRide('Applied');
|
// Get.find<HomeCaptainController>().changeToAppliedRide('Applied');
|
||||||
|
|
||||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
// Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||||
'Driver Is Going To Passenger',
|
// 'Driver Is Going To Passenger',
|
||||||
box.read(BoxName.nameDriver).toString(), //todo name driver
|
// box.read(BoxName.nameDriver).toString(), //todo name driver
|
||||||
tokenPassenger,
|
// tokenPassenger,
|
||||||
[],
|
// [],
|
||||||
'start.wav');
|
// 'start.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: tokenPassenger.toString(),
|
||||||
|
title: 'Driver Is Going To Passenger'.tr,
|
||||||
|
body: box.read(BoxName.nameDriver).toString(),
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'start',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSocialPressed = false;
|
bool isSocialPressed = false;
|
||||||
@@ -427,15 +446,15 @@ class MapDriverController extends GetxController {
|
|||||||
'order_id': (rideId).toString(),
|
'order_id': (rideId).toString(),
|
||||||
'status': 'Begin'
|
'status': 'Begin'
|
||||||
});
|
});
|
||||||
final fcm = Get.isRegistered<FirebaseMessagesController>()
|
|
||||||
? Get.find<FirebaseMessagesController>()
|
NotificationService.sendNotification(
|
||||||
: Get.put(FirebaseMessagesController());
|
target: tokenPassenger.toString(),
|
||||||
fcm.sendNotificationToDriverMAP(
|
title: 'Trip is Begin',
|
||||||
'Trip is Begin',
|
body: box.read(BoxName.nameDriver).toString(),
|
||||||
box.read(BoxName.nameDriver).toString(),
|
isTopic: false, // Important: this is a token
|
||||||
tokenPassenger,
|
tone: 'start',
|
||||||
[],
|
driverList: [],
|
||||||
'start.wav');
|
);
|
||||||
rideIsBeginPassengerTimer();
|
rideIsBeginPassengerTimer();
|
||||||
|
|
||||||
update();
|
update();
|
||||||
@@ -752,17 +771,30 @@ class MapDriverController extends GetxController {
|
|||||||
Get.put(DriverBehaviorController())
|
Get.put(DriverBehaviorController())
|
||||||
.sendSummaryToServer(driverId, rideId);
|
.sendSummaryToServer(driverId, rideId);
|
||||||
|
|
||||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
// Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||||
"Driver Finish Trip",
|
// "Driver Finish Trip",
|
||||||
'${'you will pay to Driver'.tr} $paymentAmount \$',
|
// '${'you will pay to Driver'.tr} $paymentAmount \$',
|
||||||
tokenPassenger,
|
// tokenPassenger,
|
||||||
[
|
// [
|
||||||
box.read(BoxName.driverID),
|
// box.read(BoxName.driverID),
|
||||||
rideId,
|
// rideId,
|
||||||
box.read(BoxName.tokenDriver),
|
// box.read(BoxName.tokenDriver),
|
||||||
paymentAmount.toString()
|
// paymentAmount.toString()
|
||||||
],
|
// ],
|
||||||
'ding.wav');
|
// 'ding.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: tokenPassenger.toString(),
|
||||||
|
title: "Driver Finish Trip",
|
||||||
|
body: '${'you will pay to Driver'.tr} $paymentAmount \$'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'ding',
|
||||||
|
driverList: [
|
||||||
|
box.read(BoxName.driverID),
|
||||||
|
rideId,
|
||||||
|
box.read(BoxName.tokenDriver),
|
||||||
|
paymentAmount.toString()
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
Get.to(() => RatePassenger(), arguments: {
|
Get.to(() => RatePassenger(), arguments: {
|
||||||
'passengerId': passengerId,
|
'passengerId': passengerId,
|
||||||
@@ -1617,17 +1649,30 @@ class MapDriverController extends GetxController {
|
|||||||
|
|
||||||
if (distance < 300) {
|
if (distance < 300) {
|
||||||
// 300 متر قبل الوجهة
|
// 300 متر قبل الوجهة
|
||||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
// Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||||
"You are near the destination",
|
// "You are near the destination",
|
||||||
"You are near the destination".tr,
|
// "You are near the destination".tr,
|
||||||
tokenPassenger,
|
// tokenPassenger,
|
||||||
[
|
// [
|
||||||
|
// box.read(BoxName.driverID),
|
||||||
|
// rideId,
|
||||||
|
// box.read(BoxName.tokenDriver),
|
||||||
|
// paymentAmount.toString()
|
||||||
|
// ],
|
||||||
|
// 'ding.wav',
|
||||||
|
// );
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: tokenPassenger.toString(),
|
||||||
|
title: "You are near the destination",
|
||||||
|
body: "You are near the destination".tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'ding',
|
||||||
|
driverList: [
|
||||||
box.read(BoxName.driverID),
|
box.read(BoxName.driverID),
|
||||||
rideId,
|
rideId,
|
||||||
box.read(BoxName.tokenDriver),
|
box.read(BoxName.tokenDriver),
|
||||||
paymentAmount.toString()
|
paymentAmount.toString()
|
||||||
],
|
],
|
||||||
'ding.wav',
|
|
||||||
);
|
);
|
||||||
// يمكن إضافة أي إجراء آخر هنا عند الاقتراب من الوجهة
|
// يمكن إضافة أي إجراء آخر هنا عند الاقتراب من الوجهة
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import 'package:sefer_driver/controller/functions/crud.dart';
|
|||||||
import 'package:sefer_driver/main.dart';
|
import 'package:sefer_driver/main.dart';
|
||||||
|
|
||||||
import '../../../views/widgets/mydialoug.dart';
|
import '../../../views/widgets/mydialoug.dart';
|
||||||
|
import '../../firebase/notification_service.dart';
|
||||||
|
|
||||||
class CaptainWalletController extends GetxController {
|
class CaptainWalletController extends GetxController {
|
||||||
bool isLoading = false;
|
bool isLoading = false;
|
||||||
@@ -291,13 +292,23 @@ class CaptainWalletController extends GetxController {
|
|||||||
'paymentMethod': paymentMethod2.toString(),
|
'paymentMethod': paymentMethod2.toString(),
|
||||||
});
|
});
|
||||||
if (res1 != 'failure') {
|
if (res1 != 'failure') {
|
||||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
// Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||||
'Transfer',
|
// 'Transfer',
|
||||||
'${'You have transfer to your wallet from'.tr}'
|
// '${'You have transfer to your wallet from'.tr}'
|
||||||
'${box.read(BoxName.nameDriver)}',
|
// '${box.read(BoxName.nameDriver)}',
|
||||||
amountToNewDriverMap[0]['token'].toString(),
|
// amountToNewDriverMap[0]['token'].toString(),
|
||||||
[],
|
// [],
|
||||||
'order1.wav');
|
// 'order1.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: amountToNewDriverMap[0]['token'].toString(),
|
||||||
|
title: 'Transfer'.tr,
|
||||||
|
body: '${'You have transfer to your wallet from'.tr}'
|
||||||
|
'${box.read(BoxName.nameDriver)}',
|
||||||
|
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'ding',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
await addSeferWallet('payout fee', '5');
|
await addSeferWallet('payout fee', '5');
|
||||||
|
|
||||||
Get.defaultDialog(
|
Get.defaultDialog(
|
||||||
|
|||||||
@@ -140,6 +140,9 @@ class MyTranslation extends Translations {
|
|||||||
"What is the feature of our wallet?": "ما هي مميزات محفظتنا؟",
|
"What is the feature of our wallet?": "ما هي مميزات محفظتنا؟",
|
||||||
"What is Types of Trips in Intaleq?":
|
"What is Types of Trips in Intaleq?":
|
||||||
"ما هي أنواع الرحلات في Intaleq؟",
|
"ما هي أنواع الرحلات في Intaleq؟",
|
||||||
|
"No rides available for your vehicle type.": "لا توجد رحلات متاحة .",
|
||||||
|
"Failed to fetch rides. Please try again.":
|
||||||
|
"فشل في جلب الرحلات. يرجى المحاولة مرة أخرى.",
|
||||||
'''Types of Trips in Intaleq:
|
'''Types of Trips in Intaleq:
|
||||||
|
|
||||||
Comfort: For cars newer than 2017 with air conditioning.
|
Comfort: For cars newer than 2017 with air conditioning.
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import '../../constant/links.dart';
|
|||||||
import '../../constant/style.dart';
|
import '../../constant/style.dart';
|
||||||
import '../../main.dart';
|
import '../../main.dart';
|
||||||
import '../../views/widgets/elevated_btn.dart';
|
import '../../views/widgets/elevated_btn.dart';
|
||||||
|
import '../firebase/notification_service.dart';
|
||||||
import '../functions/crud.dart';
|
import '../functions/crud.dart';
|
||||||
|
|
||||||
class PassengerNotificationController extends GetxController {
|
class PassengerNotificationController extends GetxController {
|
||||||
@@ -53,8 +54,16 @@ class PassengerNotificationController extends GetxController {
|
|||||||
'title': title,
|
'title': title,
|
||||||
'body': body,
|
'body': body,
|
||||||
});
|
});
|
||||||
FirebaseMessagesController()
|
// FirebaseMessagesController()
|
||||||
.sendNotificationToPassengerToken(title, body, 'token', [], 'ding.wav');
|
// .sendNotificationToPassengerToken(title, body, 'token', [], 'ding.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: 'token'.toString(),
|
||||||
|
title: title,
|
||||||
|
body: body,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'ding',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:sefer_driver/constant/box_name.dart';
|
import 'package:sefer_driver/constant/box_name.dart';
|
||||||
import 'package:sefer_driver/constant/colors.dart';
|
|
||||||
import 'package:sefer_driver/constant/links.dart';
|
import 'package:sefer_driver/constant/links.dart';
|
||||||
import 'package:sefer_driver/controller/functions/crud.dart';
|
import 'package:sefer_driver/controller/functions/crud.dart';
|
||||||
import 'package:sefer_driver/controller/functions/encrypt_decrypt.dart';
|
|
||||||
import 'package:sefer_driver/main.dart';
|
import 'package:sefer_driver/main.dart';
|
||||||
import 'package:sefer_driver/views/widgets/error_snakbar.dart';
|
import 'package:sefer_driver/views/widgets/error_snakbar.dart';
|
||||||
import 'package:sefer_driver/views/widgets/mydialoug.dart';
|
import 'package:sefer_driver/views/widgets/mydialoug.dart';
|
||||||
@@ -24,9 +22,10 @@ class RatingController extends GetxController {
|
|||||||
|
|
||||||
void _redirectToAppStore() async {
|
void _redirectToAppStore() async {
|
||||||
// URLs for App Store and Google Play Store
|
// URLs for App Store and Google Play Store
|
||||||
const appStoreUrl = 'https://apps.apple.com/app/6502189302';
|
const appStoreUrl =
|
||||||
|
'https://apps.apple.com/st/app/intaleq-driver/id6482995159';
|
||||||
const playStoreUrl =
|
const playStoreUrl =
|
||||||
'https://play.google.com/store/apps/details?id=com.sefer_driver';
|
'https://play.google.com/store/apps/details?id=com.intaleq_driver';
|
||||||
final url = GetPlatform.isIOS ? appStoreUrl : playStoreUrl;
|
final url = GetPlatform.isIOS ? appStoreUrl : playStoreUrl;
|
||||||
|
|
||||||
if (await launchUrl(Uri.parse(url))) {
|
if (await launchUrl(Uri.parse(url))) {
|
||||||
@@ -59,13 +58,14 @@ class RatingController extends GetxController {
|
|||||||
if (res != 'failure') {
|
if (res != 'failure') {
|
||||||
try {
|
try {
|
||||||
// Attempt to parse the response as JSON
|
// Attempt to parse the response as JSON
|
||||||
final parsedResponse = jsonDecode(res);
|
final parsedResponse = (res);
|
||||||
|
|
||||||
if (parsedResponse['status'] == 'success') {
|
if (parsedResponse['status'] == 'success') {
|
||||||
// Display a success message
|
// Display a success message
|
||||||
CRUD().post(link: AppLink.sendEmailRateingApp, payload: {
|
CRUD().post(link: AppLink.sendEmailRateingApp, payload: {
|
||||||
"name": payload["name"],
|
"name": payload["name"],
|
||||||
"email": payload["email"],
|
"email": payload["email"],
|
||||||
|
"phone": payload["phone"],
|
||||||
"rating": rating.toString(),
|
"rating": rating.toString(),
|
||||||
"comment": payload["comment"],
|
"comment": payload["comment"],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ import 'package:sefer_driver/main.dart';
|
|||||||
import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart';
|
import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart';
|
||||||
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
|
import 'package:sefer_driver/views/widgets/elevated_btn.dart';
|
||||||
|
|
||||||
|
import '../firebase/notification_service.dart';
|
||||||
|
|
||||||
// import '../home/captin/home_captain_controller.dart';
|
// import '../home/captin/home_captain_controller.dart';
|
||||||
|
|
||||||
class RateController extends GetxController {
|
class RateController extends GetxController {
|
||||||
@@ -67,12 +69,20 @@ class RateController extends GetxController {
|
|||||||
'driverID': box.read(BoxName.driverID).toString(),
|
'driverID': box.read(BoxName.driverID).toString(),
|
||||||
});
|
});
|
||||||
|
|
||||||
Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
// Get.find<FirebaseMessagesController>().sendNotificationToDriverMAP(
|
||||||
'Wallet Added'.tr,
|
// 'Wallet Added'.tr,
|
||||||
'Wallet Added${(remainingFee).toStringAsFixed(0)}'.tr,
|
// 'Wallet Added${(remainingFee).toStringAsFixed(0)}'.tr,
|
||||||
Get.find<MapDriverController>().tokenPassenger,
|
// Get.find<MapDriverController>().tokenPassenger,
|
||||||
[],
|
// [],
|
||||||
'tone2.wav');
|
// 'tone2.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: Get.find<MapDriverController>().tokenPassenger.toString(),
|
||||||
|
title: 'Wallet Added'.tr,
|
||||||
|
body: 'Wallet Added${(remainingFee).toStringAsFixed(0)}'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'tone2',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
walletChecked = 'true';
|
walletChecked = 'true';
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import 'package:sefer_driver/views/widgets/mydialoug.dart';
|
|||||||
import '../../../../../constant/colors.dart';
|
import '../../../../../constant/colors.dart';
|
||||||
import '../../../../../constant/links.dart';
|
import '../../../../../constant/links.dart';
|
||||||
import '../../../../../controller/firebase/firbase_messge.dart';
|
import '../../../../../controller/firebase/firbase_messge.dart';
|
||||||
|
import '../../../../../controller/firebase/notification_service.dart';
|
||||||
import '../../../../../controller/functions/crud.dart';
|
import '../../../../../controller/functions/crud.dart';
|
||||||
import '../../../../../controller/home/captin/order_request_controller.dart';
|
import '../../../../../controller/home/captin/order_request_controller.dart';
|
||||||
import '../../../../../controller/home/navigation/navigation_view.dart';
|
import '../../../../../controller/home/navigation/navigation_view.dart';
|
||||||
@@ -318,8 +319,16 @@ void _sendAcceptanceNotification(String? customerToken, rideId) {
|
|||||||
// Safely check for customer token
|
// Safely check for customer token
|
||||||
final String? token = customerToken;
|
final String? token = customerToken;
|
||||||
if (token != null && token.isNotEmpty) {
|
if (token != null && token.isNotEmpty) {
|
||||||
_firebaseMessagesController.sendNotificationToDriverMAP('Accepted Ride',
|
// _firebaseMessagesController.sendNotificationToDriverMAP('Accepted Ride',
|
||||||
'your ride is applied'.tr, token, bodyToPassenger, 'start.wav');
|
// 'your ride is applied'.tr, token, bodyToPassenger, 'start.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: token.toString(),
|
||||||
|
title: 'Accepted Ride',
|
||||||
|
body: 'your ride is Accepted'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'start',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
} else {}
|
} else {}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ import 'package:sefer_driver/views/widgets/elevated_btn.dart';
|
|||||||
|
|
||||||
import '../../../../constant/box_name.dart';
|
import '../../../../constant/box_name.dart';
|
||||||
import '../../../../constant/style.dart';
|
import '../../../../constant/style.dart';
|
||||||
|
import '../../../../controller/firebase/notification_service.dart';
|
||||||
import '../../../../main.dart';
|
import '../../../../main.dart';
|
||||||
|
import '../../../../print.dart';
|
||||||
|
|
||||||
// Changed: إعادة تصميم كاملة لتصبح شريط معلومات علوي مدمج
|
// Changed: إعادة تصميم كاملة لتصبح شريط معلومات علوي مدمج
|
||||||
class PassengerInfoWindow extends StatelessWidget {
|
class PassengerInfoWindow extends StatelessWidget {
|
||||||
@@ -154,12 +156,23 @@ class PassengerInfoWindow extends StatelessWidget {
|
|||||||
if (await controller
|
if (await controller
|
||||||
.calculateDistanceBetweenDriverAndPassengerLocation() <
|
.calculateDistanceBetweenDriverAndPassengerLocation() <
|
||||||
140) {
|
140) {
|
||||||
fcm.sendNotificationToDriverMAP(
|
// fcm.sendNotificationToDriverMAP(
|
||||||
'Hi ,I Arrive your site',
|
// 'Hi ,I Arrive your site',
|
||||||
'I Arrive at your site'.tr,
|
// 'I Arrive at your site'.tr,
|
||||||
controller.tokenPassenger,
|
// controller.tokenPassenger,
|
||||||
[],
|
// [],
|
||||||
'ding.wav',
|
// 'ding.wav',
|
||||||
|
// );
|
||||||
|
Log.print(
|
||||||
|
'controller.tokenPassenger: ${controller.tokenPassenger}');
|
||||||
|
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: controller.tokenPassenger.toString(),
|
||||||
|
title: 'Hi ,I Arrive your site'.tr,
|
||||||
|
body: 'I Arrive at your site'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'ding',
|
||||||
|
driverList: [],
|
||||||
);
|
);
|
||||||
controller.startTimerToShowDriverWaitPassengerDuration();
|
controller.startTimerToShowDriverWaitPassengerDuration();
|
||||||
controller.isArrivedSend = false;
|
controller.isArrivedSend = false;
|
||||||
@@ -239,13 +252,22 @@ class PassengerInfoWindow extends StatelessWidget {
|
|||||||
kolor: AppColor.deepPurpleAccent,
|
kolor: AppColor.deepPurpleAccent,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
MyDialog().getDialog('Are you sure to cancel?'.tr, '', () async {
|
MyDialog().getDialog('Are you sure to cancel?'.tr, '', () async {
|
||||||
fcm.sendNotificationToDriverMAP(
|
// fcm.sendNotificationToDriverMAP(
|
||||||
'Driver Cancelled Your Trip',
|
// 'Driver Cancelled Your Trip',
|
||||||
'You will need to pay the cost to the driver, or it will be deducted from your next trip'
|
// 'You will need to pay the cost to the driver, or it will be deducted from your next trip'
|
||||||
.tr,
|
// .tr,
|
||||||
controller.tokenPassenger,
|
// controller.tokenPassenger,
|
||||||
[],
|
// [],
|
||||||
'cancel.wav');
|
// 'cancel.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: controller.tokenPassenger.toString(),
|
||||||
|
title: 'Driver Cancelled Your Trip',
|
||||||
|
body:
|
||||||
|
'You will need to pay the cost to the driver, or it will be deducted from your next trip',
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'cancel',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
box.write(BoxName.rideStatus, 'Cancel');
|
box.write(BoxName.rideStatus, 'Cancel');
|
||||||
await controller.addWaitingTimeCostFromPassengerToDriverWallet();
|
await controller.addWaitingTimeCostFromPassengerToDriverWallet();
|
||||||
controller.isdriverWaitTimeEnd = false;
|
controller.isdriverWaitTimeEnd = false;
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ import '../../../../constant/box_name.dart';
|
|||||||
import '../../../../constant/colors.dart';
|
import '../../../../constant/colors.dart';
|
||||||
import '../../../../constant/style.dart';
|
import '../../../../constant/style.dart';
|
||||||
import '../../../../controller/firebase/firbase_messge.dart';
|
import '../../../../controller/firebase/firbase_messge.dart';
|
||||||
|
import '../../../../controller/firebase/notification_service.dart';
|
||||||
import '../../../../controller/functions/launch.dart';
|
import '../../../../controller/functions/launch.dart';
|
||||||
import '../../../../controller/home/captin/map_driver_controller.dart';
|
import '../../../../controller/home/captin/map_driver_controller.dart';
|
||||||
import '../../../../main.dart';
|
import '../../../../main.dart';
|
||||||
@@ -339,23 +340,39 @@ class SosConnect extends StatelessWidget {
|
|||||||
_buildMessageTile(
|
_buildMessageTile(
|
||||||
text: "Where are you, sir?".tr,
|
text: "Where are you, sir?".tr,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
fcm.sendNotificationToDriverMAP(
|
// fcm.sendNotificationToDriverMAP(
|
||||||
'message From Driver',
|
// 'message From Driver',
|
||||||
"Where are you, sir?".tr,
|
// "Where are you, sir?".tr,
|
||||||
controller.tokenPassenger,
|
// controller.tokenPassenger,
|
||||||
[],
|
// [],
|
||||||
'ding.wav');
|
// 'ding');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: controller.tokenPassenger.toString(),
|
||||||
|
title: 'message From Driver'.tr,
|
||||||
|
body: "Where are you, sir?".tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'ding',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
}),
|
}),
|
||||||
_buildMessageTile(
|
_buildMessageTile(
|
||||||
text: "I've been trying to reach you but your phone is off.".tr,
|
text: "I've been trying to reach you but your phone is off.".tr,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
fcm.sendNotificationToDriverMAP(
|
// fcm.sendNotificationToDriverMAP(
|
||||||
'message From Driver',
|
// 'message From Driver',
|
||||||
"I've been trying to reach you but your phone is off.".tr,
|
// "I've been trying to reach you but your phone is off.".tr,
|
||||||
controller.tokenPassenger,
|
// controller.tokenPassenger,
|
||||||
[],
|
// [],
|
||||||
'ding.wav');
|
// 'ding');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: controller.tokenPassenger.toString(),
|
||||||
|
title: 'message From Driver'.tr,
|
||||||
|
body: "I've been trying to reach you but your phone is off.".tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'ding',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
}),
|
}),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
@@ -374,12 +391,20 @@ class SosConnect extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
fcm.sendNotificationToDriverMAP(
|
// fcm.sendNotificationToDriverMAP(
|
||||||
'message From Driver',
|
// 'message From Driver',
|
||||||
controller.messageToPassenger.text,
|
// controller.messageToPassenger.text,
|
||||||
controller.tokenPassenger,
|
// controller.tokenPassenger,
|
||||||
[],
|
// [],
|
||||||
'ding.wav');
|
// 'ding');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: controller.tokenPassenger.toString(),
|
||||||
|
title: 'message From Driver'.tr,
|
||||||
|
body: 'change device'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'cancel',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
controller.messageToPassenger.clear();
|
controller.messageToPassenger.clear();
|
||||||
Get.back();
|
Get.back();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import '../../../../constant/box_name.dart';
|
|||||||
import '../../../../constant/links.dart';
|
import '../../../../constant/links.dart';
|
||||||
import '../../../../controller/firebase/firbase_messge.dart';
|
import '../../../../controller/firebase/firbase_messge.dart';
|
||||||
import '../../../../controller/firebase/local_notification.dart';
|
import '../../../../controller/firebase/local_notification.dart';
|
||||||
|
import '../../../../controller/firebase/notification_service.dart';
|
||||||
import '../../../../controller/functions/crud.dart';
|
import '../../../../controller/functions/crud.dart';
|
||||||
import '../../../../main.dart';
|
import '../../../../main.dart';
|
||||||
import '../../../../models/model/order_data.dart';
|
import '../../../../models/model/order_data.dart';
|
||||||
@@ -228,12 +229,20 @@ class _OrderOverlayState extends State<OrderOverlay>
|
|||||||
? Get.find<FirebaseMessagesController>()
|
? Get.find<FirebaseMessagesController>()
|
||||||
: Get.put(FirebaseMessagesController());
|
: Get.put(FirebaseMessagesController());
|
||||||
|
|
||||||
fmc.sendNotificationToDriverMAP(
|
// fmc.sendNotificationToDriverMAP(
|
||||||
"Accepted Ride",
|
// "Accepted Ride",
|
||||||
'your ride is Accepted'.tr,
|
// 'your ride is Accepted'.tr,
|
||||||
_getData(9).toString(),
|
// _getData(9).toString(),
|
||||||
bodyToPassenger,
|
// bodyToPassenger,
|
||||||
'start.wav',
|
// 'start.wav',
|
||||||
|
// );
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: _getData(9).toString(),
|
||||||
|
title: "Accepted Ride",
|
||||||
|
body: 'your ride is Accepted'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'start',
|
||||||
|
driverList: [],
|
||||||
);
|
);
|
||||||
final payload = {
|
final payload = {
|
||||||
// بيانات أساسية
|
// بيانات أساسية
|
||||||
|
|||||||
@@ -13,10 +13,12 @@ import 'dart:math' as math;
|
|||||||
import '../../../../constant/colors.dart';
|
import '../../../../constant/colors.dart';
|
||||||
import '../../../../constant/links.dart';
|
import '../../../../constant/links.dart';
|
||||||
import '../../../../constant/style.dart';
|
import '../../../../constant/style.dart';
|
||||||
|
import '../../../../controller/firebase/notification_service.dart';
|
||||||
import '../../../../controller/functions/crud.dart';
|
import '../../../../controller/functions/crud.dart';
|
||||||
import '../../../../controller/functions/encrypt_decrypt.dart';
|
import '../../../../controller/functions/encrypt_decrypt.dart';
|
||||||
import '../../../../controller/functions/launch.dart';
|
import '../../../../controller/functions/launch.dart';
|
||||||
import '../../../../controller/home/captin/order_request_controller.dart';
|
import '../../../../controller/home/captin/order_request_controller.dart';
|
||||||
|
import '../../../../print.dart';
|
||||||
import '../../../widgets/elevated_btn.dart';
|
import '../../../widgets/elevated_btn.dart';
|
||||||
|
|
||||||
class OrderRequestPage extends StatefulWidget {
|
class OrderRequestPage extends StatefulWidget {
|
||||||
@@ -279,12 +281,20 @@ class _OrderRequestPageState extends State<OrderRequestPage> {
|
|||||||
? Get.find<FirebaseMessagesController>()
|
? Get.find<FirebaseMessagesController>()
|
||||||
: Get.put(FirebaseMessagesController());
|
: Get.put(FirebaseMessagesController());
|
||||||
|
|
||||||
fmc.sendNotificationToDriverMAP(
|
// fmc.sendNotificationToDriverMAP(
|
||||||
"Accepted Ride",
|
// "Accepted Ride",
|
||||||
'your ride is Accepted'.tr,
|
// 'your ride is Accepted'.tr,
|
||||||
controller.myList[9].toString(),
|
// controller.myList[9].toString(),
|
||||||
bodyToPassenger,
|
// bodyToPassenger,
|
||||||
'start.wav',
|
// 'start',
|
||||||
|
// );
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: controller.myList[9].toString(),
|
||||||
|
title: "Accepted Ride",
|
||||||
|
body: 'your ride is Accepted'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'start',
|
||||||
|
driverList: [],
|
||||||
);
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
box.write(BoxName.rideArguments, {
|
box.write(BoxName.rideArguments, {
|
||||||
@@ -338,6 +348,8 @@ class _OrderRequestPageState extends State<OrderRequestPage> {
|
|||||||
});
|
});
|
||||||
Get.to(() => PassengerLocationMapPage(),
|
Get.to(() => PassengerLocationMapPage(),
|
||||||
arguments: box.read(BoxName.rideArguments));
|
arguments: box.read(BoxName.rideArguments));
|
||||||
|
Log.print(
|
||||||
|
'box.read(BoxName.rideArguments): ${box.read(BoxName.rideArguments)}');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -372,13 +384,22 @@ class _OrderRequestPageState extends State<OrderRequestPage> {
|
|||||||
box.read(BoxName.tokenDriver).toString(),
|
box.read(BoxName.tokenDriver).toString(),
|
||||||
];
|
];
|
||||||
|
|
||||||
FirebaseMessagesController()
|
// FirebaseMessagesController()
|
||||||
.sendNotificationToPassengerToken(
|
// .sendNotificationToPassengerToken(
|
||||||
'Order Under Review'.tr,
|
// 'Order Under Review'.tr,
|
||||||
'${box.read(BoxName.nameDriver)} ${'is reviewing your order. They may need more information or a higher price.'.tr}',
|
// '${box.read(BoxName.nameDriver)} ${'is reviewing your order. They may need more information or a higher price.'.tr}',
|
||||||
controller.myList[9].toString(),
|
// controller.myList[9].toString(),
|
||||||
bodyToPassenger,
|
// bodyToPassenger,
|
||||||
'notification.wav');
|
// 'notification');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: controller.myList[9].toString(),
|
||||||
|
title: 'Order Under Review'.tr,
|
||||||
|
body:
|
||||||
|
'${box.read(BoxName.nameDriver)} ${'is reviewing your order. They may need more information or a higher price.'.tr}',
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'start',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
|
|
||||||
controller.refuseOrder(
|
controller.refuseOrder(
|
||||||
EncryptionHelper.instance.encryptData(
|
EncryptionHelper.instance.encryptData(
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:google_maps_flutter/google_maps_flutter.dart';
|
|||||||
import '../../../../constant/colors.dart'; // Your AppColor
|
import '../../../../constant/colors.dart'; // Your AppColor
|
||||||
import '../../../../constant/links.dart'; // Your AppLink
|
import '../../../../constant/links.dart'; // Your AppLink
|
||||||
import '../../../../constant/style.dart'; // Your AppStyle
|
import '../../../../constant/style.dart'; // Your AppStyle
|
||||||
|
import '../../../../controller/firebase/notification_service.dart';
|
||||||
import '../../../../controller/functions/crud.dart';
|
import '../../../../controller/functions/crud.dart';
|
||||||
import '../../../../controller/functions/launch.dart';
|
import '../../../../controller/functions/launch.dart';
|
||||||
import '../../../../controller/home/captin/order_request_controller.dart';
|
import '../../../../controller/home/captin/order_request_controller.dart';
|
||||||
@@ -385,16 +386,28 @@ class OrderSpeedRequest extends StatelessWidget {
|
|||||||
box.read(BoxName.tokenDriver).toString(),
|
box.read(BoxName.tokenDriver).toString(),
|
||||||
rideId.toString(),
|
rideId.toString(),
|
||||||
];
|
];
|
||||||
Get.put(FirebaseMessagesController())
|
// Get.put(FirebaseMessagesController())
|
||||||
.sendNotificationToDriverMAP(
|
// .sendNotificationToDriverMAP(
|
||||||
'Accepted Ride',
|
// 'Accepted Ride',
|
||||||
'your ride is applied'.tr,
|
// 'your ride is applied'.tr,
|
||||||
controller.arguments?['DriverList']
|
// controller.arguments?['DriverList']
|
||||||
?[9]
|
// ?[9]
|
||||||
?.toString() ??
|
// ?.toString() ??
|
||||||
_getData(9), // Safer access
|
// _getData(9), // Safer access
|
||||||
bodyToPassenger,
|
// bodyToPassenger,
|
||||||
'start.wav');
|
// 'start.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: controller.arguments?['DriverList']
|
||||||
|
?[9]
|
||||||
|
?.toString() ??
|
||||||
|
_getData(9),
|
||||||
|
title: 'Accepted Ride',
|
||||||
|
body: 'your ride is applied'.tr,
|
||||||
|
isTopic:
|
||||||
|
false, // Important: this is a token
|
||||||
|
tone: 'start',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
|
|
||||||
// Using rideId (_getData(16)) for order_id consistently
|
// Using rideId (_getData(16)) for order_id consistently
|
||||||
CRUD().postFromDialogue(
|
CRUD().postFromDialogue(
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import '../../constant/colors.dart';
|
|||||||
import '../../constant/links.dart';
|
import '../../constant/links.dart';
|
||||||
import '../../constant/style.dart';
|
import '../../constant/style.dart';
|
||||||
import '../../controller/firebase/firbase_messge.dart';
|
import '../../controller/firebase/firbase_messge.dart';
|
||||||
|
import '../../controller/firebase/notification_service.dart';
|
||||||
import '../../controller/functions/crud.dart';
|
import '../../controller/functions/crud.dart';
|
||||||
import '../../controller/home/captin/home_captain_controller.dart';
|
import '../../controller/home/captin/home_captain_controller.dart';
|
||||||
import '../../controller/notification/ride_available_controller.dart';
|
import '../../controller/notification/ride_available_controller.dart';
|
||||||
@@ -338,12 +339,20 @@ class RideAvailableCard extends StatelessWidget {
|
|||||||
payload: {'id': rideInfo['id'], 'status': 'Applied'});
|
payload: {'id': rideInfo['id'], 'status': 'Applied'});
|
||||||
}
|
}
|
||||||
|
|
||||||
FirebaseMessagesController().sendNotificationToPassengerToken(
|
// FirebaseMessagesController().sendNotificationToPassengerToken(
|
||||||
"Accepted Ride".tr,
|
// "Accepted Ride".tr,
|
||||||
'your ride is Accepted'.tr,
|
// 'your ride is Accepted'.tr,
|
||||||
rideInfo['passengerToken'].toString(),
|
// rideInfo['passengerToken'].toString(),
|
||||||
bodyToPassenger,
|
// bodyToPassenger,
|
||||||
'start.wav');
|
// 'start.wav');
|
||||||
|
NotificationService.sendNotification(
|
||||||
|
target: rideInfo['passengerToken'].toString(),
|
||||||
|
title: 'Accepted Ride',
|
||||||
|
body: 'your ride is Accepted'.tr,
|
||||||
|
isTopic: false, // Important: this is a token
|
||||||
|
tone: 'start',
|
||||||
|
driverList: [],
|
||||||
|
);
|
||||||
Get.back();
|
Get.back();
|
||||||
Get.to(() => PassengerLocationMapPage(), arguments: {
|
Get.to(() => PassengerLocationMapPage(), arguments: {
|
||||||
'passengerLocation': rideInfo['start_location'].toString(),
|
'passengerLocation': rideInfo['start_location'].toString(),
|
||||||
|
|||||||
Reference in New Issue
Block a user