skip to Main Content

I am having trouble by getting my messages stored in realtime db in order.

Here’s my db structure

messages: {
  $chatId: {
     $messageId: {
       timestamp: 1664884736728,
       sender:"36a72WVw4weQEoXfk3T9gCtOL9n2",
       message: "Hello world"
     }
  }
}

This is my chat repository

  //get all messages of a chat
  Query getMessages(String chatId) {
    //get all messages of a chat
    final messages = _database.ref().child("messages/$chatId");
    //return all messages of a chat
    return messages;
  }
}

and this is how I am displaying it

StreamBuilder(
                stream: _chatRepository.getMessages(chatId).onValue,
                builder: (context, AsyncSnapshot snapshot) {
                  if (snapshot.data != null &&
                      snapshot.data?.snapshot?.value != null &&
                      snapshot.hasData) {
                    final messages = Map.from(snapshot.data?.snapshot.value as Map);
                    return ListView.builder(
                      itemCount: messages.length,
                      scrollDirection: Axis.vertical,
                      itemBuilder: (context, index) {
                        final currChat = messages.values.toList()[index];
                        return BubbleCustom(...),
                        );
                      },
                    );
                  }
                  return Container();
                },
              ),

This is my index in realTimeDB


{
  "rules": {
    "messages": {
      "$chatId": {
        ".indexOn": ["timestamp"]
      }
    }
  }
}

I need to get them in timestamp order. Is there any way I can do this? I hope you can help me. Thanks in advance!

2

Answers


  1. Chosen as BEST ANSWER

    I solved it by doing it in the frontend like this:

      final messages = Map.from(snapshot.data?.snapshot.value as Map);
                      //sort messages by timestamp ascending order
                      final messagesList = messages.values.toList();
                      messagesList.sort((a, b) => a["timestamp"].compareTo(b["timestamp"]));
                      final newMessagelist = List.from(messagesList.reversed);
       return ListView.builder(
                        physics: const BouncingScrollPhysics(),
                        reverse: true,
                        itemCount: newMessagelist.length,
                        scrollDirection: Axis.vertical,
                        itemBuilder: (context, index) {
                          final currChat = newMessagelist[index];
                          return BubbleCustom(
                            text: currChat["message"],
                            isSender: currChat["sender"] == senderUser.id,
                            tail: true,
                            textStyle: TextStyle(
                              fontSize: 16,
                              color: currChat["sender"] == senderUser.id ? Colors.white : Colors.black,
                            ),
                          );
                        },
                      );
    

    with reverse: true and inverting the list before I render it.


  2. You can use orderByChild to get the messages in the order of a specific child. So there that’d be:

    stream: _chatRepository.getMessages(chatId).orderByChild('timestamp').onValue
    

    Don’t forget to define an index for timestamp, so that the sorting can be done on the database server.

    To learn more on this, see the Firebase documentation on sorting and filtering data.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search