Итак, я пытаюсь создать форму регистрации во флаттере, используя потоки и шаблон blo c.
Проблема в том, что ошибка, добавленная в приемник для одного из моих потоков, кажется, не сохраняется?
Кажется, что метод submitValid не учитывает ошибку, добавленную в поток паролей, поэтому кнопка входа в систему может быть нажата, когда она не должна
Шаги для воспроизведения:
Заполните действующий адрес электронной почты
Заполните действительный пароль (поле пароля)
Заполните действительный пароль (поле для повторного ввода пароля)
Удалить все из поля для повторного ввода
Удалить все из поля для ввода пароля.
Введите действительный пароль в поле пароля, и кнопка входа в систему будет активна, даже если поле повторного ввода пусто.
Вот мой код вместе со скриншотом.
Blo c .dart
import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'validators.dart';
import 'dart:io';
import 'package:rxdart/rxdart.dart';
class Bloc extends Object with Validators {
final _email = BehaviorSubject<String>();
final _password = BehaviorSubject<String>();
final _passwordretype = BehaviorSubject<String>();
final _isSignedIn = BehaviorSubject<bool>();
//Add data to stream
Stream<String> get email => _email.stream.transform(validateEmail);
Stream<String> get password => _password.stream.transform(validatePassword);
Stream<String> get passwordretype=> _passwordretype.stream.transform(validatePasswordRetype)
.doOnData((String c){
if(0 != _password.value.compareTo(c)){
_passwordretype.addError("Passwords do not match");
}
});
Stream<bool> get signInStatus => _isSignedIn.stream;
Stream<bool> get submitValid =>
Rx.combineLatest3(email, password, passwordretype, (e, p, r) => true);
//Change data
Function(String) get changeEmail => _email.sink.add;
Function(String) get changePassword => _password.sink.add;
Function(String) get changePasswordRetype => _passwordretype.sink.add;
Function(bool) get showProgressBar => _isSignedIn.add;
register() async {
final FirebaseAuth _auth = FirebaseAuth.instance;
try {
showProgressBar(true);
final FirebaseUser user = (await _auth.createUserWithEmailAndPassword(
email: _email.value,
password: _password.value,
))
.user;
if (user != null) {
// setState(() {
// _success = true;
// _userEmail = user.email;
// Navigator.of(context).pushNamedAndRemoveUntil(
// '/home', (Route<dynamic> route) => false);
//
//// Navigator.of(context).pushReplacementNamed('/home');
//
// });
} else {
// Scaffold.of(context).showSnackBar(SnackBar(
// content: Text("Error occured, please try again later"),
// ));
// _success = false;
}
} catch (err) {
_isSignedIn.addError(err);
print(err);
// setState(() {
// _showLoading = false;
// _error = true;
// });
}
}
dispose() {
_email.drain();
_email.close();
_password.drain();
_password.close();
_passwordretype.drain();
_passwordretype.close();
}
}
RegistrationScreen.dart * 104 0 * import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:lendy/src/blocs/bloc.dart';
import 'package:lendy/src/blocs/provider.dart';
class SignupScreen extends StatelessWidget {
// final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
// final TextEditingController _emailController = TextEditingController();
// final TextEditingController _passwordController = TextEditingController();
// final TextEditingController _passwordController2 = TextEditingController();
final FirebaseAuth _auth = FirebaseAuth.instance;
// final GoogleSignIn _googleSignIn = GoogleSignIn();
String _userID = "";
bool _success;
String _userEmail;
@override
Widget build(BuildContext context) {
final bloc = Provider.of(context);
return Scaffold(
appBar: AppBar(
title: Text("Signup"),
),
body: Container(
child: Column(
children: <Widget>[
emailField(bloc),
passwordField(bloc),
passwordFieldRe(bloc),
SizedBox(
height: 10.0,
),
button(bloc)
],
),
),
);
}
Widget emailField(Bloc bloc) {
return StreamBuilder(
stream: bloc.email,
builder: (context, snapshot) {
return TextField(
onChanged: bloc.changeEmail,
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Enter email address',
labelText: 'Email-address',
errorText: snapshot.error),
);
},
);
}
Widget passwordField(Bloc bloc) {
return StreamBuilder(
stream: bloc.password,
builder: (context, snapshot) {
return TextField(
onChanged: bloc.changePassword,
decoration: InputDecoration(
hintText: 'Enter password',
labelText: 'Password',
errorText: snapshot.error),
);
});
}
Widget passwordFieldRe(Bloc bloc) {
return StreamBuilder(
stream: bloc.passwordretype,
builder: (context, snapshot) {
return TextField(
onChanged: bloc.changePasswordRetype,
decoration: InputDecoration(
hintText: 'Retype password',
labelText: 'Password',
errorText: snapshot.error),
);
});
}
Widget button(Bloc bloc) {
return StreamBuilder(
stream: bloc.submitValid,
builder: (context, snapshot) {
return RaisedButton(
child: Text('Register'),
color: Colors.blue,
//if true
onPressed: snapshot.hasData
? () {
// bloc.showProgressBar(true);
bloc.register();
}
: null);
},
);
}
Widget buttons(Bloc bloc) {
return StreamBuilder(
stream: bloc.submitValid,
builder: (context, snapshot1) {
return StreamBuilder(
stream: bloc.signInStatus,
builder: (context, snapshot2) {
if (!snapshot2.hasData || snapshot2.hasError) {
return Column(
children: <Widget>[
RaisedButton(
child: Text('Register'),
color: Colors.blue,
onPressed: snapshot1.hasData
? () {
bloc.register();
}
: null,
),
snapshot2.hasError ? Text("ee") : Container()
],
);
} else {
return CircularProgressIndicator();
}
},
);
},
);
}
Widget submitButton(Bloc bloc) {
return StreamBuilder(
stream: bloc.signInStatus,
builder: (context, snapshot) {
if (snapshot.hasError || !snapshot.hasData) {
return buttons(bloc);
} else {
return CircularProgressIndicator();
}
});
}
/
Validators.dart
import 'dart:async';
class Validators {
final validateEmail = StreamTransformer<String, String>.fromHandlers(
handleData: (email, sink){
if (RegExp(
r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
.hasMatch(email)){
sink.add(email);
} else {
sink.addError('Please enter a valid email address.');
}
}
);
final validatePassword = StreamTransformer<String, String>.fromHandlers(
handleData: (password, sink){
if (password.length > 3){
sink.add(password);
} else {
sink.addError('Password is too short.');
}
}
);
final validatePasswordRetype = StreamTransformer<String, String>.fromHandlers(
handleData: (password, sink){
print("HANDLE DATA");
if (password.length > 3){
sink.add(password);
} else {
sink.addError('Password is too short.');
}
}
);
}
снимок экрана