How to send a verification email on registerUsingEmailPassword() in flutter - flutter

I wan't when a user clicks sign up button an email verification is sent. So far with my code on signup an email verification is sent but user can't navigate to the next page (CircularProgressIndicator keeps on loading)
Here is my code
onPressed: () async {
if (_regFormKey.currentState!.validate()) {
setState(() {
_isProcessing = true;
});
User? user = await FireAuth.registerUsingEmailPassword(
name: nameController,
email: _emailController.text,
password: _passwordController.text,
);
if (user != null) {
bool EmailSent = user.sendEmailVerification() as bool;
//I think something is wrong here
if (EmailSent) {
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(
builder: (context) => ProfilePage(user: user),
),
ModalRoute.withName('/'),
); }
} else{
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(' Account exists or Network problems'),
backgroundColor: Colors.red,
));}
setState(() {
_isProcessing = false;
});
}}

sendEmailVerification() returns a Future<void> so EmailSent is not going to get set. You should await the verification call in a try...catch to handle the response.
More like this:
if (user != null) {
try {
await user.sendEmailVerification();
/// sent successfully
// TODO: put your navigation here
} catch (e) {
/// error sending verification
// TODO: show snackbar
// TODO: set _isProcessing to false
}
}

Related

Shows warning: Do not use BuildContexts across async gaps

if (_formKey.currentState!.validate()) {
try {
final newUser =
await _auth.createUserWithEmailAndPassword(
email: email.text, password: password.text);
if (newUser != null) {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => DashboardScreen(),
// ));
Navigator.pushNamed(context, 'dashboard');
}
setState(() {});
} catch (e) {
print(e);
}
}
},
this warning shown on Navigator.pushNamed(context,'dashboard');
trying to navigate to the dashboar screen.
1.
You have to put delay for other process can finish till then
Future.delayed(Duration(milliseconds: 200)).then((value) {
Navigator.pushNamed(context, 'dashboard')
});
2.
add if (!mounted) return; before Navigator.pushNamed(context, 'dashboard')
3.
Please put await before the navigator flutter because you used an asynchronously method call so you have to wait until the process is finished then you can navigate to your pages
await Navigator.pushNamed(context, 'dashboard');
4.
Also, you can store your navigator into a var and then use it.
final nav = Navigator.of(context);
nav.pushNamed('dashboard');

Check if Firebase User is null in Flutter

I'm making a Flutter App and I want to check if the user is registered in the database when he logs in the app.
So basically if he's registered and he logs in with no errors, there will be a loading indicator and he will be redirected to the Homepage.
If he made an error (wrong email/password for example) he will get snackbar displaying the error.
The problem is that I couldn't find the right 'if statement' to check if the user is registered or not.
Here's my Login button :
`
TextButton(
onPressed: () async {
if (_key.currentState!.validate()) {
var email = _emailController.text;
var password = _passwordController.text;
User? user =
(await _auth.login(email, password, context));
user != null
? setState(() => loading = true)
: setState(() => loading = false);
print(loading);
}
},
child: loading
? const CircularProgressIndicator()
: Text('Connect'),
),
`
And the login function :
Future login(String email, password, BuildContext context) async {
try {
User user = (await _auth.signInWithEmailAndPassword(
email: email, password: password))
.user!;
Navigator.pushNamed(context, DiscoverPage.id);
} on FirebaseAuthException catch (error) {
var message = '';
switch (error.code) {
case 'user-not-found':
message = 'User not found';
}
print(error.code);
ScaffoldMessenger.of(context).showSnackBar(
CustomSnackBar(message, context),
);
}
}
'loading' is initiated to false and when I print(loading) it always returns false, no matter if there's an error or not. The setState dont seem to work.
What am I missing here ?
Thanks.
try this:
try {
User user = (await _auth.signInWithEmailAndPassword(
email: email, password: password))
.user!;
if(FirebaseAuth.instance.currentUser != null) {
Navigator.pushNamed(context, DiscoverPage.id);
}
} on ...

Flutter_Bloc 8 and Firebase Verify Email -- Clear Prior State?

I am trying to utilize FirebaseAuth's verify email functionality in my Flutter app. I'm using Flutter_BLoC 8. The code works, but when I verify the email address by clicking the link in the generated email, the prior state is apparently still buffered in my app and I need to click TWICE on the 'Continue' button to proceed to the Home Screen.
Here's my code:
ElevatedButton(
onPressed: () async {
context.read<EmailVerificationBloc>().add(const IsEmailVerified());
final isVerified = context.read<EmailVerificationBloc>().state;
if (isVerified == const EmailVerificationState.verified()) {
context.router.replace(const HomeRoute());
} else {
showErrorFlash(context, 'Email Is Not Verified');
}
},
child: const Center(
child: Text('Continue'),
),
),
Here's the BLoC event:
Future<void> _onIsEmailVerified(IsEmailVerified event, Emitter emit) async {
final successOrFailure = await _authRepository.isUserEmailVerified();
successOrFailure.fold(
(failure) {
emit(EmailVerificationState.error(failure));
},
(success) {
if (success) emit(const EmailVerificationState.verified());
},
);
}
And lastly, here's the repository method that's being called:
Future<Either<AuthFailure, bool>> isUserEmailVerified() async {
try {
await _currentUser!.reload(); // We will only call on authenticated users, so we don't expect null
return right(_currentUser!.emailVerified);
} on FirebaseAuthException catch (e) {
final error = e.code;
switch (error) {
case 'network-request-failed':
return left(const AuthFailure.noNetworkConnection());
default:
return left(const AuthFailure.unexpectedError());
}
} on PlatformException {
return left(const AuthFailure.unexpectedError());
}
}
Any ideas on how I can, for lack of a better term, flush the prior state? I'm sort of new to Flutter and BLoC, so I'm hopeful it's a relatively easy thing I'm just overlooking.
Thanks in advance.

Flutter Session stores data but can't make decisions based off it

I'm using FlutterSession to store phone number/email (based on user's choice) as a method of logging into the app. The session works fine in case of email but when I store and retrieve phone number, it shows me the snapshot has no data.
This is the method where I'm setting the session value for the phone number:
void phoneSignIn() async {
if (phoneNumber == null || phoneNumber.length < 10) {
print('Please enter a valid phone number!');
}
else {
await fillers.session.set("phoneNum", phoneNumber);
print('Phone number is: '+ phoneNumber);
setState(() {
phoneSignedIn = true;
});
var sessionCheck = await fillers.session.get("phoneNum");
print("Session value: $sessionCheck");
print(phoneSignedIn);
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => OnboardOne()));
}
}
In the above code, I've made sure using print statements that the session is storing phone number value and also that the phoneSignedIn bool is set to true.
This is the method where I'm setting session value for email:
void signIn() async {
response = await Dio().post(url,
data: {
"email": emailVal,
"password": passwordVal
}
);
if (response.statusCode == 200) {
await fillers.session.set('email', emailVal);
await fillers.session.set('password', passwordVal);
print('Sign In successful!');
print('Email: $emailVal');
print('Password: $passwordVal');
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => OnboardOne()));
}
else
{
print('Exited with statuscode ${response.statusCode}');
print('Email: $emailVal');
print('Password: $passwordVal');
}
}
This is my firstpage where I decide on which page to go based on whether the user has logged in or not:
class _FirstPageState extends State<FirstPage> {
#override
Widget build(BuildContext context) {
return Material(
child: FutureBuilder(
future: phoneSignedIn ? session.get("phoneNum") : session.get('email'),
builder: (context, snapshot) {
return snapshot.hasData ? Dashboard() : SignUpIn();
}
),
);
}
}
As you can see, I've done nothing different in the email sign in (except using a backend api to auth the email). Ultimately, I'm using the same technique to store both the email and phone number. But when I've signed in using phone number and then reopen the app, the app goes to the SignUpIn() page, when it should actually go to the Dashboard() page.
Also, on the dashboard, there's a button "Sign Out", on pressing which, the session values are cleared.
What am I doing wrong?

How to do autologin with three diffrent userTypes in flutter and firebase?

I have this app that do login with firebase auth and firestore to get the userType, This code is written obviously in the login page, What I want to add is autologin ASA the app runs which firebase offers with the correct userType So the first proplem how to transfer the email value to the main.dart page as I search in the firestore with the email to get the userType, Second proplem is that When I tried to do auto login in the login page with three different userTypes It does login but not auto login
CODE :
#override
void initState() {
super.initState();
FirebaseAuth.instance.currentUser().then(
(result) {
if (result != null) {
if (userType == 'userType1') {
Navigator.pushReplacementNamed(context, '/userType1page');
}
if (userType == 'userType2') {
Navigator.pushReplacementNamed(context, '/userType2page');
}
if (userType == 'userType3') {
Navigator.pushReplacementNamed(context, '/userType3page');
}
}
So Here It gets the user But no auto login, what I observed that When U remove the other IFs inside the big if and do 1 Navigation It works So don't know what to do, Please Help me I asked three questions before and didn't get an answer.
PS : NEW TO FLUTTER :)
#FLUTTER_FOREVER
Getting user Data from firestore:
void getUserData() async {
try {
firestoreInstance
.collection('Users')
.document(usernameController.text)
.get()
.then((value) {
setState(() {
email = (value.data)['email'];
password = (value.data)['password'];
gender = (value.data)['gender'];
username = (value.data)['username'];
userType = (value.data)['userType'];
});
});
} catch (e) {
print(e.toString);
}
}
Logining in :
void login() async {
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
firebaseAuth
.signInWithEmailAndPassword(
email: emailController.text, password: passwordController.text)
.then((result) {
{
if (userType == 'Student') {
Navigator.pushReplacementNamed(context, '/StudentsPage');
} else if (userType == 'Teacher') {
Navigator.pushReplacementNamed(context, '/TeacherPage');
} else if (userType == 'Admin') {
Navigator.pushReplacementNamed(context, '/AdminPage');
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Error'),
content: Text(
'Please make sure that you have an internet connection '),
actions: [
FlatButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
},
);
}
}
I found the answer I must identify the var userType inside the initState and It worked by using the getUserData() function but I had a problem I can't use usernameController because It's a var and I didn't defined it so any idea how to get the userType with the document reference usernameController Which I can't identify X-( 'R.I.P #omardeveloper'