[英]Bad state: Cannot add new events after phoneCodeAutoRetrievalTimeout callback from FirebaseAuth.veryfyPhone gets called. Futter
I'm implementing FirebaseAuth verify phone adapting this guide https://medium.com/@tapanrgohil/firebase-phone-authentication-in-flutter-with-bloc-pattern-4ddc2d43d76c as I don't want to sign in but just link the new PhoneAuthentication to existing user and I'm using AuthenticationBloc
instead of Losing Bloc es in the guide.我正在实施 FirebaseAuth 验证电话以适应本指南https://medium.com/@tapanrgohil/firebase-phone-authentication-in-flutter-with-bloc-pattern-4ddc2d43d76c因为我不想登录但只是链接现有用户的新 PhoneAuthentication 并且我在指南中使用
AuthenticationBloc
而不是 Losing Bloc es。
I start the phone verification process in PaymentScreen
and I tried providing AuthenticationBloc
directly in PaymentScreen
's MultiBlocProvider
, thinking create a new AuthenticationBloc
but the error is the same.我在
PaymentScreen
启动电话验证过程,并尝试直接在PaymentScreen
的MultiBlocProvider
提供AuthenticationBloc
,想创建一个新的AuthenticationBloc
但错误是相同的。
In AuthenticationBloc
basically an internal StreamController
takes care of all phone verification events.在
AuthenticationBloc
基本上一个内部StreamController
负责所有电话验证事件。 Incoming States
in PaymentScreen
's BlocListener
just react popping and showing dialogs as in case of AutoRetrieveCodeTimeout
showing manual otp insert dialog, errors, wrong otp and so on.传入
States
在PaymentScreen
的BlocListener
刚反应过来弹出,并显示在的情况下,对话AutoRetrieveCodeTimeout
显示手动OTP插入对话框,错误,错误的OTP等。 To find out what's causing the bad state I first commented out all context pops just to make sure it wast that, and then I commented out all .close()
in the stream.为了找出导致错误状态的原因,我首先注释掉所有上下文弹出,以确保它是那个,然后我注释掉流中的所有
.close()
。
These are the prints from console:这些是来自控制台的打印:
I/flutter ( 7710): VerifyPhoneNumberEvent received
I/flutter ( 7710): _mapVerifyPhoneNumberToState started
I/BiChannelGoogleApi( 7710): [FirebaseAuth: ] getGoogleApiForMethod() returned Gms: com.google.firebase.auth.api.internal.zzaq@7f6fccb
I/flutter ( 7710): _mapVerifyPhoneNumberToState PhoneCodeSent
I/flutter ( 7710): PhoneCodeSentEvent received
I/flutter ( 7710): _mapVerifyPhoneNumberToState PhoneCodeAutoRetrievalTimeout
I/flutter ( 7710): Bloc error is Bad state: Cannot add new events after calling close
I/flutter ( 7710): Bloc error is Bad state: Cannot add new events after calling close
I/flutter ( 7710): Bloc error is Bad state: Cannot add new events after calling close
I/flutter ( 7710): Bloc error is Bad state: Cannot add new events after calling close
I/flutter ( 7710): Bloc error is Bad state: Cannot add new events after calling close
I/flutter ( 7710): Bloc error is Bad state: Cannot add new events after calling close
Can you spot what is closing the bloc?你能发现是什么在关闭这个集团吗?
Many thanks.非常感谢。
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
final UserRepository _userRepository;
AuthenticationBloc({@required UserRepository userRepository})
: assert(userRepository != null),
_userRepository = userRepository;
StreamSubscription subscription;
String verificationId = "";
@override
AuthenticationState get initialState => Uninitialized();
@override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event) async* {
if (event is StartApp) {
yield* _startAppToState();
}
if (event is AppStarted) {
yield* _mapAppStartedToState();
} else if (event is LoggedIn) {
yield* _mapLoggedInToState();
} else if (event is LoggedOut) {
yield* _mapLoggedOutToState();
}
// phone verification
if (event is VerifyPhoneNumberEvent) {
print('VerifyPhoneNumberEvent received');
yield VerifyingState();
subscription = _mapVerifyPhoneNumberToState(event.phoneNumber).listen((event) {
add(event);
});
} else if (event is PhoneCodeSentEvent) {
print('PhoneCodeSentEvent received');
yield OtpSentState();
} else if (event is VerificationCompletedEvent) {
print('VerificationCompletedEvent received');
yield VerificationCompleteState(firebaseUser: event.firebaseUser, isVerified: event.isVerified);
} else if (event is VerificationExceptionEvent) {
print('VerificationExceptionEvent received');
yield VerificationExceptionState(message: event.message);
} else if (event is VerifySmsCodeEvent) {
print('VerifySmsCodeEvent received');
yield VerifyingState();
try {
AuthResult result =
await _userRepository.verifyAndLinkAuthCredentials(verificationId: verificationId, smsCode: event.smsCode);
if (result.user != null) {
yield VerificationCompleteState(firebaseUser: result.user, isVerified: true);
} else {
yield OtpExceptionState(message: "Invalid otp!",verificationId: verificationId);
}
} catch (e) {
yield OtpExceptionState(message: "Invalid otp!", verificationId: verificationId);
print(e);
}
} else if ( event is PhoneCodeAutoRetrievalTimeoutEvent){
yield PhoneCodeAutoRetrievalTimeoutState(verificationId: event.verificationId);
}
if(event is SendVerificationCodeEvent) {
yield*_mapVerificationCodeToState(event);
}
}
Stream<AuthenticationEvent> _mapVerifyPhoneNumberToState(String phoneNumber) async* {
print('_mapVerifyPhoneNumberToState started');
StreamController<AuthenticationEvent> phoneVerificationStreamController = StreamController();
final phoneVerificationCompleted = (AuthCredential authCredential) {
print('_mapVerifyPhoneNumberToState PhoneVerificationCompleted');
// _userRepository.getUser();
_userRepository.getCurrentUser().catchError((onError) {
print(onError);
}).then((user) {
phoneVerificationStreamController.add(VerificationCompletedEvent(firebaseUser: user, isVerified: true));
// phoneVerificationStreamController.close();
});
};
final phoneVerificationFailed = (AuthException authException) {
print('_mapVerifyPhoneNumberToState PhoneVerificationFailed');
print(authException.message);
phoneVerificationStreamController.add(VerificationExceptionEvent(onError.toString()));
// phoneVerificationStreamController.close();
};
final phoneCodeSent = (String verificationId, [int forceResent]) {
print('_mapVerifyPhoneNumberToState PhoneCodeSent');
this.verificationId = verificationId;
phoneVerificationStreamController.add(PhoneCodeSentEvent());
};
final phoneCodeAutoRetrievalTimeout = (String verificationId) {
// after this print Bloc error is Bad state: Cannot add new events after calling close
print('_mapVerifyPhoneNumberToState PhoneCodeAutoRetrievalTimeout');
this.verificationId = verificationId;
// phoneVerificationStreamController.close();
// phoneVerificationStreamController.add(PhoneCodeAutoRetrievalTimeoutEvent(verificationId: verificationId));
};
await _userRepository.verifyPhone(
phoneNumber: phoneNumber,
timeOut: Duration(seconds: 0), // 0 triggers PhoneCodeAutoRetrievalTimeout immediately
phoneVerificationFailed: phoneVerificationFailed,
phoneVerificationCompleted: phoneVerificationCompleted,
phoneCodeSent: phoneCodeSent,
autoRetrievalTimeout: phoneCodeAutoRetrievalTimeout);
yield* phoneVerificationStreamController.stream;
}
Stream<AuthenticationState> _startAppToState() async* {
Timer(Duration(seconds: 5), () {
add(AppStarted());
});
}
Stream<AuthenticationState> _mapAppStartedToState() async* {
try {
final isSignedIn = await _userRepository.isSignedIn();
if (isSignedIn) {
final user = await _userRepository.getUser();
yield Authenticated(user);
} else {
yield Unauthenticated();
}
} catch (_) {
yield Unauthenticated();
}
}
Stream<AuthenticationState> _mapLoggedInToState() async* {
yield Authenticated(await _userRepository.getUser());
}
Stream<AuthenticationState> _mapLoggedOutToState() async* {
yield Unauthenticated();
_userRepository.signOut();
}
Stream<AuthenticationState> _mapVerificationCodeToState(SendVerificationCodeEvent event) async* {
print('_mapVerificationCodeToState started');
yield VerifyingState();
try {
AuthResult result =
await _userRepository.verifyAndLinkAuthCredentials(verificationId: verificationId, smsCode: event.smsCode);
if (result.user != null) {
yield VerificationCompleteState(firebaseUser: result.user, isVerified: true);
} else {
yield OtpExceptionState(message: "Invalid otp!", verificationId: verificationId);
}
} catch (e) {
yield OtpExceptionState(message: "Invalid otp!", verificationId: verificationId);
print(e);
}
}
}
class VerifyPhoneNumberEvent extends AuthenticationEvent {
final String phoneNumber;
VerifyPhoneNumberEvent({this.phoneNumber});
}
class VerifySmsCodeEvent extends AuthenticationEvent {
final String smsCode;
VerifySmsCodeEvent({this.smsCode});
}
class PhoneCodeSentEvent extends AuthenticationEvent {}
class VerificationCompletedEvent extends AuthenticationEvent {
final FirebaseUser firebaseUser;
final bool isVerified;
VerificationCompletedEvent({@required this.firebaseUser, @required this.isVerified});
@override
List<Object> get props => [firebaseUser,isVerified];
@override
String toString() => 'VerificationCompleteEvent{user:${firebaseUser.displayName}, isVerified: $isVerified}';
}
class VerificationExceptionEvent extends AuthenticationEvent {
final String message;
VerificationExceptionEvent(this.message);
}
class PhoneCodeAutoRetrievalTimeoutEvent extends AuthenticationEvent {
final String verificationId;
PhoneCodeAutoRetrievalTimeoutEvent({@required this.verificationId});
@override
List<Object> get props => [verificationId];
@override
String toString() => 'PhoneCodeAutoRetrievalTimeoutEvent {verificationId: $verificationId}';
}
class OtpSentState extends AuthenticationState {}
class VerifyingState extends AuthenticationState {}
class OtpVerifiedState extends AuthenticationState {}
class PhoneCodeAutoRetrievalTimeoutState extends AuthenticationState {
final String verificationId;
PhoneCodeAutoRetrievalTimeoutState({@required this.verificationId});
@override
List<Object> get props => [verificationId];
@override
String toString() => 'PhoneCodeAutoRetrievalTimeoutState {verificationId: $verificationId}';
}
class VerificationCompleteState extends AuthenticationState {
final FirebaseUser firebaseUser;
final bool isVerified;
VerificationCompleteState({@required this.firebaseUser, @required this.isVerified});
FirebaseUser getUser(){
return firebaseUser;
}
@override
List<Object> get props => [firebaseUser, isVerified];
@override
String toString() => 'VerificationCompleteState{user:${firebaseUser.displayName}, isVerified: $isVerified}';
}
class VerificationExceptionState extends AuthenticationState {
final String message;
VerificationExceptionState({this.message});
@override
// TODO: implement props
List<Object> get props => [message];
}
class OtpExceptionState extends AuthenticationState {
final String message;
final String verificationId;
OtpExceptionState({@required this.message, @required this.verificationId});
@override
// TODO: implement props
List<Object> get props => [message, verificationId];
}
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<AuthenticationBloc>(
create: (context) => AuthenticationBloc(userRepository: UserRepository()),
lazy: false,
),
BlocProvider<UserBloc>(
create: (context) => UserBloc(),
lazy: false,
),
BlocProvider<BookingBloc>(
create: (context) => BookingBloc(user: widget.user),
),
BlocProvider<OrderBloc>(
create: (context) => OrderBloc(user: widget.user),
),
BlocProvider<PaymentBloc>(
create: (context) => PaymentBloc(user: widget.user),
lazy: false,
),
BlocProvider<CartBloc>(
create: (context) => CartBloc()..add(LoadCart()),
),
],
child:
BlocBuilder<PaymentBloc, PaymentState>(builder: (context, state) {
if (state is InitialStatePayment) {
return MultiBlocListener(
listeners: [
BlocListener<AuthenticationBloc, AuthenticationState>(
listener: (BuildContext context, AuthenticationState state){
// ain't no sunshine
if (state is VerificationExceptionState ) {
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
AppLocalizations.instance
.text('Phone verification error'),
style: TextStyle(color: Colors.white))));
}
//manually insert OTP
if (state is PhoneCodeAutoRetrievalTimeoutState) {
print('PhoneCodeAutoRetrievalTimeoutState');
// setState(() {
controller.text = null;
// });
// Navigator.of(context,rootNavigator: false).pop(context);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
return VerifyOtpDialog(
controller: controller,
onPressed: (){
if (controller.text.length == 6) {
// Navigator.of(context,rootNavigator: false).pop(context);
BlocProvider.of<AuthenticationBloc>(context).add(SendVerificationCodeEvent(verificationId: state.verificationId, smsCode: controller.text.replaceAll(' ', '')));
} else {
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
AppLocalizations.instance
.text('Wrong code'),
style: TextStyle(color: Colors.white))));
}
}
);
}
);
}
// if at the first you don't succeed..
if (state is OtpExceptionState) {
// setState(() {
controller.text = null;
// });
// Navigator.of(context,rootNavigator: false).pop(context);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
return VerifyOtpRetryDialog(
controller: controller,
onPressed: (){
if (controller.text.length == 6) {
// Navigator.of(context,rootNavigator: false).pop();
BlocProvider.of<AuthenticationBloc>(context).add(SendVerificationCodeEvent(verificationId: state.verificationId, smsCode: controller.text.replaceAll(' ', '')));
} else {
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
AppLocalizations.instance
.text('Wrong code'),
style: TextStyle(color: Colors.white))));
}
}
);
}
);
}
// kool and the gang
if (state is VerificationCompleteState) {
if (state.isVerified == true) {
// setState(() {
isVerified = state.isVerified;
// });
// Navigator.of(context,rootNavigator: false).pop(context);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
return VerifiedPhoneConfirmationDialog();
}
);
Timer(Duration(milliseconds: 1200), (){
// Navigator.of(context,rootNavigator: false).pop();
});
// TODO: Save user isVerified to LocalDb and Firebase
}
}
}
),
...
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
return SingleChildScrollView(
child: ValidatePhoneDialog(
controller: controller,
onPressed: (){
if (controller.text.length >= 9){
// Navigator.pop(context);
showDialog(
context:context,
barrierDismissible: false,
builder: (BuildContext context){
return VerifyingDialog();
}
);
BlocProvider.of<AuthenticationBloc>(context).add(VerifyPhoneNumberEvent(phoneNumber: controller.text.replaceAll(' ', '')));
} else {
scaffoldKey.currentState.showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
AppLocalizations.instance
.text('Wrong number'),
style: TextStyle(color: Colors.white))));
}
}
),
);
}
);
After a few trials I Found out that the main problem was using the AuthenticationBloc
so I made a dedicated PhoneAuthenticationBloc
while still using AuthenticationState
and AuthenticationState
and take care of the event/state routing without a `StreamController.经过几次试验,我发现主要问题是使用
AuthenticationBloc
所以我制作了一个专用的PhoneAuthenticationBloc
同时仍然使用AuthenticationState
和AuthenticationState
并在没有`StreamController 的情况下处理事件/状态路由。
I'll leave the classes here so to be helpful to others.我会把课程留在这里,以便对他人有所帮助。
class PhoneAuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
final UserRepository _userRepository;
PhoneAuthenticationBloc({@required UserRepository userRepository})
: assert(userRepository != null),
_userRepository = userRepository;
String verificationId = "";
@override
AuthenticationState get initialState => Uninitialized();
@override
Stream<AuthenticationState> mapEventToState(
AuthenticationEvent event) async* {
// phone verification
if (event is VerifyPhoneNumberEvent) {
print('VerifyPhoneNumberEvent received');
yield VerifyingState();
yield* _mapVerifyPhoneNumberToState(event);
}
if (event is PhoneCodeSentEvent) {
print('PhoneCodeSentEvent received');
yield OtpSentState();
}
if (event is VerificationCompletedEvent) {
print('VerificationCompletedEvent received');
yield VerificationCompleteState(firebaseUser: event.firebaseUser, isVerified: event.isVerified);
}
if (event is VerificationExceptionEvent) {
print('VerificationExceptionEvent received');
yield VerificationExceptionState(message: event.message);
}
if ( event is PhoneCodeAutoRetrievalTimeoutEvent){
yield PhoneCodeAutoRetrievalTimeoutState(verificationId: event.verificationId);
}
if(event is SendVerificationCodeEvent) {
yield VerifyingState();
yield*_mapVerificationCodeToState(event);
}
}
Stream<AuthenticationState> _mapVerifyPhoneNumberToState(VerifyPhoneNumberEvent event) async* {
print('_mapVerifyPhoneNumberToState V2 started');
final phoneVerificationCompleted = (AuthCredential authCredential) {
print('_mapVerifyPhoneNumberToState PhoneVerificationCompleted');
_userRepository.getCurrentUser().catchError((onError) {
print(onError);
}).then((user) {
add(VerificationCompletedEvent(firebaseUser: user, isVerified: true));
});
};
final phoneVerificationFailed = (AuthException authException) {
print('_mapVerifyPhoneNumberToState PhoneVerificationFailed');
print(authException.message);
add(VerificationExceptionEvent(onError.toString()));
};
final phoneCodeSent = (String verificationId, [int forceResent]) {
print('_mapVerifyPhoneNumberToState PhoneCodeSent');
this.verificationId = verificationId;
add(PhoneCodeSentEvent());
};
final phoneCodeAutoRetrievalTimeout = (String verificationId) {
print('_mapVerifyPhoneNumberToState PhoneCodeAutoRetrievalTimeout');
this.verificationId = verificationId;
add(PhoneCodeAutoRetrievalTimeoutEvent(verificationId: verificationId));
};
await _userRepository.verifyPhone(
phoneNumber: event.phoneNumber,
timeOut: Duration(seconds: 0),
phoneVerificationFailed: phoneVerificationFailed,
phoneVerificationCompleted: phoneVerificationCompleted,
phoneCodeSent: phoneCodeSent,
autoRetrievalTimeout: phoneCodeAutoRetrievalTimeout);
}
Stream<AuthenticationState> _mapVerificationCodeToState(SendVerificationCodeEvent event) async* {
print('_mapVerificationCodeToState started');
AuthResult result = await _userRepository.verifyAndLinkAuthCredentials(verificationId: verificationId, smsCode: event.smsCode)
.catchError((e){
print('verifyAndLinkAuthCredentials error: $e');
});
print(result);
if (result != null) {
yield VerificationCompleteState(firebaseUser: result.user, isVerified: true);
} else {
yield OtpExceptionState(message: "Invalid otp!", verificationId: verificationId);
}
}
}
Future<void> verifyPhone(
{@required String phoneNumber,
@required Duration timeOut,
@required PhoneVerificationFailed phoneVerificationFailed,
@required PhoneVerificationCompleted phoneVerificationCompleted,
@required PhoneCodeSent phoneCodeSent,
@required PhoneCodeAutoRetrievalTimeout autoRetrievalTimeout}) async {
_firebaseAuth.verifyPhoneNumber(
phoneNumber: phoneNumber,
timeout: timeOut,
verificationCompleted: phoneVerificationCompleted,
verificationFailed: phoneVerificationFailed,
codeSent: phoneCodeSent,
codeAutoRetrievalTimeout: autoRetrievalTimeout);
}
Future<AuthResult> verifyAndLinkAuthCredentials(
{@required String verificationId, @required String smsCode}) async {
AuthCredential authCredential = PhoneAuthProvider.getCredential(
verificationId: verificationId, smsCode: smsCode);
// return _firebaseAuth.signInWithCredential(authCredential);
FirebaseUser user = await _firebaseAuth.currentUser();
return user.linkWithCredential(authCredential).catchError((e) {
print('UserRepository.verifyAndLinkAuthCredentials() error: $e');
// return;
});
}
class VerifyPhoneNumberEvent extends AuthenticationEvent {
final String phoneNumber;
VerifyPhoneNumberEvent({this.phoneNumber});
}
class VerifySmsCodeEvent extends AuthenticationEvent {
final String smsCode;
VerifySmsCodeEvent({this.smsCode});
}
class PhoneCodeSentEvent extends AuthenticationEvent {}
class VerificationCompletedEvent extends AuthenticationEvent {
final FirebaseUser firebaseUser;
final bool isVerified;
VerificationCompletedEvent({@required this.firebaseUser, @required this.isVerified});
@override
List<Object> get props => [firebaseUser,isVerified];
@override
String toString() => 'VerificationCompleteEvent{user:${firebaseUser.displayName}, isVerified: $isVerified}';
}
class VerificationExceptionEvent extends AuthenticationEvent {
final String message;
VerificationExceptionEvent(this.message);
}
class PhoneCodeAutoRetrievalTimeoutEvent extends AuthenticationEvent {
final String verificationId;
PhoneCodeAutoRetrievalTimeoutEvent({@required this.verificationId});
@override
List<Object> get props => [verificationId];
@override
String toString() => 'PhoneCodeAutoRetrievalTimeoutEvent {verificationId: $verificationId}';
}
class OtpSentState extends AuthenticationState {}
class VerifyingState extends AuthenticationState {}
class OtpVerifiedState extends AuthenticationState {}
class PhoneCodeAutoRetrievalTimeoutState extends AuthenticationState {
final String verificationId;
PhoneCodeAutoRetrievalTimeoutState({@required this.verificationId});
@override
List<Object> get props => [verificationId];
@override
String toString() => 'PhoneCodeAutoRetrievalTimeoutState {verificationId: $verificationId}';
}
class VerificationCompleteState extends AuthenticationState {
final FirebaseUser firebaseUser;
final bool isVerified;
VerificationCompleteState({@required this.firebaseUser, @required this.isVerified});
FirebaseUser getUser(){
return firebaseUser;
}
@override
List<Object> get props => [firebaseUser, isVerified];
@override
String toString() => 'VerificationCompleteState{user:${firebaseUser.displayName}, isVerified: $isVerified}';
}
class VerificationExceptionState extends AuthenticationState {
final String message;
VerificationExceptionState({this.message});
@override
// TODO: implement props
List<Object> get props => [message];
}
class OtpExceptionState extends AuthenticationState {
final String message;
final String verificationId;
OtpExceptionState({@required this.message, @required this.verificationId});
@override
// TODO: implement props
List<Object> get props => [message, verificationId];
}
showDialog(
context: context,
barrierDismissible: false,
builder:
(BuildContext dialogContext) {
return SingleChildScrollView(
child: ValidatePhoneDialog(
controller: controller,
onPressed: () {
if (controller
.text.length >=
9) {
BlocProvider.of<
PhoneAuthenticationBloc>(
context)
.add(VerifyPhoneNumberEvent(
phoneNumber:
controller
.text
.replaceAll(
' ',
'')));
} else {
scaffoldKey.currentState
.showSnackBar(SnackBar(
backgroundColor:
Colors
.redAccent,
content: Text(
AppLocalizations
.instance
.text(
'Wrong number'),
style: TextStyle(
color: Colors
.white))));
}
}),
);
});
BlocListener<PhoneAuthenticationBloc, AuthenticationState>(
listener:
(BuildContext context, AuthenticationState state) {
if (state is VerifyingState) {
Navigator.of(context, rootNavigator: false).pop(context);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return VerifyingDialog();
});
}
if (state is VerificationExceptionState) {
// ain't no sunshine
Navigator.of(context, rootNavigator: false).pop(context);
// Todo retry
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext dialogContext) {
return SingleChildScrollView(
child: ValidatePhoneRetryDialog(
controller: controller,
onPressed: () {
if (controller.text.length >= 9) {
BlocProvider.of<PhoneAuthenticationBloc>(
context)
.add(VerifyPhoneNumberEvent(
phoneNumber: controller.text
.replaceAll(' ', '')));
// Navigator.pop(context);
Navigator.of(context, rootNavigator: false)
.pop();
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return VerifyingDialog();
});
} else {
scaffoldKey.currentState.showSnackBar(
SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
AppLocalizations.instance
.text('Wrong number'),
style: TextStyle(
color: Colors.white))));
}
}),
);
});
// scaffoldKey.currentState.showSnackBar(SnackBar(
// backgroundColor: Colors.redAccent,
// content: Text(
// AppLocalizations.instance
// .text('Phone verification error'),
// style: TextStyle(color: Colors.white))));
}
if (state is PhoneCodeAutoRetrievalTimeoutState) {
//manually insert OTP
print('PhoneCodeAutoRetrievalTimeoutState');
setState(() {
controller.text = '';
});
Navigator.of(context, rootNavigator: false).pop(context);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext dialogContext) {
return SingleChildScrollView(
child: VerifyOtpDialog(
controller: controller,
onPressed: () {
if (controller.text.length == 6) {
BlocProvider.of<PhoneAuthenticationBloc>(
context)
.add(SendVerificationCodeEvent(
verificationId:
state.verificationId,
smsCode: controller.text
.replaceAll(' ', '')));
} else {
scaffoldKey.currentState.showSnackBar(
SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
AppLocalizations.instance
.text('Wrong code'),
style: TextStyle(
color: Colors.white))));
}
}),
);
});
}
if (state is OtpExceptionState) {
// if at the first you don't succeed..
Navigator.of(context, rootNavigator: false).pop(context);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext dialogContext) {
return SingleChildScrollView(
child: VerifyOtpRetryDialog(
controller: controller,
onPressed: () {
if (controller.text.length == 6) {
BlocProvider.of<PhoneAuthenticationBloc>(
context)
.add(SendVerificationCodeEvent(
verificationId:
state.verificationId,
smsCode: controller.text
.replaceAll(' ', '')));
} else {
scaffoldKey.currentState.showSnackBar(
SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
AppLocalizations.instance
.text('Wrong code'),
style: TextStyle(
color: Colors.white))));
}
}),
);
});
}
if (state is VerificationCompleteState) {
// kool and the gang
if (state.isVerified == true) {
setState(() {
isVerified = state.isVerified;
});
Navigator.of(context, rootNavigator: false).pop(context);
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext dialogContext) {
return VerifiedPhoneConfirmationDialog();
});
BlocProvider.of<UserBloc>(context)
.add(UserPhoneVerified(user: widget.user));
Timer(Duration(milliseconds: 1200), () {
Navigator.of(context, rootNavigator: false).pop();
});
// TODO: Save user isVerified to LocalDb and Firebase
}
}
}),
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.