Display Firestore map data in Flutter - flutter

I am building a password manager and I'm trying to save on Firestore reads by displaying data in Map. The idea is to have a document (for each password category) and have the passwords stored as maps in it. See example screenshots here:
The idea is that users click on each password (map) and the app takes them to the relevant one using indexes. I then want the data from each map to be sorted separately so that they can live in their own Text widgets. But I haven't seen any possibility of displaying map data in Flutter yet.
I've tried some of the examples from here but haven't been able to display the data from the map - https://github.com/fireship-io/flutter-base/blob/master/lib/main.dart
Any suggestions would be much appreciated.
new StreamBuilder(
stream: Firestore.instance
.collection('users')
.document(userDocSTRING.toString())
.collection(userPassSTRING.toString())
.snapshots(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
// If no data is present, display a waiting indicator to the user
// If Null, red screen displays
return Center(child: CircularProgressIndicator());
} else {
// Debug print for Ryan
// print(snapshot.data[0].data.toString());
return new ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot documentSnapshot =
snapshot.data.documents[index];
return ListTile(
leading: Container(
child: IconButton(
icon: Icon(Icons.content_copy),
color: lightCardCOLOR,
title: Text(documentSnapshot['Name']
As you can see from the code above, fetching fields from documents is easy enough but I don't want each password to have it's own document. I want a document to hold multiple Maps which corresponds to a password. So documentSnapshot['Name'] I want to be the name or value of a map

I'll suggest that your attempt to "save on Firestore reads" is making it more difficult for you to model and display the data. It also won't scale, since the maximum size of a document is 1MB. Consider storing each password in a different document to make this easier. Document reads are not really very expensive, and the Firebase SDK will cache them locally to avoid the cost of reads when queried.

Related

Issue in firestore database

I want to show current user data in my flutter app. But it print on screen " No data found".
This my database data
That error also happened error
My security rule
enter image description here
Here is my code
Container(
child: StreamBuilder(
stream: FirebaseFirestore.instance.collection("user3").where("id",isEqualTo:FirebaseAuth.instance.currentUser!.uid).snapshots(),
builder: (BuildContext context,AsyncSnapshot<QuerySnapshot> snapshot){
if(!snapshot.hasData){
return Text("Loading please wait........");
}
if (snapshot.hasData && snapshot.data!.docs.length > 0) {
DocumentSnapshot userData = snapshot.data!.docs[0];
// Build the widget using the userData
} else {
return Center(child: Text("No data found"));
}
return Container();
},
),
),
The long numeric values (e.g. "167582...") in your database screenshot do not look like a UID that any of the Firebase Authentication providers would generate.
Add this code right before you query the database:
print(FirebaseAuth.instance.currentUser!.uid)
This will show you the value that you're querying for, which (given my opening statement) probably looks quite different from the value in your database.
If that is indeed the case, the problem starts when you write the document. At that point you'll want to make sure that you write the value of FirebaseAuth.instance.currentUser!.uid to the id field.

Need I do pagination for flutter StreamBuilder?

I'm new to flutter, and now I'm creating an app which has a feed page, I'm using StreamBuilder + firestore to do this, the code is like this:
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('posts')
.orderBy('createdAt', descending: true)
.snapshots(),
builder: (context,
AsyncSnapshot<QuerySnapshot<Map<String, dynamic>>> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(
color: primaryColor,
),
);
}
return ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) => Container(
child: createPostViewFromSnapShot(snapshot.data!.docs[index]),// it returns a widget
),
);
},
);
You can see from the code I didn't do pagination, I want to know when the code runs, it fetch all the post from firestore ? Or it will fetch data by block or something like pagination ?
I want to know if it's necessary to do pagination for StreamBuilder?
Avoid creating Widgets in Methods. That way you cause your App to
become I'm-performant. Because the Widget is not sat directly in the
Tree, but a method, every build that methods gets called, no matter
if the resulting widget would have to be actually be rebuilt.
That stream will not always emit events where data is not null. You will most likely get an exception for using snapshot.data! bang operator
Take a closer look at the documentation: https://firebase.flutter.dev/docs/firestore/usage/
FlutterFire provides support for dealing with realtime changes to
collections and documents. A new event is provided on the initial
request, and any subsequent changes to collection/document whenever a
change occurs (modification, deleted or added).
For what you are trying to achieve, it would be better to initially fetch a limited set of documents from your collection.
collectionReference.limit(42).get()
You can than fetch the next elements by using https://firebase.flutter.dev/docs/firestore/usage/#start--end-cursors

How to create chatRoom with flutter and firestore

I have created a chat with flutter and I need to use into my app, where 1group of user will chat with another kind of user group.
At the moment my chat is developed in this manner and I create record in firebase so:
CollectionReference addMessage = FirebaseFirestore.instance.collection('Messages');
Future<void> createMessageRecord() {
return addMessage
.add(
{ 'id': firebaseUser.uid,
'text': textMessage,
'timeStamp': DateTime.now().millisecondsSinceEpoch.toString(),
},
)
I retrieve them:
StreamBuilder(
stream: FirebaseFirestore.instance.collection('Messages').orderBy('timeStamp', descending: true).snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData)
return Center(child: CircularProgressIndicator());
I display them:
ListView.builder(
reverse: true,
padding: EdgeInsets.only(top: 15.0),
itemCount: snapshot.data.docs.length,
itemBuilder: (BuildContext context, int index) {
final message = snapshot.data.docs[index];
final bool isMe = message['id'] == firebaseUser.uid;
return _buildMessage(message, isMe);
the chat works pretty good but all users of course will have the same chat.
What I want to do is limit the chat displaying just for the 2 users.
the first one who starts the chat and and second one who get.
At the moment I have created into firestore a collection called "Messages" and into I have the 3 documents id text timeStamp```
I dont know how to limit the displaying data just for this 2 users
Instead of having one single document for all of the messages create a document per conversaiton this way you will only retrive the corresponding messages.
Also as mentioned on the comment by #Uni you shoudl be using realtime database also you can take a look at several examples on the web on how to accomplish that. for example

Is there a way to get StreamBuilder to load content slightly before the user scrolls down to it to reduce delay (Flutter)?

Currently my app loads the information (including pictures) into cards from Cloud Firestore, but it only starts loading the information when it appears on the user's screen. I used FadeInImage in _makeCard to make it a bit more usable while loading, but it's still too slow. Is there a way to make StreamBuilder load, for example, the nearest 10 cards that are off the screen? If not, is there a better way to create a list that is loaded from Firestore? This is my code currently:
StreamBuilder(
stream: Firestore.instance.collection('Cards').snapshots(),
builder: (context, snapshot) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return _makeCard(context, snapshot.data.documents[index]);
},
childCount:
snapshot.hasData ? snapshot.data.documents.length : 0,
),
);
})
I don't have a lot of experience with coding, so let me know if there is anything I can clarify.

How can I query another collection inside a streambuilder that queries a different collection?

I'm trying to query a document field from a different firestore collection than the one of the streambuilder. Right now, with the streambuilder I am able to query one of the documents i need, however I don't how i'm to query another collection in that same stream builder. I thought about using a global variable from another class where I had already queried the document I want but that didn't seem to work.
This is the stream builder
Container(
height: MediaQuery.of(context).size.height,
margin: EdgeInsets.only(top: 0),
padding: EdgeInsets.only(top: 0),
child: StreamBuilder(
stream: Firestore.instance
.collection('Tournaments')
.document('Fortnite Tournaments')
.collection('Fortnite Tourneys')
.document(docID)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return new Text("Loading");
}
var tourneyDetails = snapshot.data;
return ListView(
children: <Widget>[
..........
The collection i'm trying to query is called "users"
Why i need to query a field in a different collection is because i'm writing an if statement that needs both of the fields
if (int.parse("Field_i_am_trying_to_get_from_another_collection") > int.parse(tourneyDetails[ 'tourneycost']))
print('You have the money');
else {
print('You're broke');
}
That condition is going to be executed when the raised button is clicked. Essentially, My problem is that I am currently not sure how I can query the data from that other collection.
Not sure if i explained that well but comment if you need more context or code, Thanks.
You can use provider instead of creating global variable.
see Provider package: https://pub.dev/packages/provider
if the current user is the user you want, then you can take the current user data from firestore when the app is loading and provide the user to where you want to use.
see this article if you don't know what provider is:
Flutter StateManagement with Provider