繁体   English   中英

Flutter Firestore 如何显示我最近聊天的人的列表

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM