Load Firestore document first in Flutter - firebase

Thanks in advance!
Flutter & Firestore
I'm checking if the user is an admin. I have a collection 'users', within: a bool: admin: true or false. If it's true it shows the admin Screen. Else it shows the main screen.
The problem: the first 1 second I get this Screen. (see screen shot, only 1 second visible) Is there an option to use a loading indicator when the app gets the data from firestore.
I tried adding if (currentUser.admin == null) {}
But that doesn't work.
User currentUser;
//I made a separate modal document
#override
void initState() {
super.initState();
pageController = PageController(initialPage: 0);
getUser();
}
getUser() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
DocumentSnapshot doc =
await Firestore.instance.collection("users").document(user.uid).get();
setState(() {
currentUser = User.fromDocument(doc);
});
print(currentUser.admin);
}
#override
Widget build(BuildContext context) {
if (currentUser.admin == true) {
return AdminScreen(
currentUser: currentUser,
);
} else {
return mainScreen();
}
}
}
Screenshot
UPDATE: tried this:
getUser() async {
final FirebaseUser user = await FirebaseAuth.instance.currentUser();
DocumentSnapshot doc =
await Firestore.instance.collection("users").document(user.uid).get();
if (doc.exists) {
try {
setState(() {
currentUser = User.fromDocument(doc);
});
} catch (e) {
print(e);
}
}

Found it!
For anyone having the same issue.
This was the problem:
if (currentUser.admin == true)
It should be: if (currentUser == null) or if (currentUser != null)
it doesn't work with currentUser.xxxx

You can also do as follows
Firestore.instance
.collection('driverListedRides')
.getDocuments()
.then((QuerySnapshot snapshot) => {
snapshot.documents.forEach((f) {
String _variableName = f.data["YourCollectionFieldId"];
})
});

Related

Upload and save image into firebase Storage flutter dart

i'm trying to upload picture and register user information into firebase storage and firestore the problem is it's not accepting this code for some reason it says i need to put ; after _registerUser()
here is the code i'm using to save and upload information :
Future<void> uploadAndSaveImage() async {
if (_imageFile != null) {
_passwordTextEditingController.text ==
_cPasswordTextEditingController.text
? _emailTextEditingController.text.isNotEmpty &&
_passwordTextEditingController.text.isNotEmpty &&
_cPasswordTextEditingController.text.isNotEmpty &&
_nameTextEditingController.text.isNotEmpty
?uploadToStorage() , _registerUser()
: displayDialog("Please fill up the registration complete form..")
: displayDialog("Password do not match.");
} else {
showDialog(
context: context,
builder: ((c) {
return ErrorAlertDialog(
message: "Please select an image.",
);
}));
}
}
the regiser user function :
FirebaseAuth _auth = FirebaseAuth.instance;
void _registerUser() async {
FirebaseUser firebaseUser;
await _auth
.createUserWithEmailAndPassword(
email: _emailTextEditingController.text.trim(),
password: _passwordTextEditingController.text.trim(),
)
.then((auth) {
firebaseUser = auth.user;
}).catchError((error) {
Navigator.pop(context);
showDialog(
context: context,
builder: (c) {
return ErrorAlertDialog(
message: error.message.toString(),
);
});
});
if (firebaseUser != null) {
saveUserInfoToFireStore(firebaseUser).then((value) {
Navigator.pop(context);
Route route = MaterialPageRoute(builder: (c) => StoreHome());
Navigator.pushReplacement(context, route);
});
}
}
Ps: i'm still new to this it's my third app with flutter
I have used this code to upload the user image from local storage to Firebase with uid as the reference name.
final _firebaseAuth = FirebaseAuth.instance;
FirebaseStorage firebaseStorage = FirebaseStorage.instance;
FirebaseFirestore firebaseFirestore = FirebaseFirestore.instance;
final imgPicker = ImagePicker();
File image;
String photoUrl = "";
bool _uploading = false;
uploadPic() async {
try {
setState(() {
_uploading = true;
});
// picking Image from local storage
final file = await imgPicker.getImage(
source: ImageSource.gallery,
);
if (file != null) {
image = File(file.path);
} else {
setState(() {
_uploading = false;
});
}
// creating ref at Firebase Storage with userID
Reference ref =
firebaseStorage.ref(_firebaseAuth.currentUser.uid).child("dp");
ref.putFile(image).whenComplete(() {
print("Pic Uploaded Successfully!");
setState(() {
_uploading = false;
});
// refreshing the UI when photo updated
getUploadedPic();
});
} catch (e) {
print(e);
}
}
After uploading you may get the image URL as follow:
getUploadedPic() async {
// getting dp URL link
photoUrl = await firebaseStorage
.ref("${_firebaseAuth.currentUser.uid}/dp")
.getDownloadURL()
.whenComplete(() => print("URL UPLOADED AT: $photoUrl"));
}

Trying to login with google but always return null

hey guys i trying to login with google using firebase in flutter but its always return null in the next page
how can i get the current user in the next page after login with google
i already connect with firebase and generate sha-1 and sha-256
here's the code
login button
onPressed: () async {
setState(() {
_isSigningIn = true;
});
try {
final user = await googleSignIn.signIn();
final googleAuth = await user.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken
);
final googleAccount = await FirebaseAuth.instance.signInWithCredential(credential);
if(googleAccount != null) {
Navigator.pushReplacementNamed(context, HomeScreen.id);
}
} catch (e) {
final snackbar = SnackBar(content: Text(e.toString()));
_scaffoldKey.currentState.showSnackBar(snackbar);
} finally {
setState(() {
_isSigningIn = false;
});
}
},
home_screen.dart
class _HomeScreenState extends State<HomeScreen> {
final _auth = FirebaseAuth.instance;
User _currentUser;
void getCurrentUser() async {
try {
var currentUser = await _auth.currentUser;
if (currentUser != null) {
_currentUser = currentUser;
}
} catch(e) {
print(e);
}
}
#override
void initState() {
super.initState();
getCurrentUser();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_currentUser.email),
),
);
}
}
thank you
This line is an asynchronous function, it is for this reason that you receive null, you must add an await.
final googleAccount = await FirebaseAuth.instance.signInWithCredential(credential);
In addition to this, to access the information of the current user you must do it this way.
googleAccount.user

Firestore: Data are Returned Back without the Right Favorite Items Status True or False

I have a flutter app and I am trying to fetch favorites data from cloud firestore database depending on userId.
The problem is that data are returned back without the right favorite items status true or false.
when I print favoriteData in console, I receive empty map like this: {}
Here is my code and how I tried to achieve this:
Future<void> fetchProducts() async {
final List<Product> loadedProducts = [];
var userId = await getCurrentUser();
final response = await Firestore
.instance
.collection("products")
.getDocuments();
final favoriteResponse = await Firestore.instance
.collection("userFavorites")
.document(userId)
.collection("MyFavorites")
.getDocuments();
final favoriteData = favoriteResponse.documents.asMap();
try{
print(favoriteData.toString());
response.documents.forEach((element) {
loadedProducts.add(Product(
id: element.documentID,
title: element.data['title'],
price: element.data['price'],
isFavorite: favoriteData == null ? false : favoriteData[element.documentID] ?? false,
));
});
_items = loadedProducts;
notifyListeners();
}catch(error){
print(error);
}
}
Here where I call fetchProducts which includes favourited items:
class _ProductsScreenState extends State<ProductsScreen> {
var _showOnlyFavorites = false;
var _isInit = true;
var _isLoading =false;
#override
void initState() {
super.initState();
}
#override
void didChangeDependencies() {
if(_isInit){
setState(() {
_isLoading = true;
});
Provider.of<Products>(context,listen: false).fetchProducts().then((_) {
setState(() {
_isLoading = false;
});
});
}
_isInit = false;
super.didChangeDependencies();
}
Here is a screenshot of documents I am trying to get their value:

How to obtain a specific field in a Firebase document

Trying to capture a specific field from my documents. Here is the code for the wrapper,
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
final user = Provider.of<User>(context);
print(user);
// return either the Home or Authenticate widget
if (user == null) {
return Authenticate();
} else {
return FirmHomePage();
}
}
}
and this is the code that we used for printing in the console.
void idss() async {
FirebaseUser userid = await FirebaseAuth.instance.currentUser();
var document = await Firestore.instance.collection('Users').getDocuments();
for (var document in document.documents) {
messagetext = document.data['JobType'];
usettype = messagetext;
print(messagetext);
}
}
We want to check our user to set a path for them.
FirebaseUser userid = await FirebaseAuth.instance.currentUser();
final QuerySnapshot result = await Firestore.instance.collection('Users')
.where('uid', isEqualTo: currentUser.uid) .getDocuments();
final List < DocumentSnapshot > documents = result.documents;
if (documents.length == 1) {
//your code here
}else{
//your code here
}

Firebase email verification Flutter

I know this question has been asked a lot and I have spent a lot of time reading and trying to implement the answers. So I am trying to get the response from isEmailVerified from Firebase Auth to work and it does work but right now it always returns false unless I refresh the app or close it and reopen it. which is obviously a bad user experience. How do I get the response to update without having to close the app.
here is the relevant pieces of code.
Future<bool> isEmailVerified() async {
FirebaseUser user = await _auth.currentUser();
if (user == null) {
return false;
} else {
await user.reload();
user = await _auth.currentUser();
return user.isEmailVerified;
}
}
main.dart
child: Consumer<Auth>(
builder: (_, auth, __) => MaterialApp(
theme: Provider.of<ThemeNotifier>(context).getTheme(),
home: FutureBuilder(
future: Future.wait([auth.isEmailVerified(), auth.tryAutoLogin()]),
builder: (BuildContext ctx, AsyncSnapshot authResultSnapshot) =>
authResultSnapshot.connectionState == ConnectionState.done
? authResultSnapshot.data[1]
? authResultSnapshot.data[0]
? HearingsScreen()
: SplashScreen(
emailVerified: true,
)
: LoginScreen()
: SplashScreen(),
),
It is not returning true until I restart the app
Things I have tried besides this:
1) await user.getIdToken(refresh: true);
2) sign user out then back in
3) firebase_user_stream package
Any help is appreciated.
I have implemented the same scenario in a splash screen with below code, you can change it as per your requirement. :
//To check is User is logged in
Future<bool> isLoggedIn() async {
FirebaseUser user = await _fireBaseAuth.currentUser();
if (user == null) {
return false;
}
return user.isEmailVerified;
}
and
countDownTime() async {
return Timer(
Duration(seconds: splashDuration),
() async {
if (await userAuth.isLoggedIn()) {
Navigator.pushReplacement(
context,
ScaleRoute(
widget: HomeScreen(),),
);
}
} else {
Navigator.pushReplacement(
context,
ScaleRoute(
widget: LoginScreen(),),
);
}
},
);
}
and
#override
void initState() {
super.initState();
countDownTime();
}
Update
One needs to implement isEmailVerified in initState() function periodically which can be the ideal approach to execute the verification with firebase.
bool _isUserEmailVerified;
Timer _timer;
#override
void initState() {
super.initState();
// ... any code here ...
Future(() async {
_timer = Timer.periodic(Duration(seconds: 10), (timer) async {
await FirebaseAuth.instance.currentUser()..reload();
var user = await FirebaseAuth.instance.currentUser();
if (user.isEmailVerified) {
setState((){
_isUserEmailVerified = user.isEmailVerified;
});
timer.cancel();
}
});
});
}
#override
void dispose() {
super.dispose();
if (_timer != null) {
_timer.cancel();
}
}

Resources