diff --git a/android/app/build.gradle b/android/app/build.gradle
index e88811b..8fc02fb 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -44,8 +44,8 @@ android {
applicationId = "com.intaleq_driver"
minSdk = 29
targetSdk = 36
- versionCode = 16 // I've used the higher version number from your first file
- versionName = '1.0.16' // I've used the higher version name
+ versionCode = 17 // I've used the higher version number from your first file
+ versionName = '1.0.17' // I've used the higher version name
multiDexEnabled = true
ndk {
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index b843fc9..6c1228e 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -49,12 +49,12 @@
android:value="2" />
-
+ android:value="main.dart" /> -->
-
+
-
-
+ android:exported="false" /> -->
+
diff --git a/bubble-master/lib/bubble.dart b/bubble-master/lib/bubble.dart
index 00fa44a..eb5ce12 100755
--- a/bubble-master/lib/bubble.dart
+++ b/bubble-master/lib/bubble.dart
@@ -21,7 +21,7 @@ class Bubble {
/// puts app in background and shows floaty-bubble head
Future startBubbleHead({bool sendAppToBackground = true}) async {
ByteData bytes = await rootBundle.load(
- 'assets/images/s.png',
+ 'assets/images/logo.png',
);
var buffer = bytes.buffer;
var encodedImage = base64.encode(Uint8List.view(buffer));
diff --git a/lib/constant/links.dart b/lib/constant/links.dart
index ca5882f..8a6c161 100755
--- a/lib/constant/links.dart
+++ b/lib/constant/links.dart
@@ -8,8 +8,7 @@ import 'box_name.dart';
class AppLink {
static String serverPHP = box.read('serverPHP');
- static String seferPaymentServer =
- 'https://walletintaleq.intaleq.xyz/v1/main';
+ static String paymentServer = 'https://walletintaleq.intaleq.xyz/v1/main';
static String seferPaymentServer0 =
'https://walletintaleq.intaleq.xyz/v1/main';
@@ -26,7 +25,7 @@ class AppLink {
static String loginJwtDriver = "$server/loginJwtDriver.php";
static String loginJwtWalletDriver =
- "$seferPaymentServer/loginJwtWalletDriver.php";
+ "$paymentServer/loginJwtWalletDriver.php";
static String loginFirstTimeDriver = "$server/loginFirstTimeDriver.php";
static String googleMapsLink = 'https://maps.googleapis.com/maps/api/';
@@ -48,25 +47,25 @@ class AppLink {
static String addTokens = "$ride/firebase/add.php";
static String addTokensDriver = "$ride/firebase/addDriver.php";
static String addTokensDriverWallet =
- "$seferPaymentServer/ride/firebase/addDriver.php";
+ "$paymentServer/ride/firebase/addDriver.php";
//=======================Wallet===================
- static String wallet = '$seferPaymentServer/ride/passengerWallet';
- static String walletDriver = '$seferPaymentServer/ride/driverWallet';
+ static String wallet = '$paymentServer/ride/passengerWallet';
+ static String walletDriver = '$paymentServer/ride/driverWallet';
static String getAllPassengerTransaction =
"$wallet/getAllPassengerTransaction.php";
static String payWithMTNConfirm =
- "$seferPaymentServer/ride/mtn/driver/confirm_payment.php";
+ "$paymentServer/ride/mtn/driver/confirm_payment.php";
static String payWithMTNStart =
- "$seferPaymentServer/ride/mtn/driver/mtn_start.php";
+ "$paymentServer/ride/mtn/driver/mtn_start.php";
static String payWithSyriatelConfirm =
- "$seferPaymentServer/ride/syriatel/driver/confirm_payment.php";
+ "$paymentServer/ride/syriatel/driver/confirm_payment.php";
static String payWithSyriatelStart =
- "$seferPaymentServer/ride/syriatel/driver/start_payment.php";
+ "$paymentServer/ride/syriatel/driver/start_payment.php";
static String payWithEcashDriver =
- "$seferPaymentServer/ride/ecash/driver/payWithEcash.php";
+ "$paymentServer/ride/ecash/driver/payWithEcash.php";
static String payWithEcashPassenger =
- "$seferPaymentServer/ride/ecash/passenger/payWithEcash.php";
+ "$paymentServer/ride/ecash/passenger/payWithEcash.php";
// wl.tripz-egypt.com/v1/main/ride/ecash/driver
static String getWalletByPassenger = "$wallet/getWalletByPassenger.php";
static String getPassengersWallet = "$wallet/get.php";
@@ -136,35 +135,34 @@ class AppLink {
static String addKazanPercent = "$ride/kazan/add.php";
////-----------------DriverPayment------------------
- static String addDrivePayment = "$seferPaymentServer/ride/payment/add.php";
+ static String addDrivePayment = "$paymentServer/ride/payment/add.php";
static String payWithPayMobCardDriver =
- "$seferPaymentServer/ride/payMob/paymob_driver/payWithCard.php";
+ "$paymentServer/ride/payMob/paymob_driver/payWithCard.php";
static String payWithWallet =
- "$seferPaymentServer/ride/payMob/paymob_driver/payWithWallet.php";
+ "$paymentServer/ride/payMob/paymob_driver/payWithWallet.php";
static String paymetVerifyDriver =
- "$seferPaymentServer/ride/payMob/paymob_driver/paymet_verfy.php";
+ "$paymentServer/ride/payMob/paymob_driver/paymet_verfy.php";
static String updatePaymetToPaid =
- "$seferPaymentServer/ride/payment/updatePaymetToPaid.php";
+ "$paymentServer/ride/payment/updatePaymetToPaid.php";
static String paymobPayoutDriverWallet =
- "$seferPaymentServer/ride/payMob/paymob_driver/paymob_payout.php'";
+ "$paymentServer/ride/payMob/paymob_driver/paymob_payout.php'";
- static String addSeferWallet = "$seferPaymentServer/ride/seferWallet/add.php";
- static String getSeferWallet = "$seferPaymentServer/ride/seferWallet/get.php";
+ static String addSeferWallet = "$paymentServer/ride/seferWallet/add.php";
+ static String getSeferWallet = "$paymentServer/ride/seferWallet/get.php";
static String addDriverPaymentPoints =
- "$seferPaymentServer/ride/driverPayment/add.php";
+ "$paymentServer/ride/driverPayment/add.php";
static String addPaymentTokenDriver =
- "$seferPaymentServer/ride/driverWallet/addPaymentToken.php"; //driverWallet/addPaymentToken.php
+ "$paymentServer/ride/driverWallet/addPaymentToken.php"; //driverWallet/addPaymentToken.php
static String addPaymentTokenPassenger =
- "$seferPaymentServer/ride/passengerWallet/addPaymentTokenPassenger.php";
+ "$paymentServer/ride/passengerWallet/addPaymentTokenPassenger.php";
static String getDriverPaymentPoints =
- "$seferPaymentServer/ride/driverWallet/get.php";
- static String getDriverPaymentToday =
- "$seferPaymentServer/ride/payment/get.php";
+ "$paymentServer/ride/driverWallet/get.php";
+ static String getDriverPaymentToday = "$paymentServer/ride/payment/get.php";
static String getCountRide = "$ride/payment/getCountRide.php";
static String getAllPaymentFromRide =
- "$seferPaymentServer/ride/payment/getAllPayment.php";
+ "$paymentServer/ride/payment/getAllPayment.php";
static String getAllPaymentVisa =
- "$seferPaymentServer/ride/payment/getAllPaymentVisa.php";
+ "$paymentServer/ride/payment/getAllPaymentVisa.php";
//-----------------Passenger NotificationCaptain------------------
static String addNotificationPassenger =
diff --git a/lib/controller/auth/captin/login_captin_controller.dart b/lib/controller/auth/captin/login_captin_controller.dart
index cb5158a..898e757 100755
--- a/lib/controller/auth/captin/login_captin_controller.dart
+++ b/lib/controller/auth/captin/login_captin_controller.dart
@@ -325,10 +325,8 @@ class LoginDriverController extends GetxController {
key: BoxName.fingerPrint, value: fingerPrint.toString());
// print(jsonDecode(token)['data'][0]['token'].toString());
// print(box.read(BoxName.tokenDriver).toString());
- if (box.read(BoxName.emailDriver).toString() ==
- '963992952235@intaleqapp.com') {
- Get.offAll(() => HomeCaptain());
- }
+ // if (box.read(BoxName.emailDriver).toString() !=
+ // '963992952235@intaleqapp.com') {
if (token != 'failure') {
if ((jsonDecode(token)['data'][0]['token'].toString()) !=
box.read(BoxName.tokenDriver).toString()) {
@@ -353,6 +351,7 @@ class LoginDriverController extends GetxController {
},
);
}
+ // }
}
Get.offAll(() => HomeCaptain());
@@ -379,7 +378,7 @@ class LoginDriverController extends GetxController {
logintest(String driverID, email) async {
isloading = true;
update();
- await SecurityHelper.performSecurityChecks();
+ // await SecurityHelper.performSecurityChecks();
// Log.print('(BoxName.emailDriver): ${box.read(BoxName.emailDriver)}');
var res = await CRUD().get(link: AppLink.loginFromGoogleCaptin, payload: {
@@ -388,75 +387,77 @@ class LoginDriverController extends GetxController {
});
// print('res is $res');
- if (res == 'failure') {
- await isPhoneVerified();
- // Get.snackbar('Failure', '', backgroundColor: Colors.red);
- } else {
- var jsonDecoeded = jsonDecode(res);
- var d = jsonDecoeded['data'][0];
- if (jsonDecoeded.isNotEmpty) {
- if (jsonDecoeded['status'] == 'success' &&
- d['is_verified'].toString() == '1') {
- box.write(BoxName.emailDriver, d['email']);
- box.write(BoxName.firstTimeLoadKey, 'false');
- box.write(BoxName.driverID, (d['id']));
- box.write(BoxName.isTest, '1');
- box.write(BoxName.gender, (d['gender']));
- box.write(BoxName.phoneVerified, d['is_verified'].toString());
- box.write(BoxName.phoneDriver, (d['phone']));
- box.write(BoxName.is_claimed, d['is_claimed']);
- box.write(BoxName.isInstall, d['isInstall']);
- // box.write(
- // BoxName.isGiftToken, d['isGiftToken']);
- box.write(BoxName.nameArabic, (d['name_arabic']));
- box.write(BoxName.carYear, d['year']);
- box.write(BoxName.bankCodeDriver, (d['bankCode']));
- box.write(BoxName.accountBankNumberDriver, (d['accountBank']));
- box.write(
- BoxName.nameDriver,
- '${(d['first_name'])}'
- ' ${(d['last_name'])}');
- if (((d['model']).toString().contains('دراجه') ||
- d['make'].toString().contains('دراجه '))) {
- if ((d['gender']).toString() == 'Male') {
- box.write(BoxName.carTypeOfDriver, 'Scooter');
- } else {
- box.write(BoxName.carTypeOfDriver, 'Pink Bike');
- }
- } else if (int.parse(d['year'].toString()) > 2016) {
- if (d['gender'].toString() != 'Male') {
- box.write(BoxName.carTypeOfDriver, 'Lady');
- } else {
- box.write(BoxName.carTypeOfDriver, 'Comfort');
- }
- } else if (int.parse(d['year'].toString()) > 2002 &&
- int.parse(d['year'].toString()) < 2016) {
- box.write(BoxName.carTypeOfDriver, 'Speed');
- } else if (int.parse(d['year'].toString()) < 2002) {
- box.write(BoxName.carTypeOfDriver, 'Awfar Car');
+ // if (res == 'failure') {
+ // await isPhoneVerified();
+ // // Get.snackbar('Failure', '', backgroundColor: Colors.red);
+ // } else
+ // {
+ var jsonDecoeded = jsonDecode(res);
+ var d = jsonDecoeded['data'][0];
+ if (jsonDecoeded.isNotEmpty) {
+ if (jsonDecoeded['status'] == 'success' &&
+ d['is_verified'].toString() == '1') {
+ box.write(BoxName.emailDriver, d['email']);
+ box.write(BoxName.firstTimeLoadKey, 'false');
+ box.write(BoxName.driverID, (d['id']));
+ box.write(BoxName.isTest, '1');
+ box.write(BoxName.gender, (d['gender']));
+ box.write(BoxName.phoneVerified, d['is_verified'].toString());
+ box.write(BoxName.phoneDriver, (d['phone']));
+ box.write(BoxName.is_claimed, d['is_claimed']);
+ box.write(BoxName.isInstall, d['isInstall']);
+ // box.write(
+ // BoxName.isGiftToken, d['isGiftToken']);
+ box.write(BoxName.nameArabic, (d['name_arabic']));
+ box.write(BoxName.carYear, d['year']);
+ box.write(BoxName.bankCodeDriver, (d['bankCode']));
+ box.write(BoxName.accountBankNumberDriver, (d['accountBank']));
+ box.write(
+ BoxName.nameDriver,
+ '${(d['first_name'])}'
+ ' ${(d['last_name'])}');
+ if (((d['model']).toString().contains('دراجه') ||
+ d['make'].toString().contains('دراجه '))) {
+ if ((d['gender']).toString() == 'Male') {
+ box.write(BoxName.carTypeOfDriver, 'Scooter');
+ } else {
+ box.write(BoxName.carTypeOfDriver, 'Pink Bike');
}
- updateAppTester(AppInformation.appName);
-
- var token = await CRUD().get(
- link: AppLink.getDriverToken,
- payload: {'captain_id': (box.read(BoxName.driverID)).toString()});
-
- String fingerPrint = await DeviceHelper.getDeviceFingerprint();
- await storage.write(
- key: BoxName.fingerPrint, value: fingerPrint.toString());
-
- Get.off(() => HomeCaptain());
- } else {
- Get.offAll(() => PhoneNumberScreen());
-
- isloading = false;
- update();
+ } else if (int.parse(d['year'].toString()) > 2016) {
+ if (d['gender'].toString() != 'Male') {
+ box.write(BoxName.carTypeOfDriver, 'Lady');
+ } else {
+ box.write(BoxName.carTypeOfDriver, 'Comfort');
+ }
+ } else if (int.parse(d['year'].toString()) > 2002 &&
+ int.parse(d['year'].toString()) < 2016) {
+ box.write(BoxName.carTypeOfDriver, 'Speed');
+ } else if (int.parse(d['year'].toString()) < 2002) {
+ box.write(BoxName.carTypeOfDriver, 'Awfar Car');
}
- } else {
- mySnackbarSuccess('');
+ // updateAppTester(AppInformation.appName);
- isloading = false;
- update();
+ // var token = await CRUD().get(
+ // link: AppLink.getDriverToken,
+ // payload: {'captain_id': (box.read(BoxName.driverID)).toString()});
+
+ // String fingerPrint = await DeviceHelper.getDeviceFingerprint();
+ // await storage.write(
+ // key: BoxName.fingerPrint, value: fingerPrint.toString());
+
+ Get.off(() => HomeCaptain());
+ // } else {
+ // Get.offAll(() => PhoneNumberScreen());
+
+ // isloading = false;
+ // update();
+ // }
+ // }
+ // else {
+ // mySnackbarSuccess('');
+
+ // isloading = false;
+ // update();
}
}
}
diff --git a/lib/controller/auth/captin/opt_token_controller.dart b/lib/controller/auth/captin/opt_token_controller.dart
index 5250026..5c1bea4 100644
--- a/lib/controller/auth/captin/opt_token_controller.dart
+++ b/lib/controller/auth/captin/opt_token_controller.dart
@@ -1,6 +1,7 @@
import 'dart:async';
import 'package:get/get.dart';
+import 'package:sefer_driver/print.dart';
import 'package:sefer_driver/views/home/Captin/home_captain/home_captin.dart';
import '../../../constant/box_name.dart';
@@ -87,10 +88,10 @@ class OtpVerificationController extends GetxController {
);
if (response != 'failure') {
+ Log.print('response: ${response}');
Get.back(); // توجه إلى الصفحة التالية
await CRUD().post(
- link:
- '${AppLink.seferPaymentServer}/auth/token/update_driver_auth.php',
+ link: '${AppLink.paymentServer}/auth/token/update_driver_auth.php',
payload: {
'token': box.read(BoxName.tokenDriver).toString(),
'fingerPrint': finger.toString(),
diff --git a/lib/controller/auth/captin/phone_helper_controller.dart b/lib/controller/auth/captin/phone_helper_controller.dart
index b6bc571..3bdb756 100644
--- a/lib/controller/auth/captin/phone_helper_controller.dart
+++ b/lib/controller/auth/captin/phone_helper_controller.dart
@@ -30,7 +30,7 @@ class PhoneAuthHelper {
final data = (response);
Log.print('data: ${data}');
// if (data['status'] == 'success') {
- mySnackbarSuccess('An OTP has been sent to your WhatsApp number.'.tr);
+ mySnackbarSuccess('An OTP has been sent to your number.'.tr);
return true;
// } else {
// mySnackeBarError(data['message'] ?? 'Failed to send OTP.');
diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart
index ab76893..dfdd07a 100755
--- a/lib/controller/firebase/firbase_messge.dart
+++ b/lib/controller/firebase/firbase_messge.dart
@@ -85,9 +85,9 @@ class FirebaseMessagesController extends GetxController {
if (message.data.isNotEmpty && message.notification != null) {
fireBaseTitles(message);
}
- if (message.data.isNotEmpty && message.notification != null) {
- fireBaseTitles(message);
- }
+ // if (message.data.isNotEmpty && message.notification != null) {
+ // fireBaseTitles(message);
+ // }
});
FirebaseMessaging.onBackgroundMessage((RemoteMessage message) async {});
@@ -387,33 +387,12 @@ class FirebaseMessagesController extends GetxController {
// }));
// }
- Future passengerDialog(String message) {
- return Get.defaultDialog(
- barrierDismissible: false,
- title: 'message From passenger'.tr,
- titleStyle: AppStyle.title,
- middleTextStyle: AppStyle.title,
- middleText: message.tr,
- confirm: MyElevatedButton(
- title: 'Ok'.tr,
- onPressed: () {
- // FirebaseMessagesController().sendNotificationToPassengerToken(
- // 'Hi ,I will go now'.tr,
- // 'I will go now'.tr,
- // Get.find().driverToken, []);
- // Get.find()
- // .startTimerDriverWaitPassenger5Minute();
-
- Get.back();
- }));
- }
-
late String serviceAccountKeyJson;
@override
Future onInit() async {
super.onInit();
try {
- getToken();
+ // getToken();
var encryptedKey = Env.privateKeyFCM;
// Log.print('encryptedKey: ${encryptedKey}');
serviceAccountKeyJson =
@@ -425,67 +404,84 @@ class FirebaseMessagesController extends GetxController {
}
void sendNotificationAll(String title, body, tone) async {
- // Get the token you want to subtract.
- String token = box.read(BoxName.tokenFCM);
- tokens = box.read(BoxName.tokens);
- // Subtract the token from the list of tokens.
- tokens.remove(token);
+ // توكني الحالي (لا أرسل لنفسي)
+ final String myToken = box.read(BoxName.tokenFCM) ?? '';
+ // اقرأ قائمة كل التوكنات
+ final List all =
+ List.from(box.read(BoxName.tokens) ?? const []);
- // Save the list of tokens back to the box.
- // box.write(BoxName.tokens, tokens);
- tokens = box.read(BoxName.tokens);
- for (var i = 0; i < tokens.length; i++) {
- if (serviceAccountKeyJson.isEmpty) {
- print("🔴 Error: Service Account Key is empty");
- return;
- }
- // Initialize AccessTokenManager
- final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
+ // استبعد توكنك واحذف الفارغ
+ final targets = all.where((t) => t.isNotEmpty && t != myToken).toList();
- // Obtain an OAuth 2.0 access token
- final accessToken = await accessTokenManager.getAccessToken();
- // Log.print('accessToken: ${accessToken}');
+ if (serviceAccountKeyJson.isEmpty) {
+ print("🔴 Error: Service Account Key is empty");
+ return;
+ }
+ final accessTokenManager = AccessTokenManager(serviceAccountKeyJson);
+ final accessToken = await accessTokenManager.getAccessToken();
- // Send the notification
- final response = await http
- .post(
- Uri.parse(
- 'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': 'Bearer $accessToken',
+ for (final t in targets) {
+ // ⚠️ المهم: استخدم t (توكن الهدف)، وليس المتغير myToken
+ final response = await http.post(
+ Uri.parse(
+ 'https://fcm.googleapis.com/v1/projects/ride-b1bd8/messages:send'),
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer $accessToken',
+ },
+ body: jsonEncode({
+ 'message': {
+ 'token': t,
+ 'notification': {'title': title, 'body': body},
+ 'android': {
+ 'priority': 'HIGH', // القيم الصحيحة: HIGH/NORMAL
+ 'notification': {'sound': tone},
+ // (اختياري) TTL لتجنّب رسائل قديمة
+ 'ttl': '30s',
},
- body: jsonEncode({
- 'message': {
- 'token': token,
- 'notification': {
- 'title': title,
- 'body': body,
- },
- // 'data': {
- // 'DriverList': jsonEncode(data),
- // },
- 'android': {
- 'priority': 'high', // Set priority to high
- 'notification': {
- 'sound': tone,
- },
- },
- 'apns': {
- 'headers': {
- 'apns-priority': '10', // Set APNs priority to 10
- },
- 'payload': {
- 'aps': {
- 'sound': tone,
- },
- },
- },
+ 'apns': {
+ 'headers': {
+ 'apns-priority': '10',
+ // لو iOS: حدد نوع الدفع
+ 'apns-push-type': 'alert',
},
- }),
- )
- .whenComplete(() {})
- .catchError((e) {});
+ 'payload': {
+ 'aps': {'sound': tone}
+ },
+ },
+ },
+ }),
+ );
+
+ if (response.statusCode != 200) {
+ // حاول تقرأ الخطأ وتشيل التوكنات التالفة
+ _handleV1Error(response, badToken: t);
+ await Future.delayed(const Duration(milliseconds: 50)); // تخفيف ضغط
+ }
+ }
+ }
+
+ void _handleV1Error(http.Response res, {required String badToken}) {
+ try {
+ final body = jsonDecode(res.body);
+ final err = body['error']?['status']?.toString() ?? '';
+ // أمثلة شائعة:
+ if (err.contains('UNREGISTERED') || err.contains('NOT_FOUND')) {
+ removeInvalidToken(badToken);
+ } else if (err.contains('INVALID_ARGUMENT')) {
+ // payload غير صحيح
+ print(
+ '⚠️ INVALID_ARGUMENT for $badToken: ${body['error']?['message']}');
+ } else if (err.contains('RESOURCE_EXHAUSTED') ||
+ err.contains('QUOTA_EXCEEDED')) {
+ // تجاوزت الحصة—خفّف السرعة/قسّم الإرسال (FCM v1 له حصة/دقيقة)
+ // https docs: 600k req/min per project (token bucket)
+ print('⏳ Throttled by FCM: slow down sending rate.');
+ } else {
+ print('FCM v1 error: ${res.statusCode} ${res.body}');
+ }
+ } catch (_) {
+ print('FCM v1 error: ${res.statusCode} ${res.body}');
}
}
@@ -523,7 +519,7 @@ class FirebaseMessagesController extends GetxController {
'passengerList': jsonEncode(map),
},
'android': {
- 'priority': 'high', // Set priority to high
+ 'priority': 'HIGH ', // Set priority to high
'notification': {
'sound': tone,
},
@@ -605,7 +601,7 @@ class FirebaseMessagesController extends GetxController {
'passengerList': jsonEncode(map),
},
'android': {
- 'priority': 'high', // Set priority to high
+ 'priority': 'HIGH ', // Set priority to high
'notification': {
'sound': tone,
},
@@ -692,7 +688,7 @@ class FirebaseMessagesController extends GetxController {
'DriverList': jsonEncode(data),
},
'android': {
- 'priority': 'high', // Set priority to high
+ 'priority': 'HIGH ', // Set priority to high
'notification': {
'sound': tone,
},
diff --git a/lib/controller/firebase/notification_service.dart b/lib/controller/firebase/notification_service.dart
new file mode 100644
index 0000000..ecb3000
--- /dev/null
+++ b/lib/controller/firebase/notification_service.dart
@@ -0,0 +1,71 @@
+import 'package:http/http.dart' as http;
+import 'dart:convert';
+
+class NotificationService {
+ // استبدل هذا الرابط بالرابط الصحيح لملف PHP على السيرفر الخاص بك
+ static const String _serverUrl =
+ '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 sendNotification({
+ required String target,
+ required String title,
+ required String body,
+ bool isTopic = false,
+ }) async {
+ try {
+ final response = await http.post(
+ Uri.parse(_serverUrl),
+ headers: {
+ 'Content-Type': 'application/json; charset=UTF-8',
+ },
+ body: jsonEncode({
+ 'target': target,
+ 'title': title,
+ 'body': body,
+ 'isTopic': isTopic,
+ }),
+ );
+
+ if (response.statusCode == 200) {
+ print('Notification sent successfully.');
+ print('Server Response: ${response.body}');
+ } else {
+ print(
+ 'Failed to send notification. Status code: ${response.statusCode}');
+ print('Server Error: ${response.body}');
+ }
+ } catch (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
+ );
+}
diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart
index 6cdfe55..d42adee 100755
--- a/lib/controller/functions/crud.dart
+++ b/lib/controller/functions/crud.dart
@@ -108,8 +108,6 @@ class CRUD {
final sc = response.statusCode;
final body = response.body;
- Log.print('body: ${body}');
- Log.print('body: ${body}');
// 2xx
if (sc >= 200 && sc < 300) {
@@ -193,6 +191,9 @@ class CRUD {
'Bearer ${r(box.read(BoxName.jwt)).toString().split(Env.addd)[0]}'
},
);
+ // Log.print('response: ${response.body}');
+ // Log.print('req: ${response.request}');
+ // Log.print('payload: ${payload}');
if (response.statusCode == 200) {
var jsonData = jsonDecode(response.body);
@@ -263,9 +264,6 @@ class CRUD {
'X-HMAC-Auth': hmac.toString(),
},
);
- // Log.print('response.request: ${response.request}');
- // Log.print('response.body: ${response.body}');
- // Log.print('response.payload: ${payload}');
if (response.statusCode == 200) {
var jsonData = jsonDecode(response.body);
diff --git a/lib/controller/home/captin/home_captain_controller.dart b/lib/controller/home/captin/home_captain_controller.dart
index f0ba3fe..42bc257 100755
--- a/lib/controller/home/captin/home_captain_controller.dart
+++ b/lib/controller/home/captin/home_captain_controller.dart
@@ -336,7 +336,7 @@ class HomeCaptainController extends GetxController {
CRUD().post(link: AppLink.addTokensDriver, payload: payload);
await CRUD().post(
- link: "${AppLink.seferPaymentServer}/ride/firebase/addDriver.php",
+ link: "${AppLink.paymentServer}/ride/firebase/addDriver.php",
payload: payload);
// MapDriverController().driverCallPassenger();
// box.write(BoxName.statusDriverLocation, 'off');
diff --git a/lib/controller/home/captin/map_driver_controller.dart b/lib/controller/home/captin/map_driver_controller.dart
index 7963228..e3147a5 100755
--- a/lib/controller/home/captin/map_driver_controller.dart
+++ b/lib/controller/home/captin/map_driver_controller.dart
@@ -335,7 +335,7 @@ class MapDriverController extends GetxController {
// Get.find().changeToAppliedRide('Applied');
Get.find().sendNotificationToDriverMAP(
- 'Driver Is Going To Passenger'.tr,
+ 'Driver Is Going To Passenger',
box.read(BoxName.nameDriver).toString(), //todo name driver
tokenPassenger,
[],
@@ -431,7 +431,7 @@ class MapDriverController extends GetxController {
? Get.find()
: Get.put(FirebaseMessagesController());
fcm.sendNotificationToDriverMAP(
- 'Trip is Begin'.tr,
+ 'Trip is Begin',
box.read(BoxName.nameDriver).toString(),
tokenPassenger,
[],
@@ -732,8 +732,7 @@ class MapDriverController extends GetxController {
));
apiCalls.add(CRUD().postWallet(
- link:
- "${AppLink.seferPaymentServer}/ride/payment/process_ride_payments.php",
+ link: "${AppLink.paymentServer}/ride/payment/process_ride_payments.php",
payload: paymentProcessingPayload,
));
@@ -754,7 +753,7 @@ class MapDriverController extends GetxController {
.sendSummaryToServer(driverId, rideId);
Get.find().sendNotificationToDriverMAP(
- "Driver Finish Trip".tr,
+ "Driver Finish Trip",
'${'you will pay to Driver'.tr} $paymentAmount \$',
tokenPassenger,
[
@@ -1619,7 +1618,7 @@ class MapDriverController extends GetxController {
if (distance < 300) {
// 300 متر قبل الوجهة
Get.find().sendNotificationToDriverMAP(
- "You are near the destination".tr,
+ "You are near the destination",
"You are near the destination".tr,
tokenPassenger,
[
diff --git a/lib/controller/home/captin/order_request_controller.dart b/lib/controller/home/captin/order_request_controller.dart
index fbf71d7..b6451d9 100755
--- a/lib/controller/home/captin/order_request_controller.dart
+++ b/lib/controller/home/captin/order_request_controller.dart
@@ -1,4 +1,5 @@
import 'dart:convert';
+import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter_overlay_window/flutter_overlay_window.dart';
@@ -37,10 +38,13 @@ class OrderRequestController extends GetxController {
Future onInit() async {
print('OrderRequestController onInit called');
await initializeOrderPage();
- bool isOverlayActive = await FlutterOverlayWindow.isActive();
- if (isOverlayActive) {
- await FlutterOverlayWindow.closeOverlay();
+ if (Platform.isAndroid) {
+ bool isOverlayActive = await FlutterOverlayWindow.isActive();
+ if (isOverlayActive) {
+ await FlutterOverlayWindow.closeOverlay();
+ }
}
+
addCustomStartIcon();
addCustomEndIcon();
startTimer(
@@ -61,6 +65,7 @@ class OrderRequestController extends GetxController {
Future initializeOrderPage() async {
final myListString = Get.arguments['myListString'];
+ Log.print('myListString0000: ${myListString}');
if (Get.arguments['DriverList'] == null ||
Get.arguments['DriverList'].isEmpty) {
diff --git a/lib/controller/home/navigation/decode_polyline_isolate.dart b/lib/controller/home/navigation/decode_polyline_isolate.dart
new file mode 100644
index 0000000..98348dc
--- /dev/null
+++ b/lib/controller/home/navigation/decode_polyline_isolate.dart
@@ -0,0 +1,41 @@
+import 'package:google_maps_flutter/google_maps_flutter.dart';
+
+// تم تعديل الدالة لتقبل وسيط من نوع `dynamic` لحل مشكلة عدم تطابق الأنواع مع دالة `compute`.
+// هذه الدالة لا تزال تعمل كدالة من المستوى الأعلى (Top-level function)
+// وهو شرط أساسي لاستخدامها مع دالة compute.
+List decodePolylineIsolate(dynamic encodedMessage) {
+ // التأكد من أن الرسالة المستقبلة هي من نوع String
+ if (encodedMessage is! String) {
+ // إرجاع قائمة فارغة أو إظهار خطأ إذا كان النوع غير صحيح
+ return [];
+ }
+ final String encoded = encodedMessage;
+
+ List points = [];
+ int index = 0, len = encoded.length;
+ int lat = 0, lng = 0;
+
+ while (index < len) {
+ int b, shift = 0, result = 0;
+ do {
+ b = encoded.codeUnitAt(index++) - 63;
+ result |= (b & 0x1f) << shift;
+ shift += 5;
+ } while (b >= 0x20);
+ int dlat = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
+ lat += dlat;
+
+ shift = 0;
+ result = 0;
+ do {
+ b = encoded.codeUnitAt(index++) - 63;
+ result |= (b & 0x1f) << shift;
+ shift += 5;
+ } while (b >= 0x20);
+ int dlng = ((result & 1) != 0 ? ~(result >> 1) : (result >> 1));
+ lng += dlng;
+
+ points.add(LatLng(lat / 1E5, lng / 1E5));
+ }
+ return points;
+}
diff --git a/lib/controller/home/navigation/navigation_controller.dart b/lib/controller/home/navigation/navigation_controller.dart
index 4963ab9..6faeec6 100644
--- a/lib/controller/home/navigation/navigation_controller.dart
+++ b/lib/controller/home/navigation/navigation_controller.dart
@@ -1,12 +1,11 @@
import 'dart:async';
import 'dart:io';
import 'dart:math';
-import 'dart:math' as math;
+import 'package:flutter/foundation.dart'; // <<<--- إضافة مهمة لاستخدام دالة compute
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
-import 'package:google_polyline_algorithm/google_polyline_algorithm.dart';
import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/env/env.dart';
@@ -16,6 +15,7 @@ import '../../../constant/links.dart';
import '../../../print.dart';
import '../../functions/crud.dart';
import '../../functions/tts.dart';
+import 'decode_polyline_isolate.dart';
class NavigationController extends GetxController {
// --- متغيرات الحالة العامة ---
@@ -319,24 +319,24 @@ class NavigationController extends GetxController {
// ٤. دوال مساعدة وتجهيز البيانات
// =======================================================================
- void _prepareStepData() {
+ // <<<--- التعديل الأول: تغيير الدالة لتكون async
+ Future _prepareStepData() async {
_stepBounds.clear();
_stepPolylines.clear();
if (routeSteps.isEmpty) return;
for (final step in routeSteps) {
final pointsString = step['polyline']['points'];
- final List> points =
- decodePolyline(pointsString).cast>();
- final polylineCoordinates = points
- .map((point) => LatLng(point[0].toDouble(), point[1].toDouble()))
- .toList();
+ // <<<--- التعديل الثاني: استخدام compute لفك التشفير في خيط منفصل
+ // وتصحيح طريقة التعامل مع القائمة المُرجعة
+ final List polylineCoordinates = await compute(
+ decodePolylineIsolate as ComputeCallback>,
+ pointsString);
+
_stepPolylines.add(polylineCoordinates); // تخزين نقاط الخطوة
_stepBounds.add(_boundsFromLatLngList(polylineCoordinates));
}
}
- // ... باقي دوال الكنترولر بدون تغيير ...
- // (selectDestination, onMapLongPressed, startNavigationTo, getRoute, etc.)
Future selectDestination(dynamic place) async {
placeDestinationController.clear();
placesDestination = [];
@@ -401,11 +401,11 @@ class NavigationController extends GetxController {
}
Future getRoute(LatLng origin, LatLng destination) async {
- final String key = Platform.isAndroid ? Env.mapAPIKEY : Env.mapAPIKEYIOS;
+ final String key = Env.mapAPIKEY;
final url =
'${AppLink.googleMapsLink}directions/json?language=ar&destination=${destination.latitude},${destination.longitude}&origin=${origin.latitude},${origin.longitude}&key=${key}&mode=driving';
var response = await CRUD().getGoogleApi(link: url, payload: {});
- Log.print('response: ${response}');
+ // Log.print('response: ${response}');
if (response == null || response['routes'].isEmpty) {
Get.snackbar('خطأ', 'لم يتم العثور على مسار.');
@@ -414,11 +414,11 @@ class NavigationController extends GetxController {
polylines.clear();
final pointsString = response['routes'][0]['overview_polyline']['points'];
- final List> points =
- decodePolyline(pointsString).cast>();
- _fullRouteCoordinates = points
- .map((point) => LatLng(point[0].toDouble(), point[1].toDouble()))
- .toList();
+
+ // <<<--- التعديل الثالث: استخدام compute هنا أيضًا للمسار الرئيسي
+ _fullRouteCoordinates = await compute(
+ decodePolylineIsolate as ComputeCallback>,
+ pointsString);
polylines.add(
Polyline(
@@ -441,7 +441,9 @@ class NavigationController extends GetxController {
routeSteps = List