diff --git a/android/app/build.gradle b/android/app/build.gradle index de3907d..29f94b8 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,91 +1,4 @@ -// -//def localProperties = new Properties() -//def localPropertiesFile = rootProject.file('local.properties') -//if (localPropertiesFile.exists()) { -// localPropertiesFile.withReader('UTF-8') { reader -> -// localProperties.load(reader) -// } -//} -// -//def flutterRoot = localProperties.getProperty('flutter.sdk') -//if (flutterRoot == null) { -// throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -//} -// -//def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -//if (flutterVersionCode == null) { -// flutterVersionCode = '12' -//} -// -//def flutterVersionName = localProperties.getProperty('flutter.versionName') -//if (flutterVersionName == null) { -// flutterVersionName = '1.1.2' -//} -// -//apply plugin: 'com.android.application' -//apply plugin: 'kotlin-android' -//// apply plugin: 'com.google.gms.google-services' -//apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" -//def keystoreProperties = new Properties() -//def keystorePropertiesFile = rootProject.file('key.properties') -// -// -//android { -// namespace "com.mobileapp.store.ride" -// compileSdkVersion 34 -// ndkVersion flutter.ndkVersion -// -// compileOptions { -// sourceCompatibility JavaVersion.VERSION_1_8 -// targetCompatibility JavaVersion.VERSION_1_8 -// } -// -// kotlinOptions { -// jvmTarget = '1.8' -// } -// -// sourceSets { -// main.java.srcDirs += 'src/main/kotlin' -// } -// -// defaultConfig { -// // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). -// applicationId "com.mobileapp.store.ride" -// // You can update the following values to match your application needs. -// // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. -// minSdkVersion 23 -// targetSdkVersion 34 -// versionCode 67 -// versionName '1.5.67' -// // manifestPlaceholders = [mapsApiKey: 'android/app/src/main/AndroidManifest.xml'] -// } -// -// signingConfigs { -// release { -// keyAlias keystoreProperties['keyAlias'] -// keyPassword keystoreProperties['keyPassword'] -// storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null -// storePassword keystoreProperties['storePassword'] -// } -// } -// buildTypes { -// release { -// signingConfig signingConfigs.release -// } -// } -// -// -//} -// -//flutter { -// source '../..' -//} -// -//dependencies { -// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -// // implementation platform('com.google.firebase:firebase-bom:32.1.1') -// -//} + def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { @@ -124,7 +37,7 @@ if (keystorePropertiesFile.exists()) { android { namespace "com.mobileapp.store.ride" - compileSdk 34 + compileSdk 35 ndkVersion "26.1.10909125" compileOptions { @@ -148,8 +61,8 @@ android { // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. minSdk = 23 targetSdk = flutter.targetSdkVersion - versionCode = 106 - versionName = '1.6.106' + versionCode = 108 + versionName = '1.6.108' multiDexEnabled =true // manifestPlaceholders can be specified here if needed @@ -167,6 +80,9 @@ android { buildTypes { release { signingConfig signingConfigs.release +// minifyEnabled true +// shrinkResources true +// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index 6a85ad6..b405d45 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -41,11 +41,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 77 + 78 CFBundleSignature ???? CFBundleVersion - 4.3.77 + 4.3.78 NSHumanReadableCopyright FirebaseAppDelegateProxyEnabled diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart index 334f19c..18d324c 100644 --- a/lib/controller/firebase/firbase_messge.dart +++ b/lib/controller/firebase/firbase_messge.dart @@ -139,6 +139,7 @@ class FirebaseMessagesController extends GetxController { Get.find().statusRide == 'Apply'; Get.find().isSearchingWindow == false; Get.find().update(); + Get.find().rideAppliedFromDriver(true); // driverAppliedTripSnakBar(); } else if (message.notification!.title! == 'Promo'.tr) { @@ -236,7 +237,7 @@ class FirebaseMessagesController extends GetxController { title: 'Cancel'.tr, kolor: AppColor.redColor, onPressed: () { - Get.offAll(const MapPagePassenger()); + Get.offAll(() => const MapPagePassenger()); }, ) // Get.find() @@ -256,18 +257,16 @@ class FirebaseMessagesController extends GetxController { box.write(BoxName.passengerWalletTotal, 0); } Get.find().tripFinishedFromDriver(); - - Get.to(() => RateDriverFromPassenger(), arguments: { - 'driverId': driverList[0].toString(), - 'rideId': driverList[1].toString(), - 'price': driverList[3].toString() - }); notificationController.showNotification( 'Don’t forget your personal belongings.'.tr, 'Please make sure you have all your personal belongings and that any remaining fare, if applicable, has been added to your wallet before leaving. Thank you for choosing the Sefer app' .tr, 'ding'); - // } + Get.to(() => RateDriverFromPassenger(), arguments: { + 'driverId': driverList[0].toString(), + 'rideId': driverList[1].toString(), + 'price': driverList[3].toString() + }); } else if (message.notification!.title! == "Finish Monitor".tr) { Get.defaultDialog( titleStyle: AppStyle.title, diff --git a/lib/controller/firebase/local_notification.dart b/lib/controller/firebase/local_notification.dart index 44f7b31..fb2fc26 100644 --- a/lib/controller/firebase/local_notification.dart +++ b/lib/controller/firebase/local_notification.dart @@ -7,6 +7,8 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:timezone/data/latest.dart' as tz; import 'package:timezone/timezone.dart' as tz; +import '../../main.dart'; + class NotificationController extends GetxController { final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); @@ -63,6 +65,55 @@ class NotificationController extends GetxController { // Assume _flutterLocalNotificationsPlugin is initialized somewhere in your code + // void scheduleNotificationsForSevenDays( + // String title, String message, String tone) async { + // final AndroidNotificationDetails android = AndroidNotificationDetails( + // 'high_importance_channel', + // 'High Importance Notifications', + // importance: Importance.max, + // priority: Priority.high, + // sound: RawResourceAndroidNotificationSound(tone), + // ); + + // const DarwinNotificationDetails ios = DarwinNotificationDetails( + // sound: 'default', + // presentAlert: true, + // presentBadge: true, + // presentSound: true, + // ); + + // final NotificationDetails details = + // NotificationDetails(android: android, iOS: ios); + + // // Check for the exact alarm permission on Android 12 and above + // if (Platform.isAndroid) { + // if (await Permission.scheduleExactAlarm.isDenied) { + // if (await Permission.scheduleExactAlarm.request().isGranted) { + // print('SCHEDULE_EXACT_ALARM permission granted'); + // } else { + // print('SCHEDULE_EXACT_ALARM permission denied'); + // return; + // } + // } + // } + + // // Schedule notifications for the next 7 days + // for (int day = 0; day < 7; day++) { + // // Schedule for 8:00 AM + // await _scheduleNotificationForTime( + // day, 8, 0, title, message, details, day * 1000 + 1); + + // // Schedule for 3:00 PM + // await _scheduleNotificationForTime( + // day, 15, 0, title, message, details, day * 1000 + 2); // Unique ID + + // // Schedule for 8:00 PM + // await _scheduleNotificationForTime( + // day, 20, 0, title, message, details, day * 1000 + 3); // Unique ID + // } + + // print('Notifications scheduled successfully for the next 7 days'); + // } void scheduleNotificationsForSevenDays( String title, String message, String tone) async { final AndroidNotificationDetails android = AndroidNotificationDetails( @@ -97,17 +148,37 @@ class NotificationController extends GetxController { // Schedule notifications for the next 7 days for (int day = 0; day < 7; day++) { - // Schedule for 8:00 AM - await _scheduleNotificationForTime( - day, 8, 0, title, message, details, day * 1000 + 1); + // List of notification times + final notificationTimes = [ + {'hour': 8, 'minute': 0, 'id': day * 1000 + 1}, // 8:00 AM + {'hour': 15, 'minute': 0, 'id': day * 1000 + 2}, // 3:00 PM + {'hour': 20, 'minute': 0, 'id': day * 1000 + 3}, // 8:00 PM + ]; - // Schedule for 3:00 PM - await _scheduleNotificationForTime( - day, 15, 0, title, message, details, day * 1000 + 2); // Unique ID + for (var time in notificationTimes) { + final notificationId = time['id'] as int; - // Schedule for 8:00 PM - await _scheduleNotificationForTime( - day, 20, 0, title, message, details, day * 1000 + 3); // Unique ID + // Check if this notification ID is already stored + bool isScheduled = box.read('notification_$notificationId') ?? false; + + if (!isScheduled) { + // Schedule the notification if not already scheduled + await _scheduleNotificationForTime( + day, + time['hour'] as int, + time['minute'] as int, + title, + message, + details, + notificationId, + ); + + // Mark this notification ID as scheduled in GetStorage + box.write('notification_$notificationId', true); + } else { + print('Notification with ID $notificationId is already scheduled.'); + } + } } print('Notifications scheduled successfully for the next 7 days'); diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart index 91f3047..c309e9e 100644 --- a/lib/controller/functions/crud.dart +++ b/lib/controller/functions/crud.dart @@ -33,7 +33,7 @@ class CRUD { Log.print('response.request: ${response.request}'); Log.print('payload: ${payload}'); - Log.print('response.reasonPhrase: ${response.reasonPhrase}'); + // Log.print('response.reasonPhrase: ${response.reasonPhrase}'); Log.print('response.body: ${response.body}'); // print(payload); diff --git a/lib/controller/home/map_passenger_controller.dart b/lib/controller/home/map_passenger_controller.dart index 3f825d3..bf3e671 100644 --- a/lib/controller/home/map_passenger_controller.dart +++ b/lib/controller/home/map_passenger_controller.dart @@ -407,7 +407,7 @@ class MapPassengerController extends GetxController { box.read(BoxName.carType), 4000); // confirmRideForAllDriverAvailable(); - icreaseForSameRideAndDelay(); + increaseForSameRideAndDelay(); } } } @@ -932,13 +932,14 @@ class MapPassengerController extends GetxController { } } - void tripFinishedFromDriver() async { + void tripFinishedFromDriver() { isRideFinished = true; rideTimerBegin = false; statusRideVip = 'Finished'; box.write(BoxName.arrivalTime, ''); remainingTimeTimerRideBegin = 0; box.write(BoxName.passengerWalletTotal, '0'); + update(); if (box.read(BoxName.parentTripSelected) == true) { FirebaseMessagesController().sendNotificationToPassengerToken( "Finish Monitor".tr, @@ -950,7 +951,6 @@ class MapPassengerController extends GetxController { box.write(BoxName.parentTripSelected, false); box.remove(BoxName.tokenParent); } - update(); } // bool isBeginRideFromDriver = false; @@ -998,6 +998,8 @@ class MapPassengerController extends GetxController { try { var res = await CRUD().get( link: AppLink.getRideStatusBegin, payload: {'ride_id': rideId}); + print(res); + print('1002'); if (res != 'failure') { var decode = jsonDecode(res); _beginRideStreamController @@ -1067,6 +1069,8 @@ class MapPassengerController extends GetxController { var res = await CRUD().get( link: AppLink.getRideStatusFromStartApp, payload: {'passenger_id': box.read(BoxName.passengerID)}); + print(res); + print('1070'); if (res == 'failure') { print( "No rides found for the given passenger ID within the last hour."); @@ -1330,7 +1334,7 @@ class MapPassengerController extends GetxController { Set notifiedDrivers = {}; - addRideToNotificationDriverString() async { + addRideToNotificationDriverAvailable() async { await CRUD().post(link: AppLink.addWaitingRide, payload: { 'id': rideId.toString(), 'start_location': @@ -1343,11 +1347,12 @@ class MapPassengerController extends GetxController { 'passenger_id': box.read(BoxName.passengerID).toString(), 'status': 'waiting', 'carType': box.read(BoxName.carType), - 'passengerRate': passengerRate, - 'price_for_passenger': totalME.toString(), - 'distance': distance.toString(), - 'duration': duration ?? '10', + 'passengerRate': passengerRate.toStringAsFixed(2), + 'price_for_passenger': totalME.toStringAsFixed(2), + 'distance': distance.toStringAsFixed(1), + 'duration': duration.toStringAsFixed(1), }); + if (AppLink.endPoint != AppLink.seferCairoServer) { CRUD().post( link: '${AppLink.endPoint}/notificationCaptain/addWaitingRide.php', @@ -1363,10 +1368,10 @@ class MapPassengerController extends GetxController { 'passenger_id': box.read(BoxName.passengerID).toString(), 'status': 'waiting', 'carType': box.read(BoxName.carType), - 'passengerRate': passengerRate, - 'price_for_passenger': totalME.toString(), - 'distance': distance.toString(), - 'duration': duration ?? '10', + 'passengerRate': passengerRate.toStringAsFixed(2), + 'price_for_passenger': totalME.toStringAsFixed(2), + 'distance': distance.toStringAsFixed(1), + 'duration': duration.toStringAsFixed(0), }); } } @@ -1382,7 +1387,7 @@ class MapPassengerController extends GetxController { // if (dataCarsLocationByPassenger != 'failure' && // dataCarsLocationByPassenger != null && // dataCarsLocationByPassenger.containsKey('data') && - // dataCarsLocationByPassenger['data'] != null) { + // dataCarsLocationByPassenger['message'] != null) { // driversFound = true; // break; // Exit loop if drivers are found // } @@ -1445,7 +1450,7 @@ class MapPassengerController extends GetxController { // "endtime": durationToAdd.toString(), // "price": totalPassenger.toStringAsFixed(2), // "passenger_id": box.read(BoxName.passengerID).toString(), - // "driver_id": dataCarsLocationByPassenger['data'][carsOrder]['driver_id'] + // "driver_id": dataCarsLocationByPassenger['message'][carsOrder]['driver_id'] // .toString(), // "status": "waiting", // 'carType': box.read(BoxName.carType), @@ -1477,8 +1482,8 @@ class MapPassengerController extends GetxController { // box.read(BoxName.carType), 3000); // if (dataCarsLocationByPassenger != null && // dataCarsLocationByPassenger.containsKey('data') && - // dataCarsLocationByPassenger['data'] != null) { - // for (var driverData in dataCarsLocationByPassenger['data']) { + // dataCarsLocationByPassenger['message'] != null) { + // for (var driverData in dataCarsLocationByPassenger['message']) { // String driverId = driverData['driver_id'].toString(); // if (!notifiedDrivers.contains(driverId)) { // notifiedDrivers.add(driverId); @@ -1549,7 +1554,7 @@ class MapPassengerController extends GetxController { // "endtime": durationToAdd.toString(), // "price": totalPassenger.toStringAsFixed(2), // "passenger_id": box.read(BoxName.passengerID).toString(), - // "driver_id": dataCarsLocationByPassenger['data'][carsOrder]['driver_id'] + // "driver_id": dataCarsLocationByPassenger['message'][carsOrder]['driver_id'] // .toString(), // "status": "waiting", // 'carType': box.read(BoxName.carType), @@ -1563,116 +1568,117 @@ class MapPassengerController extends GetxController { // update(); // } - icreaseForSameRideAndDelay() async { - bool driversFound = false; - for (int attempt = 0; attempt < 8; attempt++) { - await getCarsLocationByPassengerAndReloadMarker( - box.read(BoxName.carType), 4500); + increaseForSameRideAndDelay() async { + reSearchAfterCanceledFromDriver(); + // bool driversFound = false; + // for (int attempt = 0; attempt < 8; attempt++) { + // await getCarsLocationByPassengerAndReloadMarker( + // box.read(BoxName.carType), 4500); - // Check if dataCarsLocationByPassenger is valid and contains drivers - if (dataCarsLocationByPassenger != 'failure' && - dataCarsLocationByPassenger != null && - dataCarsLocationByPassenger.containsKey('data') && - dataCarsLocationByPassenger['data'] != null) { - driversFound = true; - break; // Exit loop if drivers are found - } + // // Check if dataCarsLocationByPassenger is valid and contains drivers + // if (dataCarsLocationByPassenger != 'failure' && + // dataCarsLocationByPassenger != null && + // dataCarsLocationByPassenger.containsKey('message') && + // dataCarsLocationByPassenger['message'] != null) { + // driversFound = true; + // break; // Exit loop if drivers are found + // } - // Wait 2 seconds before next attempt - await Future.delayed(const Duration(seconds: 2)); - } + // // Wait 2 seconds before next attempt + // await Future.delayed(const Duration(seconds: 2)); + // } - // If no drivers were found after 4 attempts, show a dialog - if (!driversFound) { - Get.dialog( - BackdropFilter( - filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), - child: CupertinoAlertDialog( - title: Text( - "No Car or Driver Found in your area.".tr, - style: AppStyle.title.copyWith( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - content: Text( - "No Car or Driver Found in your area.".tr, - style: AppStyle.title.copyWith(fontSize: 16), - ), - actions: [ - CupertinoDialogAction( - onPressed: () { - Get.back(); - Get.offAll(() => const MapPagePassenger()); - }, - child: Text('OK'.tr, - style: const TextStyle(color: AppColor.greenColor)), - ), - ], - ), - ), - barrierDismissible: false, - ); + // // If no drivers were found after 4 attempts, show a dialog + // if (!driversFound) { + // Get.dialog( + // BackdropFilter( + // filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + // child: CupertinoAlertDialog( + // title: Text( + // "No Car or Driver Found in your area.".tr, + // style: AppStyle.title.copyWith( + // fontSize: 20, + // fontWeight: FontWeight.bold, + // ), + // ), + // content: Text( + // "No Car or Driver Found in your area.".tr, + // style: AppStyle.title.copyWith(fontSize: 16), + // ), + // actions: [ + // CupertinoDialogAction( + // onPressed: () { + // Get.back(); + // Get.offAll(() => const MapPagePassenger()); + // }, + // child: Text('OK'.tr, + // style: const TextStyle(color: AppColor.greenColor)), + // ), + // ], + // ), + // ), + // barrierDismissible: false, + // ); - return; - } - PaymentController paymentController = Get.find(); - rideConfirm = true; - shouldFetch = true; - isBottomSheetShown = false; - timeToPassengerFromDriverAfterApplied = 60; - // confirmRideForAllDriverAvailable(); - for (var i = 0; i < dataCarsLocationByPassenger['data'].length; i++) { - List body = [ - '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', - '${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}', - totalPassenger.toStringAsFixed(2), - totalDriver.toStringAsFixed(2), - durationToRide.toString(), - distance.toStringAsFixed(2), - dataCarsLocationByPassenger['data'][i]['driver_id'].toString(), - box.read(BoxName.passengerID).toString(), - box.read(BoxName.name).toString(), - box.read(BoxName.tokenFCM).toString(), - box.read(BoxName.phone).toString(), - durationByPassenger.toString(), - distanceByPassenger.toString(), - paymentController.isWalletChecked.toString(), - dataCarsLocationByPassenger['data'][i]['token'].toString(), - durationToPassenger.toString(), - rideId.toString(), - rideTimerBegin.toString(), - dataCarsLocationByPassenger['data'][i]['driver_id'].toString(), - durationToRide.toString(), - Get.find().wayPoints.length > 1 - ? 'haveSteps' - : 'startEnd', - placesCoordinate[0], - placesCoordinate[1], - placesCoordinate[2], - placesCoordinate[3], - placesCoordinate[4], - costForDriver.toStringAsFixed(2), - double.parse(box.read(BoxName.passengerWalletTotal)) < 0 - ? double.parse(box.read(BoxName.passengerWalletTotal)) - .toStringAsFixed(2) - : '0', - box.read(BoxName.email).toString(), - data[0]['start_address'], - data[0]['end_address'], - box.read(BoxName.carType), - kazan.toStringAsFixed(0), - passengerRate.toStringAsFixed(2), - ]; - // Log.print('body: ${body}'); + // return; + // } + // PaymentController paymentController = Get.find(); + // rideConfirm = true; + // shouldFetch = true; + // isBottomSheetShown = false; + // timeToPassengerFromDriverAfterApplied = 60; + // // confirmRideForAllDriverAvailable(); + // for (var i = 0; i < dataCarsLocationByPassenger['message'].length; i++) { + // List body = [ + // '${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}', + // '${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}', + // totalPassenger.toStringAsFixed(2), + // totalDriver.toStringAsFixed(2), + // durationToRide.toString(), + // distance.toStringAsFixed(2), + // dataCarsLocationByPassenger['message'][i]['driver_id'].toString(), + // box.read(BoxName.passengerID).toString(), + // box.read(BoxName.name).toString(), + // box.read(BoxName.tokenFCM).toString(), + // box.read(BoxName.phone).toString(), + // durationByPassenger.toString(), + // distanceByPassenger.toString(), + // paymentController.isWalletChecked.toString(), + // dataCarsLocationByPassenger['message'][i]['token'].toString(), + // durationToPassenger.toString(), + // rideId.toString(), + // rideTimerBegin.toString(), + // dataCarsLocationByPassenger['message'][i]['driver_id'].toString(), + // durationToRide.toString(), + // Get.find().wayPoints.length > 1 + // ? 'haveSteps' + // : 'startEnd', + // placesCoordinate[0], + // placesCoordinate[1], + // placesCoordinate[2], + // placesCoordinate[3], + // placesCoordinate[4], + // costForDriver.toStringAsFixed(2), + // double.parse(box.read(BoxName.passengerWalletTotal)) < 0 + // ? double.parse(box.read(BoxName.passengerWalletTotal)) + // .toStringAsFixed(2) + // : '0', + // box.read(BoxName.email).toString(), + // data[0]['start_address'], + // data[0]['end_address'], + // box.read(BoxName.carType), + // kazan.toStringAsFixed(0), + // passengerRate.toStringAsFixed(2), + // ]; + // // Log.print('body: ${body}'); - FirebaseMessagesController().sendNotificationToDriverMAP( - 'OrderSpeed', - rideId.toString(), - dataCarsLocationByPassenger['data'][i]['token'].toString(), - body, - 'order.wav'); - } + // FirebaseMessagesController().sendNotificationToDriverMAP( + // 'OrderSpeed', + // rideId.toString(), + // dataCarsLocationByPassenger['message'][i]['token'].toString(), + // body, + // 'order.wav'); + // } } int tick = 0; // Move tick outside the function to maintain its state @@ -1760,6 +1766,7 @@ class MapPassengerController extends GetxController { update(); } + String driversStatusForSearchWindow = ''; Future confirmRideForAllDriverAvailable() async { bool driversFound = false; const maxAttempts = 8; @@ -1770,7 +1777,7 @@ class MapPassengerController extends GetxController { await getCarsLocationByPassengerAndReloadMarker( box.read(BoxName.carType), reloadDuration); // await getNearestDriverByPassengerLocation(); - + driversStatusForSearchWindow = 'We are search for nearst driver'.tr; if (isDriversDataValid()) { driversFound = true; break; @@ -1783,9 +1790,16 @@ class MapPassengerController extends GetxController { showNoDriversDialog(); return; } - + driversStatusForSearchWindow = 'Your order is being prepared'.tr; + Log.print('driversStatusForSearchWindow: ${driversStatusForSearchWindow}'); + update(); await postRideDetailsToServer(); + driversStatusForSearchWindow = 'Your order sent to drivers'.tr; await notifyAvailableDrivers(); + + driversStatusForSearchWindow = 'The drivers are reviewing your request'.tr; + Log.print('driversStatusForSearchWindow: ${driversStatusForSearchWindow}'); + update(); delayAndFetchRideStatusForAllDriverAvailable(rideId); update(); } @@ -1823,8 +1837,8 @@ class MapPassengerController extends GetxController { bool isDriversDataValid() { return dataCarsLocationByPassenger != 'failure' && dataCarsLocationByPassenger != null && - dataCarsLocationByPassenger.containsKey('data') && - dataCarsLocationByPassenger['data'] != null; + dataCarsLocationByPassenger.containsKey('message') && + dataCarsLocationByPassenger['message'] != null; } void showNoDriversDialog() { @@ -1889,7 +1903,8 @@ class MapPassengerController extends GetxController { "endtime": durationToAdd.toString(), "price": totalPassenger.toStringAsFixed(2), "passenger_id": box.read(BoxName.passengerID).toString(), - "driver_id": dataCarsLocationByPassenger['data'][carsOrder]['driver_id'] + "driver_id": dataCarsLocationByPassenger['message'][carsOrder] + ['driver_id'] .toString(), "status": "waiting", 'carType': box.read(BoxName.carType), @@ -1911,9 +1926,9 @@ class MapPassengerController extends GetxController { box.read(BoxName.carType), 3000); if (dataCarsLocationByPassenger != null && - dataCarsLocationByPassenger.containsKey('data') && - dataCarsLocationByPassenger['data'] != null) { - for (var driverData in dataCarsLocationByPassenger['data']) { + dataCarsLocationByPassenger.containsKey('message') && + dataCarsLocationByPassenger['message'] != null) { + for (var driverData in dataCarsLocationByPassenger['message']) { String driverId = driverData['driver_id'].toString(); if (!notifiedDrivers.contains(driverId)) { notifiedDrivers.add(driverId); @@ -1926,14 +1941,18 @@ class MapPassengerController extends GetxController { driverLng, ); - double distanceToDriverInKm = distanceToDriverInMeters / 1000; + double distanceToDriverInKm = distanceToDriverInMeters * + 1.25 / //to approximate to stright distance + 1000; double durationToDriverInHours = distanceToDriverInKm / 25; // 25 km/h as default speed double durationToDriverInSeconds = durationToDriverInHours * 3600; durationToPassenger = durationToDriverInSeconds.toInt(); - distanceByPassenger = distanceToDriverInMeters.toStringAsFixed(0); + distanceByPassenger = + (distanceToDriverInMeters * 1.25).toStringAsFixed(0); + Future.delayed(const Duration(microseconds: 10)); final body = constructNotificationBody(driverData); - Log.print('body:ww ${body}'); + // Log.print('body:ww ${body}'); FirebaseMessagesController().sendNotificationToDriverMAP( 'OrderSpeed', rideId, @@ -1961,8 +1980,8 @@ class MapPassengerController extends GetxController { box.read(BoxName.name).toString(), box.read(BoxName.tokenFCM).toString(), box.read(BoxName.phone).toString(), - durationToPassenger.toString(), - distanceByPassenger.toString(), + durationToPassenger.toStringAsFixed(0) ?? '120', + distanceByPassenger.toString() ?? '2000', paymentController.isWalletChecked.toString(), driverData['token'].toString(), durationToPassenger.toString(), @@ -1996,12 +2015,13 @@ class MapPassengerController extends GetxController { StreamController.broadcast(); Stream get rideStatusStream => _rideStatusStreamController.stream; - void delayAndFetchRideStatusForAllDriverAvailable(String rideId) { + Future delayAndFetchRideStatusForAllDriverAvailable( + String rideId) async { const int maxAttempts = 15; int attemptCounter = 0; bool isApplied = false; tick = 0; - + await addRideToNotificationDriverAvailable(); Timer.periodic(const Duration(seconds: 1), (timer) async { if (attemptCounter >= maxAttempts || isApplied) { timer.cancel(); @@ -2014,8 +2034,10 @@ class MapPassengerController extends GetxController { try { var res = await getRideStatus(rideId); + Log.print('res:2022 ${res}'); String rideStatusDelayed = res.toString(); - addRideToNotificationDriverString(); + Log.print('rideStatusDelayed: ${rideStatusDelayed}'); + _rideStatusStreamController .add(rideStatusDelayed); // Emit the ride status // addRideToNotificationDriverString(); @@ -2025,41 +2047,23 @@ class MapPassengerController extends GetxController { "Order Cancelled".tr, "you canceled order".tr, 'ding'); _rideStatusStreamController .close(); // Close stream after cancellation + // + // } else if (rideStatusDelayed == 'Apply' || rideStatusDelayed == 'Applied') { - await getUpdatedRideForDriverApply(rideId); - NotificationController().showNotification( - 'Order Accepted'.tr, - '$driverName ${'accepted your order at price'.tr} ${totalPassenger.toStringAsFixed(1)} ${'with type'.tr} ${box.read(BoxName.carType)}', - 'ding'); - if (box.read(BoxName.carType) == 'Speed' || - box.read(BoxName.carType) == 'Awfar Car') { - NotificationController().showNotification( - 'The captain is responsible for the route.'.tr, - 'This price is fixed even if the route changes for the driver.' - .tr, - 'ding'); - } else if (box.read(BoxName.carType) == 'Comfort' || - box.read(BoxName.carType) == 'Lady') { - NotificationController().showNotification('Attention'.tr, - 'The price may increase if the route changes.'.tr, 'ding'); - } - isApplied = true; - statusRide = 'Apply'; - rideConfirm = false; - isSearchingWindow = false; - - startTimer(); - update(); - startTimerFromDriverToPassengerAfterApplied(); - + rideAppliedFromDriver(isApplied); timer.cancel(); - _rideStatusStreamController.close(); // Close stream after applying - } else if (attemptCounter >= maxAttempts && + // Close stream after applying + } else if (attemptCounter >= maxAttempts || rideStatusDelayed != 'Cancel') { - timer.cancel(); + timer.cancel(); //todo // addRideToNotificationDriverString(); // Show dialog to increase fee... + MyDialog().getDialog( + 'Are you want to wait drivers to accept your order'.tr, '', () { + Get.back(); + addRideToNotificationDriverAvailable(); + }); update(); _rideStatusStreamController .close(); // Close stream after max attempts @@ -2070,6 +2074,36 @@ class MapPassengerController extends GetxController { }); } + rideAppliedFromDriver(bool isApplied) async { + await getUpdatedRideForDriverApply(rideId); + NotificationController().showNotification( + 'Order Accepted'.tr, + '$driverName ${'accepted your order at price'.tr} ${totalPassenger.toStringAsFixed(1)} ${'with type'.tr} ${box.read(BoxName.carType)}', + 'ding'); + if (box.read(BoxName.carType) == 'Speed' || + box.read(BoxName.carType) == 'Awfar Car') { + NotificationController().showNotification( + 'The captain is responsible for the route.'.tr, + 'This price is fixed even if the route changes for the driver.'.tr, + 'ding'); + } else if (box.read(BoxName.carType) == 'Comfort' || + box.read(BoxName.carType) == 'Lady') { + NotificationController().showNotification('Attention'.tr, + 'The price may increase if the route changes.'.tr, 'ding'); + } + isApplied = true; + statusRide = 'Apply'; + rideConfirm = false; + isSearchingWindow = false; + update(); + startTimer(); +// todo stop this because this method in startTimer() + // startTimerFromDriverToPassengerAfterApplied(); + + // timer.cancel(); + _rideStatusStreamController.close(); + } + // Listening to the Stream void listenToRideStatusStream() { rideStatusStream.listen((rideStatus) { @@ -2084,15 +2118,12 @@ class MapPassengerController extends GetxController { } reSearchAfterCanceledFromDriver() async { - await getCarsLocationByPassengerAndReloadMarker( - box.read(BoxName.carType), 3000); - - updateConfirmRideForAllDriverAvailable(); shouldFetch = true; // Stop further fetches statusRide = 'wait'; rideConfirm = true; isSearchingWindow = true; update(); + updateConfirmRideForAllDriverAvailable(); } void start15SecondTimer(String rideId) { @@ -2131,7 +2162,8 @@ class MapPassengerController extends GetxController { final response = await CRUD().get( link: "${AppLink.endPoint}/ride/rides/getRideStatus.php", payload: {'id': rideId}); - + print(response); + print('2140'); return jsonDecode(response)['data']; } @@ -2492,11 +2524,12 @@ class MapPassengerController extends GetxController { } else { noCarString = false; dataCarsLocationByPassenger = jsonDecode(res); - Log.print('dataCarsLocationByPassenger: ${dataCarsLocationByPassenger}'); + Log.print( + 'dataCarsLocationByPassenger:getCarsLocationByPassengerAndReloadMarker ${dataCarsLocationByPassenger}'); // Check if 'message' is present and not null - if (dataCarsLocationByPassenger['data'] != null && - dataCarsLocationByPassenger['data'].isNotEmpty) { + if (dataCarsLocationByPassenger != null && + dataCarsLocationByPassenger.isNotEmpty) { // Check if carsOrder is within bounds // if (carsOrder < dataCarsLocationByPassenger['message'].length) { // driverId = dataCarsLocationByPassenger['message'][carsOrder] @@ -2508,7 +2541,7 @@ class MapPassengerController extends GetxController { // ['token'] // .toString(); // } else { - // print('carsOrder is out of bounds for message array'); + print('carsOrder is in of bounds for message array'); // return false; // } } else { @@ -2519,8 +2552,8 @@ class MapPassengerController extends GetxController { carsLocationByPassenger.clear(); // Clear existing markers - for (var i = 0; i < dataCarsLocationByPassenger['data'].length; i++) { - var json = dataCarsLocationByPassenger['data'][i]; + for (var i = 0; i < dataCarsLocationByPassenger['message'].length; i++) { + var json = dataCarsLocationByPassenger['message'][i]; _updateOrCreateMarker( MarkerId(json['latitude']).toString(), LatLng( @@ -3778,13 +3811,15 @@ class MapPassengerController extends GetxController { if (!rideConfirm) { if (dataCarsLocationByPassenger != 'failure' && dataCarsLocationByPassenger != null && - dataCarsLocationByPassenger['data'] != null && - dataCarsLocationByPassenger['data'].length > 0) { + dataCarsLocationByPassenger['message'] != null && + dataCarsLocationByPassenger['message'].length > 0) { double nearestDistance = double.infinity; // Initialize nearest distance CarLocation? nearestCar; - for (var i = 0; i < dataCarsLocationByPassenger['data'].length; i++) { - var carLocation = dataCarsLocationByPassenger['data'][i]; + for (var i = 0; + i < dataCarsLocationByPassenger['message'].length; + i++) { + var carLocation = dataCarsLocationByPassenger['message'][i]; Log.print('carLocation: $carLocation'); try { diff --git a/lib/controller/local/translations.dart b/lib/controller/local/translations.dart index 6bfd249..c0d2313 100644 --- a/lib/controller/local/translations.dart +++ b/lib/controller/local/translations.dart @@ -617,6 +617,9 @@ iOS [https://getapp.cc/app/6458734951] "Tip is ": " مَبْلَغ الأُكْرَامِيَّة هُوَ", "Are you sure to delete this location?": "هل أنت متأكد من حذف هذا الموقع؟", + 'Are you want to wait drivers to accept your order': + 'هل تريد الانتظار حتى يقبل السائقون طلبك؟', + "deleted": "تم الحذف", 'Trip is begin': "الرحلة قد بدأت", 'This price is fixed even if the route changes for the driver.': @@ -625,6 +628,9 @@ iOS [https://getapp.cc/app/6458734951] "احتمالية زيادة السعر عند تغيير المسار", "The captain is responsible for the route.": "الكابتن مسؤول عن المسار", + 'Your order is being prepared': "جاري تجهيز الطلب", + 'The drivers are reviewing your request': 'يدرس السائقين طلبك', + 'Your order sent to drivers': 'تم إرسال طلبك إلى السائقين', "يمكنك الاتصال أو تسجيل صوت لهذه الرحلة": "You can call or record audio of this trip", diff --git a/lib/views/home/map_widget.dart/searching_captain_window.dart b/lib/views/home/map_widget.dart/searching_captain_window.dart index 5dc5d64..d98c834 100644 --- a/lib/views/home/map_widget.dart/searching_captain_window.dart +++ b/lib/views/home/map_widget.dart/searching_captain_window.dart @@ -137,11 +137,13 @@ class SearchingCaptainWindow extends StatelessWidget { right: 0, child: Container( decoration: AppStyle.boxDecoration1, - height: Get.height * .2, + height: Get.height * .25, child: Column( + mainAxisAlignment: MainAxisAlignment.spaceAround, // Use Stack for overlapping widgets children: [ // Text elements + SizedBox( width: Get.width * .7, child: const LinearProgressIndicator( @@ -151,9 +153,13 @@ class SearchingCaptainWindow extends StatelessWidget { ), ), Text( - "We are searching for the nearest driver to you".tr, + mapPassengerController.driversStatusForSearchWindow, style: AppStyle.title, ), + // Text( + // "We are searching for the nearest driver to you".tr, + // style: AppStyle.title, + // ), Text( 'please wait till driver accept your order'.tr, style: AppStyle.title, diff --git a/lib/views/widgets/my_dialog.dart b/lib/views/widgets/my_dialog.dart index 335d8e4..add3cc1 100644 --- a/lib/views/widgets/my_dialog.dart +++ b/lib/views/widgets/my_dialog.dart @@ -81,7 +81,7 @@ class MyDialogContent extends GetxController { onPressed: () async { await textToSpeechController.speakText(title); }, - child: const Icon(CupertinoIcons.headphones, + child: const Icon(CupertinoIcons.speaker_2, color: AppColor.primaryColor), ), content! diff --git a/shorebird.yaml b/shorebird.yaml index aaa3af7..10c3a35 100644 --- a/shorebird.yaml +++ b/shorebird.yaml @@ -1,11 +1,11 @@ # This file is used to configure the Shorebird updater used by your app. # Learn more at https://docs.shorebird.dev -# This file should be checked into version control. +# This file does not contain any sensitive information and should be checked into version control. -# This is the unique identifier assigned to your app. -# Your app_id is not a secret and is just used to identify your app -# when requesting patches from Shorebird's servers. -app_id: 8a571d7f-dfbf-4a65-be62-17eed08cbd5c +# Your app_id is the unique identifier assigned to your app. +# It is used to identify your app when requesting patches from Shorebird's servers. +# It is not a secret and can be shared publicly. +app_id: 496cb3ac-c25c-455d-9d2e-5ebbea13ab03 # auto_update controls if Shorebird should automatically update in the background on launch. # If auto_update: false, you will need to use package:shorebird_code_push to trigger updates.