diff --git a/assets/images/lock-icon.png b/assets/images/lock-icon.png
new file mode 100644
index 00000000..39645887
Binary files /dev/null and b/assets/images/lock-icon.png differ
diff --git a/assets/images/svg/Check Mark.lottie b/assets/images/svg/Check Mark.lottie
new file mode 100644
index 00000000..28630fbd
Binary files /dev/null and b/assets/images/svg/Check Mark.lottie differ
diff --git a/assets/images/svg/qlogin.svg b/assets/images/svg/qlogin.svg
deleted file mode 100644
index 3fcf2ffd..00000000
--- a/assets/images/svg/qlogin.svg
+++ /dev/null
@@ -1,9 +0,0 @@
-
diff --git a/lib/config/localized_values.dart b/lib/config/localized_values.dart
index 7922976e..211e4108 100644
--- a/lib/config/localized_values.dart
+++ b/lib/config/localized_values.dart
@@ -2329,6 +2329,8 @@ const Map localizedValues = {
"clickPrivacyPolicy": {"en": "Please click here to view the privacy policy", "ar": "الرجاء الضغط هنا لعرض سياسة الخصوصية"},
"welcomeToDrSulaiman": {"en": "Welcome to Dr. Sulaiman Al Habib Medical Group", "ar": "مرحباً بكم في مجموعة الدكتور سليمان الحبيب الطبية"},
"dontHaveAccount": {"en": "Don’t have an account?", "ar": "ليس لديك حساب؟"},
+ "loginByOTP": {"en": "Login By OTP", "ar":"تسجيل الدخول باستخدام OTP"},
+ "loginBy": {"en": "Login By", "ar":"تسجيل الدخول بواسطة"}
"prepareToElevate": {"en": "Prepared to elevate your health and well-being?", "ar": "هل أنت مستعد لتحسين صحتك ورفاهتك؟"},
"alreadyHaveAccount": {"en": "Already have an account?", "ar": "هل لديك حساب بالفعل؟"},
"loginNow": {"en": "Login Now", "ar": "تسجيل الدخول الآن"}
diff --git a/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart b/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart
index d51c8dea..2bd1b5f4 100644
--- a/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart
+++ b/lib/new_ui/otp/otp_validation_bootmsheet_widget.dart
@@ -109,6 +109,7 @@ class CustomButton extends StatelessWidget {
this.fontFamily,
this.fontWeight = FontWeight.w500,
this.isDisabled = false,
+
this.icon,
}) : super(key: key);
diff --git a/lib/pages/landing/landing_page.dart b/lib/pages/landing/landing_page.dart
index 18171bf1..0ce516bc 100644
--- a/lib/pages/landing/landing_page.dart
+++ b/lib/pages/landing/landing_page.dart
@@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:io';
+import 'package:flutter/services.dart';
import 'package:hmg_patient_app/config/config.dart';
import 'package:hmg_patient_app/config/shared_pref_kay.dart';
import 'package:hmg_patient_app/core/model/ImagesInfo.dart';
@@ -9,11 +10,15 @@ import 'package:hmg_patient_app/core/viewModels/appointment_rate_view_model.dart
import 'package:hmg_patient_app/core/viewModels/project_view_model.dart';
import 'package:hmg_patient_app/models/Appointments/toDoCountProviderModel.dart';
import 'package:hmg_patient_app/models/Authentication/authenticated_user.dart';
+import 'package:hmg_patient_app/models/Authentication/check_paitent_authentication_req.dart';
+import 'package:hmg_patient_app/models/Authentication/select_device_imei_res.dart';
import 'package:hmg_patient_app/models/LiveCare/IncomingCallData.dart';
import 'package:hmg_patient_app/pages/BookAppointment/Search.dart';
import 'package:hmg_patient_app/pages/DrawerPages/family/my-family.dart';
import 'package:hmg_patient_app/pages/ToDoList/ToDo.dart';
import 'package:hmg_patient_app/pages/landing/home_page_2.dart';
+import 'package:hmg_patient_app/pages/login/saved_login.dart';
+import 'package:hmg_patient_app/pages/login/welcome.dart';
import 'package:hmg_patient_app/pages/medical/medical_profile_page_new.dart';
import 'package:hmg_patient_app/services/authentication/auth_provider.dart';
import 'package:hmg_patient_app/services/clinic_services/get_clinic_service.dart';
@@ -41,6 +46,8 @@ import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_zoom_videosdk/native/zoom_videosdk.dart';
+import 'package:hmg_patient_app/widgets/quick_login.dart';
+import 'package:local_auth/local_auth.dart';
import 'package:provider/provider.dart';
import '../../locator.dart';
@@ -69,7 +76,7 @@ class LandingPage extends StatefulWidget {
class _LandingPageState extends State with WidgetsBindingObserver {
var authProvider = new AuthProvider();
AppointmentRateViewModel appointmentRateViewModel = locator();
-
+ final LocalAuthentication auth = LocalAuthentication();
int currentTab = 0;
late PageController pageController;
late ProjectViewModel projectViewModel;
@@ -77,9 +84,9 @@ class _LandingPageState extends State with WidgetsBindingObserver {
var notificationCount = '';
var themeNotifier;
DateTime? currentBackPressTime;
-
+ bool authenticated = false;
// SignalRUtil signalRUtil;
-
+ // bool isDoneQuickLogin =false;
late ToDoCountProviderModel toDoProvider;
bool _showBottomNavigationBar = true;
@@ -100,26 +107,26 @@ class _LandingPageState extends State with WidgetsBindingObserver {
bool isTalking = false;
var sharedPref = new AppSharedPreferences();
-
- var data = {
- "AppointmentNo": "2016059247",
- "ProjectID": "15",
- "NotificationType": "10",
- "background": "0",
- "doctorname": "Call from postman",
- "clinicname": "LIVECARE FAMILY MEDICINE AND GP",
- "speciality": "General Practioner",
- "appointmentdate": "2022-01-19",
- "appointmenttime": "12:10",
- "PatientName": "Testing",
- "session_id": "1_MX40NjIwOTk2Mn5-MTY0NzI1NjYxNDI2OX5ySXhlVjZjam13RFdMVmdleWVsSDhzQkx-fg",
- "token":
- "T1==cGFydG5lcl9pZD00NjIwOTk2MiZzaWc9OGMyY2IyYWFiZmZmMzI4ZmEwMjgxNDdmMGFhZGI0N2JiZjdmZWY4MjpzZXNzaW9uX2lkPTFfTVg0ME5qSXdPVGsyTW41LU1UWTBOekkxTmpZeE5ESTJPWDV5U1hobFZqWmphbTEzUkZkTVZtZGxlV1ZzU0RoelFreC1mZyZjcmVhdGVfdGltZT0xNjQ3MjU2NjE0Jm5vbmNlPTAuMjgzNDgyNjM1NDczNjQ2OCZyb2xlPW1vZGVyYXRvciZleHBpcmVfdGltZT0xNjQ3MjU4NDE0JmluaXRpYWxfbGF5b3V0X2NsYXNzX2xpc3Q9",
- "DoctorImageURL": "https://image.shutterstock.com/image-vector/sample-stamp-square-grunge-sign-260nw-1474408826.jpg",
- "callerID": "9920",
- "PatientID": "1231755",
- "is_call": "true"
- };
+ //
+ // var data = {
+ // "AppointmentNo": "2016059247",
+ // "ProjectID": "15",
+ // "NotificationType": "10",
+ // "background": "0",
+ // "doctorname": "Call from postman",
+ // "clinicname": "LIVECARE FAMILY MEDICINE AND GP",
+ // "speciality": "General Practioner",
+ // "appointmentdate": "2022-01-19",
+ // "appointmenttime": "12:10",
+ // "PatientName": "Testing",
+ // "session_id": "1_MX40NjIwOTk2Mn5-MTY0NzI1NjYxNDI2OX5ySXhlVjZjam13RFdMVmdleWVsSDhzQkx-fg",
+ // "token":
+ // "T1==cGFydG5lcl9pZD00NjIwOTk2MiZzaWc9OGMyY2IyYWFiZmZmMzI4ZmEwMjgxNDdmMGFhZGI0N2JiZjdmZWY4MjpzZXNzaW9uX2lkPTFfTVg0ME5qSXdPVGsyTW41LU1UWTBOekkxTmpZeE5ESTJPWDV5U1hobFZqWmphbTEzUkZkTVZtZGxlV1ZzU0RoelFreC1mZyZjcmVhdGVfdGltZT0xNjQ3MjU2NjE0Jm5vbmNlPTAuMjgzNDgyNjM1NDczNjQ2OCZyb2xlPW1vZGVyYXRvciZleHBpcmVfdGltZT0xNjQ3MjU4NDE0JmluaXRpYWxfbGF5b3V0X2NsYXNzX2xpc3Q9",
+ // "DoctorImageURL": "https://image.shutterstock.com/image-vector/sample-stamp-square-grunge-sign-260nw-1474408826.jpg",
+ // "callerID": "9920",
+ // "PatientID": "1231755",
+ // "is_call": "true"
+ // };
void _requestIOSPermissions() {
flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation()?.requestPermissions(
@@ -368,25 +375,42 @@ class _LandingPageState extends State with WidgetsBindingObserver {
var data = await sharedPref.getObject(IMEI_USER_DATA);
sharedPref.remove(REGISTER_DATA_FOR_LOGIIN);
if (data != null) {
- Navigator.of(context).pushNamed(CONFIRM_LOGIN);
+ SelectDeviceIMEIRES savedData = SelectDeviceIMEIRES.fromJson(data);
+ Navigator.of(context).pushReplacement(
+ MaterialPageRoute(
+ builder: (BuildContext context) => SavedLogin(savedData),
+ ),
+ );
+
+
} else {
- // AppGlobal.context = context;
GifLoaderDialogUtils.showMyDialog(context);
authService.selectDeviceImei(DEVICE_TOKEN).then((value) async {
GifLoaderDialogUtils.hideDialog(context);
var data = await sharedPref.getObject(IMEI_USER_DATA);
if (value != null) {
+ SelectDeviceIMEIRES savedData = SelectDeviceIMEIRES.fromJson(data);
setUserValues(value);
- Navigator.of(context).pushNamed(CONFIRM_LOGIN);
+ Navigator.of(context).pushReplacement(
+ MaterialPageRoute(
+ builder: (BuildContext context) => SavedLogin(savedData),
+ ),
+ );
} else {
GifLoaderDialogUtils.hideDialog(context);
- Navigator.of(context).pushNamed(
- WELCOME_LOGIN,
+ Navigator.of(context).pushReplacement(
+ MaterialPageRoute(
+ builder: (BuildContext context) => WelcomeLogin(),
+ ),
);
}
}).catchError((err) {
GifLoaderDialogUtils.hideDialog(context);
- Navigator.of(context).pushNamed(WELCOME_LOGIN);
+ Navigator.of(context).pushReplacement(
+ MaterialPageRoute(
+ builder: (BuildContext context) => WelcomeLogin(),
+ ),
+ );
});
}
}
@@ -450,10 +474,12 @@ class _LandingPageState extends State with WidgetsBindingObserver {
getNotificationCount(token) async {
if (await sharedPref.getObject(USER_PROFILE) != null) {
var data = AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE));
+
if (data != null) {
authService.getDashboard().then((value) => {
if (value != null)
{
+
setState(() {
notificationCount =
value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'] > 99 ? '99+' : value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'].toString();
@@ -652,6 +678,7 @@ class _LandingPageState extends State with WidgetsBindingObserver {
var data = AuthenticatedUser.fromJson(await sharedPref.getObject(USER_PROFILE));
if (data != null) {
authService.registeredAuthenticatedUser(data, token, 0, 0).then((res) => {});
+ checkLastLoginStatus(data, token);
authService.getDashboard().then((value) async {
setState(() {
if (value != null) {
@@ -659,7 +686,7 @@ class _LandingPageState extends State with WidgetsBindingObserver {
notificationCount = value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'] > 99 ? '99+' : value['List_PatientDashboard'][0]['UnreadPatientNotificationCount'].toString();
model.setState(model.count, model.ancillaryCount, true, notificationCount);
sharedPref.setString(NOTIFICATION_COUNT, notificationCount);
- checkLastLoginStatus();
+
}
});
// if (await AppSharedPreferences().getBool(IS_LAST_APPOINTMENT_RATE_SHOWN) == null || !await AppSharedPreferences().getBool(IS_LAST_APPOINTMENT_RATE_SHOWN)) {
@@ -706,12 +733,68 @@ class _LandingPageState extends State with WidgetsBindingObserver {
sharedPref.setString(IS_COVID_CONSENT_SHOWN, "true");
}
- checkLastLoginStatus() async{
+ checkLastLoginStatus(AuthenticatedUser user, String deviceToken) async{
int lastLoginStatus = await sharedPref.getInt(LAST_LOGIN) != null ? await sharedPref.getInt(LAST_LOGIN) : 1;
if(lastLoginStatus == 1 || lastLoginStatus == 2){
- print("SMS or Whatsapp Consent");
+ showQuickLoginBottomSheet(context, user, deviceToken,false);
}
}
-}
+
+ void showQuickLoginBottomSheet(BuildContext context, AuthenticatedUser user, String deviceToken, bool isDone) {
+ showModalBottomSheet(
+ context: context,
+ backgroundColor: Colors.transparent,
+ isScrollControlled: true,
+ builder: (context) => QuickLoginBottomSheet(
+ isDone:isDone,
+ onPressed: (){
+ loginWithFingerPrintFace(3, 1, user, deviceToken);
+ },),
+ );
+ }
+ loginWithFingerPrintFace(type, int isActive, AuthenticatedUser user, String deviceToken ) async {
+ try {
+ authenticated = await auth.authenticate(
+ localizedReason: 'Scan your fingerprint to authenticate',
+ options: AuthenticationOptions(
+ useErrorDialogs: true,
+ stickyAuth: true,
+ ),
+ authMessages: [
+ // IOSAuthMessages(
+ // cancelButton: 'cancel',
+ // goToSettingsButton: 'settings',
+ // goToSettingsDescription: 'Please set up your Touch ID.',
+ // lockOut: 'Please reenable your Touch ID'),
+ ],
+ );
+ } on PlatformException catch (e) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: 'Please enable your Touch or Face ID');
+ }
+ if (authenticated == true) {
+ Navigator.of(context).pop();
+ int lastLogin = 1;
+ var availableBiometrics = await auth.getAvailableBiometrics();
+
+ if (availableBiometrics.contains(BiometricType.strong)) {
+ lastLogin = 3; // Assume Face or secure fingerprint
+ } else if (availableBiometrics.contains(BiometricType.weak)) {
+ lastLogin = 2; // Likely weak fingerprint
+ }
+
+ await sharedPref.setInt(LAST_LOGIN, lastLogin);
+ showQuickLoginBottomSheet(context, user, deviceToken, true);
+ insertIMEI(lastLogin);
+ }
+ }
+
+ insertIMEI(lastLogin) {
+ authService.insertDeviceImei(lastLogin).then((value) => {}).catchError((err) {
+ print(err);
+ });
+ }
+ }
+
diff --git a/lib/pages/livecare/incoming_call.dart b/lib/pages/livecare/incoming_call.dart
index 2c0a1ef7..229a2c32 100644
--- a/lib/pages/livecare/incoming_call.dart
+++ b/lib/pages/livecare/incoming_call.dart
@@ -1,13 +1,10 @@
import 'dart:ui';
-import 'package:camera/camera.dart';
import 'package:hmg_patient_app/models/LiveCare/IncomingCallData.dart';
import 'package:hmg_patient_app/pages/conference/widgets/platform_exception_alert_dialog.dart';
import 'package:hmg_patient_app/pages/conference/zoom/call_screen.dart';
import 'package:hmg_patient_app/pages/landing/landing_page.dart';
-import 'package:hmg_patient_app/pages/videocall-webrtc-rnd/webrtc/start_video_call.dart';
import 'package:hmg_patient_app/pages/webRTC/OpenTok/OpenTok.dart';
-import 'package:hmg_patient_app/pages/webRTC/signaling.dart';
import 'package:hmg_patient_app/services/livecare_services/livecare_provider.dart';
import 'package:hmg_patient_app/uitl/translations_delegate_base.dart';
import 'package:hmg_patient_app/uitl/utils_new.dart';
@@ -31,7 +28,7 @@ class _IncomingCallState extends State with SingleTickerProviderSt
bool openCallInWeb = true;
final player = AudioPlayer();
- late CameraController _controller;
+ // late CameraController _controller;
late Future _initializeControllerFuture;
bool isCameraReady = false;
diff --git a/lib/pages/login/confirm-login.dart b/lib/pages/login/confirm-login.dart
index 595a6a8b..422955ba 100644
--- a/lib/pages/login/confirm-login.dart
+++ b/lib/pages/login/confirm-login.dart
@@ -369,7 +369,7 @@ class _ConfirmLogin extends State {
checkUserAuthentication(type) {
showLoader(true);
- var req = getCommonRequest(type: type);
+ var req = authService.getCommonRequest(type: type, registerd_data: this.registerd_data, deviceToken: this.deviceToken, mobileNumber: this.mobileNumber, zipCode: this.zipCode, patientOutSA: this.patientOutSA, loginTokenID: this.loginTokenID, selectedOption: this.selectedOption, user: this.user!);
req.logInTokenID = "";
var request = CheckPatientAuthenticationReq.fromJson(req.toJson());
@@ -400,7 +400,7 @@ class _ConfirmLogin extends State {
}
sendActivationCode(type) async {
- var request = this.getCommonRequest(type: type);
+ var request = this.authService.getCommonRequest(type: type, registerd_data: this.registerd_data, deviceToken: this.deviceToken, mobileNumber: this.mobileNumber, zipCode: this.zipCode, patientOutSA: this.patientOutSA, loginTokenID: this.loginTokenID, selectedOption: this.selectedOption, user: this.user!);
request.sMSSignature = await SMSOTP.getSignature();
GifLoaderDialogUtils.showMyDialog(context);
if (healthId != null || widget.isDubai) {
@@ -478,7 +478,7 @@ class _ConfirmLogin extends State {
// this.checkActivationCode();
// } else {
- var request = this.getCommonRequest(type: type);
+ var request = this.authService.getCommonRequest(type: type, registerd_data: this.registerd_data, deviceToken: this.deviceToken, mobileNumber: this.mobileNumber, zipCode: this.zipCode, patientOutSA: this.patientOutSA, loginTokenID: this.loginTokenID, selectedOption: this.selectedOption, user: this.user!);
this.getMobileInfo(request);
//}
}
@@ -563,39 +563,39 @@ class _ConfirmLogin extends State {
//this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN);
}
- getCommonRequest({type}) {
- var request = SendActivationRequest();
- request.patientMobileNumber = this.mobileNumber;
- request.mobileNo = '0' + this.mobileNumber.toString();
- request.deviceToken = this.deviceToken;
- request.projectOutSA = this.patientOutSA == true ? true : false;
- request.loginType = this.selectedOption;
- request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2;
- request.zipCode = this.zipCode;
-
- request.logInTokenID = this.loginTokenID ?? "";
-
- if (this.registerd_data != null) {
- request.searchType = this.registerd_data.searchType != null ? this.registerd_data.searchType : 1;
- request.patientID = this.registerd_data.patientID != null ? this.registerd_data.patientID : 0;
- request.patientIdentificationID = request.nationalID = this.registerd_data.patientIdentificationID != null ? this.registerd_data.patientIdentificationID : '0';
- request.dob = this.registerd_data.dob;
- request.isRegister = this.registerd_data.isRegister;
- } else {
- request.searchType = request.searchType != null ? request.searchType : 2;
- request.patientID = this.user!.patientID != null ? this.user!.patientID : 0;
- request.nationalID = request.nationalID != null ? request.nationalID : '0';
- request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0';
- request.isRegister = false;
- }
- request.deviceTypeID = request.searchType;
- return request;
- }
+ // getCommonRequest({type}) {
+ // var request = SendActivationRequest();
+ // request.patientMobileNumber = this.mobileNumber;
+ // request.mobileNo = '0' + this.mobileNumber.toString();
+ // request.deviceToken = this.deviceToken;
+ // request.projectOutSA = this.patientOutSA == true ? true : false;
+ // request.loginType = this.selectedOption;
+ // request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2;
+ // request.zipCode = this.zipCode;
+ //
+ // request.logInTokenID = this.loginTokenID ?? "";
+ //
+ // if (this.registerd_data != null) {
+ // request.searchType = this.registerd_data.searchType != null ? this.registerd_data.searchType : 1;
+ // request.patientID = this.registerd_data.patientID != null ? this.registerd_data.patientID : 0;
+ // request.patientIdentificationID = request.nationalID = this.registerd_data.patientIdentificationID != null ? this.registerd_data.patientIdentificationID : '0';
+ // request.dob = this.registerd_data.dob;
+ // request.isRegister = this.registerd_data.isRegister;
+ // } else {
+ // request.searchType = request.searchType != null ? request.searchType : 2;
+ // request.patientID = this.user!.patientID != null ? this.user!.patientID : 0;
+ // request.nationalID = request.nationalID != null ? request.nationalID : '0';
+ // request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0';
+ // request.isRegister = false;
+ // }
+ // request.deviceTypeID = request.searchType;
+ // return request;
+ // }
checkActivationCode({value}) async {
// Navigator.pop(context);
GifLoaderDialogUtils.showMyDialog(context);
- var request = this.getCommonRequest().toJson();
+ var request = authService.getCommonRequest(registerd_data: this.registerd_data, deviceToken: this.deviceToken, mobileNumber: this.mobileNumber, zipCode: this.zipCode, patientOutSA: this.patientOutSA, loginTokenID: this.loginTokenID, selectedOption: this.selectedOption, user: this.user! ).toJson();
dynamic res;
if (healthId != null || widget.isDubai) {
if (!widget.isDubai) {
diff --git a/lib/pages/login/saved_login.dart b/lib/pages/login/saved_login.dart
new file mode 100644
index 00000000..50ebe25e
--- /dev/null
+++ b/lib/pages/login/saved_login.dart
@@ -0,0 +1,441 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:hmg_patient_app/config/config.dart';
+import 'package:hmg_patient_app/config/shared_pref_kay.dart';
+import 'package:hmg_patient_app/core/service/client/base_app_client.dart';
+import 'package:hmg_patient_app/core/viewModels/project_view_model.dart';
+import 'package:hmg_patient_app/extensions/string_extensions.dart';
+import 'package:hmg_patient_app/models/Authentication/authenticated_user.dart';
+import 'package:hmg_patient_app/models/Authentication/check_activation_code_response.dart';
+import 'package:hmg_patient_app/models/Authentication/select_device_imei_res.dart';
+import 'package:hmg_patient_app/new_ui/otp/otp_validation_bootmsheet_widget.dart';
+import 'package:hmg_patient_app/pages/landing/landing_page.dart';
+import 'package:hmg_patient_app/pages/login/welcome.dart';
+import 'package:hmg_patient_app/services/authentication/auth_provider.dart' hide sharedPref;
+import 'package:hmg_patient_app/uitl/app_toast.dart';
+import 'package:hmg_patient_app/uitl/date_uitl.dart';
+import 'package:hmg_patient_app/uitl/gif_loader_dialog_utils.dart';
+import 'package:hmg_patient_app/uitl/translations_delegate_base.dart';
+import 'package:hmg_patient_app/uitl/utils.dart' hide sharedPref;
+import 'package:hmg_patient_app/widgets/text/app_texts_widget.dart';
+import 'package:local_auth/local_auth.dart';
+import 'package:provider/provider.dart';
+
+
+class SavedLogin extends StatefulWidget {
+ final SelectDeviceIMEIRES savedLoginData;
+ const SavedLogin(this.savedLoginData, {Key? key}) : super(key: key);
+
+ @override
+ _SavedLogin createState() => _SavedLogin();
+}
+
+class _SavedLogin extends State {
+ TextEditingController get phoneController =>
+ TextEditingController(
+ text: widget.savedLoginData.mobile!.startsWith('0')
+ ? widget.savedLoginData.mobile!.substring(1)
+ : widget.savedLoginData.mobile,
+ );
+
+ final authService = new AuthProvider();
+ late ProjectViewModel projectViewModel;
+
+
+ @override
+ Widget build(BuildContext context) {
+
+ projectViewModel = Provider.of(context);
+
+ return Scaffold(
+ backgroundColor: const Color(0xFFF8F8FA),
+ body: SafeArea(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 24.0),
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ const Spacer(flex: 2),
+ // Welcome back text
+ const Text(
+ 'Welcome back',
+ style: TextStyle(
+ fontSize: 22,
+ color: Color(0xFF6C757D),
+ fontWeight: FontWeight.w400,
+ ),
+ ),
+ const SizedBox(height: 16),
+ // Names
+ Column(
+ children: [
+ Text(
+ widget.savedLoginData.name!.toLowerCase().capitalizeFirstofEach,
+ style: TextStyle(
+ fontSize: 28,
+ fontWeight: FontWeight.bold,
+ color: Colors.grey[800],
+ ),
+ ),
+ // Text(
+ // 'Abdul Ghaffar',
+ // style: TextStyle(
+ // fontSize: 28,
+ // fontWeight: FontWeight.bold,
+ // color: Colors.grey[800],
+ // ),
+ // ),
+ ],
+ ),
+ const SizedBox(height: 24),
+ Container(
+ padding: const EdgeInsets.all(16),
+ decoration: BoxDecoration(
+ color: Colors.white,
+ border: Border.all(color: Colors.white),
+ borderRadius: BorderRadius.circular(8.0),
+ ),
+ child: Column(children: [
+
+ // Last login info
+ Text(
+ 'Last Login by ${getType(widget.savedLoginData!.logInType!, context)}',
+ style: const TextStyle(
+ fontSize: 14,
+ color: Color(0xFF6C757D),
+ ),
+ ),
+ Text(
+ widget.savedLoginData.createdOn != null ? DateUtil.getFormattedDate(DateUtil.convertStringToDate( widget.savedLoginData!.createdOn!), "d MMMM, y 'at' HH:mm") : '--',
+ style: const TextStyle(
+ fontSize: 16,
+ ),
+ ),
+ Container(
+ margin: EdgeInsets.all(16),
+ child: SvgPicture.asset("assets/images/svg/apple-finder.svg", color: Colors.red, height: 54, width: 54,),),
+ // Face ID login button
+ CustomButton(
+ text: "${TranslationBase.of(context).loginBy} ${getType(widget.savedLoginData!.logInType!, context)}",
+ onPressed: (){
+ loginWithFingerPrintFace(widget.savedLoginData!.logInType!, widget.savedLoginData!.iMEI!);
+
+ },
+ backgroundColor:Color(0xffFEE9EA),
+ borderColor:Color(0xffFEE9EA),
+ textColor: Color(0xffED1C2B),
+ fontSize: 12,
+ padding : EdgeInsets.fromLTRB(0, 10, 0, 10),
+ // icon: "assets/images/svg/apple-finder.svg",
+ ),
+ ],),),
+ const SizedBox(height: 24),
+ Padding(
+ padding: EdgeInsets.symmetric(horizontal: 16.0),
+
+ child: Text(
+ 'OR',
+ style: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.w500
+ ),
+ ),
+ ),
+ const SizedBox(height: 24),
+ // OTP login button
+ CustomButton(
+ text:TranslationBase.of(context).loginByOTP,
+ onPressed: (){
+
+ showModalBottomSheet(
+ context: context,
+ isScrollControlled: true,
+ isDismissible: false,
+ backgroundColor: Colors.transparent,
+ builder: (bottomSheetContext) => Padding(
+ padding: EdgeInsets.only(bottom: MediaQuery.of(bottomSheetContext).viewInsets.bottom),
+ child: SingleChildScrollView(
+ child: GenericBottomSheet(
+ countryCode: "966",
+ initialPhoneNumber: "",
+ textController: phoneController!, // Assumed to be a TextEditingController
+ buttons: [
+ Padding(
+ padding: const EdgeInsets.only(bottom: 10),
+ child: CustomButton(
+ text: "Send me OTP on SMS",
+ onPressed: () {
+ int? val = Utils.onOtpBtnPressed(OTPType.sms, phoneController);
+ if (val != null) {
+ //checkUserAuthentication(val);
+ }
+ },
+ backgroundColor: Colors.red,
+ borderColor: Colors.red,
+ textColor: Colors.white,
+ icon: "assets/images/svg/message.svg",
+ ),
+ ),
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 8),
+ child: AppText(
+ "OR",
+ fontSize: 16,
+ fontFamily: 'poppins',
+ color: Color(0xFF2E3039),
+ fontWeight: FontWeight.w500,
+ ),
+ ),
+ ],
+ ),
+ Padding(
+ padding: const EdgeInsets.only(bottom: 10),
+ child: CustomButton(
+ text: "Send me OTP on WhatsApp",
+ onPressed: () {
+ int? val = Utils.onOtpBtnPressed(OTPType.whatsapp, phoneController);
+ if (val != null) {
+ //checkUserAuthentication(val);
+ }
+ },
+ backgroundColor: Colors.white,
+ borderColor: Color(0xFF2E3039),
+ textColor: Color(0xFF2E3039),
+ icon: "assets/images/svg/whatsapp.svg",
+ ),
+ ),
+ ],
+ ),
+ ),
+ ));},
+ backgroundColor:Colors.white,
+ borderColor:Colors.black,
+ textColor: Colors.black,
+ padding : EdgeInsets.fromLTRB(0, 14, 0, 14),
+ // icon: "assets/images/svg/apple-finder.svg",
+ ),
+ const Spacer(flex: 2),
+ // OR divider
+
+ const SizedBox(height: 24),
+ // Guest and Switch account
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ TextButton(
+ onPressed: () { Navigator.of(context).pushReplacement(
+ MaterialPageRoute(
+ builder: (BuildContext context) => LandingPage(),
+
+ ),
+ );},
+ child: const Text(
+ 'Guest',
+ style: TextStyle(
+ color: Color(0xFFED1C2B),
+ fontSize: 16,
+ fontWeight: FontWeight.w500,
+ ),
+ ),
+ ),
+ const SizedBox(width: 24),
+ TextButton(
+ onPressed: () {
+ Navigator.of(context).pushReplacement(
+ MaterialPageRoute(
+ builder: (BuildContext context) => WelcomeLogin(),
+
+ ),
+ );
+
+ },
+ child: const Text(
+ 'Switch account',
+ style: TextStyle(
+ color: Color(0xFFED1C2B),
+ fontSize: 16,
+ fontWeight: FontWeight.w500,
+ ),
+ ),
+ ),
+ ],
+ ),
+ const SizedBox(height: 20),
+ ],
+ ),
+ ),
+ ),
+
+ );
+ }
+
+ String getType(int type, BuildContext context) {
+ final t = TranslationBase.of(context);
+ final types = {
+ 1: t.verifySMS,
+ 2: t.verifyFingerprint,
+ 3: t.verifyFaceID,
+ 4: t.verifyWhatsApp,
+ };
+ return types[type] ?? t.verifySMS;
+ }
+
+ //need to move this function on provider to avoid multiple repeat
+
+ loginWithFingerPrintFace(type, String deviceToken ) async {
+ bool authenticated = false;
+ final LocalAuthentication auth = LocalAuthentication();
+
+ try {
+ authenticated = await auth.authenticate(
+ localizedReason: 'Scan your fingerprint to authenticate',
+ options: const AuthenticationOptions(
+ useErrorDialogs: true,
+ stickyAuth: true,
+ ),
+ authMessages: [
+ // Optional: uncomment for iOS custom messages
+ // IOSAuthMessages(
+ // cancelButton: 'Cancel',
+ // goToSettingsButton: 'Settings',
+ // goToSettingsDescription: 'Please set up your Touch ID.',
+ // lockOut: 'Please re-enable your Touch ID.',
+ // ),
+ ],
+ );
+ } on PlatformException catch (e) {
+ GifLoaderDialogUtils.hideDialog(context);
+ AppToast.showErrorToast(message: 'Please enable your Touch or Face ID');
+ return;
+ }
+
+
+ if (authenticated) {
+ int lastLogin = 1;
+ var availableBiometrics = await auth.getAvailableBiometrics();
+
+ if (availableBiometrics.contains(BiometricType.strong)) {
+ lastLogin = 3; // Assume Face or secure fingerprint
+ } else if (availableBiometrics.contains(BiometricType.weak)) {
+ lastLogin = 2; // Likely weak fingerprint
+ }
+
+ var request = authService.getCommonRequest(
+ type: type,
+ registerd_data: null,
+ deviceToken: widget.savedLoginData.iMEI,
+ mobileNumber: int.parse(widget.savedLoginData.mobile!),
+ zipCode: widget.savedLoginData.outSA == 1 ? '971' : '966',
+ patientOutSA: widget.savedLoginData.outSA,
+ loginTokenID: null,
+ selectedOption: lastLogin,
+ user: widget.savedLoginData,
+ );
+
+ getMobileInfo(request, lastLogin);
+ }
+}
+
+
+ getMobileInfo(request,int lastLogin) {
+ // GifLoaderDialogUtils.showMyDialog(context);
+ this.authService.getLoginInfo(request).then((result) {
+ GifLoaderDialogUtils.hideDialog(context);
+ if (result['SMSLoginRequired'] == false) {
+ // this.loginTokenID = result['LogInTokenID'];
+ // this.patientOutSA = result['PatientOutSA'];
+ // setDefault();
+ checkActivationCode(lastLogin,result['LogInTokenID']);
+ }
+ }).catchError((err) {
+ GifLoaderDialogUtils.hideDialog(context);
+ print(err);
+ });
+ }
+
+
+ checkActivationCode(int loginType, String loginToken) async {
+
+ AppGlobal.context = context;
+ GifLoaderDialogUtils.showMyDialog(context);
+ var request = authService.getCommonRequest(
+ type: loginType,
+ registerd_data: null,
+ deviceToken: widget.savedLoginData.iMEI,
+ mobileNumber: int.parse(widget.savedLoginData.mobile!),
+ zipCode: widget.savedLoginData.outSA == 1 ? '971' : '966',
+ patientOutSA: widget.savedLoginData.outSA,
+ loginTokenID: loginToken,
+ selectedOption: loginType,
+ user: widget.savedLoginData,
+ ).toJson();
+ dynamic res;
+
+ authService
+ .checkActivationCode(request, null)
+ .then((result) async => {
+ res = result,
+ if (result is Map)
+ {
+ result = CheckActivationCode.fromJson(result as Map),
+ // if (result.errorCode == '699')
+ // {
+ // //699 block run here
+ // GifLoaderDialogUtils.hideDialog(context),
+ // Future.delayed(Duration(seconds: 2), () {
+ // AppToast.showErrorToast(message: result.errorEndUserMessage);
+ // Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: Login));
+ // })
+ // }
+ // else if (this.registerd_data != null && this.registerd_data.isRegister == true)
+ // {
+ // widget.changePageViewIndex!(1),
+ // Navigator.popUntil(context, (route) => Utils.route(route, equalsTo: RegisterNew)),
+ // }
+ // else
+ {
+ sharedPref.remove(FAMILY_FILE),
+ result.list.isFamily = false,
+ // userData = result.list,
+ sharedPref.setString(BLOOD_TYPE, result.patientBloodType ?? ""),
+ //Remove o+ from here Added by Aamir
+ authenticatedUserObject.user = result.list,
+ projectViewModel.setPrivilege(privilegeList: res),
+ await sharedPref.setObject(MAIN_USER, result.list),
+ await sharedPref.setObject(USER_PROFILE, result.list),
+ // loginTokenID = result.logInTokenID,
+ await sharedPref.setObject(LOGIN_TOKEN_ID, result.logInTokenID),
+ await sharedPref.setString(TOKEN, result.authenticationTokenID),
+ // checkIfUserAgreedBefore(result),
+ projectViewModel.analytics.loginRegistration.login_successful(),
+ }
+ }
+ // else
+ // {
+ // // Navigator.of(context).pop(),
+ // GifLoaderDialogUtils.hideDialog(context),
+ // Future.delayed(Duration(seconds: 1), () {
+ // Navigator.of(context).pop();
+ // AppToast.showErrorToast(message: result, localContext: context);
+ // startSMSService(tempType);
+ // }),
+ //
+ // projectViewModel.analytics.loginRegistration.login_fail(error: result),
+ // projectViewModel.analytics.errorTracking.log('otp_verification_at_confirm_login', error: result)
+ // }
+ });
+ }
+
+
+ insertIMEI(lastLogin) {
+
+ authService.insertDeviceImei(lastLogin).then((value) => {}).catchError((err) {
+ print(err);
+ });
+ }
+}
\ No newline at end of file
diff --git a/lib/pages/login/welcome.dart b/lib/pages/login/welcome.dart
index e0405520..33a02900 100644
--- a/lib/pages/login/welcome.dart
+++ b/lib/pages/login/welcome.dart
@@ -102,6 +102,7 @@ class _WelcomeLogin extends State {
@override
Widget build(BuildContext context) {
projectViewModel = context.read();
+ toDoProvider = context.read();
return AppScaffold(
appBarTitle: TranslationBase.of(context).welcome,
isShowDecPage: false,
@@ -284,7 +285,8 @@ class _WelcomeLogin extends State {
}
checkUserAuthentication(type) {
- showLoader(true);
+ // showLoader(true);
+ GifLoaderDialogUtils.showMyDialog(context);
var req = getCommonRequest(type: type);
req.logInTokenID = "";
@@ -525,7 +527,8 @@ class _WelcomeLogin extends State {
? user!.logInType
: null;
- showLoader(false);
+ // showLoader(false);
+ GifLoaderDialogUtils.hideDialog(context);
//this.cs.sharedService.getStorage(AuthenticationService.LAST_LOGIN);
}
diff --git a/lib/routes.dart b/lib/routes.dart
index ec391bd3..b48cd5d7 100644
--- a/lib/routes.dart
+++ b/lib/routes.dart
@@ -15,6 +15,7 @@ import 'package:hmg_patient_app/pages/login/login-type.dart';
import 'package:hmg_patient_app/pages/login/login.dart';
import 'package:hmg_patient_app/pages/login/register-info.dart';
import 'package:hmg_patient_app/pages/login/register.dart';
+import 'package:hmg_patient_app/pages/login/saved_login.dart';
import 'package:hmg_patient_app/pages/login/welcome.dart';
import 'package:hmg_patient_app/pages/packages_offers/OfferAndPackagesCartPage.dart';
import 'package:hmg_patient_app/pages/packages_offers/PackageOrderCompletedPage.dart';
@@ -58,7 +59,6 @@ const String OPENTOK_CALL_PAGE = 'OPENTOK_CALL_PAGE';
const String CART_ORDER_PAGE = 'cart-order-page';
const String CALL_PAGE = 'CALL_PAGE';
const String INCOMING_CALL_PAGE = 'INCOMING_CALL_PAGE';
-
const String HEALTH_WEATHER = 'health-weather';
const APP_UPDATE = 'app-update';
diff --git a/lib/services/authentication/auth_provider.dart b/lib/services/authentication/auth_provider.dart
index 6c03f9e9..8e338426 100644
--- a/lib/services/authentication/auth_provider.dart
+++ b/lib/services/authentication/auth_provider.dart
@@ -18,6 +18,7 @@ import 'package:hmg_patient_app/models/Authentication/insert_device_imei_request
import 'package:hmg_patient_app/models/Authentication/register_user_requet.dart';
import 'package:hmg_patient_app/models/Authentication/registered_authenticated_user_req.dart';
import 'package:hmg_patient_app/models/Authentication/select_device_imei_res.dart';
+import 'package:hmg_patient_app/models/Authentication/send_activation_request.dart';
import 'package:hmg_patient_app/models/Request.dart';
import 'package:hmg_patient_app/routes.dart';
import 'package:hmg_patient_app/uitl/app_shared_preferences.dart';
@@ -1937,4 +1938,33 @@ class AuthProvider with ChangeNotifier {
model.setState(0, 0, false, null);
Navigator.of(AppGlobal.context).pushReplacementNamed(HOME);
}
+
+ SendActivationRequest getCommonRequest({type, required registerd_data,required deviceToken,required mobileNumber,required zipCode,required patientOutSA, required loginTokenID, required selectedOption, required SelectDeviceIMEIRES user} ) {
+ var request = SendActivationRequest();
+ request.patientMobileNumber = mobileNumber;
+ request.mobileNo = '0' + mobileNumber.toString();
+ request.deviceToken = deviceToken;
+ request.projectOutSA = patientOutSA == true ? true : false;
+ request.loginType = selectedOption;
+ request.oTPSendType = type == 1 ? type : 2; //this.selectedOption == 1 ? 1 : 2;
+ request.zipCode = zipCode;
+
+ request.logInTokenID = loginTokenID ?? "";
+
+ if (registerd_data != null) {
+ request.searchType = registerd_data.searchType != null ? registerd_data.searchType : 1;
+ request.patientID = registerd_data.patientID != null ? registerd_data.patientID : 0;
+ request.patientIdentificationID = request.nationalID = registerd_data.patientIdentificationID != null ? registerd_data.patientIdentificationID : '0';
+ request.dob = registerd_data.dob;
+ request.isRegister = registerd_data.isRegister;
+ } else {
+ request.searchType = request.searchType != null ? request.searchType : 2;
+ request.patientID = user!.patientID != null ? user!.patientID : 0;
+ request.nationalID = request.nationalID != null ? request.nationalID : '0';
+ request.patientIdentificationID = request.patientIdentificationID != null ? request.patientIdentificationID : '0';
+ request.isRegister = false;
+ }
+ request.deviceTypeID = request.searchType;
+ return request;
+ }
}
diff --git a/lib/splashPage.dart b/lib/splashPage.dart
index ebff30a2..ac51a490 100644
--- a/lib/splashPage.dart
+++ b/lib/splashPage.dart
@@ -51,7 +51,7 @@ class _SplashScreenState extends State {
if (!_privilegeService.hasError) {
Navigator.of(context).pushReplacement(
MaterialPageRoute(
- builder: (BuildContext context) => WelcomeLogin(),
+ builder: (BuildContext context) => LandingPage(),
// builder: (BuildContext context) => LandingPage(),
),
);
diff --git a/lib/uitl/translations_delegate_base.dart b/lib/uitl/translations_delegate_base.dart
index bea13750..c8b93fd6 100644
--- a/lib/uitl/translations_delegate_base.dart
+++ b/lib/uitl/translations_delegate_base.dart
@@ -3477,6 +3477,8 @@ class TranslationBase {
String get welcomeToDrSulaiman => localizedValues["welcomeToDrSulaiman"][locale.languageCode];
String get prepareToElevate => localizedValues["prepareToElevate"][locale.languageCode];
String get dontHaveAccount => localizedValues["dontHaveAccount"][locale.languageCode];
+ String get loginByOTP => localizedValues['loginByOTP'][locale.languageCode];
+ String get loginBy => localizedValues['loginBy'][locale.languageCode];
String get alreadyHaveAccount => localizedValues["alreadyHaveAccount"][locale.languageCode];
String get loginNow => localizedValues["loginNow"][locale.languageCode];
diff --git a/lib/widgets/quick_login.dart b/lib/widgets/quick_login.dart
new file mode 100644
index 00000000..ae57f2af
--- /dev/null
+++ b/lib/widgets/quick_login.dart
@@ -0,0 +1,129 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_svg/flutter_svg.dart';
+import 'package:hmg_patient_app/new_ui/otp/otp_validation_bootmsheet_widget.dart';
+import 'package:hmg_patient_app/uitl/translations_delegate_base.dart';
+import 'package:hmg_patient_app/uitl/utils.dart';
+import 'package:hmg_patient_app/widgets/buttons/defaultButton.dart';
+
+
+
+class QuickLoginBottomSheet extends StatefulWidget {
+ final VoidCallback onPressed;
+ final bool isDone;
+
+ const QuickLoginBottomSheet({required this.onPressed, this.isDone = false});
+
+ @override
+ _QuickLoginBottomSheet createState() => _QuickLoginBottomSheet();
+}
+class _QuickLoginBottomSheet extends State {
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ decoration: const BoxDecoration(
+ color: Colors.white,
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(24),
+ topRight: Radius.circular(24),
+ ),
+ ),
+ padding: const EdgeInsets.all(24),
+ child: Column( mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.center,children: [
+
+
+ widget.isDone ? Column(children: [
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [ InkWell(
+ onTap: () {
+ Navigator.of(context).pop();
+ },
+ child: SvgPicture.asset("assets/images/svg/cross-circle.svg", width: 24, height: 24)),],),
+ Utils.showLottie(context: context, assetPath: 'assets/animations/lottie/checkmark.json', width: 120, height: 120, repeat: true),
+
+
+ const Text(
+ 'All Set! Now you can login with Face ID or Biometric',
+ textAlign: TextAlign.center,
+ style: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.bold,
+ color: Colors.black,
+ fontFamily: 'Poppins',
+
+ ),
+ ),
+
+ ],) : Column(
+ mainAxisSize: MainAxisSize.min,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+
+ Image.asset("assets/images/lock-icon.png", height: 101,),
+ const SizedBox(height: 10),
+ const Text(
+ 'Enable Quick Login',
+ style: TextStyle(
+ fontSize: 26,
+ fontWeight: FontWeight.bold,
+ color: Colors.black,
+ ),
+ ),
+
+ const SizedBox(height: 5),
+
+ // Description
+ const Text(
+ 'Enabling the quick login will verify through your existing device Face ID / Biometric',
+ style: TextStyle(
+ fontSize: 16,
+ color: Color(0xFF666666),
+ height: 1.5,
+ ),
+ ),
+
+
+
+ const SizedBox(height: 24),
+
+ // Buttons
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ Expanded(child:
+
+ CustomButton(
+ text: "Enable Quick Login",
+ onPressed:widget.onPressed,
+ backgroundColor:Color(0xffED1C2B),
+ borderColor:Color(0xffED1C2B),
+ textColor: Colors.white,
+ icon: "assets/images/svg/apple-finder.svg",
+ )),
+ ],
+ ),
+ SizedBox(height: 16,),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.end,
+ children: [
+ Expanded(child:
+
+ CustomButton(
+ text: "Not Now",
+ onPressed: (){ Navigator.pop(context);},
+ backgroundColor:Color(0xffFEE9EA),
+ borderColor:Color(0xffFEE9EA),
+ textColor: Colors.red,
+ // icon: "assets/images/svg/apple-finder.svg",
+ )),
+ ],
+ ),
+ ],
+ )],),
+ );
+ }
+
+
+}
\ No newline at end of file
diff --git a/pubspec.yaml b/pubspec.yaml
index 131b639f..e5e4d524 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -27,7 +27,7 @@ dependencies:
get_it: ^8.0.3
health: ^13.1.1
fl_chart: ^1.0.0
- camera: ^0.11.1
+# camera: ^0.11.2
permission_handler: ^12.0.0+1
flutter_html: ^3.0.0-beta.2
flutter_widget_from_html: ^0.16.0
@@ -83,6 +83,7 @@ dependencies:
flutter_local_notifications: any
device_calendar: ^4.3.3
geolocator: ^14.0.2
+ geolocator_android: ^5.0.2
geocoding: ^4.0.0
jiffy: ^6.2.1