import 'dart:async'; import 'dart:developer'; import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; import 'package:get_it/get_it.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import '../config/style.dart'; import '../models/map/address/AdressResponse.dart'; import '../models/map/address/Geometry.dart'; import '../models/map/place/PredictionModel.dart'; import '../models/map/route/local_route.dart'; import '../models/map/route/route_response.dart'; import '../services/map_services/decode_polyline.dart'; import '../services/map_services/map_services.dart'; import '../services/map_services/reverse_geocode.dart'; import '../services/map_services/route.dart'; import '../services/map_services/search.dart'; import '../utils/load_marker.dart'; class LocationProvider with ChangeNotifier { LatLng? current; // loc.Location location=loc.Location(); bool serviceEnabled=false; // late loc.PermissionStatus permissionGranted; MapServices get service => GetIt.I(); bool loader=false; LatLng? cameraPosition; Set markers = {}; Set addressMarker = {}; Completer mapController = Completer(); Completer addressMapController = Completer(); ReverseGeocode revGeocode = ReverseGeocode(); CameraPosition kGooglePlex = const CameraPosition( target: LatLng(23.661429, 54.388161), zoom: 12, ); AdressResponseModel? draggingAdress; AdressResponseModel? addressModel1; AdressResponseModel? addressModel2; AdressResponseModel? addressModel3; AdressResponseModel? addressModel4; RoutesAPI routeService = RoutesAPI(); String? encodedPolyline; Set polylines = {}; List polylineCoordinates = []; bool loading=false; String? distance; String? duration; SearchAPI search = SearchAPI(); List places=[]; Geomtry? position; disposeMap(){ current=null; serviceEnabled=false; loader=false; cameraPosition=null; markers = {}; addressMarker = {}; mapController = Completer(); addressMapController = Completer(); revGeocode = ReverseGeocode(); kGooglePlex = const CameraPosition( target: LatLng(23.661429, 54.388161), zoom: 12, ); draggingAdress=null; encodedPolyline=null; polylines = {}; polylineCoordinates = []; loading=false; distance=null; duration=null; places=[]; position=null; } setMapComponents(){ current=null; loader=false; cameraPosition=null; markers = {}; mapController = Completer(); kGooglePlex = const CameraPosition( target: LatLng(37.42796133580664, -122.085749655962), zoom: 14.4746, ); draggingAdress=null; } setAddressMapComponent(){ addressMapController = Completer(); addressMarker = {}; } setMapController(controller){ mapController=controller; notifyListeners(); } disposePlaces(){ places=[]; } addMarker(LatLng pos){ if(assetMarker!=null){ markers.add( Marker( markerId: const MarkerId('marker'), position: pos, icon: assetMarker!, anchor: const Offset(0.5, 1.2), )); notifyListeners(); } } Future askLocationPermission() async { bool serviceEnabled; LocationPermission permission; try{ serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { // Location services are not enabled don't continue // accessing the position and request users of the // App to enable the location services. return Future.error('Location services are disabled.'); } permission = await Geolocator.checkPermission(); permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { // Permissions are denied, next time you could try // requesting permissions again (this is also where // Android's shouldShowRequestPermissionRationale // returned true. According to Android guidelines // your App should show an explanatory UI now. return Future.error('Location permissions are denied'); } } if (permission == LocationPermission.deniedForever) { // Permissions are denied forever, handle appropriately. return Future.error( 'Location permissions are permanently denied, we cannot request permissions.'); } notifyListeners(); return true; // permissionGranted = await location.hasPermission(); // if (permissionGranted == loc.PermissionStatus.denied) { // permissionGranted = await location.requestPermission(); // if (permissionGranted != loc.PermissionStatus.granted) { // log("permission not granted !!!"); // return false; // } else { // serviceEnabled = await location.serviceEnabled(); // if (!serviceEnabled) { // serviceEnabled = await location.requestService(); // if (!serviceEnabled) { // return false; // } // return true; // }else{ // return true; // } // } // } // return true; }catch(e){ log(e.toString()); loading=false; notifyListeners(); return false; } } Future getAdress(double latitude, double longitude) async { try{ var addresses = await service.getAdress(latitude.toString(),longitude.toString()); if(addresses.data!=null && addresses.data!.results!=null && addresses.data!.results!.first.formattedAddress!=null){ var adr = addresses.data!.results!.first.formattedAddress; log(adr??'no address yet'); return adr; }else{ // popup(NavigatorService.navigatorKey.currentContext!,"Ok",title: "Error",description:"Please check your internet connection"); return null; } }catch(e){ log(e.toString()); loading=false; notifyListeners(); return null; } } initLoc() async{ log("initLoc !!!!!!!!!!!!!!!!"); if(await askLocationPermission()){ final pos = await Geolocator.getCurrentPosition(); current = LatLng(pos.latitude, pos.longitude); return current; } } ///***************************************** get location ************************************************/ Future getCurrentLocation({bool? init,int? count}) async { try{ loader=true; if(init!=null && init){ Future.delayed(Duration.zero,(){ notifyListeners(); }); }else{ notifyListeners(); } if(current==null){ if(await askLocationPermission()){ final pos = await Geolocator.getCurrentPosition(); current = LatLng(pos.latitude, pos.longitude); if(current!=null){ if(init!=null){ moveCamera(current!); final result=await getDraggingAdress(current!.latitude,current!.longitude,count); if(result!=null){ loader=false; if(init){ Future.delayed(Duration.zero,(){ notifyListeners(); }); }else{ notifyListeners(); } return current; } } } loader=false; if(init!=null && init){ Future.delayed(Duration.zero,(){ notifyListeners(); }); }else{ notifyListeners(); } return current; }else{ loader=false; if(init!=null && init){ Future.delayed(Duration.zero,(){ notifyListeners(); }); }else{ notifyListeners(); } } }else{ if(init!=null){ moveCamera(current!); final result=await getDraggingAdress(current!.latitude,current!.longitude,count); if(result!=null){ loader=false; if(init){ Future.delayed(Duration.zero,(){ notifyListeners(); }); }else{ notifyListeners(); } return current; } } loader=false; if(init!=null && init){ Future.delayed(Duration.zero,(){ notifyListeners(); }); }else{ notifyListeners(); } return current; } }catch(e){ loader=false; if(init!=null && init){ Future.delayed(Duration.zero,(){ notifyListeners(); }); }else{ notifyListeners(); } log(e.toString()); return null; } loader=false; if(init!=null && init){ Future.delayed(Duration.zero,(){ notifyListeners(); }); }else{ notifyListeners(); } return null; } double calculateDistance(lat1, lon1, lat2, lon2) { var p = 0.017453292519943295; var c = math.cos; var a = 0.5 - c((lat2 - lat1) * p) / 2 + c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p)) / 2; var result = 1000 * 12742 * math.asin(math.sqrt(a)); return roundDouble(result, 2)/1000; } double roundDouble(double value, int places) { num mod = math.pow(10.0, places); return ((value * mod).round().toDouble() / mod); } void onCameraIdle(int? count) async { if (cameraPosition != null) { await getDraggingAdress(cameraPosition!.latitude,cameraPosition!.longitude,count); notifyListeners(); } } Future moveCamera(LatLng pos) async { final GoogleMapController controller = await mapController.future ; controller.moveCamera(CameraUpdate.newCameraPosition(CameraPosition( target: pos, zoom: 16, ))); notifyListeners(); } addAddressMarker(LatLng pos){ if(assetMarker!=null){ addressMarker.add( Marker( markerId: const MarkerId('marker'), position: pos, icon: assetMarker!, anchor: const Offset(0.5, 1.2), )); notifyListeners(); } } Future addressMoveCamera(LatLng pos) async { final GoogleMapController controller = await addressMapController.future ; controller.moveCamera(CameraUpdate.newCameraPosition(CameraPosition( target: pos, zoom: 16, ))); notifyListeners(); } Future getDraggingAdress(double latitude, double longitude,int? count) async { try{ var addresses = await revGeocode.getAddress(latitude.toString(),longitude.toString()); if(addresses.data!=null){ draggingAdress=addresses.data; if(count!=null){ switch (count) { case 1: addressModel1 = addresses.data; break; case 2: addressModel2 = addresses.data; break; case 3: addressModel3 = addresses.data; break; case 4: addressModel4 = addresses.data; break; } } notifyListeners(); return addresses.data!; } return null; }catch(e){ log(e.toString()); loading=false; notifyListeners(); return null; } } /// *************************************************************************** get local route *********************************************************/ Future getLocalRouteInfos (LatLng start,LatLng end) async { try{ var route =await getRoute(start.latitude, start.longitude, end.latitude, end.longitude); log("route !!!!!!!!!!!!!"); if(route!=null && route.routes!=null && route.routes!.isNotEmpty && route.routes!.first.overviewPolyline!=null && route.routes!.first.overviewPolyline!.points!=null ){ var encodedPolyline=route.routes!.first.overviewPolyline!.points; if(encodedPolyline!=null){ List decoded = DecodePolyline.decodePoly(encodedPolyline); List converted =DecodePolyline.convertToLatLng(decoded); var localDistance=route.routes!.first.legs?.first.distance?.text; var localDuration=route.routes!.first.legs?.first.duration?.text; LocalRoute model=LocalRoute(route:converted,distance: localDistance,duration: localDuration); return model; }else{ loading=false; notifyListeners(); } }else{ loading=false; notifyListeners(); // popup(context,"Ok",title: "Error",description:"Error loading this route, Please Try another !"); } return null; }catch(e){ log(e.toString()); loading=false; notifyListeners(); return null; } } Future getPlaceById(String id) async { try{ var result = await search.searchById(id); if(result.statusCode==200 || result.statusCode==201 && result.data!=null){ if(result.data!.result!=null && result.data!.result!.geometry!=null){ position=result.data!.result!.geometry!; notifyListeners(); return position; } return null; } }catch(e){ log(e.toString()); loading=false; notifyListeners(); return null; } return null; // return addresses.data; } /// *************************************************************************** show local route *********************************************************/ showRoute(LocalRoute? route,BuildContext context) async { if (route != null && route.route != null) { polylines.add( Polyline( width: 5, polylineId: const PolylineId('polyLine'), color: AppStyle.primary, points: route.route! ) ); notifyListeners(); } else { loading = false; notifyListeners(); // popup(context, "Ok", title: "Error", // description: "Error loading this route, Please Try another !"); } } Future getAddressFromCoordinates(BuildContext context,LatLng coordinates,int? count) async { try{ loading=true; notifyListeners(); var address = await getDraggingAdress(coordinates.latitude, coordinates.longitude,count); if (address != null) { moveCamera(LatLng(coordinates.latitude, coordinates.longitude)); loading=false; notifyListeners(); // If error is null, list is guaranteed to be not empty. }else{ loading=false; notifyListeners(); // popup(NavigatorService.navigatorKey.currentContext!,"Ok",title: "Error",description:"An error has occurred while getting this address' data,Please try again"); } }catch(e){ log(e.toString()); loading=false; notifyListeners(); } } Future getRoute(double startLatitude, double startLongitude,double endLatitude,double endLongitude) async { try{ var addresses = await routeService.getRoute(startLatitude.toString(),startLongitude.toString(),endLatitude.toString(),endLongitude.toString()); if(addresses.data!=null){ return addresses.data!; }else{ // popup(NavigatorService.navigatorKey.currentContext!,"Ok",title: "Error",description:"An error has occurred , Please Try later !"); } }catch(e){ log(e.toString()); loading=false; notifyListeners(); return null; } return null; } void onCameraMove(LatLng cam) { cameraPosition = cam; notifyListeners(); } Future getPlaces(String address) async { try{ var result = await search.search(address); if(result.statusCode==200 || result.statusCode==201){ if(result.data!=null && result.data!.predictions!=null){ places=result.data!.predictions!; notifyListeners(); } } }catch(e){ log(e.toString()); loading=false; notifyListeners(); } } }