![](/img/trans.png)
[英]Flutter Firestore How to list people I only have chat history with?
[英]Flutter Firestore how to show the list of people i have recently chat with
希望一切都好我正在开发一个 flutter 应用程序,在该应用程序中我卡在了聊天模块中,聊天工作正常并且也可以发送消息。 但我想在聊天屏幕页面上显示我最近聊天的人。
当我们与某人聊天时,就像 messenger whats 应用程序一样,它会出现在这样的聊天屏幕上。
这是我的聊天室屏幕
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/services.dart';
import 'package:flutter_chat_ui/flutter_chat_ui.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:uuid/uuid.dart';
class chatroom extends StatelessWidget {
final Map<String, dynamic> userMap;
final String chatRoomId;
chatroom({required this.chatRoomId, required this.userMap});
final TextEditingController _message = TextEditingController();
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
File? imageFile;
Future getImage() async {
ImagePicker _picker = ImagePicker();
await _picker.pickImage(source: ImageSource.gallery).then((xFile) {
if (xFile != null) {
imageFile = File(xFile.path);
uploadImage();
}
});
}
Future uploadImage() async {
String fileName = Uuid().v1();
int status = 1;
await _firestore
.collection("chatroom")
.doc(chatRoomId)
.collection('chats')
.doc(fileName)
.set({
"sendBy": _auth.currentUser!.displayName,
"message":"",
"type":"img",
"time": FieldValue.serverTimestamp(),
});
var ref =
FirebaseStorage.instance.ref().child('images').child("$fileName.jpg");
var uploadTask = await ref.putFile(imageFile!).catchError((error) async{
await _firestore
.collection("chatroom")
.doc(chatRoomId)
.collection('chats')
.doc(fileName).delete();
status = 0 ;
});
if(status==1){
String imageUrl = await uploadTask.ref.getDownloadURL();
await _firestore
.collection("chatroom")
.doc(chatRoomId)
.collection('chats')
.doc(fileName).update({
"message": imageUrl,
});
print(imageUrl);
}
}
void onSendMessage() async {
if (_message.text.isNotEmpty) {
Map<String, dynamic> messages = {
"sendBy": _auth.currentUser!.displayName,
"message": _message.text,
"type": "text",
"time": FieldValue.serverTimestamp(),
};
await _firestore
.collection('chatroom')
.doc(chatRoomId)
.collection('chats')
.add(messages);
_message.clear();
} else {
print("Enter Some Text");
}
}
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
return Scaffold(
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.black,
title: Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 0),
child: StreamBuilder<DocumentSnapshot>(
stream: _firestore
.collection("registration")
.doc(userMap['uid'])
.snapshots(),
builder: (context, snapshot) {
if (snapshot.data != null) {
return Container(
child: Column(
children: [
Text(
userMap['name'],
style: GoogleFonts.roboto(
color: Colors.white,
fontSize: 18,
),
),
Padding(
padding: const EdgeInsets.only(right: 100),
child: Text(
snapshot.data!['status'],
style: GoogleFonts.roboto(
color: Colors.white,
fontSize: 14,
),
),
),
],
),
);
} else {
return Container();
}
},
),
),
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: size.height / 1.25,
width: size.width,
child: StreamBuilder<QuerySnapshot>(
stream: _firestore
.collection('chatroom')
.doc(chatRoomId)
.collection('chats')
.orderBy("time", descending: false)
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.data != null) {
return ListView.builder(
itemCount: snapshot.data?.docs.length,
itemBuilder: (context, index) {
Map<String, dynamic> map = snapshot.data!.docs[index]
.data() as Map<String, dynamic>;
return messages(size, map,context);
},
);
} else {
return Container();
}
},
),
),
],
),
),
bottomNavigationBar: Container(
color: Colors.white,
height: size.height / 10,
width: size.width,
alignment: Alignment.center,
child: Container(
height: size.height / 12,
width: size.width / 1.1,
child: Row(
children: [
Container(
height: size.height / 17,
width: size.width / 1.3,
child: TextField(
controller: _message,
decoration: InputDecoration(
suffixIcon: IconButton(
onPressed: () => getImage(),
icon: Icon(Icons.photo),
),
hintText: "Send Message",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
),
),
),
),
IconButton(
onPressed: onSendMessage,
icon: Icon(Icons.send),
)
],
),
),
),
);
}
Widget messages(Size size, Map<String, dynamic> map, BuildContext context) {
return map['type'] == "text"
? Container(
width: size.width,
alignment: map['sendBy'] == _auth.currentUser!.displayName
? Alignment.centerRight
: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
padding: EdgeInsets.symmetric(vertical: 10, horizontal: 14),
margin: EdgeInsets.symmetric(vertical: 5, horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(15),
color: Colors.blue,
),
child: Text(
map['message'],
style: GoogleFonts.roboto(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
),
)
: Container(
height: size.height / 2.5,
width: size.width,
padding: EdgeInsets.symmetric(vertical: 5,horizontal: 5),
alignment: map['sendBy'] == _auth.currentUser!.displayName
? Alignment.centerRight
: Alignment.centerLeft,
child: InkWell(
onTap: () => Navigator.of(context).push(
MaterialPageRoute(builder: (_)=> ShowImage(imageURl: map['message'],
),
),
),
child: Container(
height: size.height / 2.5,
width: size.width / 2,
decoration: BoxDecoration(
border: Border.all(),
),
alignment: map['message']!="" ? null :Alignment.center,
child: map['message'] != ""
? Image.network(map['message'],fit: BoxFit.cover,)
: CircularProgressIndicator(),
),
),
);
}
}
class ShowImage extends StatelessWidget {
final imageURl;
const ShowImage({required this.imageURl, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final Size size = MediaQuery.of(context).size;
return Scaffold(
body: Container(
height: size.height,
width: size.width,
color: Colors.black,
child: Image.network(imageURl),
),
);
}
}
这是我的聊天主屏幕
import 'package:bpe_application/chat/chatroom.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_fonts/google_fonts.dart';
class Conversation extends StatefulWidget {
@override
_ConversationState createState() => _ConversationState();
}
class _ConversationState extends State<Conversation> with WidgetsBindingObserver {
late final String chatRoomId;
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
@override
void initState() {
// TODO: implement initState
super.initState();
WidgetsBinding.instance.addObserver(this);
setStatus("Online");
}
void setStatus(String status) async{
await _firestore.collection('registration').doc(_auth.currentUser!.uid).update({
"status": status,
});
}
@override
void didChangeAppLifecycleState(AppLifecycleState state){
if (state == AppLifecycleState.resumed){
//online
setStatus("Online");
}else{
//offline
setStatus("Offline");
}
}
final FirebaseAuth _auth = FirebaseAuth.instance;
Map<String, dynamic>? userMap;
bool isLoading= false;
final TextEditingController _search = TextEditingController();
ScrollController scrollController = ScrollController();
String chatroomId(String user1, String user2){
if(user1[0].toLowerCase().codeUnits[0] > user2.toLowerCase().codeUnits[0]){
return "$user1$user2";
}else{
return "$user2$user1";
}
}
void onSearch() async {
FirebaseFirestore _firestore = FirebaseFirestore.instance;
setState(() {
isLoading = true;
});
await _firestore.collection("registration").
where("email", isEqualTo: _search.text).
get().then((value) {
setState(() {
userMap= value.docs[0].data();
isLoading=false;
});
print(userMap);
}
);
}
void listView() async {
FirebaseFirestore _firestore = FirebaseFirestore.instance;
setState(() {
isLoading = true;
});
await _firestore.collection("registration").
where("email", isEqualTo: _search.text).
get().then((value) {
setState(() {
userMap= value.docs[0].data();
isLoading=false;
});
print(userMap);
}
);
}
@override
Widget build(BuildContext context) {
final size= MediaQuery.of(context).size;
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent, //top bar color
systemNavigationBarColor: Colors.black, //bottom bar color
systemNavigationBarIconBrightness: Brightness.dark,
));
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
elevation: 0.0,
backgroundColor: Colors.transparent,
title: Padding(
padding: const EdgeInsets.fromLTRB(70, 0, 0, 0),
child: Text(
"Chat",
style: GoogleFonts.limelight(color: Colors.white),
),
),
),
body: isLoading? Center(
child: Container(
height: size.height/20,
width: size.width/20,
child: CircularProgressIndicator(),
),
)
: ClipRRect(
borderRadius: new BorderRadius.only(
topLeft: const Radius.circular(40.0),
topRight: const Radius.circular(40.0),
),
child: Container(
height: 800.0,
width: double.infinity,
color: Colors.grey.shade200,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(mainAxisSize: MainAxisSize.min, children: [
SizedBox(
height: 10,
),
Container(
height: size.height/14,
width: size.width,
alignment: Alignment.center,
child: Container(
height: size.height/14,
width: size.width/1.2,
child: TextField(
controller: _search,
decoration: InputDecoration(
hintText: "Search",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
)
),
),
),
),
SizedBox(
height: size.height/70,
),
ElevatedButton(
onPressed: onSearch,
child: Text(
"Search",style: GoogleFonts.roboto(
color: Colors.white,
),
),
),
SizedBox(
height: size.height/60,
),
userMap != null
? ListTile(
onTap: () {
String roomId = chatroomId(
_auth.currentUser!.displayName!,
userMap!['name']);
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => chatroom(
chatRoomId: roomId,
userMap: userMap!,
),
),
);
},
leading: Icon(
Icons.account_box,
color: Colors.black,
),
title: Text(
userMap!['name'],
style: GoogleFonts.roboto(
color: Colors.black,
fontSize: 17,
fontWeight: FontWeight.w500,
),
),
subtitle: Text(userMap!['email']),
trailing: Icon(
Icons.chat,
color: Colors.black,
),
)
: Container(),
],
),
),
),
),
);
}
}
我没有使用共享偏好,它没有共享偏好,并且仅在我搜索时显示人员。 想要显示最近与我聊天的人,以及搜索功能。
Firebase图像 在此处输入图像描述
请再次注意我没有使用共享首选项
正如评论员所评论的那样:
每次向收件人发送消息时,请始终提取收件人的userID
,然后将recipientUserId
存储在一个集合中,如下所示:
_firestore.collection("users")
.doc(your_uid)
.collection(<your_conversation_subcollection>)
.document(recipientUserID).set(recipientDetails);
您可以使用recipientDetails
详细信息中的timestamp
字段来跟踪消息的发送时间。
然后,您可以使用他们的recipientUserId
查询到目前为止与您聊天的所有收件人的消息子集合。
您可以使用.orderBy('timestamp')
按时间戳对结果进行排序
有关更多信息,请参阅文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.