This commit is contained in:
Hamza-Ayed
2024-08-03 00:50:14 +03:00
parent 74abae1b38
commit 871b9a4d09
24 changed files with 689 additions and 211 deletions

View File

@@ -5,6 +5,7 @@ import 'dart:math' as math;
import 'package:SEFER/controller/functions/tts.dart';
import 'package:SEFER/views/home/map_page_passenger.dart';
import 'package:SEFER/views/widgets/my_dialog.dart';
import 'package:SEFER/views/widgets/my_textField.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
@@ -739,7 +740,10 @@ class MapPassengerController extends GetxController {
var res = await CRUD().get(
link: AppLink.getRideStatusFromStartApp,
payload: {'passenger_id': box.read(BoxName.passengerID)});
if (res == 'failure') {}
if (res == 'failure') {
print(
"No rides found for the given passenger ID within the last hour.");
}
rideStatusFromStartApp = jsonDecode(res);
if (rideStatusFromStartApp['data']['status'] == 'Begin') {
statusRide = 'Begin';
@@ -968,12 +972,6 @@ class MapPassengerController extends GetxController {
}
}
// Example usage
void someFunction() {
String whatsAppLink = 'https://maps.google.com/maps?q=37.4220,-122.0841';
handleWhatsAppLink(whatsAppLink);
}
void goToWhatappLocation() async {
if (sosFormKey.currentState!.validate()) {
changeIsWhatsAppOrder(true);
@@ -999,7 +997,8 @@ class MapPassengerController extends GetxController {
late String make = '';
late String licensePlate = '';
confirmRideForFirstDriver() async {
await getCarsLocationByPassengerAndReloadMarker();
startCarLocationSearch(box.read(BoxName.carType));
// await getCarsLocationByPassengerAndReloadMarker();
await getNearestDriverByPassengerLocationAPIGOOGLE();
if (dataCarsLocationByPassenger != 'failure') {
@@ -1097,10 +1096,12 @@ class MapPassengerController extends GetxController {
box.read(BoxName.carType),
kazan.toStringAsFixed(0),
passengerRate.toStringAsFixed(2),
]; //
];
Log.print('body: ${body}');
FirebaseMessagesController().sendNotificationToDriverMAP(
'Order'.tr,
jsonDecode(value)['message'].toString(),
'from: $startNameAddress\nto: $startNameAddress\ndistanceFromMe: $distanceByPassenger\nDistance :$distance\nPrice ; $totalPassenger',
// jsonDecode(value)['message'].toString(),
dataCarsLocationByPassenger['message'][carsOrder]['token']
.toString(),
body,
@@ -1108,6 +1109,8 @@ class MapPassengerController extends GetxController {
// polylineCoordinates.toString()
);
Log.print(
'body: ${dataCarsLocationByPassenger['message'][carsOrder]['token']}');
});
delayAndFetchRideStatus(rideId);
if (shouldFetch == false) {
@@ -1135,12 +1138,13 @@ class MapPassengerController extends GetxController {
bool isDriversTokensSend = false;
confirmRideForAllDriverAvailable() async {
// isDriversTokensSend = true;
driversToken.remove(driverToken);
PaymentController paymentController = Get.find<PaymentController>();
rideConfirm = true;
shouldFetch = true;
isBottomSheetShown = false;
timeToPassengerFromDriverAfterApplied = 60;
driversToken.remove(driverToken);
List<String> body = [
'${data[0]["start_location"]['lat']},${data[0]["start_location"]['lng']}',
'${data[0]["end_location"]['lat']},${data[0]["end_location"]['lng']}',
@@ -1196,44 +1200,57 @@ class MapPassengerController extends GetxController {
update();
}
int tick = 0; // Move tick outside the function to maintain its state
void delayAndFetchRideStatus(String rideId) {
Timer(const Duration(seconds: 1), () async {
Timer.periodic(const Duration(seconds: 1), (timer) async {
if (shouldFetch) {
if (remainingTimeToPassengerFromDriverAfterApplied > 0) {
var res = await getRideStatus(rideId);
String res = await getRideStatus(rideId);
// var decod = jsonDecode(res);
if (res.toString() == 'Apply') {
// getUpdatedRideForDriverApply(rideId);
Log.print('tick: $tick');
if (res.toString() == 'waiting' && tick == 15) {
timer.cancel(); // Stop the current timer
delayAndFetchRideStatusForAllDriverAvailable(rideId);
} else if (res.toString() == 'Apply') {
timer.cancel(); // Stop the current timer
shouldFetch = false; // Stop further fetches
statusRide = 'Apply';
rideConfirm = false;
isSearchingWindow = false;
update();
startTimerFromDriverToPassengerAfterApplied();
// startTimer();
} else if (res.toString() == 'Refused') {
statusRide = 'Refused';
// isDriversTokensSend = false;
if (isDriversTokensSend == false) {
confirmRideForAllDriverAvailable();
isDriversTokensSend = true;
}
} // Start 15-second timer
} else if (isDriversTokensSend == false) {
delayAndFetchRideStatus(
rideId); // Repeat the delay and fetch operation
// No need to recall delayAndFetchRideStatus as Timer.periodic is already running
update();
}
tick++;
} else {
timer
.cancel(); // Stop the timer if remainingTimeToPassengerFromDriverAfterApplied <= 0
}
} else {
timer.cancel(); // Stop the timer if shouldFetch is false
}
});
}
void delayAndFetchRideStatusForAllDriverAvailable(String rideId) {
Timer(const Duration(milliseconds: 1000), () async {
if (shouldFetch) {
int attemptCounter = 0;
const int maxAttempts = 15;
void fetchRideStatus() async {
if (shouldFetch && attemptCounter < maxAttempts) {
attemptCounter++;
var res = await getRideStatus(rideId);
// var decod = jsonDecode(res);
if (res.toString() == 'Apply') {
getUpdatedRideForDriverApply(rideId);
@@ -1243,10 +1260,28 @@ class MapPassengerController extends GetxController {
isSearchingWindow = false;
update();
startTimerFromDriverToPassengerAfterApplied();
} else if (res.toString() == 'Refused') {
delayAndFetchRideStatusForAllDriverAvailable(rideId);
} else {
Timer(const Duration(seconds: 2),
fetchRideStatus); // Continue fetching for other statuses
}
} else {
// Stop fetching after maxAttempts or if shouldFetch is false
shouldFetch = false;
MyDialog().getDialog('upgrade price'.tr,
'You can upgrade price to may driver accept your order'.tr, () {
Get.back();
});
update();
print('Stopped fetching ride status after 30 seconds.');
}
}
fetchRideStatus(); // Initial call to start the process
}
void start15SecondTimer(String rideId) {
Timer(const Duration(seconds: 15), () {
delayAndFetchRideStatusForAllDriverAvailable(rideId);
});
}
@@ -1431,89 +1466,134 @@ class MapPassengerController extends GetxController {
Map<String, Timer> _animationTimers = {};
final int updateIntervalMs = 100; // Update every 100ms
final double minMovementThreshold =
1.0; // Minimum movement in meters to trigger update
10; // Minimum movement in meters to trigger update
Future<void> getCarsLocationByPassengerAndReloadMarker() async {
void startCarLocationSearch(String carType) {
int searchInterval = 5; // Interval in seconds
int boundIncreaseStep = 4500; // Initial bounds in meters
int maxAttempts = 3; // Maximum attempts to increase bounds
int attempt = 0; // Current attempt
Timer.periodic(Duration(seconds: searchInterval), (Timer timer) async {
if (attempt >= maxAttempts) {
timer.cancel();
noCarString = true;
dataCarsLocationByPassenger = 'failure';
update();
return;
}
bool foundCars = await getCarsLocationByPassengerAndReloadMarker(
carType, boundIncreaseStep);
if (foundCars) {
timer.cancel();
} else {
attempt++;
boundIncreaseStep = boundIncreaseStep + 1500; // Increase bounds
}
});
}
Future<bool> getCarsLocationByPassengerAndReloadMarker(
String carType, int boundIncreaseStep) async {
if (statusRide == 'wait') {
LatLngBounds bounds = calculateBounds(
passengerLocation.latitude, passengerLocation.longitude, 7000);
carsLocationByPassenger = [];
LatLngBounds bounds = calculateBounds(passengerLocation.latitude,
passengerLocation.longitude, boundIncreaseStep.toDouble());
var res;
var res = await _fetchCarLocations(bounds);
switch (carType) {
case 'Lady':
res = await CRUD()
.get(link: AppLink.getFemalDriverLocationByPassenger, payload: {
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
});
break;
case 'Comfort':
res = await CRUD()
.get(link: AppLink.getCarsLocationByPassengerComfort, payload: {
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
});
break;
case 'Speed':
res = await CRUD()
.get(link: AppLink.getCarsLocationByPassengerSpeed, payload: {
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
});
break;
case 'Delivery':
res = await CRUD()
.get(link: AppLink.getCarsLocationByPassengerDelivery, payload: {
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
});
break;
default:
res = await CRUD()
.get(link: AppLink.getCarsLocationByPassenger, payload: {
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
});
}
if (res == 'failure') {
noCarString = true;
dataCarsLocationByPassenger = res;
// noCarString = true;
// dataCarsLocationByPassenger = res;
// update();
return false;
} else {
noCarString = false;
dataCarsLocationByPassenger = jsonDecode(res);
driverId = dataCarsLocationByPassenger['message'][carsOrder]
['driver_id']
.toString();
gender = dataCarsLocationByPassenger['message'][carsOrder]['gender']
.toString();
_updateMarkers(dataCarsLocationByPassenger['message']);
carsLocationByPassenger.clear(); // Clear existing markers
for (var i = 0;
i < dataCarsLocationByPassenger['message'].length;
i++) {
var json = dataCarsLocationByPassenger['message'][i];
_updateOrCreateMarker(
MarkerId(json['latitude']).toString(),
LatLng(double.parse(json['latitude']),
double.parse(json['longitude'])),
double.parse(json['heading']),
_getIconForCar(json),
);
driversToken.add(json['token']);
}
update();
return true;
}
update();
}
}
Future<String> _fetchCarLocations(LatLngBounds bounds) async {
var payload = {
'southwestLat': bounds.southwest.latitude.toString(),
'southwestLon': bounds.southwest.longitude.toString(),
'northeastLat': bounds.northeast.latitude.toString(),
'northeastLon': bounds.northeast.longitude.toString(),
};
String link;
switch (box.read(BoxName.carType)) {
case 'Lady':
link = AppLink.getFemalDriverLocationByPassenger;
break;
case 'Speed':
link = AppLink.getCarsLocationByPassengerSpeed;
break;
case 'Delivery':
link = AppLink.getCarsLocationByPassengerDelivery;
break;
default:
link = AppLink.getCarsLocationByPassenger;
}
return await CRUD().get(link: link, payload: payload);
}
void _updateMarkers(List<dynamic> carsData) {
driversToken.clear();
for (var json in carsData) {
String markerId = json['driver_id'].toString();
LatLng newPosition = LatLng(
double.parse(json['latitude']),
double.parse(json['longitude']),
);
double newHeading = double.parse(json['heading']);
BitmapDescriptor icon = _getIconForCar(json);
_updateOrCreateMarker(markerId, newPosition, newHeading, icon);
driversToken.add(json['token']);
}
// Remove markers for cars that are no longer present
markers.removeWhere((marker) => !carsData
.any((car) => car['driver_id'].toString() == marker.markerId.value));
return false;
}
BitmapDescriptor _getIconForCar(Map<String, dynamic> carData) {
if (carData['model'].toString().contains('دراجة')) {
return motoIcon;
} else if (carData['gender'] == 'Male'.tr) {
return carIcon;
} else {
} else if (carData['gender'] == 'Female') {
return ladyIcon;
} else {
return carIcon;
}
}
@@ -1611,6 +1691,8 @@ class MapPassengerController extends GetxController {
'sosPhone': sosPhonePassengerProfile.text,
},
);
box.write(
BoxName.sosPhonePassenger, sosPhonePassengerProfile.text);
}
}));
}
@@ -1714,12 +1796,12 @@ class MapPassengerController extends GetxController {
Future runEvery30SecondsUntilConditionMet() async {
// Calculate the duration of the trip in minutes.
double tripDurationInMinutes = durationToPassenger / 6;
double tripDurationInMinutes = durationToPassenger / 5;
int loopCount = tripDurationInMinutes.ceil();
// If the trip duration is less than or equal to 50 minutes, then break the loop.
for (var i = 0; i < loopCount; i++) {
// Wait for 50 seconds.
await Future.delayed(const Duration(seconds: 4));
await Future.delayed(const Duration(seconds: 5));
if (rideTimerBegin == true || statusRide == 'Apply') {
await getDriverCarsLocationToPassengerAfterApplied();
reloadMarkerDriverCarsLocationToPassengerAfterApplied();
@@ -1761,7 +1843,7 @@ class MapPassengerController extends GetxController {
}
void reloadMarkerDriverCarsLocationToPassengerAfterApplied() {
clearMarkersExceptStartEnd();
// clearMarkersExceptStartEnd();
LatLng driverPosition = LatLng(
double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0]
@@ -1780,9 +1862,9 @@ class MapPassengerController extends GetxController {
? motoIcon
: datadriverCarsLocationToPassengerAfterApplied['message'][0]
['gender'] ==
'Male'.tr
? carIcon
: ladyIcon;
'Female'
? ladyIcon
: carIcon;
_updateMarkerPosition(driverPosition, heading, icon);
}
@@ -1834,6 +1916,18 @@ class MapPassengerController extends GetxController {
update();
}
searchNewDriverAfterRejectingFromDriver() {
//
shouldFetch = true; // Stop further fetches
statusRide = 'wait';
rideConfirm = true;
isSearchingWindow = true;
confirmRideForFirstDriver();
update();
}
Future<void> cancelRideAfterRejectFromAll() async {
clearPlacesDestination();
clearPolyline();
@@ -1869,6 +1963,10 @@ class MapPassengerController extends GetxController {
"order_id": rideId.toString(), // Convert to String
"status": 'Cancel'
});
await CRUD().post(link: AppLink.updateRides, payload: {
"id": rideId.toString(), // Convert to String
"status": 'Cancel'
});
print('Cancel');
FirebaseMessagesController().sendNotificationToDriverMAP(
'Cancel Trip',
@@ -2169,7 +2267,7 @@ class MapPassengerController extends GetxController {
void addCustomCarIcon() {
ImageConfiguration config = ImageConfiguration(
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
size: const Size(30, 35), devicePixelRatio: Get.pixelRatio);
BitmapDescriptor.asset(
config,
'assets/images/car.png',
@@ -2332,7 +2430,7 @@ class MapPassengerController extends GetxController {
startMarkerReloading() async {
int reloadCount = 0;
Timer.periodic(const Duration(seconds: 2), (timer) {
Timer.periodic(const Duration(seconds: 5), (timer) {
reloadCount++;
if (!rideConfirm) {
@@ -2348,11 +2446,13 @@ class MapPassengerController extends GetxController {
}
reloadMarkers() async {
if (statusRide == 'wait') {
clearMarkersExceptStartEnd();
await getCarsLocationByPassengerAndReloadMarker();
await getNearestDriverByPassengerLocation();
}
// if (statusRide == 'wait') {
clearMarkersExceptStartEnd();
// _smoothlyUpdateMarker();
startCarLocationSearch(box.read(BoxName.carType));
// await getCarsLocationByPassengerAndReloadMarker();
await getNearestDriverByPassengerLocation();
// }
}
String durationByPassenger = '';
@@ -2361,6 +2461,7 @@ class MapPassengerController extends GetxController {
String distanceByPassenger = '';
late Duration durationFromDriverToPassenger;
double nearestDistance = double.infinity;
Future<CarLocation?> getNearestDriverByPassengerLocation() async {
if (polyLines.isEmpty || data.isEmpty) {
return null; // Early return if data is empty
@@ -2380,7 +2481,7 @@ class MapPassengerController extends GetxController {
double.parse(carLocation['latitude']),
double.parse(carLocation['longitude']),
);
durationToPassenger = (distance * 35 * (1000 / 3600))
durationToPassenger = (distance * 25 * (1000 / 3600))
.round(); //////35 is avg of speed in city
// Update the UI with the distance and duration
update();
@@ -2487,13 +2588,38 @@ class MapPassengerController extends GetxController {
update();
} else {
Get.defaultDialog(
barrierDismissible: false,
title: 'The Driver Will be in your location soon .'.tr,
middleText: 'The distance less than 500 meter.'.tr,
confirm: MyElevatedButton(
title: 'Ok'.tr,
onPressed: () {
Get.back();
},
confirm: Column(
children: [
MyElevatedButton(
kolor: AppColor.greenColor,
title: 'Ok'.tr,
onPressed: () {
Get.back();
},
),
MyElevatedButton(
kolor: AppColor.redColor,
title: 'No, I want to cancel this trip'.tr,
onPressed: () {
Get.back();
MyDialog().getDialog(
'Attention'.tr,
'You will be charged for the cost of the driver coming to your location.'
.tr,
() async {
Get.back();
Get.find<PaymentController>()
.payToDriverForCancelAfterAppliedAndHeNearYou(rideId);
// isCancelRidePageShown = true;
// update();
},
);
},
),
],
),
);
// cancel: MyElevatedButton(
@@ -2528,7 +2654,8 @@ class MapPassengerController extends GetxController {
isLoading = true;
update();
remainingTime = 25; //to make cancel every call
await getCarsLocationByPassengerAndReloadMarker();
startCarLocationSearch(box.read(BoxName.carType));
// await getCarsLocationByPassengerAndReloadMarker();
var coordDestination = destination.split(',');
double latPassengerDestination = double.parse(coordDestination[0]);
double lngPassengerDestination = double.parse(coordDestination[1]);
@@ -2731,7 +2858,8 @@ class MapPassengerController extends GetxController {
getMapPoints(String originSteps, String destinationSteps, int index) async {
isWayPointStopsSheetUtilGetMap = false;
// haveSteps = true;
await getCarsLocationByPassengerAndReloadMarker();
startCarLocationSearch(box.read(BoxName.carType));
// await getCarsLocationByPassengerAndReloadMarker();
// isLoading = true;
update();
var url =