flutter how to get OTP autofill into otpController.text from firebase
--: when get OTP in mobile, need to auto-fills OTP in a text box, i am doing it in _onVerificationCompleted method.
_onVerificationCompleted(PhoneAuthCredential authCredential) async {
debugPrint("verification completed ${authCredential.smsCode}");
User? user = FirebaseAuth.instance.currentUser;
setState(() {
// need otp so i can autofill in a textbox
otpController.text = authCredential.smsCode!;
});
if (authCredential.smsCode != null) {
try {
UserCredential credential =
await user!.linkWithCredential(authCredential);
} on FirebaseAuthException catch (e) {
if (e.code == 'provider-already-linked') {
await auth.signInWithCredential(authCredential);
}
}
}
}
Future<void> sendOtp() async {
print(numController.text);
await auth.verifyPhoneNumber(
phoneNumber: "+91" + numController.text,
verificationCompleted: _onVerificationCompleted,
verificationFailed: (FirebaseAuthException e) {
if (e.code == 'invalid-phone-number') {
print('The provided phone number is not valid.');
}
},
codeSent: (String verificationId, int? resendToken) async {
this.verificationId = verificationId;
signature = await SmsAutoFill().getAppSignature;
print("app signature");
print(signature);
setState(() {
visibleValMobile = false;
visibleValOtp = true;
sendOtpMobile = "We Have Send OTP On " + numController.text;
});
},
codeAutoRetrievalTimeout: (String verificationId) {
print('codeAutoRetrievalTimeout');
},
);
}
flutter when get OTP in mobile, it auto-fills a text box
There are plenty of options like otp_autofill, alt_sms_autofill and sms_autofill
For the alt_sms_autofill example, https://stackoverflow.com/a/70076071/4639894
Related
I have some mistakes with flutter and firebase, if someone can help would be great here is my auth controller
class AuthController extends GetxController {
final FirebaseAuth auth = FirebaseAuth.instance;
final Rxn<User> _firebaseUser = Rxn<User>();
Rx<XFile>? _pickedImage;
XFile? get profilePhoto => _pickedImage?.value;
// final user = FirebaseAuth.instance.currentUser.obs;
Rxn<User> get user => _firebaseUser;
// final user = FirebaseAuth.instance.currentUser;
#override
onInit() {
_firebaseUser.bindStream(auth.authStateChanges());
super.onInit();
}
// void register(
// String name, String email, String password, XFile? image) async {
// try {
// UserCredential _authResult = await auth.createUserWithEmailAndPassword(
// email: email.trim(), password: password);
// //create user in database.dart
// String downloadUrl = await uploadToStorage(image!);
// UserModel _user = UserModel(
// id: _authResult.user?.uid,
// name: name,
// email: _authResult.user?.email,
// profilePic: downloadUrl,
// );
// if (await Database().createNewUser(_user)) {
// Get.find<UserController>().user = _user;
// }
// } catch (e) {
// Get.snackbar(
// "Error creating Account",
// e.toString(),
// snackPosition: SnackPosition.BOTTOM,
// );
// }
// }
void register(
String name, String email, String password, XFile? image) async {
try {
if (name.isNotEmpty &&
email.isNotEmpty &&
password.isNotEmpty &&
image != null) {
// save out user to our ath and firebase firestore
UserCredential _authResult = await auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
String downloadUrl = await uploadToStorage(image);
UserModel _user = UserModel(
id: _authResult.user?.uid,
name: name,
email: _authResult.user?.email,
profilePic: downloadUrl,
);
if (await Database().createNewUser(_user)) {
Get.find<UserController>().user = _user;
} else {
Get.snackbar(
'Error Creating Account',
'Please enter all the fields',
);
}
}
} catch (e) {
Get.snackbar(
'Error Creating Account',
e.toString(),
);
}
}
void login(String email, password) async {
try {
UserCredential _authResult = await auth.signInWithEmailAndPassword(
email: email.trim(), password: password);
Get.find<UserController>().user =
await Database().getUser(_authResult.user?.uid ?? '');
} catch (e) {
Get.snackbar("About User", "User message",
snackPosition: SnackPosition.BOTTOM,
titleText: Text("Acount creation failed"),
messageText:
Text(e.toString(), style: TextStyle(color: Colors.white)));
}
}
Future<void> signOut() async {
await auth.signOut();
Get.find<UserController>().clear();
}
Future pickImage() async {
print("call on click add photo icon");
final ImagePicker _picker = ImagePicker();
final XFile? pickedImage =
await _picker.pickImage(source: ImageSource.gallery);
print('picked image filled with image from gallery'); //This doesnt print at
if (pickedImage != null) {
Get.snackbar('Profile Picture',
'You have successfully selected your profile picture!');
// print(pickedImage.path);
}
_pickedImage = Rx<XFile>(pickedImage!);
// print(_pickedImage);
// print(profilePhoto);
}
// upload to firebase storage
Future<String> uploadToStorage(XFile? image) async {
Reference ref = FirebaseStorage.instance
.ref('')
.child('profilePics')
.child(auth.currentUser!.uid);
// print(ref);
UploadTask uploadTask = ref.putFile(File(image?.path ?? 'idemo'));
print(uploadTask);
// TaskSnapshot snap = await uploadTask;
String downloadUrl = await (await uploadTask).ref.getDownloadURL();
print(downloadUrl);
return downloadUrl;
}
}
Here is my function to createNewUser
class Database {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
Future<bool> createNewUser(UserModel user) async {
try {
await _firestore.collection("users").doc(user.id).set({
"name": user.name,
"email": user.email,
"profilePhoto": user.profilePic
});
return true;
} catch (e) {
print(e);
return false;
}
}
Here is HomeController
class HomeController extends GetxController {
final Rxn<List<TodoModel>> todoList = Rxn<List<TodoModel>>([]);
var selectedDate = DateTime.now().obs;
List<TodoModel>? get todos => todoList.value;
#override
void onInit() {
super.onInit();
String? uid = Get.find<AuthController>().auth.currentUser?.uid ?? '';
print(uid);
todoList.bindStream(Database().todoStream(uid));
}
chooseDate() async {
DateTime? pickedDate = await showDatePicker(
context: Get.context!,
initialDate: selectedDate.value,
firstDate: DateTime(2000),
lastDate: DateTime(2024),
//initialEntryMode: DatePickerEntryMode.input,
// initialDatePickerMode: DatePickerMode.year,
);
if (pickedDate != null && pickedDate != selectedDate.value) {
selectedDate.value = pickedDate;
}
}
}
and here is View page
GetX<HomeController>(
init: Get.put<HomeController>(HomeController()),
builder: (HomeController todoController) {
if (todoController.todos != null) {
// print(todoController.todos?.done ?? false);
return Expanded(
child: ListView.builder(
itemCount: todoController.todos?.length,
itemBuilder: (_, index) {
return TodoCard(
uid: controller.user.value?.uid ?? '',
todo: todoController.todos![index],
);
},
),
);
} else {
return Text("loading...");
}
},
),
So, I have an error when I register a new user I got this error:
The following assertion was thrown building Builder(dirty):
a document path must be a non-empty string
Failed assertion: line 116 pos 14: ‘path.isNotEmpty’
And here is output from terminal:
The relevant error-causing widget was
GetMaterialApp
lib/main.dart:23
When the exception was thrown, this was the stack
#2 _JsonCollectionReference.doc
#3 Database.todoStream
#4 HomeController.onInit
#5 GetLifeCycleBase._onStart
#6 InternalFinalCallback.call
#7 GetInstance._startController
#8 GetInstance._initDependencies
#9 GetInstance.find
#10 GetInstance.put
#11 Inst.put
So a problem is with this path, and when I reload from the visual studio I god the right user with the right data. So the problem is when I register a user for the first time.
It looks like uid is empty, which you should also be able to see from looking up print(uid); in your output.
When your application or web page loads, Firebase automatically tries to restore the previously signed in user from its local state. This requires that it makes a call to the server however (for example to check if the account has been disabled) and while that call is going on, your main code continues to execute and the currentUser variable is going to be null.
Your code needs to take this into account. The easiest way to do this is to not depend on currentUser, but instead to use an reactively respond to changes in the authentication state as shown in the first example in the documentation on getting the current user:
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user != null) {
print(user.uid);
}
});
The authStateChange method here returns a stream that fires an event whenever the authentication state changes, so when the user signs in or signs out. The common way to use this stream is to either set the user to the state of your widget, or to use the stream directly in a StreamBuilder.
I have different methods in my app to log in:
Facebook
Google
Apple
Email
For the question I'll focus on the first 2 ones. When the user logs in with Facebook the providers look like this:
That's fine but if I log out and log in again, this time with a new Google account but using same email, the providers look like this:
Now, if I log out and log in again with Facebook I face the account-exists-with-different-credential error. Something for which I have the logic prepared and show its provider login method, but this user should have both provider available and he should be able to log in with both methods.
This is my code:
Future facebookSignIn(BuildContext context) async {
final LoginResult result = await FacebookAuth.instance.login();
if (result.status == LoginStatus.success) {
final AccessToken accessToken = result.accessToken!;
AuthCredential credential =
FacebookAuthProvider.credential(accessToken.token);
await _firebaseCredential(context, credential);
}
}
Future googleSignIn(BuildContext context,
[String? email, facebookCredential]) async {
try {
GoogleSignInAccount googleUser;
dynamic popup = await _googleSignIn.signIn();
// cancelled login
if (popup == null) {
return null;
}
googleUser = popup;
GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await _firebaseCredential(context, credential);
} on FirebaseAuthException catch (e) {
// await FirebaseCrashlytics.instance.recordError(
// e,
// StackTrace.fromString("/googleSignIn"),
// reason: e.message,
// );
// return null;
}
}
_firebaseCredential(BuildContext context, credential) async {
try {
User user =
(await FirebaseAuth.instance.signInWithCredential(credential)).user!;
// Provider.of<MyRents>(context, listen: false).updateUI();
await firebaseProfile.updateUserData(context, user);
} on FirebaseAuthException catch (error) {
// final error = e as FirebaseAuthException;
if (error.code == 'account-exists-with-different-credential') {
String email = error.email!;
// AuthCredential pendingCredential = e.credential;
List<String> signInMethods =
await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
// If the user has several sign-in methods,
// the first method in the list will be the "recommended" method to use.
if (signInMethods.first == 'google.com' ||
signInMethods.first == 'facebook.com') {
// TODO: fix facebook
return await googleSignIn(context, email, credential);
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(error.message!)));
}
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(error.message!)));
}
}
}
Am I missing something?
flutter_facebook_auth: ^4.3.3
google_sign_in: ^5.2.1
Future googleSignIn(BuildContext context,
[String? email, facebookCredential]) async {
try {
GoogleSignInAccount googleUser;
dynamic popup = await _googleSignIn.signIn();
// cancelled login
if (popup == null) {
return null;
}
googleUser = popup;
GoogleSignInAuthentication googleAuth = await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await _firebaseCredential(context, credential);
} on FirebaseAuthException catch (e) {
// await FirebaseCrashlytics.instance.recordError(
// e,
// StackTrace.fromString("/googleSignIn"),
// reason: e.message,
// );
// return null;
}
}
Future facebookSignIn(BuildContext context) async {
final LoginResult result = await FacebookAuth.instance.login();
if (result.status == LoginStatus.success) {
final AccessToken accessToken = result.accessToken!;
AuthCredential credential =
FacebookAuthProvider.credential(accessToken.token);
await _firebaseCredential(context, credential);
}
}
// other methods...
_firebaseCredential(BuildContext context, credential) async {
try {
User user =
(await FirebaseAuth.instance.signInWithCredential(credential)).user!;
await firebaseProfile.updateUserData(context, user);
} on FirebaseAuthException catch (error) {
if (error.code == 'account-exists-with-different-credential') {
String email = error.email!;
List<String> signInMethods =
await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
// bool newUser = (signInMethods.length > 0) ? false : true;
// If the user has several sign-in methods,
// the first method in the list will be the "recommended" method to use.
var user;
switch (signInMethods.first) {
case 'google.com':
user = await googleSignIn(context, email, credential);
break;
case 'facebook.com':
user = await facebookSignIn(context);
break;
case 'apple.com':
user = await appleSignIn(context);
break;
case 'password':
// since password is managed by user we force have email provider only
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(translate('auth.signInMethods_password'))));
break;
// TODO: apple
}
await linkProvider(context, credential);
return user;
}
return ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(error.message!)));
}
}
// just some extra error covering
Future linkProvider(BuildContext context, credential) async {
try {
await FirebaseAuth.instance.currentUser?.linkWithCredential(credential);
} on FirebaseAuthException catch (e) {
switch (e.code) {
case "provider-already-linked":
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(translate('auth.provider_already_linked'))));
break;
case "invalid-credential":
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(translate('auth.invalid_credential'))));
break;
case "credential-already-in-use":
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text(translate('auth.credential_already_in_use'))));
break;
default:
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(translate('auth.something_happened'))));
}
}
}
If you do Google -> Facebook it will look like this:
Other way around only Google will be present if your Google email is a trusted email (gmail). More info about that:
https://groups.google.com/g/firebase-talk/c/ms_NVQem_Cw/m/8g7BFk1IAAAJ
Display name returns null right after registration. However, if i login with the same email id, the display name shows up magically. Looked up some of the answers here but didn't find anything relevant to implementation in flutter.
My Code:
Future createUserWithEmailAndPassword(
String email, String password, String name) async {
try {
UserCredential userCredential = await _auth
.createUserWithEmailAndPassword(email: email, password: password);
await userCredential.user.updateProfile(displayName: name);
print(userCredential.user.displayName);
User user = userCredential.user;
db.setProfileonRegistration(user.uid, name);
return _userFromFireBase(userCredential.user);
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
return null;
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
return null;
}
} catch (e) {
print(e);
return null;
}
}
The rest of the function is not waiting for line 6, but you are expecting the code is waiting for successful execution of that line before continue
Instead of using
await userCredential.user.updateProfile(displayName: name);
Try using this
Future createUserWithEmailAndPassword(
String email, String password, String name) async {
try {
UserCredential userCredential = await _auth
.createUserWithEmailAndPassword(email: email, password: password);
userCredential.user.updateProfile(displayName: name).then((_) {
print(userCredential.user.displayName);
User user = userCredential.user;
db.setProfileonRegistration(user.uid, name);
return _userFromFireBase(userCredential.user);
});
} on FirebaseAuthException catch (e) {
if (e.code == 'weak-password') {
print('The password provided is too weak.');
return null;
} else if (e.code == 'email-already-in-use') {
print('The account already exists for that email.');
return null;
}
} catch (e) {
print(e);
return null;
}
}
It will wait until
userCredential.user.updateProfile(displayName: name)
Future resolves and then continues with the rest of the code in the .then block
I am trying to implement the example given at How do I access custom claims? to my existing code.
I have a Stream which listens to auth changes and updates my own user object with the responded Firebase user. When I store my user object, I would like to get the custom claims of that user as well.
The problem is in _userFromFirebaseUser.
It says "The await expression can only be used in an async function.
Try marking the function body with either 'async' or 'async*'."
But when I do so, the error is hops to my stream where it then says "The argument type 'Future Function(User)' can't be assigned to the parameter type 'User Function(User)'." for "_userFromFirebaseUser" in
// auth change user stream
Stream<local.User> get user {
return _auth.authStateChanges().map(_userFromFirebaseUser);
}
Here is my complete authentication class:
import 'package:<my-pckg>/models/user.dart' as local;
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:<my-pckg>/services/database.dart';
//import 'package:shared_preferences/shared_preferences.dart';
class AuthService {
final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
// create user obj based on firebase user
local.User _userFromFirebaseUser(auth.User user) {
final isAdmin = (await _currentUserClaims)['admin'] == true;
return user != null
? local.User(
uid: user.uid,
email: user.email,
displayName: user.displayName,
isAdmin: isAdmin)
: null;
}
// auth change user stream
Stream<local.User> get user {
return _auth.authStateChanges().map(_userFromFirebaseUser);
}
// sign in anon
Future signInAnon() async {
try {
auth.UserCredential result = await _auth.signInAnonymously();
auth.User user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
// sign in with email and password
Future signInWithEmailAndPassword(String email, String password) async {
try {
auth.UserCredential result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
auth.User user = result.user;
print('Successfully logged in, User UID: ${user.uid}');
return user;
} catch (error) {
print(error.toString());
return null;
}
}
// register with email and password
Future registerWithEmailAndPassword(String email, String password) async {
try {
auth.UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
auth.User user = result.user;
// create a new document for the user with the uid
await DatabaseService(uid: user.uid).updateUserData(null);
print('Successfully registered, User UID: ${user.uid}');
return _userFromFirebaseUser(user);
} catch (error) {
print(error.toString());
return null;
}
}
// sign out
Future signOut() async {
try {
print('User signed out');
return await _auth.signOut();
} catch (error) {
print(error.toString());
return null;
}
}
Future<Map<dynamic, dynamic>> get _currentUserClaims async {
final user = _auth.currentUser;
// If refresh is set to true, a refresh of the id token is forced.
final idTokenResult = await user.getIdTokenResult(true);
return idTokenResult.claims;
}
}
Am I heading into the wrong direction? Is there anything obvious, that I simply do not consider?
Thanks for your help!
For those, heading into the same problem, I found the solution after further research:
You will have to change the .map to .asyncMap.
Here is the code, which works for me:
import 'package:<my-pckg>/models/user.dart' as local;
import 'package:firebase_auth/firebase_auth.dart' as auth;
import 'package:<my-pckg>/services/database.dart';
//import 'package:shared_preferences/shared_preferences.dart';
class AuthService {
final auth.FirebaseAuth _auth = auth.FirebaseAuth.instance;
// create user obj based on firebase user
Future<local.User> _userFromFirebaseUser(auth.User user) async {
final isAdmin = (await _userClaims)['admin'] == true;
return user != null
? local.User(
uid: user.uid,
email: user.email,
displayName: user.displayName,
isAdmin: isAdmin)
: null;
}
// auth change user stream
Stream<local.User> get user {
return _auth.authStateChanges().asyncMap(_userFromFirebaseUser);
}
// sign in anon
Future signInAnon() async {
try {
auth.UserCredential result = await _auth.signInAnonymously();
auth.User user = result.user;
return _userFromFirebaseUser(user);
} catch (e) {
print(e.toString());
return null;
}
}
// sign in with email and password
Future signInWithEmailAndPassword(String email, String password) async {
try {
auth.UserCredential result = await _auth.signInWithEmailAndPassword(
email: email, password: password);
auth.User user = result.user;
print('Successfully logged in, User UID: ${user.uid}');
return user;
} catch (error) {
print(error.toString());
return null;
}
}
// register with email and password
Future registerWithEmailAndPassword(String email, String password) async {
try {
auth.UserCredential result = await _auth.createUserWithEmailAndPassword(
email: email, password: password);
auth.User user = result.user;
// create a new document for the user with the uid
await DatabaseService(uid: user.uid).updateUserData(null);
print('Successfully registered, User UID: ${user.uid}');
return _userFromFirebaseUser(user);
} catch (error) {
print(error.toString());
return null;
}
}
// sign out
Future signOut() async {
try {
print('User signed out');
return await _auth.signOut();
} catch (error) {
print(error.toString());
return null;
}
}
Future<Map<dynamic, dynamic>> get _userClaims async {
final user = _auth.currentUser;
// If refresh is set to true, a refresh of the id token is forced.
final idTokenResult = await user.getIdTokenResult(true);
return idTokenResult.claims;
}
}
Found here: In flutter, how can I "merge" Firebase onAuthStateChanged with user.getTokenId() to return a Stream?
I want to add data on firestore and it wont work. can somebody help me.
This is the newest updated version and I can't figure out how...
firebase_auth: ^0.18.0+1 cloud_firestore: ^0.14.0+2
This is the sign up screen so I want to send data after I create the email and password.
I want to add the document with user uid too.
onPressed: () async {
try {
UserCredential userCredential = await FirebaseAuth
.instance
.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
);
if (userCredential != null) {
firestore
.collection("user")
.doc('user.uid')
.set({
'username': username,
'email': email,
})
.then((value) => print("User Added"))
.catchError((error) =>
print("Failed to add user: $error"));
Navigator.of(context).pushNamed(AppRoutes.authLogin);
}
} catch (e) {
print(e);
_usernameController.text = "";
_passwordController.text = "";
_repasswordController.text = "";
_emailController.text = "";
//TODO: alertdialog with error
}
setState(() {
saveAttempted = true;
});
if (_formKey.currentState.validate()) {
_formKey.currentState.save();
}
},
Can someone help me with the firestore.. Thank you..
First Create a User class.
class UserData {
final String userId;
final String fullNames;
final String email;
final String phone;
UserData(
{this.userId,
this.fullNames,
this.email,
this.phone});
Map<String, dynamic> getDataMap() {
return {
"userId": userId,
"fullNames": fullNames,
"email": email,
"phone": phone,
};
}
}
Then you can use a function like this one to save the credentials and save the data to firestore
createOrUpdateUserData(Map<String, dynamic> userDataMap) async {
FirebaseUser user = await FirebaseAuth.instance.currentUser();
DocumentReference ref =
Firestore.instance.collection('user').document(user.uid);
return ref.setData(userDataMap, merge: true);
}
==
bool validateAndSave() {
final form = _formKey.currentState;
if (form.validate()) {
form.save();
return true;
}
return false;
}
void validateAndSubmit() async {
if (validateAndSave()) {
try {
String userId = _formType == FormType.login
? await widget.auth.signIn(_email, _password)//use your signin
: await widget.auth.signUp(_email, _password);//use your signup
if (_formType == FormType.register) {
UserData userData = new UserData(
fullNames: _fullNames,
email: _email,
phone: "",
);
createOrUpdateUserData(userData.getDataMap());
}
} catch (e) {
setState(() {
_isLoading = false;
switch (e.code) {
case "ERROR_INVALID_EMAIL":
_authHint = "Your email address appears to be malformed.";
break;
case "ERROR_EMAIL_ALREADY_IN_USE":
_authHint = "Email address already used in a different account.";
break;
case "ERROR_WRONG_PASSWORD":
_authHint = "Your password is wrong.";
break;
case "ERROR_USER_NOT_FOUND":
_authHint = "User with this email doesn't exist.";
break;
case "EMAIL NOT VERIFIED":
_authHint = "Email not verified: Please go to yor email and verify";
break;
case "ERROR_USER_DISABLED":
_authHint = "User with this email has been disabled.";
break;
case "ERROR_TOO_MANY_REQUESTS":
_authHint =
"Too many Attemps. Account has temporarily disabled.\n Try again later.";
break;
case "ERROR_OPERATION_NOT_ALLOWED":
_authHint = "Signing in with Email and Password is not enabled.";
break;
case "ERROR_ACCOUNT_EXISTS_WITH_DIFFERENT_CREDENTIAL":
_authHint = "The email is in use by another account";
break;
default:
_authHint = "An undefined Error happened.";
}
});
print(e);
errorDialog(context, _authHint);
}
} else {
setState(() {
_authHint = '';
});
}
}
Then use
onpressed:(){
validateAndSubmit();
}
the formtype is an Enum
enum FormType { login, register, reset }
widget.auth.signIn and widget.auth.signUp should be replaced with your signin and signup respectively.
Added a custom error block to differentiate firebase auth errors as well.
Defining an auth page independently will help you reuse your code in future.