import 'package:country_code_picker/country_code_picker.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:news/cubits/appSystemSettingCubit.dart'; import 'package:news/ui/styles/colors.dart'; import 'package:news/ui/widgets/customTextLabel.dart'; import 'package:news/ui/widgets/SnackBarWidget.dart'; import 'package:news/app/routes.dart'; import 'package:news/utils/uiUtils.dart'; import 'package:news/utils/internetConnectivity.dart'; import 'package:news/utils/validators.dart'; class RequestOtp extends StatefulWidget { const RequestOtp({super.key}); @override RequestOtpState createState() => RequestOtpState(); } class RequestOtpState extends State { TextEditingController phoneC = TextEditingController(); String? phone, conCode; final GlobalKey _formkey = GlobalKey(); bool isLoading = false; CountryCode? code; String? verificationId; String errorMessage = ''; final FirebaseAuth _auth = FirebaseAuth.instance; int forceResendingToken = 0; @override void initState() { super.initState(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ SafeArea( child: showContent(), ), UiUtils.showCircularProgress(isLoading, Theme.of(context).primaryColor) ], )); } //show form content showContent() { return Container( padding: const EdgeInsetsDirectional.all(20.0), child: SingleChildScrollView( child: Form( key: _formkey, child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ Align( //backButton alignment: Alignment.topLeft, child: InkWell(onTap: () => Navigator.of(context).pop(), splashColor: Colors.transparent, child: const Icon(Icons.keyboard_backspace_rounded))), const SizedBox(height: 50), otpVerifySet(), enterMblSet(), receiveDigitSet(), setCodeWithMono(), reqOtpBtn() ]))), ); } otpVerifySet() { return CustomTextLabel( text: 'loginLbl', textStyle: Theme.of(context).textTheme.headlineSmall?.copyWith(color: UiUtils.getColorScheme(context).primaryContainer, fontWeight: FontWeight.w800, letterSpacing: 0.5), textAlign: TextAlign.center); } enterMblSet() { return Padding( padding: const EdgeInsets.only(top: 35.0), child: CustomTextLabel( text: 'enterMblLbl', textStyle: Theme.of(context).textTheme.bodyLarge?.copyWith(color: UiUtils.getColorScheme(context).primaryContainer, fontWeight: FontWeight.w500), ), ); } receiveDigitSet() { return Container( padding: const EdgeInsets.only(top: 20.0), child: CustomTextLabel( text: 'receiveDigitLbl', textStyle: Theme.of(context).textTheme.bodyMedium?.copyWith(color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.8), fontSize: 14), textAlign: TextAlign.left), ); } setCodeWithMono() { return Padding( padding: const EdgeInsets.only(top: 30.0), child: Container( decoration: BoxDecoration(borderRadius: BorderRadius.circular(10.0), color: Theme.of(context).colorScheme.surface), child: Row( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, children: [setCountryCode(), setMono()], ))); } setCountryCode() { double width = MediaQuery.of(context).size.width; double height = MediaQuery.of(context).size.height; return SizedBox( height: 45, child: CountryCodePicker( boxDecoration: BoxDecoration(color: Theme.of(context).colorScheme.surface), searchDecoration: InputDecoration(hintStyle: TextStyle(color: UiUtils.getColorScheme(context).primaryContainer), fillColor: UiUtils.getColorScheme(context).primaryContainer), initialSelection: context.read().getCountryCode(), dialogSize: Size(width - 50, height - 50), builder: (CountryCode? code) { return Row( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsetsDirectional.only(top: 10.0, bottom: 10.0, start: 20.0, end: 4.0), child: ClipRRect(borderRadius: BorderRadius.circular(3.0), child: Image.asset(code!.flagUri.toString(), package: 'country_code_picker', height: 30, width: 30, fit: BoxFit.cover))), Container( //CountryCode width: 55.0, height: 55.0, alignment: Alignment.center, child: CustomTextLabel( text: code.dialCode.toString(), textStyle: Theme.of(context).textTheme.titleMedium?.copyWith(color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.7)), overflow: TextOverflow.ellipsis, softWrap: true)), ], ); }, onChanged: (CountryCode countryCode) { conCode = countryCode.dialCode; }, onInit: (CountryCode? code) { conCode = code?.dialCode; })); } setMono() { return Expanded( child: Padding( padding: const EdgeInsetsDirectional.only(top: 5.0, bottom: 15.0), child: Container( height: 40, width: MediaQuery.of(context).size.width * 0.57, alignment: Alignment.center, child: TextFormField( keyboardType: const TextInputType.numberWithOptions(signed: true, decimal: true), controller: phoneC, style: Theme.of(context).textTheme.titleMedium?.copyWith(color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.7)), inputFormatters: [FilteringTextInputFormatter.digitsOnly], validator: (val) => Validators.mobValidation(val!, context), onSaved: (String? value) => phone = value, decoration: InputDecoration( hintText: UiUtils.getTranslatedLabel(context, 'enterMblLbl'), hintStyle: Theme.of(context).textTheme.titleSmall?.copyWith(color: UiUtils.getColorScheme(context).primaryContainer.withOpacity(0.5)), enabledBorder: InputBorder.none, focusedBorder: InputBorder.none, ), )), ), ); } Future verifyPhone(BuildContext context) async { try { await _auth.verifyPhoneNumber( phoneNumber: (conCode!.contains("+")) ? "$conCode${phoneC.text.trim()}" : "+$conCode${phoneC.text.trim()}", verificationCompleted: (AuthCredential phoneAuthCredential) { showSnackBar(phoneAuthCredential.toString(), context); }, verificationFailed: (FirebaseAuthException exception) { setState(() => isLoading = false); if (exception.code == "invalid-phone-number") { //invalidPhoneNumber showSnackBar(UiUtils.getTranslatedLabel(context, 'invalidPhoneNumber'), context); } else { showSnackBar('${exception.message}', context); } }, forceResendingToken: forceResendingToken, codeAutoRetrievalTimeout: (String verId) => verificationId = verId, codeSent: processCodeSent(), //smsOTPSent timeout: const Duration(seconds: 60)); } on FirebaseAuthException catch (authError) { setState(() => isLoading = false); showSnackBar(authError.message!, context); } on FirebaseException catch (e) { setState(() => isLoading = false); showSnackBar(e.toString(), context); } catch (e) { setState(() => isLoading = false); showSnackBar(e.toString(), context); } } processCodeSent() { try { smsOTPSent(String? verId, [int? forceCodeResend]) async { if (forceCodeResend != null) forceResendingToken = forceCodeResend; verificationId = verId; setState(() => isLoading = false); showSnackBar(UiUtils.getTranslatedLabel(context, 'codeSent'), context); await Navigator.of(context).pushNamed(Routes.verifyOtp, arguments: {"verifyId": verificationId, "countryCode": conCode, "mono": phoneC.text.trim()}); } return smsOTPSent; } catch (e) {} } reqOtpBtn() { return Container( alignment: Alignment.center, padding: const EdgeInsets.only(top: 60.0), child: InkWell( child: Container( height: 45.0, width: MediaQuery.of(context).size.width * 0.9, alignment: Alignment.center, decoration: BoxDecoration(color: Theme.of(context).primaryColor, borderRadius: BorderRadius.circular(7.0)), child: CustomTextLabel(text: 'reqOtpLbl', textStyle: Theme.of(context).textTheme.titleLarge?.copyWith(color: secondaryColor, fontWeight: FontWeight.w600, letterSpacing: 0.5, fontSize: 16))), onTap: () async { FocusScope.of(context).unfocus(); //dismiss keyboard if (validateAndSave()) { if (await InternetConnectivity.isNetworkAvailable()) { setState(() => isLoading = true); verifyPhone(context); } else { showSnackBar(UiUtils.getTranslatedLabel(context, 'internetmsg'), context); } } }, ), ); } //check validation of form data bool validateAndSave() { final form = _formkey.currentState; form!.save(); return (form.validate()) ? true : false; } }