How to add "this user/account does not exist" error in Flutter, using Firebase? - firebase

I am trying to make a login page in Flutter. I have used Firebase as well for user authentication and logging in. The problem is, while I can login successfully with the correct information, I am unable to display anything like a pop up error box or message that the account does not exist. This is my code :
class _LoginPageState extends State<LoginPage> {
String _email, _password;
final auth = FirebaseAuth.instance;
bool hidepwd = true;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
brightness: Brightness.light,
backgroundColor: Colors.transparent,
elevation: 0,
leading: Container(
margin: EdgeInsets.all(5),
width: 50,
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10)),
color: Color(0xffe9eefa),
),
child: IconButton(
onPressed: (){Navigator.pop(context);},
icon: Icon(
Icons.keyboard_arrow_left_rounded,
color: Color(0xff2657ce),
),
),
),
),
body: ListView(
children: <Widget>[
Container(
child: IconButton(
icon: Icon(
Icons.account_circle_rounded,
color: Color(0xff2657ce),
size:100,
),
),
),
SizedBox(height: 50,),
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
padding: EdgeInsets.only(right: 240),
child: Text('Email Address', style: TextStyle(
fontSize: 15,),),
),
SizedBox(height: 10,),
Container(
padding: EdgeInsets.symmetric(vertical: 2, horizontal: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.grey.withOpacity(0.2),
),
child: TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Email',
),
onChanged: (value) {
setState(() {
_email = value.trim();
});
},
),
),
SizedBox(height: 20,),
Container(
padding: EdgeInsets.only(right: 270),
child: Text('Password', style: TextStyle(
fontSize: 15,
),),
),
SizedBox(height: 10,),
Container(
padding: EdgeInsets.symmetric(vertical: 2, horizontal: 20),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(20)),
color: Colors.grey.withOpacity(0.2),
),
child: Row(
children: <Widget>[
Expanded(
child: TextFormField(
obscureText: hidepwd,
decoration: InputDecoration(hintText: 'Password'),
onChanged: (value) {
setState(() {
_password = value.trim();
});
},
),
),
Container(
height: 50,
width: 50,
child: IconButton(
onPressed: togglepwdVisibility,
icon: IconButton(
icon: hidepwd == true ? Icon(
Icons.visibility_off
): Icon(Icons.visibility),
),
),
)
],
),
),
SizedBox(height: 20,),
RaisedButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
color: Color(0xff5178D7),
child: Text("Log In", style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 15
),),
onPressed: (){
auth.signInWithEmailAndPassword(email: _email, password: _password).then((_){
Navigator.of(context).pushReplacement(MaterialPageRoute(builder: (context) => frontpage()));
});
}
),
SizedBox(height: 20,),
Container(
child: Center(
child: Text('---- or ----'),
),
),
SizedBox(height: 20,),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("Don't have an account? "),
InkWell(
onTap: openSignUpPage,
child: Text("Sign Up", style: TextStyle(
color: Color(0xff1A3C90),
fontWeight: FontWeight.w700
),),
)
],
)
],
),
),
),
],
),
);
}
Any ideas/suggestions on what I could add or change in my code to have that error message included when I am unable to login overall?

In your login onPressed: (){ ... }, catch the FirebaseAuthException.
Source: https://firebase.flutter.dev/docs/auth/usage/#sign-in
try {
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: "barry.allen#example.com",
password: "SuperSecretPassword!"
);
} on FirebaseAuthException catch (e) {
if (e.code == 'user-not-found') {
print('No user found for that email.');
} else if (e.code == 'wrong-password') {
print('Wrong password provided for that user.');
}
}

If you need alerts to pop on each login error you can try using the following function but only if you are using TextEdittingController:
signIn() async {
if (_loginFormKey.currentState!.validate()) {
_loginFormKey.currentState!.save();
try {
await FirebaseAuth.instance
.signInWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text)
.then((currentUser) => FirebaseFirestore.instance
.collection("users")
.doc(currentUser.user!.uid)
.get()
.then((conext) => Navigator.push(
context,
MaterialPageRoute(
builder: (context) => HomePage())))
.catchError((err) => print(err)));
} on FirebaseAuthException catch (error) {
if (error.code == 'user-not-found') {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Auth Exception!"),
content: Text("This User Does Not Exist."),
actions: <Widget>[
Row(
children: [
ElevatedButton(
child: Text("Sign In Again"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
)
],
);
});
} else if (error.code == 'wrong-password') {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Auth Exception!"),
content: Text("The Password Entered is Invalid."),
actions: <Widget>[
Row(
children: [
ElevatedButton(
child: Text("Sign In Again"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
)
],
);
});
}
}
}
}

Related

Flutter update UI on button press

If I remove the awaits from my viewModel.sendMessage() it works as expected, however I can't set the state with the value returned. Is there a way to update the UI from setState?
I'm just not sure how to do both at the same time, the parent class for this widget is a StatefulWidget, Idk if that matters. My ConversationViewModel is just a changeNotifier.
#override
Widget build(BuildContext context) {
UsViewModel viewModel = Provider.of<UsViewModel>(context, listen: false);
viewModel.setUs();
var us = Provider.of<UsViewModel>(context, listen: true).us;
return Consumer<ConversationViewModel>(builder: (BuildContext context, viewModel, Widget child) {
return Scaffold(
key: viewModel.scaffoldKey,
appBar: AppBar(
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.keyboard_backspace,
),
),
elevation: 0.0,
titleSpacing: 0,
title: buildName(),
),
body: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
Flexible(
child: StreamBuilder(
stream: messageListStream(widget.chatId),
builder: (context, snapshot) {
if (snapshot.hasData) {
List messages = snapshot.data.docs;
return ListView.builder(
controller: scrollController,
padding: EdgeInsets.symmetric(horizontal: 10.0),
itemCount: messages.length,
reverse: true,
itemBuilder: (BuildContext context, int index) {
Message message = Message.fromJson(
messages.reversed.toList()[index].data());
return ChatBubble(
message: '${message.content}',
time: message?.time,
isMe: message?.senderUid == us?.uid,
type: message?.type);
},
);
} else {
return Center(child: circularProgress(context));
}
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: BottomAppBar(
elevation: 10.0,
child: Container(
constraints: BoxConstraints(maxHeight: 100.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: TextField(
controller: messageController,
focusNode: focusNode,
style: TextStyle(
fontSize: 15.0,
color:
Theme.of(context).textTheme.headline6.color,
),
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10.0),
enabledBorder: InputBorder.none,
border: InputBorder.none,
hintText: "Type your message",
hintStyle: TextStyle(
color:
Theme.of(context).textTheme.headline6.color,
),
),
maxLines: null,
),
),
IconButton(
icon: Icon(
Feather.send,
color: Theme.of(context).colorScheme.secondary,
),
onPressed: () {
if (messageController.text.trim().isNotEmpty) {
sendMessage(viewModel, us);
}
},
),
],
),
),
),
)
],
),
),
);
});
}
sendMessage(ConversationViewModel viewModel, var us,
{bool isImage = false, int imageType}) async {
String msg;
msg = messageController.text.trim();
messageController.clear();
Message message = Message(
content: '$msg',
senderUid: us?.uid,
time: Timestamp.now(),
);
if (msg.isNotEmpty) {
String id = await viewModel.sendMessage(widget.usId, message);
setState(() {
chatId = id;
});
}
}
If you using ChangeNotifier with Provider package you don't need setState method. You should read Provider documentation: https://pub.dev/packages/provider
ft: That you create listeners for each item in this line.
isMe: message?.senderUid == context.watch<UsViewModel>.us ?.uid,
How to use a provider according to your question, added an example;
#override
Widget build(BuildContext context) {
context.read<UsViewModel>().setUs();
return Scaffold(
key: context.read<UsViewModel>().scaffoldKey,
appBar: AppBar(
leading: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.keyboard_backspace,
),
),
elevation: 0.0,
titleSpacing: 0,
title: buildName(),
),
body: Container(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
Flexible(
child: StreamBuilder(
stream: messageListStream(widget.chatId),
builder: (context, snapshot) {
if (snapshot.hasData) {
List messages = snapshot.data.docs;
return ListView.builder(
controller: scrollController,
padding: EdgeInsets.symmetric(horizontal: 10.0),
itemCount: messages.length,
reverse: true,
itemBuilder: (BuildContext context, int index) {
Message message = Message.fromJson(
messages.reversed.toList()[index].data());
return ChatBubble(
message: '${message.content}',
time: message?.time,
isMe: message?.senderUid == context.watch<UsViewModel>.us ?.uid,
type: message?.type);
},
);
} else {
return Center(child: circularProgress(context));
}
},
),
),
Align(
alignment: Alignment.bottomCenter,
child: BottomAppBar(
elevation: 10.0,
child: Container(
constraints: BoxConstraints(maxHeight: 100.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Flexible(
child: TextField(
controller: messageController,
focusNode: focusNode,
style: TextStyle(
fontSize: 15.0,
color:
Theme.of(context).textTheme.headline6.color,
),
decoration: InputDecoration(
contentPadding: EdgeInsets.all(10.0),
enabledBorder: InputBorder.none,
border: InputBorder.none,
hintText: "Type your message",
hintStyle: TextStyle(
color:
Theme.of(context).textTheme.headline6.color,
),
),
maxLines: null,
),
),
IconButton(
icon: Icon(
Feather.send,
color: Theme.of(context).colorScheme.secondary,
),
onPressed: () {
if (messageController.text.trim().isNotEmpty) {
sendMessage(context);
}
},
),
],
),
),
),
)
],
),
),
);
}
sendMessage(BuildContext context) async {
String msg;
msg = messageController.text.trim();
messageController.clear();
Message message = Message(
content: '$msg',
senderUid: context.read<UsViewModel>().us?.uid,
time: Timestamp.now(),
);
if (msg.isNotEmpty) {
String id = await context.read<UsViewModel>().sendMessage(widget.usId, message);
setState((){
chatId = id;
});
}
}

How to update and delete a data in a list according to it's document id - flutter, firebase 2021

I am trying to delete and update a list of details in flutter. For that i used doc('document_id') which was given as a solution in another stackoverflow question. I tried some another solutions given in stacker flow too. But nothing fork for me. But if I give a specific documentID I am able to delete that. Also how can I pass the selected data to update page too.
class addressProfile extends StatefulWidget {
const addressProfile({Key? key}) : super(key: key);
#override
_addressProfileState createState() => _addressProfileState();
}
class _addressProfileState extends State<addressProfile> {
var Default = 'unDefault';
delete() async {
try {
FirebaseFirestore.instance
.collection("address")
.doc('document_id')
.delete();
} catch (e) {
print(e);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey.shade100,
appBar: AppBar(
centerTitle: true,
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
title: Text(
'My Addresses',
style: TextStyle(color: Colors.black),
),
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios,
color: Colors.black,
),
onPressed: () {
Navigator.of(context).pushNamed('/profilePage');
},
),
),
body: ListView(
padding: EdgeInsets.all(16),
children: [
StreamBuilder<QuerySnapshot>(
stream:
FirebaseFirestore.instance.collection("address").snapshots(),
builder: (context, snapshot) {
if (snapshot.hasData) {
return Expanded(
child: SizedBox(
height: 700,
child: ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
QueryDocumentSnapshot x = snapshot.data!.docs[index];
return Container(
child: Card(
child: Padding(
padding: EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Text(x['firstName']),
Text(' '),
Text(x['lastName']),
],
),
Text(""),
Row(
children: [
Text(x['primaryPhone']),
Text(" / "),
Text(x['secondaryPhone']),
],
),
Text(''),
Row(
children: [
Text(x['address1']),
Text(', '),
Text(x['address2']),
Text(', '),
Text(x['city']),
Text(', '),
Text(x['region']),
],
),
Divider(
color: Colors.black,
),
Row(
children: [
Container(
child: Radio(
value: 'default',
groupValue: Default,
onChanged: (String? val) {
setState(() {
if (val != null)
Default = val;
});
}),
),
Container(
child: Text("Default"),
),
Container(
padding: EdgeInsets.only(left: 60),
child: Align(
child: ElevatedButton.icon(
onPressed: () {
if (snapshot.data!.docs.length >
1) {
delete();
Fluttertoast.showToast(
msg:
"Address deleted successfully",
toastLength:
Toast.LENGTH_SHORT,
gravity:
ToastGravity.BOTTOM,
textColor: Colors.black,
backgroundColor:
Colors.green.shade400,
);
} else {
Fluttertoast.showToast(
msg:
"Main address cannot be deleted",
toastLength:
Toast.LENGTH_SHORT,
gravity:
ToastGravity.BOTTOM,
textColor: Colors.black,
backgroundColor:
Colors.green.shade400,
);
}
},
label: Text('Delete'),
style: ElevatedButton.styleFrom(
fixedSize: Size(90, 20),
primary: Colors.red.shade500,
padding: EdgeInsets.symmetric(
horizontal: 5,
),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(
10))),
icon: Icon(
Icons.delete_outline_sharp),
),
),
),
Container(
padding: EdgeInsets.only(left: 14),
child: Align(
child: ElevatedButton.icon(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (builder) =>
updateAddress(),
),
);
},
label: Text('Update'),
style: ElevatedButton.styleFrom(
fixedSize: Size(90, 20),
primary:
Colors.green.shade500,
padding: EdgeInsets.symmetric(
horizontal: 5,
),
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(
10))),
icon: Icon(Icons.edit),
),
),
),
],
),
],
),
),
),
);
},
),
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}),
Align(
alignment: AlignmentDirectional.bottomCenter,
child: ElevatedButton(
onPressed: () {
Navigator.of(context).pushNamed('/addNewAddress');
},
child: Text(
"Add New Address",
style: TextStyle(
fontSize: 15,
letterSpacing: 2,
color: Colors.black,
),
),
style: ElevatedButton.styleFrom(
fixedSize: Size(250, 40),
primary: Colors.green.shade500,
padding: EdgeInsets.symmetric(
horizontal: 50,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10))),
),
),
],
),
);
}
}
This is so far I did. Please help me to continue.
I don't know how you have saved the data. But I got an issue like this and what I did was, I added a variable as "id" to database while saving the data. There is an auto generated id plugin for flutter (nanoid). You can add that and save the data as following.
var id = nanoid(10) //10 is the length of the id. You can give as you wish
create() async {
try {
FirebaseFirestore.instance
.collection("address")
.doc(id)
.set({
"id":id,
//other inputs
});
} catch (e) {
print(e);
}
}
Then you can use that id as a key to update ad delete.
For example according to you code to delete you can use like this in the onPress(){} of delete button,
FirebaseFirestore.instance.collection("address").doc(x['id']).delete();
So the data related to id will be deleted.
Also better to use proper name rather than "x".
Can you please try this
delete(String docId) async {
try {
FirebaseFirestore.instance
.collection("address")
.doc(docId)
.delete();
} catch (e) {
print(e);
}
}
Your delete function call
delete(snapshot.data!.docs[index].id);
Update document
void update(String docId){
FirebaseFirestore.instance.collection("address").doc(docId) .update({"field1":"fieldValue1","field2":"fieldValue2"});
}
Let me know if you find any issues in comment

How to retrive a doc from firestore with its ID with flutter

I have a collection of user_profile in my app console. I want to retrieve a doc (a particular user profile with its user id [click to check][1]).
I know that FirebaseAuth.instance.currentUser; would give me the current login user ID but that is not what I want. I want to show the details of the clicked user, not the logged_in user, can't seem to find any answer here that was helpful. Please help guys
This is the method that gets the collection
Future<DocumentSnapshot> getUserData() {
var firebaseUser = FirebaseAuth.instance.currentUser;
_firestoreInstance
.collection('user_profile')
.doc(firebaseUser.uid)
.get()
.then((value) {
print(value.data());
return value.data();
});
}
and here is my future builder
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getUserData(),
// ignore: missing_return
builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text('Error fetching user profile');
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> userData = snapshot.data.data();
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.only(top: 10),
child: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: IconButton(
onPressed: () {
// Navigator.pushNamed(context, Homepage.id);
},
icon: Icon(
Icons.arrow_back,
color: Colors.white,
size: 30,
),
),
),
GestureDetector(
onTap: () {},
child: Stack(
children: [
CircleAvatar(
radius: 70,
backgroundColor: Colors.transparent,
child: ClipOval(
child: Image.asset('assets/avatar_profile.jpg'),
),
),
Positioned(
bottom: 0,
right: 0,
child: CircleAvatar(
backgroundColor: Colors.white60,
radius: 25,
child: IconButton(
onPressed: () {},
icon: Icon(Icons.edit, color: Colors.blueGrey),
),
),
)
],
),
),
SizedBox(
height: 10,
),
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"${userData['nickname']}",
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.w900),
),
VerticalDivider(
thickness: 3,
width: 20,
color: Colors.white,
),
Text(
// '7',
"{$userData['age]}",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Card(
child: Column(
children: [
ListTile(
leading: Icon(
Icons.person,
size: 40,
),
title: Text("About me"),
isThreeLine: false,
dense: true,
subtitle: Text("${userData['aboutMe']}"),
trailing: Icon(Icons.arrow_right),
)
],
),
),
),
Expanded(
child: Container(
width: 400,
child: ListView(
children: [
ProfileListTile(
leading: Icons.phone_in_talk,
title: 'Phone Number',
subtitle: "${userData['mobile']}",
),
ProfileListTile(
leading: Icons.add_location,
title: 'Current Location',
subtitle: "${userData['location']}",
),
ProfileListTile(
leading: FontAwesomeIcons.heartbeat,
title: 'Relationship Status',
subtitle: "${userData['maritalStatus']}",
),
ProfileListTile(
leading: Icons.people,
title: 'Gender',
subtitle: 'Male',
),
ProfileListTile(
leading: Icons.looks,
title: 'Interested In',
subtitle: "${userData['InterestedIn']}",
),
],
),
),
),
],
),
),
));
}
},
);
}
}
Your code is currently not returning anything from getUserData yet. The only return you have is inside the then function, and doesn't escape to the higher level.
The simplest way to fix it is by using await:
Future<DocumentSnapshot> getUserData() async {
var firebaseUser = FirebaseAuth.instance.currentUser;
var doc = await _firestoreInstance
.collection('user_profile')
.doc(firebaseUser.uid)
.get()
return doc.data();
}
It sounds like you would like your app's users to see other people's profile.
To do that, you would first have to accept the uid of the user to display the profile. Then you can pass the uid to the future like the following example:
class ProfilePage extends StatelessWidget {
const ProfilePage({
Key key,
#required this.uid, // Here you are receiving the uid of the currently viewd user's uid
}) : super(key: key);
final String uid;
#override
Widget build(BuildContext context) {
return FutureBuilder<Map<String, dynamic>>(builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error fetching user profile'));
}
final userProfile = snapshot.data;
return Column(
children: [
// Here you would paste the contents of your user profile widget
],
);
});
}
Future<Map<String, dynamic>> getUserData() async {
final snap =
await _firestoreInstance.collection('user_profile').doc(uid).get();
return snap.data();
}
}
I was able to solve this easily by just passing from usersCard to UserProfile (my bad, lolx), since I already have this data on list users screen, there was no need to fetching them again with FutureBuilder
class UsersCard extends StatelessWidget {
final Users usersDetails;
const UsersCard({Key key, #required this.usersDetails}) : super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (_) =>
UserProfile(userDetails: usersDetails))); //im passing the data here
},
child: Stack(
children: [
Card(
semanticContainer: true,
clipBehavior: Clip.antiAliasWithSaveLayer,
child: Image.network(
'https://placeimg.com/170/170/any',
fit: BoxFit.contain,
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 5,
),
Positioned(
left: 20,
bottom: 20,
child: IntrinsicHeight(
child: Row(
children: [
Text(
'${usersDetails.nickname}',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w900),
),
VerticalDivider(
thickness: 2,
width: 20,
color: Colors.white,
),
Text(
'${usersDetails.age}',
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w900),
),
],
),
),
),
],
),
);
}
}
Here is my UsersProfile Screen
class UserProfile extends StatelessWidget {
final Users userDetails;
UserProfile({#required this.userDetails});
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Container(
padding: EdgeInsets.only(top: 10),
child: Column(
children: [
Align(
alignment: Alignment.centerLeft,
child: IconButton(
onPressed: () {
// Navigator.pushNamed(context, Homepage.id);
},
icon: Icon(
Icons.arrow_back,
color: Colors.white,
size: 30,
),
),
),
GestureDetector(
onTap: () {},
child: Stack(
children: [
CircleAvatar(
radius: 70,
backgroundColor: Colors.transparent,
child: ClipOval(
child: Image.asset('assets/avatar_profile.jpg'),
),
),
Positioned(
bottom: 0,
right: 0,
child: CircleAvatar(
backgroundColor: Colors.white60,
radius: 25,
child: IconButton(
onPressed: () {},
icon: Icon(Icons.edit, color: Colors.blueGrey),
),
),
)
],
),
),
SizedBox(
height: 10,
),
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"${userDetails.nickname}",
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.w900),
),
VerticalDivider(
thickness: 3,
width: 20,
color: Colors.white,
),
Text(
// '7',
"{$userDetails.age}",
style: TextStyle(
color: Colors.white,
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Card(
child: Column(
children: [
ListTile(
leading: Icon(
Icons.person,
size: 40,
),
title: Text("About me"),
isThreeLine: false,
dense: true,
subtitle: Text("${userDetails.aboutMe}"),
trailing: Icon(Icons.arrow_right),
)
],
),
),
),
Expanded(
child: Container(
width: 400,
child: ListView(
children: [
ProfileListTile(
leading: Icons.phone_in_talk,
title: 'Phone Number',
subtitle: "${userDetails.mobile}",
),
ProfileListTile(
leading: Icons.add_location,
title: 'Current Location',
subtitle: "${userDetails.location}",
),
ProfileListTile(
leading: FontAwesomeIcons.heartbeat,
title: 'Relationship Status',
subtitle: "${userDetails.maritalStatus}",
),
ProfileListTile(
leading: Icons.people,
title: 'Gender',
subtitle: 'Male',
),
ProfileListTile(
leading: Icons.looks,
title: 'Interested In',
subtitle: "${userDetails.interestedIn}",
),
],
),
),
),
],
),
),
),
);
}
}

Retrieving Data From Firestore in time

I have looked all over the internet for how to fix this problem and I can't find a solution anywhere. I am using flutter with firestore to make an app. I want to make it so when the user logins into the app at the top shows their name (simple right). I can get data from firestore:
Future<void> getName() async {
print("Attemping to get name!");
final firestoreInstance = await FirebaseFirestore.instance;
FirebaseAuth auth = FirebaseAuth.instance;
String uid = auth.currentUser.uid.toString();
await firestoreInstance.collection("Users").doc(uid).get().then((value) {
print("Name: " + value.data()["firstName"]);
info.firstName=((value.data()["firstName"]));
})
class info {
static String firstName;
}
but it comes in too late so the app just says "Welcome back" As you can see here and not "Welcome back, Connor" As seen here
When I look in the console the function does run but the program doesn't wait for it and continues resulting in a null.
Thanks you
EDIT as requested UI code:
class Home extends StatelessWidget {
final DatabaseReference = FirebaseDatabase.instance;
final FirebaseAuth auth = FirebaseAuth.instance;
static String firstName;
static String lastName;
static String email;
static String companyName;
static bool isNewAccount = false;
static String name = "Welcome back";
Home();
#override
Widget build(BuildContext context) {
final User user = auth.currentUser;
final uid = user.uid;
final ref = DatabaseReference.reference();
if (isNewAccount == true) {
userSetup(firstName, lastName, email, companyName);
isNewAccount = false;
}
getName(); //does get the name from the database but name will error out as it doesn't get the name fast enough (or that's what I think)
name= "Welcome back, "+info.firstName;
return WillPopScope(
onWillPop: () async => false,
child: MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
backgroundColor: Colors.cyan,
body: SingleChildScrollView(
child: Container(
margin:
EdgeInsets.only(top: MediaQuery.of(context).size.height / 16),
child: Column(
children: [
Container(
margin: EdgeInsets.only(bottom: 10),
child: Text(
name,
textAlign: TextAlign.center,
style: new TextStyle(
color: Colors.white,
fontSize: MediaQuery.of(context).size.width / 16,
),
),
),
Container(
width: 260,
height: 125,
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Text(
"CHECK-IN",
style: new TextStyle(
color: Colors.white,
fontSize: 40.0,
),
),
color: Colors.grey[850],
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => Checkin()));
},
),
),
Container(
width: 260,
height: 140,
padding: EdgeInsets.only(top: 20),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Text(
"CHECK-OUT",
style: new TextStyle(
color: Colors.white,
fontSize: 38.0,
),
),
color: Colors.grey[850],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Checkout()));
},
),
),
Container(
margin: EdgeInsets.only(top: 55),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.only(right: 20),
child: Text(
"Sign out: ",
style: new TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
Container(
child: RaisedButton(
child: Text(
"SIGN OUT",
style: new TextStyle(
fontSize: 14.0,
color: Colors.white,
),
),
color: Colors.grey[700],
onPressed: () {
context.read<AuthenticationService>().signOut();
//return MyApp();
},
),
)
],
),
),
Container(
margin: EdgeInsets.only(top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.only(right: 20),
child: Text(
"View Stats: ",
style: new TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
Container(
child: RaisedButton(
child: Text(
"STATS",
style: new TextStyle(
fontSize: 14.0,
color: Colors.white,
),
),
color: Colors.grey[700],
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Stats()));
},
),
),
],
),
),
Container(
margin: EdgeInsets.only(top: 10),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
padding: EdgeInsets.only(right: 20),
child: Text(
"View Profile: ",
style: new TextStyle(
fontSize: 15.0,
fontWeight: FontWeight.bold,
),
),
),
Container(
child: RaisedButton(
child: Text(
"PROFILE",
style: new TextStyle(
fontSize: 14.0,
color: Colors.white,
),
),
color: Colors.grey[700],
onPressed: () {
/*Navigator.push(
context,
MaterialPageRoute(
builder: (context) => Stats()));*/
},
),
),
],
),
),
Container(
width: 240,
height: 55,
margin: EdgeInsets.only(
top: MediaQuery.of(context).size.height / 12),
child: RaisedButton(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20.0),
),
child: Text(
"EMERGENCY REPORT",
style: new TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
color: Colors.grey[700],
onPressed: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => EmergencyReport()));
},
),
),
],
),
),
),
),
),
);
}
static getAccountDetails(
String firstName1, String lastName1, String email1, String companyName1) {
firstName = firstName1;
lastName = lastName1;
email = email1;
companyName = companyName1;
isNewAccount = true;
}
static getFirstName(String nameFirst) {
name = "Welcome back, "+nameFirst;
}
}
FutureBuilder<DocumentSnapshot>(
future: firestoreInstance.collection("Users").doc(uid).get(),
builder: (_,snap){
return snap.hasData ? Text(snap.data.data()["firstName"]):CircularProgressIndicator();
},)
You need to convert StatelessWidget into StatefullWidget.
After that you have to write this in initState method
void initState() {
super.initState();
getName().then((){
setState(() {
name= "Welcome back, "+info.firstName;
});
});
}

How to save login Credential with Firebase

I'm having an interface where we should log in by providing the email and password.
Below is my login page.
the interface is designed using dart with flutter.
What I want is to save the email and password when the user (checks the remember me box and then)login to the account.
When the user comes back again to the same page, the page should automatically fill the username and password for the user.
For now, it saves the credentials in the firebase authentication.
Below is my code for Remember me checkbox and login.
Widget _RememberMeCheckbox() {
return Container(
height: 20.0,
child: Row(
children: <Widget>[
Theme(
data: ThemeData(unselectedWidgetColor: Colors.white),
child: Checkbox(
value: _rememberMe,
checkColor: Colors.green,
activeColor: Colors.white,
onChanged: (value) {
setState(() {
_rememberMe = value;
});
},
),
),
Text(
'Remember me',
style: kLabelStyle,
),
],
),
);
}
Widget _LoginBtn() {
return Container(
padding: EdgeInsets.symmetric(vertical: 25.0),
width: double.infinity,
child: Form(
child: RaisedButton(
elevation: 5.0,
onPressed: () async {
final form = formKey.currentState;
form.save();
if (form.validate()) {
try {
FirebaseUser result =
await Provider.of<AuthService>(context, listen: false)
.loginUser(email: _email, password: _password);
print(result);
Navigator.of(context).pushNamed('/home');
} on AuthException catch (ex) {
return _showErrorDialog(context, ex.message);
} on Exception catch (ex) {
return _showErrorDialog(context, ex.toString());
}
}
},
padding: EdgeInsets.all(15.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
),
color: Colors.white,
child: Text(
'LOGIN',
style: TextStyle(
color: Color(0xFF527DAA),
letterSpacing: 1.5,
fontSize: 18.0,
fontWeight: FontWeight.bold,
fontFamily: 'OpenSans',
),
),
),
),
);
}
I need to do this using firebase can anyone help me?
String_email="";
String_password="";
Widget _EmailTextField() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Email',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
keyboardType: TextInputType.text,
autovalidate: false,
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.email,
color: Colors.white,
),
hintText: 'Enter your Email Address',
hintStyle: kHintTextStyle,
),
validator: (String value) {
if (value.isEmpty) {
return 'Email is Required.';
}
Pattern pattern =
r'^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$';
RegExp regex = new RegExp(pattern);
if (!regex.hasMatch(value)) {
return 'Enter valid Email Address';
}
return null;
},
onSaved: (String value) {
return _email = value;
},
),
),
],
);
}
Widget _PasswordTextField() {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Password',
style: kLabelStyle,
),
SizedBox(height: 10.0),
Container(
alignment: Alignment.centerLeft,
decoration: kBoxDecorationStyle,
height: 60.0,
child: TextFormField(
autovalidate: false,
style: TextStyle(
color: Colors.white,
fontFamily: 'OpenSans',
),
decoration: InputDecoration(
border: InputBorder.none,
contentPadding: EdgeInsets.only(top: 14.0),
prefixIcon: Icon(
Icons.lock,
color: Colors.white,
),
suffixIcon: IconButton(
icon: Icon(
_passwordVisible ? Icons.visibility : Icons.visibility_off,
color: Colors.white,
),
onPressed: _passwordVisibility,
),
hintText: 'Enter your Password',
hintStyle: kHintTextStyle,
),
obscureText: !_passwordVisible,
validator: (String value) {
if (value.isEmpty) {
return 'Password is Required.';
}
if (value.length < 6) {
return 'Password too short.';
}
return null;
},
onSaved: (String value) {
return _password = value;
},
),
),
],
);
}
There are a few options:
Read and write files: https://flutter.io/reading-writing-files/
SQLite via a Flutter plugin: https://github.com/tekartik/sqflite
SQLCipher via a Flutter plugin: https://github.com/drydart/flutter_sqlcipher
SharedPreferences via a Flutter plugin: https://github.com/flutter/plugins/tree/master/packages/shared_preferences

Resources