import 'dart:io'; import 'package:easy_localization/src/public_ext.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_svg/svg.dart'; import 'package:local_auth/local_auth.dart'; import 'package:local_auth_darwin/local_auth_darwin.dart'; import 'package:local_auth_android/local_auth_android.dart'; import 'package:mohem_flutter_app/api/login_api_client.dart'; import 'package:mohem_flutter_app/app_state/app_state.dart'; import 'package:mohem_flutter_app/classes/colors.dart'; import 'package:mohem_flutter_app/classes/date_uitl.dart'; import 'package:mohem_flutter_app/classes/utils.dart'; import 'package:mohem_flutter_app/config/routes.dart'; import 'package:mohem_flutter_app/dialogs/otp_dialog.dart'; import 'package:mohem_flutter_app/extensions/int_extensions.dart'; import 'package:mohem_flutter_app/extensions/string_extensions.dart'; import 'package:mohem_flutter_app/extensions/widget_extensions.dart'; import 'package:mohem_flutter_app/generated/locale_keys.g.dart'; import 'package:mohem_flutter_app/models/basic_member_information_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/get_mobile_login_info_list_model.dart'; import 'package:mohem_flutter_app/ui/dialogs/id/business_card_dialog.dart'; import 'package:mohem_flutter_app/ui/dialogs/id/employee_digital_id_dialog.dart'; import 'package:mohem_flutter_app/widgets/button/default_button.dart'; import 'package:mohem_flutter_app/widgets/dialogs/dialogs.dart'; // WhatsApp 4 // SMS 1 // Face ID 3 // Finger Print 2 class VerifyLastLoginScreen extends StatefulWidget { VerifyLastLoginScreen({Key? key}) : super(key: key); @override _VerifyLastLoginScreenState createState() { return _VerifyLastLoginScreenState(); } } class _VerifyLastLoginScreenState extends State { final LocalAuthentication auth = LocalAuthentication(); List _availableBioMetricType = []; GetMobileLoginInfoListModel? mobileLoginInfoListModel; //For face and finger print verification int selectedFlag = 0; bool isNeedVerifyWithFaceIDAndBiometrics = false; @override void initState() { _getAvailableBiometrics(); // setDefault(); super.initState(); } @override Widget build(BuildContext context) { if (ModalRoute.of(context)!.settings.arguments != null) { mobileLoginInfoListModel ??= ModalRoute.of(context)!.settings.arguments as GetMobileLoginInfoListModel; // String empName = AppState().isArabic(context) ? AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEAr! : AppState().memberInformationList!.eMPLOYEEDISPLAYNAMEEn!; String empName = mobileLoginInfoListModel!.employeeName!; } return Scaffold( appBar: AppBar( surfaceTintColor: Colors.transparent, backgroundColor: Colors.transparent, automaticallyImplyLeading: false, title: (mobileLoginInfoListModel?.businessCardPrivilege ?? false) ? LocaleKeys.viewBusinessCard.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { showMDialog(context, child: const BusinessCardDialog()); }) : Container(), actions: [ Center( child: LocaleKeys.employeeDigitalID.tr().toText12(color: MyColors.textMixColor, isUnderLine: true).onPress(() { showMDialog(context, child: EmployeeDigitialIdDialog()); }), ), 21.width, ], ), body: Column( children: [ ListView( padding: const EdgeInsets.all(21), physics: const BouncingScrollPhysics(), children: [ //12.height, if (true) Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ LocaleKeys.welcomeBack.tr().toText12(), mobileLoginInfoListModel?.employeeName?.toText24(isBold: true) ?? const SizedBox.shrink(), 10.height, LocaleKeys.wouldYouLikeToLoginWithCurrentUsername.tr().toText16(), Container( height: 72, margin: const EdgeInsets.only(top: 23, bottom: 23), alignment: Alignment.center, padding: const EdgeInsets.only(left: 17, right: 12), decoration: BoxDecoration(borderRadius: BorderRadius.circular(10), color: Colors.white, border: Border.all(color: const Color(0xffefefef), width: 1)), child: Column( mainAxisSize: MainAxisSize.min, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [LocaleKeys.lastLoginDetails.tr().toText16(), DateUtil.formatDateToDate(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn ?? DateTime.now().toString()), false).toText12()], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ LocaleKeys.verificationType.tr().toText10(color: MyColors.grey57Color), getVerificationType(mobileLoginInfoListModel!.loginType!).toText12(), const Expanded(child: SizedBox()), DateUtil.formatDateToTime(DateUtil.convertStringToDate(mobileLoginInfoListModel!.editedOn!)).toText12(), ], ), ], ), ), LocaleKeys.pleaseVerify.tr().toText16(), if (isNeedVerifyWithFaceIDAndBiometrics) LocaleKeys.pleaseVerifyForBio.tr().toText12(), GridView( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.only(top: 9), shrinkWrap: true, children: [if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(3), if (!isNeedVerifyWithFaceIDAndBiometrics) getButton(4), getButton(2), getButton(1)], ), ], ), // else // Column(mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Image.asset( // 'assets/images/habib-logo.png', // height: 90, // width: 90, // ), // SizedBox(height: 23), // this.onlySMSBox == false // ? Text( // TranslationBase.of(context).verifyLoginWith, // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), // ) // : Text( // TranslationBase.of(context).verifyFingerprint2, // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2B353E), letterSpacing: -0.64, height: 25 / 16), // ), // SizedBox(height: 23), // Text( // TranslationBase.of(context).pleaseVerify, // style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xff2E303A), letterSpacing: -0.64), // ), // GridView( // gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2, crossAxisSpacing: 13, mainAxisSpacing: 9), // physics: NeverScrollableScrollPhysics(), // padding: EdgeInsets.only(top: 9), // shrinkWrap: true, // children: [ // if (onlySMSBox == false) getButton(3), // if (onlySMSBox == false) getButton(2), // getButton(1), // getButton(4), // ], // ), // ]), ], ).expanded, DefaultButton(LocaleKeys.useAnotherAccount.tr(), () { Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false, arguments: false); }).insideContainer, ], ), ); } Future _getAvailableBiometrics() async { try { _availableBioMetricType = await auth.getAvailableBiometrics(); } on PlatformException catch (e) { // AppToast.showErrorToast(message: e.message); print(e); } if (mounted) setState(() {}); } String getVerificationType(int type) { if (type == 1) { return LocaleKeys.sms.tr(); } else if (type == 2) { return LocaleKeys.whatsapp.tr(); } else if (type == 3) { return LocaleKeys.face.tr(); } else if (type == 4) { return LocaleKeys.fingerPrint.tr(); } return ""; } Future loginWithFaceIDAndBiometrics() async { IOSAuthMessages iosStrings = const IOSAuthMessages(cancelButton: 'cancel', goToSettingsButton: 'settings', goToSettingsDescription: 'Please set up your Touch ID.', lockOut: 'Please reenable your Touch ID'); // IOSAuthMessages iosStrings = const IOSAuthMessages( // cancelButton: 'cancel', // goToSettingsButton: 'settings', // goToSettingsDescription: 'Please set up your Touch ID.', // lockOut: 'Please reenable your Touch ID', // ); bool authenticated = false; try { authenticated = await auth.authenticate(localizedReason: 'Scan your fingerprint to authenticate', options: const AuthenticationOptions( useErrorDialogs: true, stickyAuth: true, biometricOnly: true, ), authMessages: [ iosStrings, const AndroidAuthMessages(), ], ); } on PlatformException catch (e) { print(e); Utils.hideLoading(context); Utils.showToast("Please enable your Touch or Face ID"); } return authenticated; } Widget _loginOptionButton(String _title, String _icon, int _flag, int? _loginIndex) { // <<<<<<< HEAD bool isDisable = false; if(_flag >= 3 && _flag <= 4) { bool isFaceEnabled = (_flag == 3 && (checkBiometricIsAvailable(BiometricType.face) || checkBiometricIsAvailable(BiometricType.weak))); bool isThumbEnabled = (_flag == 4 && (checkBiometricIsAvailable(BiometricType.fingerprint) || checkBiometricIsAvailable(BiometricType.strong))); isDisable = !(isFaceEnabled || isThumbEnabled); } // ======= // bool isDisable = (_flag == 3 && !checkBiometricIsAvailable(BiometricType.face) || // _flag == 4 && !checkBiometricIsAvailable(BiometricType.fingerprint) && _flag == 4 && !checkBiometricIsAvailable(BiometricType.face)); // // >>>>>>> master return InkWell( onTap: isDisable ? null : () async { if (_flag == 0) { setState(() { // isMoreOption = true; }); } else { if (_flag == 3 || _flag == 4) { bool authenticateWithFaceAndTouchID = await loginWithFaceIDAndBiometrics(); if (!authenticateWithFaceAndTouchID) { return; } else { if (mobileLoginInfoListModel!.loginType == 3 || mobileLoginInfoListModel!.loginType == 4) { // bool authenticateWithFaceAndTouchID = await loginWithFaceIDAndBiometrics(); // if (!authenticateWithFaceAndTouchID) { // return; // } else { // performApiCall(_title, _icon, _flag, isDirectLogin: true); // } performApiCall(_title, _icon, _flag, _flag, isDirectLogin: true); } else { isNeedVerifyWithFaceIDAndBiometrics = true; selectedFlag = _flag; setState(() { return; }); } } } else { if (isNeedVerifyWithFaceIDAndBiometrics) performApiCall(_title, _icon, selectedFlag, _flag); else performApiCall(_title, _icon, _flag, _flag); } } }, child: Container( padding: const EdgeInsets.only(left: 20, right: 20, bottom: 15, top: 28), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: isDisable ? Colors.grey.withOpacity(0.3) : Colors.white, border: Border.all(color: MyColors.lightGreyEFColor, width: 1), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [SvgPicture.asset(_icon, height: 38, width: 38, color: isDisable ? MyColors.darkTextColor.withOpacity(0.7) : null), _title.toText16(height: 20 / 16)], ), ), ); } Widget getButton(int flag) { switch (flag) { case 1: return _loginOptionButton(LocaleKeys.verifyThroughSMS.tr(), 'assets/images/login/verify_sms.svg', flag, null); case 2: return _loginOptionButton(LocaleKeys.verifyThroughWhatsapp.tr(), 'assets/images/login/verify_whatsapp.svg', flag, null); case 3: return _loginOptionButton(LocaleKeys.verifyThroughFace.tr(), 'assets/images/login/verify_face.svg', flag, BiometricType.face.index); case 4: return _loginOptionButton(LocaleKeys.verifyThroughFingerprint.tr(), 'assets/images/login/verify_thumb.svg', flag, BiometricType.fingerprint.index); default: return const SizedBox(); } } bool checkBiometricIsAvailable(BiometricType biometricType) { bool isAvailable = false; for (int i = 0; i < _availableBioMetricType.length; i++) { if (biometricType == _availableBioMetricType[i]) { isAvailable = true; break; } } return isAvailable; } Future performApiCall(String _title, String _icon, int _flag, int sendVerificationFlat, {bool isDirectLogin = false}) async { try { if (isDirectLogin) { setState(() { Utils.showLoading(context); }); } else { Utils.showLoading(context); } await LoginApiClient().checkMobileAppVersion(); await LoginApiClient().memberLogin(AppState().getUserName!, AppState().password!); if (!isDirectLogin) { BasicMemberInformationModel? memberInformationModel = await LoginApiClient().mohemmSendActivationCodeByOTPNotificationType( 0, AppState().memberLoginList?.pMOBILENUMBER, sendVerificationFlat, AppState().getUserName, ); } if (isDirectLogin) performDirectApiCall(_title, _icon, _flag, "", null); if (!isDirectLogin) Utils.hideLoading(context); if (!isDirectLogin) { OtpDialog( context, sendVerificationFlat, int.tryParse(AppState().memberLoginList?.pMOBILENUMBER ?? ""), (value, TextEditingController _pinPutController) async { Utils.showLoading(context); performDirectApiCall(_title, _icon, _flag, value, _pinPutController); }, () => {Navigator.pop(context)}, onResendCode: () { performApiCall(_title, _icon, _flag, sendVerificationFlat, isDirectLogin: isDirectLogin); }, ).displayDialog(context); } } catch (ex) { Utils.hideLoading(context); Utils.handleException(ex, context, null); } } Future performDirectApiCall(String _title, String _icon, int _flag, String value, TextEditingController? _pinPutController, {bool isDirectLogin = false}) async { try { GenericResponseModel? genericResponseModel = await LoginApiClient().checkActivationCode(true, AppState().memberLoginList?.pMOBILENUMBER, value, AppState().getUserName); GenericResponseModel? genericResponseModel1 = await LoginApiClient().insertMobileLoginInfoNEW( AppState().memberLoginList?.pEMAILADDRESS ?? "", genericResponseModel?.pSESSIONID ?? 0, genericResponseModel?.memberInformationList![0].eMPLOYEENAME ?? "", _flag, AppState().memberLoginList?.pMOBILENUMBER ?? "", AppState().getUserName!, AppState().getIsHuawei ? AppState().getHuaweiPushToken : mobileLoginInfoListModel!.deviceToken!, Platform.isAndroid ? "android" : "ios", ); AppState().setMemberInformationListModel = genericResponseModel!.memberInformationList?.first; AppState().setPrivilegeListModel = genericResponseModel!.privilegeList ?? []; if (genericResponseModel.errorMessage != null) { Utils.showToast(genericResponseModel.errorMessage ?? ""); // Navigator.pop(context); } Utils.hideLoading(context); Navigator.pop(context); Navigator.pushNamedAndRemoveUntil(context, AppRoutes.dashboard, (Route route) => false); } catch (ex) { if (_pinPutController != null) { _pinPutController.clear(); otpFieldClear.value = ""; } Utils.hideLoading(context); Utils.handleException(ex, context, null); dynamic errorCode = ex; if (errorCode.error.errorStatusCode == 699) { Future.delayed(const Duration(seconds: 2), () { Navigator.pop(context); Navigator.pushNamedAndRemoveUntil(context, AppRoutes.login, (Route route) => false); }); } } } // // formatDate(date) { // return date; // return DateFormat('MMM dd, yyy, kk:mm').format(date); // } // // showLoader(bool isTrue) { // setState(() { // // isLoading = isTrue; // }); // } }