Closed Div-47 closed 1 year ago
provide code example so we can help you
Hi @Div-47, as @rashedswen mentioned, you will need to provide a link to a minimal reproduction sample in order for us to help, thanks 👍
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:meta/meta.dart';
part 'otp_event.dart';
part 'otp_state.dart';
class OtpBloc extends Bloc<OtpEvent, OtpState> {
OtpBloc() : super(OtpInitial()) {
on<InitOTP>((event, emit) async {
emit(InitOTPLoading());
await _InitOtpVerfication(event, emit);
});
on<SubmitOTP>((event, emit) async {
emit(SubmitOTPLoading());
await _SubmitOtp(event, emit);
});
on<OnOTPSent>((event, emit) async {
emit(InitOTPSuccess(event.verificationId));
});
on<OnVerificationFailed>((event, emit) {
emit(OTPError(event.message));
});
}
}
_SubmitOtp(SubmitOTP event, Emitter<OtpState> emit) async {
PhoneAuthCredential credential = PhoneAuthProvider.credential(
verificationId: event.verificationId, smsCode: event.otp);
await FirebaseAuth.instance.currentUser!.updatePhoneNumber(credential);
emit(SubmitOTPSuccess("Success"));
}
Future _InitOtpVerfication(InitOTP event, Emitter<OtpState> emit) async {
int? _resendToken;
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: event.phoneNumber,
verificationCompleted: (PhoneAuthCredential credential) async {},
verificationFailed: await (FirebaseAuthException e) {
OtpBloc().add(OnVerificationFailed(e.message ?? "Error occured!"));
},
codeSent: await (String verificationId, int? resendToken) async {
OtpBloc().add(OnOTPSent(verificationId));
_resendToken = resendToken;
},
forceResendingToken: _resendToken,
codeAutoRetrievalTimeout: (String verificationId) {},
);
}
---- this is my bloc, you can see im adding event on code sent callback and then on this event i'm emiting an state. so that state is not updating and bloc listener is not listing to this state. it got stuck with the InitOTPLoading. During this process the firebase automatic nagivating to recaptcha webview verification and then come back to screen. so i think due to this the bloc stops listening the emitted states.
@Div-47 can you format your code? like this
class OTPBody extends StatefulWidget {
const OTPBody({super.key});
@override
State< OTPBody > createState() =>
_OTPBodyState();
}
import 'package:firebase_auth/firebase_auth.dart';
import "package:flutter/material.dart";
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:service_provider/bloc/Otp/otp_bloc.dart';
import 'package:service_provider/utility.dart/baseUtility.dart';
import 'package:service_provider/utility.dart/colors.dart';
import 'package:service_provider/utility.dart/navigation_utility.dart';
import 'package:service_provider/utility.dart/text_style.dart';
import 'package:service_provider/widgets/AlertDialogs.dart';
import 'package:service_provider/widgets/buttons.dart';
import 'add_profile.dart';
class OtpCode extends StatefulWidget {
final String phoneNumber;
final bool isCustomer;
OtpCode(this.phoneNumber, this.isCustomer, {Key? key}) : super(key: key);
@override
_OtpCodeState createState() => _OtpCodeState();
}
class _OtpCodeState extends State<OtpCode> {
final TextEditingController otpController1 = TextEditingController();
final TextEditingController otpController2 = TextEditingController();
final TextEditingController otpController3 = TextEditingController();
final TextEditingController otpController4 = TextEditingController();
final TextEditingController otpController5 = TextEditingController();
final TextEditingController otpController6 = TextEditingController();
@override
void initState() {
context.read<OtpBloc>()..add(InitOTP(widget.phoneNumber));
print("init");
// TODO: implement initState
super.initState();
}
@override
void didChangeDependencies() {
print("change");
super.didChangeDependencies();
}
@override
void didUpdateWidget(covariant OtpCode oldWidget) {
print("update");
// TODO: implement didUpdateWidget
super.didUpdateWidget(oldWidget);
}
@override
Widget build(BuildContext context) {
return BlocConsumer<OtpBloc, OtpState>(
listener: (context, state) {
if (state is SubmitOTPSuccess) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(state.message)));
navigateForward(context, AddProfile(widget.isCustomer));
showDilaogBox(context, addProfilePicture(context));
}
if (state is OTPError) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(state.message)));
}
},
builder: (context, state) {
return Scaffold(
appBar: AppBar(
backgroundColor: app_color,
title: Text("OTP CODE", style: headingStyle20MBWhite()),
),
body: GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: Container(
height: double.infinity,
width: double.infinity,
color: app_background_color,
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
const SizedBox(
height: 40,
),
Container(
height: MediaQuery.of(context).size.height * .75,
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5), color: white),
child: Column(children: [
const SizedBox(
height: 40,
),
Text(
"Enter the otp code we texted to you phone number.",
style: headingStyle14MBDarkGrey(),
textAlign: TextAlign.center,
),
const SizedBox(
height: 70,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_textFieldOTP(otpController1,
first: true, last: false),
const SizedBox(width: 10),
_textFieldOTP(otpController2,
first: false, last: false),
const SizedBox(width: 10),
_textFieldOTP(otpController3,
first: false, last: false),
const SizedBox(width: 10),
_textFieldOTP(otpController4,
first: false, last: false),
const SizedBox(width: 10),
_textFieldOTP(otpController5,
first: false, last: false),
const SizedBox(width: 10),
_textFieldOTP(otpController6,
first: false, last: true)
],
),
const SizedBox(
height: 70,
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"No Code Received?",
style: headingStyle14MBDarkGrey(),
),
Text(
"Resend Now!",
style: headingStyle16MBAppColor(),
)
],
)),
const SizedBox(
height: 70,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0),
child: GestureDetector(
onTap: () {
String otp = otpController1.text +
otpController2.text +
otpController3.text +
otpController4.text +
otpController5.text +
otpController6.text;
if (state is InitOTPSuccess) {
context.read<OtpBloc>()
..add(SubmitOTP(otp, state.verificationId));
}
},
child: button("Continue",
isLoading: state is SubmitOTPLoading
? true
: false)),
)
]),
)
],
),
)),
),
),
);
},
);
}
Widget _textFieldOTP(TextEditingController controller, {bool? first, last}) {
return Container(
// padding: EdgeInsets.only(left:5,right:5),
height: 50,
child: AspectRatio(
aspectRatio: 0.8,
child: TextField(
controller: controller,
autofocus: true,
onChanged: (value) {
if (value.length == 1 && last == false) {
FocusScope.of(context).nextFocus();
}
if (value.isEmpty && first == false) {
FocusScope.of(context).previousFocus();
}
},
showCursor: false,
readOnly: false,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
keyboardType: TextInputType.number,
maxLength: 1,
decoration: InputDecoration(
counter: Offstage(),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.black12),
borderRadius: BorderRadius.circular(12)),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(width: 2, color: Colors.purple),
borderRadius: BorderRadius.circular(12)),
),
),
),
);
}
@override
void dispose() {
print("dispose");
// TODO: implement dispose
super.dispose();
}
}
I think you need to specify events added in this snippest
class OtpBloc extends Bloc<OtpEvent, OtpState> {
OtpBloc() : super(OtpInitial()) {
on((event, emit) async {
emit(InitOTPLoading());
await _InitOtpVerfication(event, emit);
});
on((event, emit) async {
emit(SubmitOTPLoading());
await _SubmitOtp(event, emit);
});
on((event, emit) async {
emit(InitOTPSuccess(event.verificationId));
});
on((event, emit) {
emit(OTPError(event.message));
});
}
}
like
on<OTPSubmit>((event, emit) async {
emit(SubmitOTPLoading());
await _SubmitOtp(event, emit);
});
because bloc needs to know what event is submitted in order to execute specific code
this is what it needs to know
on<EVENT>((event, emit) async {
// some code to execute
});
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:meta/meta.dart';
part 'otp_event.dart';
part 'otp_state.dart';
class OtpBloc extends Bloc<OtpEvent, OtpState> {
OtpBloc() : super(OtpInitial()) {
on<InitOTP>((event, emit) async {
emit(InitOTPLoading());
await _InitOtpVerfication(event, emit);
});
on<SubmitOTP>((event, emit) async {
emit(SubmitOTPLoading());
await _SubmitOtp(event, emit);
});
on<OnOTPSent>((event, emit) async {
emit(InitOTPSuccess(event.verificationId));
});
on<OnVerificationFailed>((event, emit) {
emit(OTPError(event.message));
});
}
}
_SubmitOtp(SubmitOTP event, Emitter<OtpState> emit) async {
PhoneAuthCredential credential = PhoneAuthProvider.credential(
verificationId: event.verificationId, smsCode: event.otp);
await FirebaseAuth.instance.currentUser!.updatePhoneNumber(credential);
emit(SubmitOTPSuccess("Success"));
}
Future _InitOtpVerfication(InitOTP event, Emitter<OtpState> emit) async {
int? _resendToken;
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: event.phoneNumber,
verificationCompleted: (PhoneAuthCredential credential) async {},
verificationFailed: await (FirebaseAuthException e) {
OtpBloc().add(OnVerificationFailed(e.message ?? "Error occured!"));
},
codeSent: await (String verificationId, int? resendToken) async {
OtpBloc().add(OnOTPSent(verificationId));
_resendToken = resendToken;
},
forceResendingToken: _resendToken,
codeAutoRetrievalTimeout: (String verificationId) {},
);
}
yes, its already like this that you told me, i have already specified the events in the bloc. please check
I have got the issue. Thanks for helping me out.
The bloc listener is not listening to any state after firebase phone auth recaptcha verification. i think its happening while navigating to web view for recaptcha verification and coming back to the screen then the bloc listener not working. please help.