diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart index f4c0fd8..e9abeaa 100644 --- a/lib/core/app_state.dart +++ b/lib/core/app_state.dart @@ -133,5 +133,10 @@ class AppState { _userRegistrationPayload = value; } + ///this will be called if there is any problem in getting the user location + void resetLocation(){ + userLong = 0.0; + userLong = 0.0; + } } diff --git a/lib/core/dependencies.dart b/lib/core/dependencies.dart index f5b3d05..4de7c5f 100644 --- a/lib/core/dependencies.dart +++ b/lib/core/dependencies.dart @@ -158,7 +158,8 @@ class AppDependencies { bookAppointmentsRepo: getIt(), errorHandlerService: getIt(), navigationService: getIt(), - myAppointmentsViewModel: getIt() + myAppointmentsViewModel: getIt(), + locationUtils: getIt() ), ); diff --git a/lib/core/location_util.dart b/lib/core/location_util.dart index d556034..ecfab62 100644 --- a/lib/core/location_util.dart +++ b/lib/core/location_util.dart @@ -1,12 +1,23 @@ import 'dart:io'; +import 'dart:ui'; import 'package:geolocator/geolocator.dart'; +import 'package:gms_check/gms_check.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/utils/utils.dart'; import 'package:hmg_patient_app_new/services/navigation_service.dart'; -import 'package:permission_handler/permission_handler.dart'; +import 'package:huawei_location/huawei_location.dart' as HmsLocation + show + FusedLocationProviderClient, + Location, + LocationSettingsRequest, + LocationRequest; +import 'package:location/location.dart' + show Location, PermissionStatus, LocationData; +import 'package:permission_handler/permission_handler.dart' + show Permission, PermissionListActions, PermissionStatusGetters; class LocationUtils { NavigationService navigationService; @@ -16,6 +27,7 @@ class LocationUtils { bool isShowLocationTimeoutDialog; bool isHuawei; final GeolocatorPlatform _geolocatorPlatform = GeolocatorPlatform.instance; + Future? isGMSDevice; LocationUtils({ required this.isShowConfirmDialog, @@ -23,49 +35,62 @@ class LocationUtils { required this.appState, this.isHuawei = false, this.isShowLocationTimeoutDialog = true, - }); - - void getCurrentLocation({Function(LatLng)? callBack}) async { - Geolocator.isLocationServiceEnabled().then((value) async { - if (value) { - await Geolocator.checkPermission().then((permission) async { - if (permission == LocationPermission.always || permission == LocationPermission.whileInUse) { - Geolocator.getLastKnownPosition().then((value) { - setLocation(value); - if (callBack != null) callBack(LatLng(value?.latitude ?? 24.7101433, value?.longitude ?? 46.6757709)); - }).catchError((err) { - if (isShowConfirmDialog && isShowLocationTimeoutDialog) {} - }); - } + }) { + isGMSDevice = GmsCheck().checkGmsAvailability(); + } - if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) { - if (Platform.isAndroid) { - // Utils.showPermissionConsentDialog(context, TranslationBase.of(context).locationPermissionDialog, () async { - final hasPermission = await _handlePermission(); - if (hasPermission) { - // Geolocator.getCurrentPosition(locationSettings: LocationSettings(accuracy: LocationAccuracy.medium, timeLimit: Duration(seconds: 5))).then((value) { - Geolocator.getLastKnownPosition().then((value) { - setLocation(value); - if (callBack != null) callBack(LatLng(value?.latitude ?? 24.7101433, value?.longitude ?? 46.6757709)); - }); - } else { - // if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {}); - } - // }); - } else { - if (await Permission.location.request().isGranted) { - getCurrentLocation(callBack: callBack); - } else { - setZeroLocation(); - if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {}); - } - } - } - }).catchError((err) {}); - } else { - if (isShowConfirmDialog) showErrorLocationDialog(false, failureCallBack: () {}); + void getLocation( + {Function(LatLng)? onSuccess, VoidCallback? onFailure}) async { + if (Platform.isIOS) { + getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess); + return; + } + + if (await isGMSDevice ?? true) { + getCurrentLocation(onFailure: onFailure, onSuccess: onSuccess); + return; + } + + getHMSLocation(onFailure: onFailure, onSuccess: onSuccess); + } + + void getCurrentLocation( + {Function(LatLng)? onSuccess, VoidCallback? onFailure}) async { + var location = Location(); + + bool isLocationEnabled = await location.serviceEnabled(); + //if the location service is not enabled, ask the user to enable it + if (!isLocationEnabled) { + isLocationEnabled = await location.requestService(); + if (!isLocationEnabled) { + appState.resetLocation(); + onFailure?.call(); + return; + } + } + + LocationPermission permissionGranted = await Geolocator.checkPermission(); + if (permissionGranted == LocationPermission.denied) { + permissionGranted = await Geolocator.requestPermission(); + if (permissionGranted != LocationPermission.whileInUse && + permissionGranted != LocationPermission.always) { + appState.resetLocation(); + onFailure?.call(); + return; } - }).catchError((err) {}); + } + + Position? currentLocation = await Geolocator.getLastKnownPosition(); + + if(currentLocation?.latitude == null || currentLocation?.longitude == null){ + currentLocation = await Geolocator.getCurrentPosition( + desiredAccuracy: LocationAccuracy.low); + } + + LatLng locationData = LatLng( + currentLocation?.latitude ?? 0.0, currentLocation?.longitude ?? 0.0); + saveLatLngToAppState(locationData); + onSuccess?.call(locationData); } Future checkIfGPSIsEnabled() async { @@ -166,4 +191,75 @@ class LocationUtils { ].request(); return (result[Permission.location]!.isGranted || result[Permission.locationAlways]!.isGranted); } + + void saveLatLngToAppState(LatLng locationData) { + appState.userLat = locationData.latitude; + appState.userLong = locationData.longitude; + } + + void getHMSLocation( + {VoidCallback? onFailure, Function(LatLng p1)? onSuccess}) async { + try { + var location = Location(); + HmsLocation.FusedLocationProviderClient locationService = + HmsLocation.FusedLocationProviderClient()..initFusedLocationService(); + + bool isLocationEnabled = await Geolocator.isLocationServiceEnabled(); + //if the location service is not enabled, ask the user to enable it + if (!isLocationEnabled) { + HmsLocation.LocationRequest locationRequest = + HmsLocation.LocationRequest() + ..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY; + + HmsLocation.LocationSettingsRequest request = + HmsLocation.LocationSettingsRequest( + alwaysShow: true, + needBle: false, + requests: [locationRequest], + ); + + await locationService.checkLocationSettings(request); + } + LocationPermission permissionGranted = await Geolocator.checkPermission(); + if (permissionGranted == LocationPermission.denied) { + permissionGranted = await Geolocator.requestPermission(); + if (permissionGranted != LocationPermission.whileInUse && + permissionGranted != LocationPermission.always) { + appState.resetLocation(); + onFailure?.call(); + return; + } + } + + HmsLocation.Location data = await locationService.getLastLocation(); + if (data.latitude == null || data.longitude == null) { + appState.resetLocation(); + HmsLocation.LocationRequest request = HmsLocation.LocationRequest() + ..priority = HmsLocation.LocationRequest.PRIORITY_HIGH_ACCURACY + ..interval = 1000 // 1 second + ..numUpdates = 1; + locationService.requestLocationUpdates(request); + locationService.onLocationData?.listen((location) { + data = location; + if (data.latitude == null || data.longitude == null) { + appState.resetLocation(); + onFailure?.call(); + return; + } + var locationData = + LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0); + saveLatLngToAppState(locationData); + onSuccess?.call(locationData); + }); + } else { + var locationData = LatLng(data.latitude ?? 0.0, data.longitude ?? 0.0); + + saveLatLngToAppState(locationData); + onSuccess?.call(locationData); + } + } catch (e) { + appState.resetLocation(); + onFailure?.call(); + } + } } diff --git a/lib/features/book_appointments/book_appointments_view_model.dart b/lib/features/book_appointments/book_appointments_view_model.dart index 155a388..b9750d8 100644 --- a/lib/features/book_appointments/book_appointments_view_model.dart +++ b/lib/features/book_appointments/book_appointments_view_model.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:hmg_patient_app_new/core/app_state.dart'; import 'package:hmg_patient_app_new/core/cache_consts.dart'; import 'package:hmg_patient_app_new/core/dependencies.dart'; +import 'package:hmg_patient_app_new/core/location_util.dart'; import 'package:hmg_patient_app_new/core/utils/date_util.dart'; import 'package:hmg_patient_app_new/core/utils/doctor_response_mapper.dart'; import 'package:hmg_patient_app_new/core/utils/loading_utils.dart'; @@ -38,6 +39,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { int initialSlotDuration = 0; + LocationUtils locationUtils; + List clinicsList = []; List _filteredClinicsList = []; @@ -75,7 +78,9 @@ class BookAppointmentsViewModel extends ChangeNotifier { bool shouldLoadSpecificClinic = false; String? currentlySelectedHospitalFromRegionFlow; - BookAppointmentsViewModel({required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel}); + BookAppointmentsViewModel({required this.bookAppointmentsRepo, required this.errorHandlerService, required this.navigationService, required this.myAppointmentsViewModel, required this.locationUtils}) {; + initBookAppointmentViewModel(); + } void initializeFilteredList() { _filteredClinicsList = List.from(clinicsList); @@ -98,6 +103,7 @@ class BookAppointmentsViewModel extends ChangeNotifier { isDoctorProfileLoading = true; clinicsList.clear(); doctorsList.clear(); + // getLocation(); notifyListeners(); } @@ -409,10 +415,10 @@ class BookAppointmentsViewModel extends ChangeNotifier { Future getRegionMappedProjectList() async { //todo handle the case in the location is switch on - if(hospitalList != null && hospitalList!.registeredDoctorMap != null && hospitalList!.registeredDoctorMap!.isNotEmpty){ - filteredHospitalList = hospitalList; - return; - } + // if(hospitalList != null && hospitalList!.registeredDoctorMap != null && hospitalList!.registeredDoctorMap!.isNotEmpty){ + // filteredHospitalList = hospitalList; + // return; + // } isRegionListLoading = true; notifyListeners(); final result = await bookAppointmentsRepo.getProjectList(); @@ -430,10 +436,8 @@ class BookAppointmentsViewModel extends ChangeNotifier { lat: _appState.userLat, lng: _appState.userLong, ); - var lat = await Utils.getNumFromPrefs(CacheConst.userLat); - var lng = await Utils.getNumFromPrefs(CacheConst.userLong); - var isLocationEnabled = (lat != 0) && (lng != 0); + var isLocationEnabled = (_appState.userLat != 0) && (_appState.userLong != 0); hospitalList = await DoctorMapper.sortList(isLocationEnabled, hospitalList!); @@ -481,15 +485,15 @@ class BookAppointmentsViewModel extends ChangeNotifier { notifyListeners(); } - Future isLocationEnabled() async{ - return await Location().serviceEnabled(); + bool isLocationEnabled() { + return _appState.userLong != 0.0 && _appState.userLong != 0.0; } - bool getLocationStatus() { - bool isLocationAvaiable = false; - isLocationEnabled().then((value) => isLocationAvaiable = value); - return isLocationAvaiable; - } + // bool getLocationStatus() { + // bool isLocationAvaiable = false; + // isLocationEnabled().then((value) => isLocationAvaiable = value); + // return isLocationAvaiable; + // } void setLoadSpecificClinic(bool status) { shouldLoadSpecificClinic = status; @@ -519,4 +523,9 @@ class BookAppointmentsViewModel extends ChangeNotifier { void resetFilterList(){ filteredHospitalList = hospitalList; } + + + void getLocation(){ + locationUtils.getLocation(); + } } diff --git a/lib/main.dart b/lib/main.dart index c75cf91..6abde55 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -132,6 +132,7 @@ void main() async { errorHandlerService: getIt(), navigationService: getIt(), myAppointmentsViewModel: getIt(), + locationUtils: getIt(), ), ), ChangeNotifierProvider( diff --git a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart index 1c9649b..b67ab7c 100644 --- a/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart +++ b/lib/presentation/appointments/widgets/appointment_checkin_bottom_sheet.dart @@ -52,7 +52,7 @@ class AppointmentCheckinBottomSheet extends StatelessWidget { // navigationService: myAppointmentsViewModel.navigationService, // appState: myAppointmentsViewModel.appState, // ); - locationUtils.getCurrentLocation(callBack: (value) { + locationUtils.getCurrentLocation(onSuccess: (value) { projectDetailListModel = Utils.getProjectDetailObj(_appState, patientAppointmentHistoryResponseModel.projectID); double dist = Utils.distance(value.latitude, value.longitude, double.parse(projectDetailListModel.latitude!), double.parse(projectDetailListModel.longitude!)).ceilToDouble() * 1000; print(dist); diff --git a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart index 71cc07d..8159abd 100644 --- a/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart +++ b/lib/presentation/appointments/widgets/hospital_bottom_sheet/hospital_bottom_sheet_body.dart @@ -93,7 +93,7 @@ class HospitalBottomSheetBody extends StatelessWidget { ?.hmcDoctorList?[index]; return HospitalListItem( hospitalData: hospital, - isLocationEnabled: appointmentsViewModel.getLocationStatus(), + isLocationEnabled: appointmentsViewModel.isLocationEnabled(), ).onPress(() { regionalViewModel.setHospitalModel(hospital); regionalViewModel.setBottomSheetState(AppointmentViaRegionState.CLINIC_SELECTION); diff --git a/lib/presentation/book_appointment/book_appointment_page.dart b/lib/presentation/book_appointment/book_appointment_page.dart index 825a9e9..f2430cb 100644 --- a/lib/presentation/book_appointment/book_appointment_page.dart +++ b/lib/presentation/book_appointment/book_appointment_page.dart @@ -43,6 +43,7 @@ class _BookAppointmentPageState extends State { void initState() { scheduleMicrotask(() { bookAppointmentsViewModel.initBookAppointmentViewModel(); + bookAppointmentsViewModel.getLocation(); }); super.initState(); } diff --git a/lib/presentation/home/landing_page.dart b/lib/presentation/home/landing_page.dart index ff17d63..12bc8f5 100644 --- a/lib/presentation/home/landing_page.dart +++ b/lib/presentation/home/landing_page.dart @@ -94,7 +94,7 @@ class _LandingPageState extends State { return Scaffold( backgroundColor: AppColors.bgScaffoldColor, body: SingleChildScrollView( - padding: EdgeInsets.only(top: kToolbarHeight + 12.h, bottom: 24), + padding: EdgeInsets.only(top: kToolbarHeight + 0.h, bottom: 24), child: Column( spacing: 16.h, children: [ diff --git a/lib/presentation/home/widgets/welcome_widget.dart b/lib/presentation/home/widgets/welcome_widget.dart index 4baee01..f710ab2 100644 --- a/lib/presentation/home/widgets/welcome_widget.dart +++ b/lib/presentation/home/widgets/welcome_widget.dart @@ -37,8 +37,9 @@ class WelcomeWidget extends StatelessWidget { Row( spacing: 4.h, crossAxisAlignment: CrossAxisAlignment.center, + mainAxisSize: MainAxisSize.min, children: [ - name.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, height: 1).expanded, + Flexible(child: name.toText16(weight: FontWeight.w500, textOverflow: TextOverflow.ellipsis, maxlines: 1, height: 1)), const Icon(Icons.keyboard_arrow_down, size: 20, color: Colors.black), ], ), diff --git a/pubspec.yaml b/pubspec.yaml index e55d241..5423904 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -83,6 +83,8 @@ dependencies: family_bottom_sheet: ^0.1.0 location: ^8.0.1 + gms_check: ^1.0.4 + huawei_location: ^6.14.2+301 dev_dependencies: flutter_test: