You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			280 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Dart
		
	
			
		
		
	
	
			280 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			Dart
		
	
| import 'dart:async';
 | |
| 
 | |
| import 'package:easy_localization/src/public_ext.dart';
 | |
| import 'package:flutter/material.dart';
 | |
| import 'package:flutter_svg/svg.dart';
 | |
| import 'package:mohem_flutter_app/classes/colors.dart';
 | |
| import 'package:mohem_flutter_app/extensions/int_extensions.dart';
 | |
| import 'package:mohem_flutter_app/extensions/string_extensions.dart';
 | |
| import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
 | |
| import 'package:mohem_flutter_app/widgets/button/default_button.dart';
 | |
| import 'package:mohem_flutter_app/widgets/otp_widget.dart';
 | |
| 
 | |
| final ValueNotifier<String> otpFieldClear = ValueNotifier<String>("");
 | |
| 
 | |
| class OtpDialog {
 | |
|   final int type;
 | |
|   final int? mobileNo;
 | |
|   final Function(String, TextEditingController _pinPutController) onSuccess;
 | |
|   final Function onFailure;
 | |
|   final BuildContext context;
 | |
|   final Function onResendCode;
 | |
| 
 | |
|   int remainingTime = 120;
 | |
| 
 | |
|   Future<Null>? timer;
 | |
| 
 | |
|   static BuildContext? _context;
 | |
| 
 | |
|   static bool? _loading;
 | |
| 
 | |
|   OtpDialog(this.context, this.type, this.mobileNo, this.onSuccess, this.onFailure, {required this.onResendCode});
 | |
| 
 | |
|   GlobalKey? verifyAccountForm = GlobalKey<FormState>();
 | |
| 
 | |
|   final TextEditingController _pinPutController = TextEditingController();
 | |
| 
 | |
|   TextEditingController digit1 = TextEditingController(text: "");
 | |
|   TextEditingController digit2 = TextEditingController(text: "");
 | |
|   TextEditingController digit3 = TextEditingController(text: "");
 | |
|   TextEditingController digit4 = TextEditingController(text: "");
 | |
| 
 | |
|   Map verifyAccountFormValue = {
 | |
|     'digit1': '',
 | |
|     'digit2': '',
 | |
|     'digit3': '',
 | |
|     'digit4': '',
 | |
|   };
 | |
|   final focusD1 = FocusNode();
 | |
|   final focusD2 = FocusNode();
 | |
|   final focusD3 = FocusNode();
 | |
|   final focusD4 = FocusNode();
 | |
|   String? errorMsg;
 | |
| 
 | |
|   // ProjectViewModel projectProvider;
 | |
|   String displayTime = '';
 | |
|   String? _code;
 | |
|   dynamic setState;
 | |
|   bool stopTimer = false;
 | |
| 
 | |
|   // static String signature;
 | |
| 
 | |
|   void displayDialog(BuildContext context) async {
 | |
|     return showDialog(
 | |
|         context: context,
 | |
|         barrierColor: Colors.black.withOpacity(0.63),
 | |
|         builder: (context) {
 | |
|           // projectProvider = Provider.of(context);
 | |
|           return Dialog(
 | |
|             backgroundColor: Colors.white,
 | |
|             surfaceTintColor: Colors.transparent,
 | |
|             shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
 | |
|             insetPadding: const EdgeInsets.only(left: 21, right: 21),
 | |
|             child: StatefulBuilder(builder: (context, setState) {
 | |
|               if (displayTime == '') {
 | |
|                 startTimer(setState);
 | |
|               }
 | |
| 
 | |
|               return Container(
 | |
|                 padding: EdgeInsets.all(21),
 | |
|                 child: Column(
 | |
|                   mainAxisSize: MainAxisSize.min,
 | |
|                   crossAxisAlignment: CrossAxisAlignment.start,
 | |
|                   children: [
 | |
|                     SvgPicture.asset(
 | |
|                       type == 1
 | |
|                           ? "assets/images/login/verify_sms.svg"
 | |
|                           : type == 2
 | |
|                               ? "assets/images/login/verify_whatsapp.svg"
 | |
|                               : type == 3
 | |
|                                   ? "assets/images/login/verify_face.svg"
 | |
|                                   : 'assets/images/login/verify_thumb.svg',
 | |
|                       height: 50,
 | |
|                       width: 50,
 | |
|                     ),
 | |
|                     12.height,
 | |
|                     LocaleKeys.otp.tr().toText14(),
 | |
|                     LocaleKeys.verification.tr().toText24(isBold: true),
 | |
|                     6.height,
 | |
|                     (LocaleKeys.pleaseEnterTheVerificationCodeSentTo.tr() + ' xxxxxxxx' + mobileNo.toString().substring(mobileNo.toString().length - 3)).toText16(),
 | |
|                     18.height,
 | |
|                     ValueListenableBuilder<String>(
 | |
|                       builder: (BuildContext context, String value, Widget? child) {
 | |
|                         // This builder will only get called when the _counter
 | |
|                         // is updated.
 | |
|                         return Column(
 | |
|                           crossAxisAlignment: CrossAxisAlignment.start,
 | |
|                           children: [
 | |
|                             Directionality(
 | |
|                               textDirection: TextDirection.ltr,
 | |
|                               child: Center(
 | |
|                                 child: OTPWidget(
 | |
|                                   autoFocus: true,
 | |
|                                   controller: _pinPutController,
 | |
|                                   defaultBorderColor: const Color(0xffD8D8D8),
 | |
|                                   maxLength: 4,
 | |
|                                   onTextChanged: (text) {},
 | |
|                                   pinBoxColor: Colors.white,
 | |
|                                   onDone: (code) => _onOtpCallBack(code, null),
 | |
|                                   textBorderColor: const Color(0xffD8D8D8),
 | |
|                                   pinBoxWidth: 60,
 | |
|                                   pinBoxHeight: 60,
 | |
|                                   pinTextStyle: const TextStyle(fontSize: 24.0, color: MyColors.darkTextColor),
 | |
|                                   pinTextAnimatedSwitcherTransition: ProvidedPinBoxTextAnimation.scalingTransition,
 | |
|                                   pinTextAnimatedSwitcherDuration: const Duration(milliseconds: 300),
 | |
|                                   pinBoxRadius: 10,
 | |
|                                   keyboardType: TextInputType.number,
 | |
|                                 ),
 | |
|                               ),
 | |
|                             ),
 | |
|                             10.height,
 | |
|                             stopTimer
 | |
|                                 ? Row(
 | |
|                                     children: [
 | |
|                                       Expanded(
 | |
|                                         child: LocaleKeys.codeExpire.tr().toText16(
 | |
|                                               color: MyColors.redColor,
 | |
|                                             ),
 | |
|                                       ),
 | |
|                                       12.width,
 | |
|                                       Image.asset(
 | |
|                                         "assets/icons/ic_alarm.png",
 | |
|                                         width: 20,
 | |
|                                         height: 20,
 | |
|                                         color: MyColors.redColor,
 | |
|                                       ),
 | |
|                                     ],
 | |
|                                   )
 | |
|                                 : RichText(
 | |
|                                     text: TextSpan(
 | |
|                                       text: LocaleKeys.theVerificationCodeWillExpireIn.tr() + '\n',
 | |
|                                       style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: -0.48),
 | |
|                                       children: <TextSpan>[
 | |
|                                         TextSpan(
 | |
|                                           text: displayTime,
 | |
|                                           style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: MyColors.textMixColor, letterSpacing: -0.48),
 | |
|                                         ),
 | |
|                                       ],
 | |
|                                     ),
 | |
|                                   ),
 | |
|                           ],
 | |
|                         );
 | |
|                       },
 | |
|                       valueListenable: otpFieldClear,
 | |
|                     ),
 | |
|                     18.height,
 | |
|                     DefaultButton(
 | |
|                       stopTimer ? LocaleKeys.resend.tr() : LocaleKeys.cancel.tr(),
 | |
|                       () async {
 | |
|                         if (stopTimer) {
 | |
|                           hideSMSBox(context);
 | |
|                           onResendCode();
 | |
|                         } else {
 | |
|                           stopTimer = true;
 | |
|                           // onFailure();
 | |
|                           hideSMSBox(context);
 | |
|                         }
 | |
|                       },
 | |
|                       colors: stopTimer
 | |
|                           ? null
 | |
|                           : [
 | |
|                               MyColors.pinkDarkColor,
 | |
|                               MyColors.pinkDarkColor,
 | |
|                             ],
 | |
|                     ),
 | |
|                   ],
 | |
|                 ),
 | |
|               );
 | |
|             }),
 | |
|           );
 | |
|         });
 | |
|   }
 | |
| 
 | |
|   InputDecoration buildInputDecoration(BuildContext context) {
 | |
|     return InputDecoration(
 | |
|       counterText: " ",
 | |
|       enabledBorder: const OutlineInputBorder(
 | |
|         borderRadius: BorderRadius.all(Radius.circular(10)),
 | |
|         borderSide: BorderSide(color: Colors.black),
 | |
|       ),
 | |
|       focusedBorder: OutlineInputBorder(
 | |
|         borderRadius: const BorderRadius.all(Radius.circular(10.0)),
 | |
|         borderSide: BorderSide(color: Theme.of(context).primaryColor),
 | |
|       ),
 | |
|       errorBorder: OutlineInputBorder(
 | |
|         borderRadius: const BorderRadius.all(Radius.circular(10.0)),
 | |
|         borderSide: BorderSide(color: Colors.red),
 | |
|       ),
 | |
|       // focusedErrorBorder: OutlineInputBorder(
 | |
|       //   borderRadius: const BorderRadius.all(Radius.circular(10.0)),
 | |
|       //   borderSide: BorderSide(color: Colors.red),
 | |
|       //   // borderSide: BorderSide(color: Theme.of(context).colorScheme.error),
 | |
|       // ),
 | |
|       focusedErrorBorder: OutlineInputBorder(
 | |
|         borderRadius: const BorderRadius.all(Radius.circular(10.0)),
 | |
|         borderSide: BorderSide(color: Theme.of(context).colorScheme.error),
 | |
|       ),
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // String validateCodeDigit(value) {
 | |
|   //   if (value.isEmpty) {
 | |
|   //     return ' ';
 | |
|   //   } else if (value.length == 3) {
 | |
|   //     print(value);
 | |
|   //   } else {
 | |
|   //     return null;
 | |
|   //   }
 | |
|   // }
 | |
| 
 | |
|   String getSecondsAsDigitalClock(int inputSeconds) {
 | |
|     int secNum = int.parse(inputSeconds.toString()); // don't forget the second param
 | |
|     int hours = (secNum / 3600).floor();
 | |
|     int minutes = ((secNum - hours * 3600) / 60).floor();
 | |
|     double seconds = secNum - hours * 3600 - minutes * 60;
 | |
|     String minutesString = "";
 | |
|     String secondsString = "";
 | |
|     minutesString = minutes < 10 ? "0" + minutes.toString() : minutes.toString();
 | |
|     secondsString = seconds < 10 ? "0" + seconds.toStringAsFixed(0) : seconds.toStringAsFixed(0);
 | |
|     return minutesString + ":" + secondsString;
 | |
|   }
 | |
| 
 | |
|   void startTimer(setState) {
 | |
|     remainingTime--;
 | |
|     if (stopTimer) return;
 | |
|     setState(() {
 | |
|       displayTime = getSecondsAsDigitalClock(remainingTime);
 | |
|     });
 | |
| 
 | |
|     timer = Future.delayed(const Duration(seconds: 1), () {
 | |
|       if (remainingTime > 0) {
 | |
|         startTimer(setState);
 | |
|       } else {
 | |
|         setState(() {
 | |
|           stopTimer = true;
 | |
|         });
 | |
|       }
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   void hideSMSBox(context) {
 | |
|     onFailure();
 | |
|   }
 | |
| 
 | |
|   void _onOtpCallBack(String otpCode, bool? isAutofill) {
 | |
|     if (otpCode.length == 4) {
 | |
|       // stopTimer = true;
 | |
|       otpFieldClear.value = otpCode;
 | |
|       onSuccess(otpCode, _pinPutController);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| // static getSignature() async {
 | |
| //   // if (Platform.isAndroid) {
 | |
| //   //   return await SmsRetriever.getAppSignature();
 | |
| //   // } else {
 | |
| //   //   return null;
 | |
| //   // }
 | |
| // }
 | |
| }
 |