Search code examples
firebasefluttergoogle-cloud-firestoretimestampchat

Order chat messages with timestamps


This is a chat app, I trying to order the messages uploaded to firestore db with timestamp to show the last messages descending on the listView, but I after I add the 'timestamp' field to collection and call .orderBy(Timestamp.now().toDate().toString(), descending: true) I see empty screen!, even though I see the messgese in firbaase firestore console "on web"

enter image description here

enter image description here

here when the user send new message

TextButton(
           onPressed: () {
           //Implement send functionality.
           messageEditController.clear();
           _firestore.collection('messages').add({
           'sender': _loggedInUser.email,
           'text': messageText,
            'timestamp': Timestamp.now().toString(),
            });
         },

MessagesStream class

class MessagesStream extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return StreamBuilder<QuerySnapshot>(
      stream: _firestore
          .collection('messages')
          .orderBy(Timestamp.now().toDate().toString(), descending: true)
          .snapshots(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(
            child: CircularProgressIndicator(
              backgroundColor: Colors.lightBlueAccent,
            ),
          );
        } else if (snapshot.hasData) {
          final messages = snapshot.data.docs;

          List<MessageBubble> messageBubbles = [];

          for (var message in messages) {
            final messageSender = message.data()['sender'];
            final messageText = message.data()['text'];

            final currentUser = _loggedInUser.email;

            if (currentUser == messageSender) {
              // mwssage from logged in user
            }

            // ignore: missing_return
            final messageBubble = MessageBubble(
              sender: messageSender,
              text: messageText,
              isMe: currentUser == messageSender,
            );

            messageBubbles.add(messageBubble);
          }
          return Expanded(
            child: ListView(
              padding: EdgeInsets.symmetric(vertical: 20, horizontal: 10),
              children: messageBubbles,
            ),
          );
        } else if (snapshot.hasError) {
          return Expanded(
            child: Container(
              child: Text(snapshot.hasError.toString()),
            ),
          );
        }
      },
    );

Solution

  • The orderBy does not accept values but field names to work properly.

    Try changing this part of your code to:

    _firestore
              .collection('messages')
              .orderBy('timestamp', descending: true)
              .snapshots()
    

    I would also recommend to save the timestamp value like so:

    TextButton(
               onPressed: () {
               //Implement send functionality.
               messageEditController.clear();
               _firestore.collection('messages').add({
               'sender': _loggedInUser.email,
               'text': messageText,
                'timestamp': new DateTime.now(),
                });
             },
    

    Othervise you just save a string that will not be ordered as you expect a timestamp to be ordered. If you save it only as string it will be ordered by string order and not by the real timestamp as you would like it to be.