|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
|
import 'dart:async';
|
|
|
|
|
import 'dart:convert';
|
|
|
|
|
import 'dart:math' show cos;
|
|
|
|
|
import 'dart:math' show cos, pow, sqrt;
|
|
|
|
|
import 'dart:math' as math;
|
|
|
|
|
|
|
|
|
|
import 'package:SEFER/controller/functions/tts.dart';
|
|
|
|
@@ -892,33 +892,60 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
}));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Map<String, double>? extractCoordinatesFromWhatsAppLink(String link) {
|
|
|
|
|
Map<String, double>? extractCoordinatesFromLink(String link) {
|
|
|
|
|
try {
|
|
|
|
|
// Extract the URL part from the link by finding the first occurrence of "http"
|
|
|
|
|
int urlStartIndex = link.indexOf(RegExp(r'https?://'));
|
|
|
|
|
if (urlStartIndex == -1) {
|
|
|
|
|
throw FormatException('No URL found in the provided link.');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Extract the URL and clean it
|
|
|
|
|
link = link.substring(urlStartIndex).trim();
|
|
|
|
|
|
|
|
|
|
Uri uri = Uri.parse(link);
|
|
|
|
|
|
|
|
|
|
if (uri.host == 'maps.google.com' || uri.host == 'www.google.com') {
|
|
|
|
|
String? query = uri.queryParameters['q'];
|
|
|
|
|
query ??= uri.queryParameters['ll'];
|
|
|
|
|
|
|
|
|
|
if (query != null) {
|
|
|
|
|
List<String> coordinates = query.split(',');
|
|
|
|
|
// Common coordinate query parameters
|
|
|
|
|
List<String> coordinateParams = ['q', 'cp', 'll'];
|
|
|
|
|
|
|
|
|
|
// Try to extract coordinates from query parameters
|
|
|
|
|
for (var param in coordinateParams) {
|
|
|
|
|
String? value = uri.queryParameters[param];
|
|
|
|
|
if (value != null && (value.contains(',') || value.contains('~'))) {
|
|
|
|
|
List<String> coordinates =
|
|
|
|
|
value.contains(',') ? value.split(',') : value.split('~');
|
|
|
|
|
if (coordinates.length == 2) {
|
|
|
|
|
double latitude = double.parse(coordinates[0]);
|
|
|
|
|
double longitude = double.parse(coordinates[1]);
|
|
|
|
|
double? latitude = double.tryParse(coordinates[0].trim());
|
|
|
|
|
double? longitude = double.tryParse(coordinates[1].trim());
|
|
|
|
|
if (latitude != null && longitude != null) {
|
|
|
|
|
return {
|
|
|
|
|
'latitude': latitude,
|
|
|
|
|
'longitude': longitude,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
'latitude': latitude,
|
|
|
|
|
'longitude': longitude,
|
|
|
|
|
};
|
|
|
|
|
// Try to extract coordinates from the path
|
|
|
|
|
List<String> pathSegments = uri.pathSegments;
|
|
|
|
|
for (var segment in pathSegments) {
|
|
|
|
|
if (segment.contains(',')) {
|
|
|
|
|
List<String> coordinates = segment.split(',');
|
|
|
|
|
if (coordinates.length == 2) {
|
|
|
|
|
double? latitude = double.tryParse(coordinates[0].trim());
|
|
|
|
|
double? longitude = double.tryParse(coordinates[1].trim());
|
|
|
|
|
if (latitude != null && longitude != null) {
|
|
|
|
|
return {
|
|
|
|
|
'latitude': latitude,
|
|
|
|
|
'longitude': longitude,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (uri.host == 'goo.gl') {
|
|
|
|
|
// Shortened URLs might need to be expanded first
|
|
|
|
|
// Implement additional logic to expand the URL here if necessary
|
|
|
|
|
}
|
|
|
|
|
} catch (e) {
|
|
|
|
|
print('Error parsing WhatsApp location link: $e');
|
|
|
|
|
print('Error parsing location link: $e');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
@@ -927,7 +954,7 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
double latitudeWhatsApp = 0;
|
|
|
|
|
double longitudeWhatsApp = 0;
|
|
|
|
|
void handleWhatsAppLink(String link) {
|
|
|
|
|
Map<String, double>? coordinates = extractCoordinatesFromWhatsAppLink(link);
|
|
|
|
|
Map<String, double>? coordinates = extractCoordinatesFromLink(link);
|
|
|
|
|
|
|
|
|
|
if (coordinates != null) {
|
|
|
|
|
latitudeWhatsApp = coordinates['latitude']!;
|
|
|
|
@@ -1289,118 +1316,275 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
late LatLng currentDriverLocation;
|
|
|
|
|
late double headingList;
|
|
|
|
|
|
|
|
|
|
Future getCarsLocationByPassengerAndReloadMarker() async {
|
|
|
|
|
// Future getCarsLocationByPassengerAndReloadMarker() async {
|
|
|
|
|
// if (statusRide == 'wait') {
|
|
|
|
|
// carsLocationByPassenger = [];
|
|
|
|
|
// LatLngBounds bounds = calculateBounds(
|
|
|
|
|
// passengerLocation.latitude, passengerLocation.longitude, 7000);
|
|
|
|
|
// var res;
|
|
|
|
|
// if (box.read(BoxName.carType) == '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(),
|
|
|
|
|
// });
|
|
|
|
|
// } else if (box.read(BoxName.carType) == '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(),
|
|
|
|
|
// },
|
|
|
|
|
// );
|
|
|
|
|
// } else if (box.read(BoxName.carType) == '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(),
|
|
|
|
|
// },
|
|
|
|
|
// );
|
|
|
|
|
// } else {
|
|
|
|
|
// 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;
|
|
|
|
|
// update();
|
|
|
|
|
// } else {
|
|
|
|
|
// // Get.snackbar('no car', 'message');
|
|
|
|
|
// noCarString = false;
|
|
|
|
|
// dataCarsLocationByPassenger = jsonDecode(res);
|
|
|
|
|
// // if (dataCarsLocationByPassenger.length > carsOrder) {
|
|
|
|
|
// driverId = dataCarsLocationByPassenger['message'][carsOrder]
|
|
|
|
|
// ['driver_id']
|
|
|
|
|
// .toString();
|
|
|
|
|
// gender = dataCarsLocationByPassenger['message'][carsOrder]['gender']
|
|
|
|
|
// .toString();
|
|
|
|
|
// // }
|
|
|
|
|
|
|
|
|
|
// carsLocationByPassenger.clear(); // Clear existing markers
|
|
|
|
|
|
|
|
|
|
// // late LatLng lastDriverLocation; // Initialize a variable for last location
|
|
|
|
|
|
|
|
|
|
// for (var i = 0;
|
|
|
|
|
// i < dataCarsLocationByPassenger['message'].length;
|
|
|
|
|
// i++) {
|
|
|
|
|
// var json = dataCarsLocationByPassenger['message'][i];
|
|
|
|
|
// // CarLocationModel model = CarLocationModel.fromJson(json);
|
|
|
|
|
// if (carLocationsModels.length < i + 1) {
|
|
|
|
|
// // carLocationsModels.add(model);
|
|
|
|
|
// markers.add(
|
|
|
|
|
// Marker(
|
|
|
|
|
// markerId: MarkerId(json['latitude']),
|
|
|
|
|
// position: LatLng(
|
|
|
|
|
// double.parse(json['latitude']),
|
|
|
|
|
// double.parse(json['longitude']),
|
|
|
|
|
// ),
|
|
|
|
|
// rotation: double.parse(json['heading']),
|
|
|
|
|
// icon: json['model'].toString().contains('دراجة')
|
|
|
|
|
// ? motoIcon
|
|
|
|
|
// : json['gender'] == 'Male'.tr
|
|
|
|
|
// ? carIcon
|
|
|
|
|
// : ladyIcon,
|
|
|
|
|
// ),
|
|
|
|
|
// );
|
|
|
|
|
// driversToken.add(json['token']);
|
|
|
|
|
// // driversToken = json['token'];
|
|
|
|
|
// } else {
|
|
|
|
|
// // carLocationsModels[i] = model;
|
|
|
|
|
// markers[i] = Marker(
|
|
|
|
|
// markerId: MarkerId(json['latitude']),
|
|
|
|
|
// position: LatLng(
|
|
|
|
|
// double.parse(json['latitude']),
|
|
|
|
|
// double.parse(json['longitude']),
|
|
|
|
|
// ),
|
|
|
|
|
// rotation: double.parse(json['heading']),
|
|
|
|
|
// icon: json['model'].contains('دراجة')
|
|
|
|
|
// ? motoIcon
|
|
|
|
|
// : json['gender'] == 'Male'.tr
|
|
|
|
|
// ? carIcon
|
|
|
|
|
// : ladyIcon,
|
|
|
|
|
// );
|
|
|
|
|
// // driversToken = json['token'];
|
|
|
|
|
// driversToken.add(json['token']);
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// update();
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
Map<String, Timer> _animationTimers = {};
|
|
|
|
|
final int updateIntervalMs = 100; // Update every 100ms
|
|
|
|
|
final double minMovementThreshold =
|
|
|
|
|
1.0; // Minimum movement in meters to trigger update
|
|
|
|
|
|
|
|
|
|
Future<void> getCarsLocationByPassengerAndReloadMarker() async {
|
|
|
|
|
if (statusRide == 'wait') {
|
|
|
|
|
carsLocationByPassenger = [];
|
|
|
|
|
LatLngBounds bounds = calculateBounds(
|
|
|
|
|
passengerLocation.latitude, passengerLocation.longitude, 7000);
|
|
|
|
|
var res;
|
|
|
|
|
if (box.read(BoxName.carType) == '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(),
|
|
|
|
|
});
|
|
|
|
|
} else if (box.read(BoxName.carType) == '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(),
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
} else if (box.read(BoxName.carType) == '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(),
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
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(),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var res = await _fetchCarLocations(bounds);
|
|
|
|
|
|
|
|
|
|
if (res == 'failure') {
|
|
|
|
|
noCarString = true;
|
|
|
|
|
dataCarsLocationByPassenger = res;
|
|
|
|
|
update();
|
|
|
|
|
} else {
|
|
|
|
|
// Get.snackbar('no car', 'message');
|
|
|
|
|
noCarString = false;
|
|
|
|
|
dataCarsLocationByPassenger = jsonDecode(res);
|
|
|
|
|
// if (dataCarsLocationByPassenger.length > carsOrder) {
|
|
|
|
|
|
|
|
|
|
driverId = dataCarsLocationByPassenger['message'][carsOrder]
|
|
|
|
|
['driver_id']
|
|
|
|
|
.toString();
|
|
|
|
|
gender = dataCarsLocationByPassenger['message'][carsOrder]['gender']
|
|
|
|
|
.toString();
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
carsLocationByPassenger.clear(); // Clear existing markers
|
|
|
|
|
|
|
|
|
|
// late LatLng lastDriverLocation; // Initialize a variable for last location
|
|
|
|
|
|
|
|
|
|
for (var i = 0;
|
|
|
|
|
i < dataCarsLocationByPassenger['message'].length;
|
|
|
|
|
i++) {
|
|
|
|
|
var json = dataCarsLocationByPassenger['message'][i];
|
|
|
|
|
// CarLocationModel model = CarLocationModel.fromJson(json);
|
|
|
|
|
if (carLocationsModels.length < i + 1) {
|
|
|
|
|
// carLocationsModels.add(model);
|
|
|
|
|
markers.add(
|
|
|
|
|
Marker(
|
|
|
|
|
markerId: MarkerId(json['latitude']),
|
|
|
|
|
position: LatLng(
|
|
|
|
|
double.parse(json['latitude']),
|
|
|
|
|
double.parse(json['longitude']),
|
|
|
|
|
),
|
|
|
|
|
rotation: double.parse(json['heading']),
|
|
|
|
|
icon: json['model'].toString().contains('دراجة')
|
|
|
|
|
? motoIcon
|
|
|
|
|
: json['gender'] == 'Male'.tr
|
|
|
|
|
? carIcon
|
|
|
|
|
: ladyIcon,
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
driversToken.add(json['token']);
|
|
|
|
|
// driversToken = json['token'];
|
|
|
|
|
} else {
|
|
|
|
|
// carLocationsModels[i] = model;
|
|
|
|
|
markers[i] = Marker(
|
|
|
|
|
markerId: MarkerId(json['latitude']),
|
|
|
|
|
position: LatLng(
|
|
|
|
|
double.parse(json['latitude']),
|
|
|
|
|
double.parse(json['longitude']),
|
|
|
|
|
),
|
|
|
|
|
rotation: double.parse(json['heading']),
|
|
|
|
|
icon: json['model'].contains('دراجة')
|
|
|
|
|
? motoIcon
|
|
|
|
|
: json['gender'] == 'Male'.tr
|
|
|
|
|
? carIcon
|
|
|
|
|
: ladyIcon,
|
|
|
|
|
);
|
|
|
|
|
// driversToken = json['token'];
|
|
|
|
|
driversToken.add(json['token']);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_updateMarkers(dataCarsLocationByPassenger['message']);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
BitmapDescriptor _getIconForCar(Map<String, dynamic> carData) {
|
|
|
|
|
if (carData['model'].toString().contains('دراجة')) {
|
|
|
|
|
return motoIcon;
|
|
|
|
|
} else if (carData['gender'] == 'Male'.tr) {
|
|
|
|
|
return carIcon;
|
|
|
|
|
} else {
|
|
|
|
|
return ladyIcon;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _updateOrCreateMarker(String markerId, LatLng newPosition,
|
|
|
|
|
double newHeading, BitmapDescriptor icon) {
|
|
|
|
|
Marker? existingMarker = markers.cast<Marker?>().firstWhere(
|
|
|
|
|
(m) => m?.markerId == MarkerId(markerId),
|
|
|
|
|
orElse: () => null,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (existingMarker == null) {
|
|
|
|
|
markers.add(Marker(
|
|
|
|
|
markerId: MarkerId(markerId),
|
|
|
|
|
position: newPosition,
|
|
|
|
|
rotation: newHeading,
|
|
|
|
|
icon: icon,
|
|
|
|
|
));
|
|
|
|
|
} else {
|
|
|
|
|
double distance =
|
|
|
|
|
_calculateDistance(existingMarker.position, newPosition);
|
|
|
|
|
if (distance >= minMovementThreshold) {
|
|
|
|
|
_smoothlyUpdateMarker(existingMarker, newPosition, newHeading, icon);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _smoothlyUpdateMarker(Marker oldMarker, LatLng newPosition,
|
|
|
|
|
double newHeading, BitmapDescriptor icon) {
|
|
|
|
|
String markerId = oldMarker.markerId.value;
|
|
|
|
|
LatLng startPosition = oldMarker.position;
|
|
|
|
|
double startHeading = oldMarker.rotation ?? 0;
|
|
|
|
|
|
|
|
|
|
_animationTimers[markerId]?.cancel();
|
|
|
|
|
_animationTimers[markerId] =
|
|
|
|
|
Timer.periodic(Duration(milliseconds: updateIntervalMs), (timer) {
|
|
|
|
|
double progress =
|
|
|
|
|
timer.tick / (500 / updateIntervalMs); // 500ms total duration
|
|
|
|
|
if (progress >= 1.0) {
|
|
|
|
|
timer.cancel();
|
|
|
|
|
_animationTimers.remove(markerId);
|
|
|
|
|
progress = 1.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LatLng intermediatePosition = LatLng(
|
|
|
|
|
startPosition.latitude +
|
|
|
|
|
(newPosition.latitude - startPosition.latitude) * progress,
|
|
|
|
|
startPosition.longitude +
|
|
|
|
|
(newPosition.longitude - startPosition.longitude) * progress);
|
|
|
|
|
double intermediateHeading =
|
|
|
|
|
startHeading + (newHeading - startHeading) * progress;
|
|
|
|
|
|
|
|
|
|
markers.removeWhere((m) => m.markerId == oldMarker.markerId);
|
|
|
|
|
markers.add(Marker(
|
|
|
|
|
markerId: oldMarker.markerId,
|
|
|
|
|
position: intermediatePosition,
|
|
|
|
|
rotation: intermediateHeading,
|
|
|
|
|
icon: icon,
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
update();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double _calculateDistance(LatLng start, LatLng end) {
|
|
|
|
|
// Implement distance calculation (e.g., Haversine formula)
|
|
|
|
|
// For simplicity, this is a placeholder. Replace with actual implementation.
|
|
|
|
|
return 1000 *
|
|
|
|
|
sqrt(pow(start.latitude - end.latitude, 2) +
|
|
|
|
|
pow(start.longitude - end.longitude, 2));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Future getTokenForParent() async {
|
|
|
|
|
if (box.read(BoxName.sosPhonePassenger) == null) {
|
|
|
|
|
Get.defaultDialog(
|
|
|
|
@@ -1558,6 +1742,11 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Timer? _timer;
|
|
|
|
|
// final int updateIntervalMs = 100; // Update every 100ms
|
|
|
|
|
// final double minMovementThreshold =
|
|
|
|
|
// 1.0; // Minimum movement in meters to trigger update
|
|
|
|
|
|
|
|
|
|
void clearMarkersExceptStartEnd() {
|
|
|
|
|
Set<Marker> markersToRemove = markers
|
|
|
|
|
.where((marker) =>
|
|
|
|
@@ -1567,39 +1756,72 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
|
|
|
|
|
for (Marker marker in markersToRemove) {
|
|
|
|
|
markers.remove(marker);
|
|
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void reloadMarkerDriverCarsLocationToPassengerAfterApplied() {
|
|
|
|
|
clearMarkersExceptStartEnd();
|
|
|
|
|
// for (var i = 0; i < driverCarsLocationToPassengerAfterApplied.length; i++) {
|
|
|
|
|
|
|
|
|
|
LatLng driverPosition = LatLng(
|
|
|
|
|
double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0]
|
|
|
|
|
['latitude']),
|
|
|
|
|
double.parse(datadriverCarsLocationToPassengerAfterApplied['message'][0]
|
|
|
|
|
['longitude']));
|
|
|
|
|
final driverAcceptedMarker = Marker(
|
|
|
|
|
markerId: const MarkerId('driverToPassengers'),
|
|
|
|
|
position: driverPosition,
|
|
|
|
|
rotation: double.parse(
|
|
|
|
|
datadriverCarsLocationToPassengerAfterApplied['message'][0]
|
|
|
|
|
['heading']),
|
|
|
|
|
icon: datadriverCarsLocationToPassengerAfterApplied['message'][0]['model']
|
|
|
|
|
.contains('دراجة')
|
|
|
|
|
? motoIcon
|
|
|
|
|
: datadriverCarsLocationToPassengerAfterApplied['message'][0]
|
|
|
|
|
['gender'] ==
|
|
|
|
|
'Male'.tr
|
|
|
|
|
? carIcon
|
|
|
|
|
: ladyIcon, // Default to carIcon if gender is not Male or Female
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
markers.add(driverAcceptedMarker);
|
|
|
|
|
// update();
|
|
|
|
|
mapController?.animateCamera(CameraUpdate.newLatLng(driverPosition));
|
|
|
|
|
update();
|
|
|
|
|
// } // Update the map with the new markers
|
|
|
|
|
double heading = double.parse(
|
|
|
|
|
datadriverCarsLocationToPassengerAfterApplied['message'][0]['heading']
|
|
|
|
|
.toString());
|
|
|
|
|
|
|
|
|
|
BitmapDescriptor icon =
|
|
|
|
|
datadriverCarsLocationToPassengerAfterApplied['message'][0]['model']
|
|
|
|
|
.toString()
|
|
|
|
|
.contains('دراجة')
|
|
|
|
|
? motoIcon
|
|
|
|
|
: datadriverCarsLocationToPassengerAfterApplied['message'][0]
|
|
|
|
|
['gender'] ==
|
|
|
|
|
'Male'.tr
|
|
|
|
|
? carIcon
|
|
|
|
|
: ladyIcon;
|
|
|
|
|
|
|
|
|
|
_updateMarkerPosition(driverPosition, heading, icon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _updateMarkerPosition(
|
|
|
|
|
LatLng newPosition, double newHeading, BitmapDescriptor icon) {
|
|
|
|
|
const String markerId = 'driverToPassengers';
|
|
|
|
|
Marker? existingMarker = markers.cast<Marker?>().firstWhere(
|
|
|
|
|
(m) => m?.markerId == const MarkerId(markerId),
|
|
|
|
|
orElse: () => null,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if (existingMarker == null) {
|
|
|
|
|
// If the marker doesn't exist, create it at the new position
|
|
|
|
|
markers.add(Marker(
|
|
|
|
|
markerId: const MarkerId(markerId),
|
|
|
|
|
position: newPosition,
|
|
|
|
|
rotation: newHeading,
|
|
|
|
|
icon: icon,
|
|
|
|
|
));
|
|
|
|
|
update();
|
|
|
|
|
} else {
|
|
|
|
|
// If the marker exists, check if the movement is significant enough to update
|
|
|
|
|
double distance =
|
|
|
|
|
_calculateDistance(existingMarker.position, newPosition);
|
|
|
|
|
if (distance >= minMovementThreshold) {
|
|
|
|
|
_smoothlyUpdateMarker(existingMarker, newPosition, newHeading, icon);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mapController?.animateCamera(CameraUpdate.newLatLng(newPosition));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
|
void onClose() {
|
|
|
|
|
_timer?.cancel();
|
|
|
|
|
_animationTimers.forEach((_, timer) => timer.cancel());
|
|
|
|
|
_animationTimers.clear();
|
|
|
|
|
super.onClose();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
restCounter() {
|
|
|
|
@@ -1907,9 +2129,11 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio
|
|
|
|
|
// scale: 1.0,
|
|
|
|
|
);
|
|
|
|
|
BitmapDescriptor.fromAssetImage(config, 'assets/images/picker.png',
|
|
|
|
|
mipmaps: false)
|
|
|
|
|
.then((value) {
|
|
|
|
|
BitmapDescriptor.asset(
|
|
|
|
|
config,
|
|
|
|
|
'assets/images/picker.png',
|
|
|
|
|
// mipmaps: false,
|
|
|
|
|
).then((value) {
|
|
|
|
|
markerIcon = value;
|
|
|
|
|
update();
|
|
|
|
|
});
|
|
|
|
@@ -1920,9 +2144,11 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
|
|
|
|
|
ImageConfiguration config = ImageConfiguration(
|
|
|
|
|
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
|
|
|
|
|
BitmapDescriptor.fromAssetImage(config, 'assets/images/A.png',
|
|
|
|
|
mipmaps: false)
|
|
|
|
|
.then((value) {
|
|
|
|
|
BitmapDescriptor.asset(
|
|
|
|
|
config,
|
|
|
|
|
'assets/images/A.png',
|
|
|
|
|
// mipmaps: false,
|
|
|
|
|
).then((value) {
|
|
|
|
|
startIcon = value;
|
|
|
|
|
update();
|
|
|
|
|
});
|
|
|
|
@@ -1931,9 +2157,11 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
void addCustomEndIcon() {
|
|
|
|
|
ImageConfiguration config = ImageConfiguration(
|
|
|
|
|
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
|
|
|
|
|
BitmapDescriptor.fromAssetImage(config, 'assets/images/b.png',
|
|
|
|
|
mipmaps: false)
|
|
|
|
|
.then((value) {
|
|
|
|
|
BitmapDescriptor.asset(
|
|
|
|
|
config,
|
|
|
|
|
'assets/images/b.png',
|
|
|
|
|
// mipmaps: false,
|
|
|
|
|
).then((value) {
|
|
|
|
|
endIcon = value;
|
|
|
|
|
update();
|
|
|
|
|
});
|
|
|
|
@@ -1942,9 +2170,11 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
void addCustomCarIcon() {
|
|
|
|
|
ImageConfiguration config = ImageConfiguration(
|
|
|
|
|
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
|
|
|
|
|
BitmapDescriptor.fromAssetImage(config, 'assets/images/car.png',
|
|
|
|
|
mipmaps: false)
|
|
|
|
|
.then((value) {
|
|
|
|
|
BitmapDescriptor.asset(
|
|
|
|
|
config,
|
|
|
|
|
'assets/images/car.png',
|
|
|
|
|
// mipmaps: false,
|
|
|
|
|
).then((value) {
|
|
|
|
|
carIcon = value;
|
|
|
|
|
update();
|
|
|
|
|
});
|
|
|
|
@@ -1953,9 +2183,11 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
void addCustomMotoIcon() {
|
|
|
|
|
ImageConfiguration config = ImageConfiguration(
|
|
|
|
|
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
|
|
|
|
|
BitmapDescriptor.fromAssetImage(config, 'assets/images/moto1.png',
|
|
|
|
|
mipmaps: false)
|
|
|
|
|
.then((value) {
|
|
|
|
|
BitmapDescriptor.asset(
|
|
|
|
|
config,
|
|
|
|
|
'assets/images/moto1.png',
|
|
|
|
|
// mipmaps: false,
|
|
|
|
|
).then((value) {
|
|
|
|
|
motoIcon = value;
|
|
|
|
|
update();
|
|
|
|
|
});
|
|
|
|
@@ -1964,9 +2196,11 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
void addCustomLadyIcon() {
|
|
|
|
|
ImageConfiguration config = ImageConfiguration(
|
|
|
|
|
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
|
|
|
|
|
BitmapDescriptor.fromAssetImage(config, 'assets/images/lady1.png',
|
|
|
|
|
mipmaps: false)
|
|
|
|
|
.then((value) {
|
|
|
|
|
BitmapDescriptor.asset(
|
|
|
|
|
config,
|
|
|
|
|
'assets/images/lady1.png',
|
|
|
|
|
// mipmaps: false,
|
|
|
|
|
).then((value) {
|
|
|
|
|
ladyIcon = value;
|
|
|
|
|
update();
|
|
|
|
|
});
|
|
|
|
@@ -1975,9 +2209,11 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
void addCustomStepIcon() {
|
|
|
|
|
ImageConfiguration config = ImageConfiguration(
|
|
|
|
|
size: const Size(30, 30), devicePixelRatio: Get.pixelRatio);
|
|
|
|
|
BitmapDescriptor.fromAssetImage(config, 'assets/images/brand.png',
|
|
|
|
|
mipmaps: false)
|
|
|
|
|
.then((value) {
|
|
|
|
|
BitmapDescriptor.asset(
|
|
|
|
|
config,
|
|
|
|
|
'assets/images/brand.png',
|
|
|
|
|
// mipmaps: false,
|
|
|
|
|
).then((value) {
|
|
|
|
|
tripIcon = value;
|
|
|
|
|
update();
|
|
|
|
|
});
|
|
|
|
@@ -2817,12 +3053,14 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
List driversForMishwari = [];
|
|
|
|
|
Future selectDriverAndCarForMishwariTrip() async {
|
|
|
|
|
var res = await CRUD()
|
|
|
|
|
.get(link: AppLink.selectDriverAndCarForMishwariTrip, payload: {});
|
|
|
|
|
if (res != 'failure') {
|
|
|
|
|
var d = jsonDecode(res);
|
|
|
|
|
return d['message'];
|
|
|
|
|
driversForMishwari = d['message'];
|
|
|
|
|
update();
|
|
|
|
|
} else {
|
|
|
|
|
return 'No driver available now try later time\nthanks for using our app'
|
|
|
|
|
.tr;
|
|
|
|
@@ -2839,14 +3077,10 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
// isBottomSheetShown = false;
|
|
|
|
|
update();
|
|
|
|
|
// add dialoug for select driver and car
|
|
|
|
|
List driversForMishwari = await selectDriverAndCarForMishwariTrip();
|
|
|
|
|
await selectDriverAndCarForMishwariTrip();
|
|
|
|
|
Future.delayed(Duration.zero);
|
|
|
|
|
Log.print('driversForMishwari: ${driversForMishwari}');
|
|
|
|
|
Get.to(() => CupertinoDriverListWidget(
|
|
|
|
|
drivers: driversForMishwari,
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
// add dialoug to select date and time
|
|
|
|
|
Get.to(() => CupertinoDriverListWidget());
|
|
|
|
|
|
|
|
|
|
// changeCashConfirmPageShown();
|
|
|
|
|
}
|
|
|
|
@@ -2856,15 +3090,36 @@ class MapPassengerController extends GetxController {
|
|
|
|
|
try {
|
|
|
|
|
// Prepare trip data
|
|
|
|
|
Map<String, dynamic> tripData = {
|
|
|
|
|
'driver_id': driver['id'],
|
|
|
|
|
'passenger_id': box.read(BoxName.passengerID),
|
|
|
|
|
'trip_datetime': tripDateTime.toIso8601String(),
|
|
|
|
|
// Add other necessary trip details
|
|
|
|
|
'id': driver['id'],
|
|
|
|
|
'phone': driver['phone'],
|
|
|
|
|
'gender': driver['gender'],
|
|
|
|
|
'name': driver['name'],
|
|
|
|
|
'name_english': driver['name_english'],
|
|
|
|
|
'address': driver['address'],
|
|
|
|
|
'religion': driver['religion'],
|
|
|
|
|
'age': driver['age'],
|
|
|
|
|
'education': driver['education'],
|
|
|
|
|
'license_type': driver['license_type'],
|
|
|
|
|
'national_number': driver['national_number'],
|
|
|
|
|
'car_plate': driver['car_plate'],
|
|
|
|
|
'make': driver['make'],
|
|
|
|
|
'model': driver['model'],
|
|
|
|
|
'year': driver['year'],
|
|
|
|
|
'color': driver['color'],
|
|
|
|
|
'color_hex': driver['color_hex'],
|
|
|
|
|
'displacement': driver['displacement'],
|
|
|
|
|
'fuel': driver['fuel'],
|
|
|
|
|
'token': driver['token'],
|
|
|
|
|
'rating': driver['rating'],
|
|
|
|
|
'countRide': driver['countRide'],
|
|
|
|
|
'passengerId': box.read(BoxName.passengerID),
|
|
|
|
|
'timeSelected': tripDateTime.toIso8601String(),
|
|
|
|
|
'status': 'pending', // Or other appropriate status
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Send data to server
|
|
|
|
|
var response =
|
|
|
|
|
await CRUD().post(link: AppLink.addAdminUser, payload: tripData);
|
|
|
|
|
await CRUD().post(link: AppLink.addMishwari, payload: tripData);
|
|
|
|
|
|
|
|
|
|
if (response != 'failure') {
|
|
|
|
|
// Trip saved successfully
|
|
|
|
|