I have created a chat application using flutter and store data in Firebase .Firebase contains two collections .One collection contains user details and another one collection contains user chats with other user.I want to merge two collection details .How to get other user details stored in user collections? I have attached with screenshots. Firebase collection Flutter code
Asked
Active
Viewed 1,051 times
2
-
There are no "join" type queries in Firestore. You will have to query each collection separately and merge the data in the client app. – Doug Stevenson Jun 03 '20 at 05:37
1 Answers
0
I have the same thing implemented in my Application. What I did is I use the Streambuilder widget twice, one to pull the chats, each and every chat contains a sender_id, which I then use the Id in the second Stream builder to pull user info.
Check the code below.
This is all chats page:
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('MyChatHeads')
.doc(_onlineUserId)
.collection('Heads')
.orderBy('head_time', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Scaffold(
body: Center(
child: SpinKitThreeBounce(
color: Colors.black54,
size: 20.0,
),
),
);
} else {
if (snapshot.data.documents.length == 0) {
return Scaffold(
body: placeHolder(),
);
placeHolder();
} else {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (_) => SearchUsersPage(
userId: _onlineUserId,
),
),
);
},
child: Icon(Icons.contacts_rounded),
foregroundColor: Colors.white,
backgroundColor: Color(0xff47c8b0),
),
body: ListView.builder(
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot myChatHeads = snapshot.data.documents[index];
return chatHeadItem(
index, myChatHeads, snapshot.data.documents.length);
},
),
);
}
}
},
);
}
The item in all chats page
Widget chatHeadItem(int index, DocumentSnapshot myChatHeads, int length) {
return StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Users')
.where('user_id', isEqualTo: myChatHeads['head_subject'])
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: SpinKitThreeBounce(
color: Colors.black54,
size: 20.0,
),
);
} else {
if (snapshot.data.documents.length == 0) {
return Container(
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Row(
children: [
CircleAvatar(
radius: 30,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
child: Image(
height: 56,
width: 56,
image: AssetImage('assets/images/holder.png'),
fit: BoxFit.cover,
),
),
),
SizedBox(
width: 10,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10,
),
Text(
'User not found',
style: GoogleFonts.quicksand(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 16.0,
letterSpacing: .5,
),
),
//setCompanyName(myInterviews),
SizedBox(
height: 4.0,
),
InkWell(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (_) => ChatsEngagePage(
userId: _onlineUserId,
secondUserId: myChatHeads['head_subject'],
),
),
);
},
child: Text(
'${myChatHeads['head_last_message']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.quicksand(
color: Colors.black87,
fontSize: 16.0,
letterSpacing: .5,
),
),
),
SizedBox(
height: 10,
),
],
),
),
],
),
),
);
} else {
DocumentSnapshot secondUserInfo = snapshot.data.documents[0];
return Container(
//color: Colors.green,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16.0,
),
child: Column(
children: [
index == 0
? SizedBox(
height: 6,
)
: SizedBox(
height: 0,
),
InkWell(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (_) => ChatsEngagePage(
userId: _onlineUserId,
secondUserId: myChatHeads['head_subject'],
userName: secondUserInfo['user_name'],
userImage: secondUserInfo['user_image'],
),
),
);
},
child: Row(
children: [
InkWell(
onTap: () {
Navigator.push(
context,
CupertinoPageRoute(
builder: (_) => PublicProfilePage(
userId: _onlineUserId,
secondUserId: secondUserInfo['user_id'],
),
),
);
},
child: CachedNetworkImage(
imageUrl: secondUserInfo['user_image'],
imageBuilder: (context, imageProvider) =>
CircleAvatar(
radius: 30,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage: imageProvider,
),
),
placeholder: (context, url) => CircleAvatar(
radius: 30,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage: AssetImage(
'assets/images/holder.png',
),
),
),
errorWidget: (context, url, error) =>
CircleAvatar(
radius: 30,
backgroundColor: Colors.green,
child: CircleAvatar(
radius: 28,
backgroundColor: Colors.white,
backgroundImage: AssetImage(
'assets/images/holder.png',
),
),
),
),
),
SizedBox(
width: 10,
),
Flexible(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 10,
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Text(
'${secondUserInfo['user_name']}',
style: GoogleFonts.quicksand(
color: Colors.black87,
fontWeight: FontWeight.bold,
fontSize: 16.0,
letterSpacing: .5,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
Text(
timeAgoSinceDateEn(
DateTime.fromMillisecondsSinceEpoch(
myChatHeads['head_time'],
).toString(),
),
//postSnap['press_formatted_date'],
style: GoogleFonts.quicksand(
textStyle: TextStyle(
fontSize: 14.0,
color: Colors.grey,
),
),
),
],
),
//setCompanyName(myInterviews),
SizedBox(
height: 4.0,
),
Text(
'${myChatHeads['head_last_message']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: GoogleFonts.quicksand(
color: Colors.black87,
fontSize: 16.0,
letterSpacing: .5,
),
),
SizedBox(
height: 10,
),
],
),
),
],
),
),
index == length - 1
? Container()
: Divider(
//color: Colors.red,
),
index == length - 1
? SizedBox(
height: 4,
)
: SizedBox(
height: 0,
),
],
),
),
);
}
}
},
);
}
This is a single chat page:
body: Stack(
children: [
Container(
height: double.infinity,
width: double.infinity,
color: Colors.grey[100],
child: StreamBuilder(
stream: FirebaseFirestore.instance
.collection('Chats')
.doc(userId)
.collection(secondUserId)
.orderBy('message_time', descending: true)
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: SpinKitThreeBounce(
color: Colors.black54,
size: 20.0,
),
),
);
} else {
if (snapshot.data.documents.length == 0) {
return Center(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Container(
width: MediaQuery.of(context).size.width / 3,
child: Image(
image: AssetImage('assets/images/empty.png'),
width: double.infinity,
),
),
),
);
} else {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: ListView.builder(
shrinkWrap: true,
reverse: true,
// physics: NeverScrollableScrollPhysics(),
// primary: false,
padding: EdgeInsets.zero,
itemCount: snapshot.data.documents.length,
itemBuilder: (context, index) {
DocumentSnapshot myPresses =
snapshot.data.documents[index];
if (myPresses['message_owner'] == userId) {
return Padding(
padding: index == 0
? EdgeInsets.only(bottom: height + 26)
: EdgeInsets.only(bottom: 0),
child: Bubble(
margin: BubbleEdges.only(top: 10),
nip: BubbleNip.rightTop,
alignment: Alignment.topRight,
color: Colors.lightGreen[100],
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
myPresses['message_body'],
style: GoogleFonts.quicksand(
fontSize: 16,
color: Colors.black87,
),
),
Text(
timeAgoSinceDateEn(
DateTime.fromMillisecondsSinceEpoch(
myPresses['message_time'],
).toString(),
),
//postSnap['press_formatted_date'],
style: GoogleFonts.quicksand(
textStyle: TextStyle(
fontSize: 14.0,
color: Colors.grey,
),
),
),
],
),
),
);
} else {
return Padding(
padding: index == 0
? EdgeInsets.only(bottom: height + 26)
: EdgeInsets.only(bottom: 0),
child: Bubble(
margin: BubbleEdges.only(top: 10),
alignment: Alignment.topLeft,
nip: BubbleNip.leftTop,
color: Color(0xffd4eaf5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Text(
myPresses['message_body'],
style: GoogleFonts.quicksand(
fontSize: 16,
color: Colors.black87,
),
),
Text(
timeAgoSinceDateEn(
DateTime.fromMillisecondsSinceEpoch(
myPresses['message_time'],
).toString(),
),
//postSnap['press_formatted_date'],
style: GoogleFonts.quicksand(
textStyle: TextStyle(
fontSize: 14.0,
color: Colors.grey,
),
),
),
],
),
),
);
}
},
),
);
}
}
},
),
),
Positioned(
bottom: 10.0,
left: 10.0,
right: 10.0,
child: MeasuredSize(
onChange: (Size size) {
setState(() {
print(size);
height = size.height;
});
},
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(0),
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.4),
spreadRadius: 2,
blurRadius: 3,
offset: Offset(0, 2), // changes position of shadow
),
],
),
//height: 58,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8.0, vertical: 8.0),
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Expanded(
child: TextFormField(
controller: textEditingController,
keyboardType: TextInputType.multiline,
textCapitalization: TextCapitalization.sentences,
maxLength: 800,
maxLines: null,
style: GoogleFonts.quicksand(
textStyle: TextStyle(
fontSize: 14.0,
color: Colors.black54,
letterSpacing: .5,
),
),
decoration: InputDecoration(
labelText: 'Message',
contentPadding: const EdgeInsets.symmetric(
horizontal: 0.0, vertical: 0.0),
errorStyle: TextStyle(color: Colors.brown),
),
onChanged: (val) {
setState(() => _message = val);
},
validator: (val) =>
val.length < 1 ? ('Too short') : null,
),
),
SizedBox(
width: 16,
),
InkWell(
onTap: () {
_submitMessage();
},
child: Padding(
padding:
const EdgeInsets.only(right: 8.0, bottom: 20),
child: Icon(
Icons.send_rounded,
color: Colors.green,
),
),
),
],
),
),
),
),
),
],
),

Dharman
- 30,962
- 25
- 85
- 135

Francisca Mkina
- 502
- 7
- 15