Fixes & Updates - 2026-06-01: Integrate Back-End v3 updates, fix call/connection issues across apps
This commit is contained in:
@@ -93,13 +93,13 @@ class NavigationController extends GetxController
|
||||
String totalDistanceRemaining = "";
|
||||
String estimatedTimeRemaining = "";
|
||||
dynamic currentManeuverModifier = 0;
|
||||
String arrivalTime = "--:--";
|
||||
String arrivalTime = "--:--"; // NEW: For the active navigation HUD
|
||||
|
||||
double _routeTotalDistanceM = 0;
|
||||
double _routeTotalDurationS = 0;
|
||||
|
||||
bool isNavigating = false;
|
||||
bool isMuted = false;
|
||||
bool isMuted = false; // Sound toggle state
|
||||
String distanceWithUnit = "";
|
||||
bool _cameraLockedToUser = true;
|
||||
bool _mapReady = false;
|
||||
@@ -114,6 +114,7 @@ class NavigationController extends GetxController
|
||||
Future<void> submitNewPlace(String name, String category) async {
|
||||
if (mapController == null || name.isEmpty || category.isEmpty) return;
|
||||
|
||||
// Get current center of the map as the picked location
|
||||
final LatLng pickedPos = mapController!.cameraPosition!.target;
|
||||
|
||||
isLoading = true;
|
||||
@@ -139,15 +140,21 @@ class NavigationController extends GetxController
|
||||
isLoading = false;
|
||||
if (response != null) {
|
||||
HapticFeedback.lightImpact();
|
||||
mySnackbarSuccess('Place added successfully! Thanks for your contribution.'.tr);
|
||||
mySnackbarSuccess(box.read(BoxName.lang) == 'ar'
|
||||
? 'تمت إضافة المكان بنجاح! شكراً لمساهمتك.'
|
||||
: 'Place added successfully! Thanks for your contribution.');
|
||||
isSelectingPlaceLocation = false;
|
||||
} else {
|
||||
mySnackbarWarning('Failed to add place. Please try again later.'.tr);
|
||||
mySnackbarWarning(box.read(BoxName.lang) == 'ar'
|
||||
? 'تعذر إضافة المكان. يرجى المحاولة لاحقاً.'
|
||||
: 'Failed to add place. Please try again later.');
|
||||
}
|
||||
update();
|
||||
} catch (e) {
|
||||
isLoading = false;
|
||||
mySnackbarWarning('An error occurred while connecting to the server.'.tr);
|
||||
mySnackbarWarning(box.read(BoxName.lang) == 'ar'
|
||||
? 'حدث خطأ أثناء الاتصال بالخادم.'
|
||||
: 'An error occurred while connecting to the server.');
|
||||
update();
|
||||
}
|
||||
}
|
||||
@@ -181,6 +188,7 @@ class NavigationController extends GetxController
|
||||
return 55.0;
|
||||
}
|
||||
|
||||
// Categories list for the picker
|
||||
static final List<Map<String, String>> placeCategories = [
|
||||
{
|
||||
'id': 'restaurant',
|
||||
@@ -303,6 +311,7 @@ class NavigationController extends GetxController
|
||||
_smoothedHeading = _lerpAngle(_oldHeading, _targetHeading, t);
|
||||
|
||||
if (isStyleLoaded) {
|
||||
_updateCarMarker();
|
||||
if (_cameraLockedToUser) {
|
||||
animateCameraToPosition(myLocation!,
|
||||
bearing: _smoothedHeading,
|
||||
@@ -365,7 +374,6 @@ class NavigationController extends GetxController
|
||||
void onMapCreated(IntaleqMapController controller) async {
|
||||
Log.print("DEBUG: NavigationController.onMapCreated called");
|
||||
mapController = controller;
|
||||
await onStyleLoaded();
|
||||
}
|
||||
|
||||
Future<void> onStyleLoaded() async {
|
||||
@@ -381,6 +389,7 @@ class NavigationController extends GetxController
|
||||
if (myLocation != null) {
|
||||
Log.print("DEBUG: Animating camera to initial location: $myLocation");
|
||||
animateCameraToPosition(myLocation!);
|
||||
_updateCarMarker();
|
||||
}
|
||||
if (_fullRouteCoordinates.isNotEmpty) {
|
||||
Log.print("DEBUG: Updating initial polylines");
|
||||
@@ -394,7 +403,7 @@ class NavigationController extends GetxController
|
||||
if (isNavigating || routes.isEmpty) return;
|
||||
|
||||
int? bestIndex;
|
||||
double minDistance = 100.0;
|
||||
double minDistance = 100.0; // 100 meters threshold for tap
|
||||
|
||||
for (int i = 0; i < routes.length; i++) {
|
||||
for (var coord in routes[i].coordinates) {
|
||||
@@ -422,12 +431,12 @@ class NavigationController extends GetxController
|
||||
Get.dialog(
|
||||
AlertDialog(
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||
title: Text('Start Navigation?'.tr,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold)),
|
||||
content: Text('Do you want to go to this location?'.tr),
|
||||
title: const Text('بدء الملاحة؟',
|
||||
style: TextStyle(fontWeight: FontWeight.bold)),
|
||||
content: const Text('هل تريد الذهاب إلى هذا الموقع؟'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: Text('Cancel'.tr, style: const TextStyle(color: Colors.grey)),
|
||||
child: const Text('إلغاء', style: TextStyle(color: Colors.grey)),
|
||||
onPressed: () => Get.back()),
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
@@ -435,10 +444,10 @@ class NavigationController extends GetxController
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12))),
|
||||
child:
|
||||
Text('Go Now'.tr, style: const TextStyle(color: Colors.white)),
|
||||
const Text('اذهب الآن', style: TextStyle(color: Colors.white)),
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
startNavigationTo(tappedPoint, infoWindowTitle: 'Selected Location'.tr);
|
||||
startNavigationTo(tappedPoint, infoWindowTitle: 'الموقع المحدد');
|
||||
},
|
||||
),
|
||||
],
|
||||
@@ -458,6 +467,7 @@ class NavigationController extends GetxController
|
||||
_smoothedHeading = position.heading;
|
||||
update();
|
||||
if (isStyleLoaded) animateCameraToPosition(myLocation!);
|
||||
// Start the Location Stream for real-time updates
|
||||
_startLocationStream();
|
||||
_startBatchTimers();
|
||||
} catch (e) {
|
||||
@@ -467,10 +477,12 @@ class NavigationController extends GetxController
|
||||
|
||||
void _startLocationStream() {
|
||||
_locationStreamSubscription?.cancel();
|
||||
// Listen to location updates with minimum distance filter of 2 meters
|
||||
// This provides real-time updates without the 3-4 second delay
|
||||
_locationStreamSubscription = Geolocator.getPositionStream(
|
||||
locationSettings: const LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
distanceFilter: 2,
|
||||
distanceFilter: 2, // Update every 2 meters
|
||||
),
|
||||
).listen(
|
||||
(Position position) {
|
||||
@@ -489,8 +501,9 @@ class NavigationController extends GetxController
|
||||
|
||||
try {
|
||||
final newLoc = LatLng(position.latitude, position.longitude);
|
||||
currentSpeed = position.speed * 3.6;
|
||||
currentSpeed = position.speed * 3.6; // Convert m/s to km/h
|
||||
|
||||
// Skip if movement is too small
|
||||
if (_lastProcessedLocation != null) {
|
||||
final d = Geolocator.distanceBetween(
|
||||
newLoc.latitude,
|
||||
@@ -507,6 +520,7 @@ class NavigationController extends GetxController
|
||||
Log.print(
|
||||
"DEBUG: Location update - Speed: ${currentSpeed.toStringAsFixed(1)} km/h, Loc: $newLoc");
|
||||
|
||||
// Update total distance
|
||||
if (_lastDistanceLocation != null) {
|
||||
final d = Geolocator.distanceBetween(
|
||||
_lastDistanceLocation!.latitude,
|
||||
@@ -536,6 +550,8 @@ class NavigationController extends GetxController
|
||||
_animController?.forward(from: 0.0);
|
||||
_lastProcessedLocation = newLoc;
|
||||
|
||||
if (isStyleLoaded) _updateCarMarker();
|
||||
|
||||
if (_fullRouteCoordinates.isNotEmpty) {
|
||||
_updateTraveledPolylineSmart(newLoc);
|
||||
_checkNavigationStep(newLoc);
|
||||
@@ -556,7 +572,7 @@ class NavigationController extends GetxController
|
||||
}
|
||||
|
||||
void _checkOffRoute(LatLng pos) {
|
||||
if (_autoRecalcInProgress || isLoading) return;
|
||||
if (!isNavigating || _autoRecalcInProgress || isLoading) return;
|
||||
if (_fullRouteCoordinates.isEmpty) return;
|
||||
|
||||
const int searchWindow = 80;
|
||||
@@ -591,33 +607,11 @@ class NavigationController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
/// Recalculate immediately from the latest GPS point to the destination.
|
||||
Future<void> _smartRecalculateRoute(LatLng currentPos) async {
|
||||
try {
|
||||
if (routes.isNotEmpty && selectedRouteIndex < routes.length - 1) {
|
||||
final nextIndex = selectedRouteIndex + 1;
|
||||
final nextRoute = routes[nextIndex];
|
||||
|
||||
double minDist = double.infinity;
|
||||
for (var coord in nextRoute.coordinates) {
|
||||
final d = Geolocator.distanceBetween(
|
||||
currentPos.latitude,
|
||||
currentPos.longitude,
|
||||
coord.latitude,
|
||||
coord.longitude,
|
||||
);
|
||||
if (d < minDist) minDist = d;
|
||||
}
|
||||
|
||||
if (minDist < 100) {
|
||||
selectRoute(nextIndex);
|
||||
Log.print("DEBUG: Switched to alternative route due to deviation");
|
||||
_autoRecalcInProgress = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_finalDestination != null) {
|
||||
await recalculateRoute();
|
||||
await recalculateRoute(origin: currentPos, keepNavigationActive: true);
|
||||
}
|
||||
_autoRecalcInProgress = false;
|
||||
} catch (e) {
|
||||
@@ -669,13 +663,13 @@ class NavigationController extends GetxController
|
||||
if (_trackBuffer.isEmpty) return;
|
||||
final batch = List<Map<String, dynamic>>.from(_trackBuffer);
|
||||
_trackBuffer.clear();
|
||||
final String driverId = (box.read(BoxName.driverID) ?? '').toString();
|
||||
final String passengerId = (box.read(BoxName.passengerID) ?? '').toString();
|
||||
|
||||
try {
|
||||
await CRUD().post(
|
||||
link: '${AppLink.locationServerSide}/add_batch.php',
|
||||
payload: {
|
||||
'driver_id': driverId,
|
||||
'driver_id': passengerId,
|
||||
'batch_data': jsonEncode(batch),
|
||||
'session_dist': totalDistance.toStringAsFixed(1),
|
||||
},
|
||||
@@ -685,6 +679,10 @@ class NavigationController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateCarMarker() async {
|
||||
// Car marker is now handled natively by myLocationEnabled: true.
|
||||
}
|
||||
|
||||
void animateCameraToPosition(LatLng position,
|
||||
{double? zoom, double bearing = 0.0, double tilt = 0.0}) {
|
||||
if (!_mapReady || mapController == null) return;
|
||||
@@ -774,8 +772,11 @@ class NavigationController extends GetxController
|
||||
|
||||
Future<void> _updatePolylinesSets(
|
||||
List<LatLng> traveled, List<LatLng> remaining) async {
|
||||
Log.print(
|
||||
"DEBUG: Updating polylines. Traveled: ${traveled.length}, Remaining: ${remaining.length}");
|
||||
Set<Polyline> newPolylines = {};
|
||||
|
||||
// Render Alternative Routes first
|
||||
for (int i = 0; i < routes.length; i++) {
|
||||
if (i == selectedRouteIndex) continue;
|
||||
newPolylines.add(Polyline(
|
||||
@@ -840,7 +841,7 @@ class NavigationController extends GetxController
|
||||
if (dest != null && myLocation != null) {
|
||||
getRoute(myLocation!, dest);
|
||||
} else {
|
||||
mySnackbarWarning(box.read(BoxName.lang) == 'ar' ? 'الموقع غير متاح حالياً.' : 'Location not available.');
|
||||
mySnackbarWarning('الموقع غير متاح حالياً.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -865,12 +866,13 @@ class NavigationController extends GetxController
|
||||
LatLng getAirportLatLng() {
|
||||
final String country = box.read(BoxName.countryCode) ?? 'JO';
|
||||
if (country == 'SY') {
|
||||
return const LatLng(33.4111, 36.5147);
|
||||
return const LatLng(33.4111, 36.5147); // Damascus Airport
|
||||
}
|
||||
return const LatLng(31.7225, 35.9933);
|
||||
return const LatLng(31.7225, 35.9933); // Queen Alia Airport (JO)
|
||||
}
|
||||
|
||||
Future<void> getRoute(LatLng origin, LatLng destination) async {
|
||||
Future<void> getRoute(LatLng origin, LatLng destination,
|
||||
{bool keepNavigationActive = false}) async {
|
||||
isLoading = true;
|
||||
update();
|
||||
|
||||
@@ -899,12 +901,13 @@ class NavigationController extends GetxController
|
||||
if (response.statusCode != 200) {
|
||||
isLoading = false;
|
||||
update();
|
||||
mySnackbarWarning(box.read(BoxName.lang) == 'ar' ? 'تعذر الاتصال بخدمة التوجيه.' : 'Failed to connect to routing service.');
|
||||
mySnackbarWarning('تعذر الاتصال بخدمة التوجيه.');
|
||||
return;
|
||||
}
|
||||
|
||||
final data = jsonDecode(response.body);
|
||||
|
||||
// ── Parse primary route (top-level in response) ──
|
||||
routes.clear();
|
||||
final primaryPts = data['points']?.toString() ?? "";
|
||||
if (primaryPts.isNotEmpty) {
|
||||
@@ -919,8 +922,10 @@ class NavigationController extends GetxController
|
||||
));
|
||||
}
|
||||
|
||||
// ── Parse alternative routes (in data['alternatives']) ──
|
||||
// إذا كان هناك routes بديلة متاحة من API
|
||||
if (data['alternatives'] != null && data['alternatives'] is List) {
|
||||
_hasAlternativeRoutes = (data['alternatives'] as List).isNotEmpty;
|
||||
_hasAlternativeRoutes = data['alternatives'].isNotEmpty;
|
||||
for (var alt in data['alternatives']) {
|
||||
final altPts = alt['points']?.toString() ?? "";
|
||||
if (altPts.isEmpty) continue;
|
||||
@@ -934,6 +939,9 @@ class NavigationController extends GetxController
|
||||
points: altPts,
|
||||
));
|
||||
}
|
||||
if (_hasAlternativeRoutes) {
|
||||
Log.print("DEBUG: ${routes.length - 1} alternative routes available");
|
||||
}
|
||||
} else {
|
||||
_hasAlternativeRoutes = false;
|
||||
}
|
||||
@@ -941,7 +949,7 @@ class NavigationController extends GetxController
|
||||
if (routes.isEmpty) {
|
||||
isLoading = false;
|
||||
update();
|
||||
mySnackbarWarning(box.read(BoxName.lang) == 'ar' ? 'لم يتم العثور على مسار.' : 'No route found.');
|
||||
mySnackbarWarning('لم يتم العثور على مسار.');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -965,8 +973,8 @@ class NavigationController extends GetxController
|
||||
currentStepIndex = 0;
|
||||
_nextInstructionSpoken = false;
|
||||
|
||||
isNavigating = false;
|
||||
_cameraLockedToUser = false;
|
||||
isNavigating = keepNavigationActive;
|
||||
_cameraLockedToUser = keepNavigationActive;
|
||||
_offRouteStartTime = null;
|
||||
isLoading = false;
|
||||
|
||||
@@ -986,7 +994,13 @@ class NavigationController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
if (_fullRouteCoordinates.length >= 2) {
|
||||
// Re-add car marker after polyline updates (ensures it stays on top)
|
||||
if (isStyleLoaded) _updateCarMarker();
|
||||
|
||||
if (keepNavigationActive && myLocation != null) {
|
||||
animateCameraToPosition(myLocation!,
|
||||
bearing: _smoothedHeading, zoom: _targetZoom, tilt: _targetTilt);
|
||||
} else if (_fullRouteCoordinates.length >= 2) {
|
||||
final bounds =
|
||||
data['bbox'] != null && (data['bbox'] as List).length == 4
|
||||
? LatLngBounds(
|
||||
@@ -1012,17 +1026,22 @@ class NavigationController extends GetxController
|
||||
final remainingM = _routeTotalDistanceM * fraction;
|
||||
final remainingS = _routeTotalDurationS * fraction;
|
||||
|
||||
// Distance
|
||||
final String langCode = box.read(BoxName.lang) ?? 'ar';
|
||||
if (remainingM > 1000) {
|
||||
totalDistanceRemaining = (remainingM / 1000).toStringAsFixed(1);
|
||||
// We will handle the unit in the view or provide a unit string here
|
||||
} else {
|
||||
totalDistanceRemaining = remainingM.toStringAsFixed(0);
|
||||
}
|
||||
// New variable to hold formatted distance with unit
|
||||
distanceWithUnit = _formatDistance(remainingM, langCode);
|
||||
|
||||
// Time Remaining
|
||||
final minutes = (remainingS / 60).round();
|
||||
estimatedTimeRemaining = minutes.toString();
|
||||
|
||||
// Arrival Time Calculation
|
||||
final arrival = DateTime.now().add(Duration(seconds: remainingS.toInt()));
|
||||
final h = arrival.hour > 12
|
||||
? arrival.hour - 12
|
||||
@@ -1040,6 +1059,7 @@ class NavigationController extends GetxController
|
||||
_finalDestination = destination;
|
||||
await clearRoute(isNewRoute: true);
|
||||
|
||||
// Preserve car marker if it exists
|
||||
markers = markers.where((m) => m.markerId.value == 'car').toSet();
|
||||
|
||||
markers.add(Marker(
|
||||
@@ -1065,12 +1085,23 @@ class NavigationController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> recalculateRoute() async {
|
||||
if (myLocation == null || _finalDestination == null || isLoading) return;
|
||||
Future<void> recalculateRoute(
|
||||
{LatLng? origin, bool keepNavigationActive = false}) async {
|
||||
final LatLng? routeOrigin = origin ?? myLocation;
|
||||
if (routeOrigin == null || _finalDestination == null || isLoading) return;
|
||||
|
||||
isLoading = true;
|
||||
update();
|
||||
mySnackbarInfo(box.read(BoxName.lang) == 'ar' ? 'جاري حساب مسار جديد...' : 'Calculating new route...');
|
||||
await getRoute(myLocation!, _finalDestination!);
|
||||
|
||||
markers = markers.where((m) => m.markerId.value != 'origin').toSet();
|
||||
markers.add(Marker(
|
||||
markerId: const MarkerId('origin'),
|
||||
position: routeOrigin,
|
||||
icon: InlqBitmap.fromStyleImage('start_icon'),
|
||||
));
|
||||
|
||||
await getRoute(routeOrigin, _finalDestination!,
|
||||
keepNavigationActive: keepNavigationActive);
|
||||
isLoading = false;
|
||||
update();
|
||||
}
|
||||
@@ -1087,8 +1118,11 @@ class NavigationController extends GetxController
|
||||
isNavigating = true;
|
||||
_cameraLockedToUser = true;
|
||||
|
||||
// Ensure ETA and distances are up-to-date
|
||||
_lastTraveledIndexInFullRoute = _lastTraveledIndexInFullRoute;
|
||||
_recomputeETA();
|
||||
|
||||
// Initialize current instruction if available
|
||||
if (routeSteps.isNotEmpty && currentStepIndex < routeSteps.length) {
|
||||
currentInstruction = routeSteps[currentStepIndex]['text'] ?? "";
|
||||
currentManeuverModifier = routeSteps[currentStepIndex]['sign'] ?? 0;
|
||||
@@ -1105,6 +1139,7 @@ class NavigationController extends GetxController
|
||||
}
|
||||
}
|
||||
|
||||
// Center camera on user for navigation mode
|
||||
if (myLocation != null) {
|
||||
animateCameraToPosition(myLocation!,
|
||||
bearing: _smoothedHeading, zoom: _targetZoom, tilt: _targetTilt);
|
||||
@@ -1145,22 +1180,21 @@ class NavigationController extends GetxController
|
||||
_routeTotalDistanceM = 0;
|
||||
_routeTotalDurationS = 0;
|
||||
|
||||
if (!isNewRoute) {
|
||||
await _updateCarMarker();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> _loadCustomIcons() async {
|
||||
if (mapController == null) return;
|
||||
try {
|
||||
final carBytes = await rootBundle.load('assets/images/car.png');
|
||||
final startBytes = await rootBundle.load('assets/images/A.png');
|
||||
final destBytes = await rootBundle.load('assets/images/b.png');
|
||||
await mapController!.addImage('car_icon', carBytes.buffer.asUint8List());
|
||||
await mapController!
|
||||
.addImage('start_icon', startBytes.buffer.asUint8List());
|
||||
await mapController!.addImage('dest_icon', destBytes.buffer.asUint8List());
|
||||
} catch (e) {
|
||||
Log.print("Error loading custom icons: $e");
|
||||
}
|
||||
final carBytes = await rootBundle.load('assets/images/car.png');
|
||||
final startBytes = await rootBundle.load('assets/images/A.png');
|
||||
final destBytes = await rootBundle.load('assets/images/b.png');
|
||||
await mapController!.addImage('car_icon', carBytes.buffer.asUint8List());
|
||||
await mapController!
|
||||
.addImage('start_icon', startBytes.buffer.asUint8List());
|
||||
await mapController!.addImage('dest_icon', destBytes.buffer.asUint8List());
|
||||
}
|
||||
|
||||
void _checkNavigationStep(LatLng pos) {
|
||||
@@ -1233,18 +1267,21 @@ class NavigationController extends GetxController
|
||||
if (mapController == null) return;
|
||||
|
||||
try {
|
||||
// ✅ Use searchPlaces from intaleq_maps SDK
|
||||
final results = await mapController!.searchPlaces(q);
|
||||
|
||||
|
||||
if (myLocation != null) {
|
||||
for (final p in results) {
|
||||
final plat = double.tryParse(p['latitude']?.toString() ?? '0') ?? 0.0;
|
||||
final plng = double.tryParse(p['longitude']?.toString() ?? '0') ?? 0.0;
|
||||
p['distanceKm'] = _haversineKm(myLocation!.latitude, myLocation!.longitude, plat, plng);
|
||||
final plng =
|
||||
double.tryParse(p['longitude']?.toString() ?? '0') ?? 0.0;
|
||||
p['distanceKm'] = _haversineKm(
|
||||
myLocation!.latitude, myLocation!.longitude, plat, plng);
|
||||
}
|
||||
results.sort((a, b) =>
|
||||
(a['distanceKm'] as double).compareTo(b['distanceKm'] as double));
|
||||
}
|
||||
|
||||
|
||||
placesDestination = results;
|
||||
update();
|
||||
} catch (e) {
|
||||
@@ -1258,7 +1295,7 @@ class NavigationController extends GetxController
|
||||
final lat = double.parse(place['latitude'].toString());
|
||||
final lng = double.parse(place['longitude'].toString());
|
||||
await startNavigationTo(LatLng(lat, lng),
|
||||
infoWindowTitle: place['name'] ?? (box.read(BoxName.lang) == 'ar' ? 'وجهة' : 'Destination'));
|
||||
infoWindowTitle: place['name'] ?? 'وجهة');
|
||||
}
|
||||
|
||||
void onSearchChanged(String query) {
|
||||
@@ -1278,6 +1315,9 @@ class NavigationController extends GetxController
|
||||
return R * 2 * atan2(sqrt(a), sqrt(1 - a));
|
||||
}
|
||||
|
||||
double _kmToLatDelta(double km) => km / 111.32;
|
||||
double _kmToLngDelta(double km, double lat) =>
|
||||
km / (111.32 * cos(lat * pi / 180));
|
||||
LatLngBounds _boundsFromLatLngList(List<LatLng> list) {
|
||||
double? x0, x1, y0, y1;
|
||||
for (final ll in list) {
|
||||
@@ -1328,12 +1368,12 @@ class NavigationController extends GetxController
|
||||
'name': name,
|
||||
'lat': myLocation!.latitude.toString(),
|
||||
'lng': myLocation!.longitude.toString(),
|
||||
'driver_id': box.read(BoxName.driverID),
|
||||
'passenger_id': box.read(BoxName.passengerID),
|
||||
};
|
||||
await CRUD().post(link: AppLink.getPlacesSyria, payload: payload);
|
||||
mySnackbarInfo(box.read(BoxName.lang) == 'ar'
|
||||
? "تم استلام اقتراحك! شكراً لمساهمتك."
|
||||
: "Suggestion received! Thanks for your contribution.");
|
||||
? "تم استلام اقتراحك! مكافأتك: +٥٠ نقطة"
|
||||
: "Suggestion received! Reward: +50 points");
|
||||
} finally {
|
||||
isLoading = false;
|
||||
update();
|
||||
|
||||
Reference in New Issue
Block a user