import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/foundation.dart' show debugPrint; import '../../constants.dart'; import '../../utils/helper.dart'; import '../../models/message.dart'; class ChatService { final FirebaseFirestore _firestore = FirebaseFirestore.instance; final FirebaseAuth _auth = FirebaseAuth.instance; // send message Future sendMessage(String receiverID, message) async { // get current user info final String currentUserID = _auth.currentUser!.uid; final String currentUserEmail = _auth.currentUser!.email!; final Timestamp timestamp = Timestamp.now(); // create new message Message newMessage = Message( senderID: currentUserID, senderEmail: currentUserEmail, receiverID: receiverID, message: message, timestamp: timestamp, ); // construct chat room ID for the two users String chatRoomID = getCompoundId([currentUserID, receiverID]); // create batch to add message and update last message details in one step WriteBatch batch = _firestore.batch(); // add new message to database var newMessageRef = _firestore .collection(Constants.dbCollectionChatRooms) .doc(chatRoomID) .collection(Constants.dbCollectionMessages) .doc(); // doc generates a random ID for the message batch.set(newMessageRef, newMessage.toMap()); // update last message details in chat room var chatRoomRef = _firestore.collection(Constants.dbCollectionChatRooms).doc(chatRoomID); // add to batch above batch.set( chatRoomRef, { Constants.dbFieldMessageSenderId: currentUserID, Constants.dbFieldMessageSenderEmail: currentUserEmail, Constants.dbFieldMessageTimestamp: timestamp, }, SetOptions(merge: true)); // commit batch await batch.commit(); } /// Retrieves a stream of the last message of a chatroom. Stream getLastMessageStream(String chatRoomID) { return _firestore .collection(Constants.dbCollectionChatRooms) .doc(chatRoomID) .collection(Constants.dbCollectionMessages) .orderBy(Constants.dbFieldMessageTimestamp, descending: true) .limit(1) .snapshots() .map((snapshot) { if (snapshot.docs.isEmpty) { return null; } var lastMessageDoc = snapshot.docs.first; return Message.fromMap(lastMessageDoc.data()); }); } /// Retrieves the last message of a chatroom. /// /// Returns [null] in case of an error. Future getLastMessage(String chatRoomID) async { String senderID = ''; String senderEmail = ''; String receiverID = ''; String message = ''; Timestamp timestamp = Timestamp.fromMillisecondsSinceEpoch(0); try { QuerySnapshot messageSnapshot = await _firestore .collection(Constants.dbCollectionChatRooms) .doc(chatRoomID) .collection(Constants.dbCollectionMessages) .orderBy(Constants.dbFieldMessageTimestamp, descending: true) .limit(1) .get(); if(messageSnapshot.docs.isNotEmpty) { DocumentSnapshot lastMessageDoc = messageSnapshot.docs.first; if (lastMessageDoc.exists) { senderID = lastMessageDoc[Constants.dbFieldMessageSenderId]; senderEmail = lastMessageDoc[Constants.dbFieldMessageSenderEmail]; receiverID = lastMessageDoc[Constants.dbFieldMessageReceiverId]; message = lastMessageDoc[Constants.dbFieldMessageText]; timestamp = lastMessageDoc[Constants.dbFieldMessageTimestamp]; } } else { debugPrint('Info: getLastMessage -> messageSnapshot is EMPTY'); } } catch (e) { debugPrint('Error on getLastMessage: ${e.toString()}'); return null; } return Message( senderID: senderID, senderEmail: senderEmail, receiverID: receiverID, message: message, timestamp: timestamp, ); } // get messages Stream getMessages(String userID, otherUserID) { String chatRoomID = getCompoundId([userID, otherUserID]); return _firestore .collection(Constants.dbCollectionChatRooms) .doc(chatRoomID) .collection(Constants.dbCollectionMessages) .orderBy(Constants.dbFieldMessageTimestamp, descending: false) .snapshots(); } }