Search code examples
javascriptnode.jssocket.iochatmessaging

Show delivered and blue ticks like whats app


I have created an app using socket... I am able to manage the conversation between two persons using socket connection.

Here is the code for it

User model

const schema = new Mongoose.Schema({
  firstName: { type: String, default: '', trim: true },
  lastName: { type: String, default: '', trim: true }
})

Conversation model

const schema = new Mongoose.Schema({
  name: { type: String, trim: true },
  type: { type: String, required: true, enum: ['G', 'P'] },
  members: [{ type: Schema.Types.ObjectId, ref: 'Users' }]
}, { timestamps: true })

Message Model

const schema = new Mongoose.Schema({
  conversationId: { type: Schema.Types.ObjectId, ref: 'Conversations' },
  body: { type: String, trim: true },
  author: { type: Schema.Types.ObjectId, ref: 'Users' }
}, { timestamps: true })

Done with the chatting part with this socket connection

io.on('sendMessage', async(action2) => {
    action2.author = socket.decoded.id
    action2.markRead = markReadSocket
    const createMessage = await Message.create(action2)
    const messages = await Message.aggregate([
      { "$match": { "_id": mongoose.Types.ObjectId(createMessage._id) } },
      { "$lookup": {
        "from": "users",
        "let": { "author": "$author" },
        "pipeline": [
          { "$match": { "$expr": { "$eq": [ "$_id", "$$author" ] }}},
          { "$project": { "firstName": 1, "lastName": 1, "avatar": 1 } }
        ],
        "as": "author"
      }},
      { "$unwind": "$author" },
      { "$project": {
        "author": 1, "markRead": 1, "isDelivered": 1,
        "body": 1, "conversationId": 1,
        "isIncoming": { "$ne": [ "$author._id", mongoose.Types.ObjectId(socket.decoded.id) ] },
      }}
    ])
    io.emit(action2.conversationId, messages)
  })

The above code is working fine for the one to one conversation and also for the group conversation.

Now what I want to achieve is to show delivered(two gray) and read(two blue) ticks just like the what app. Do I need to make separate collections for readBy and deliveredTo and need to save time and userId in it?

How can I do this with the nodejs and socketio? If someone has done this before then please post your code I will manage to understand it.

Any help would be appreciated!!!

Thanks in advance!!!


Solution

  • Client Side

    Pseudocode

    1. Register handler for 'newMessage' event, this will emit 'received' event
    2. Function to emit 'markSeen' event, this will execute when the message is opened (chat window)
    3. Register handler for 'delivered' event, this will display 'grey' ticks
    4. Register handler for 'markedSeen' event, this will display 'blue' ticks
    

    Functions

    // Handler for 'newMessage' event
    socket.on('newMessage', function(message) {
        chatMessages[message.MESSAGE_ID] = message;
    
        var options = {
            messageID: message.MESSAGE_ID,
            timetoken: moment().valueOf()
        };
    
        // Emit 'received' event
        socket.emit('received', options);
    });
    
    // function to emit 'markSeen' event
    function markSeen(message) {
        var options = {
            messageID: message.MESSAGE_ID
        };
    
        // Emit 'markSeen' event
        socket.emit('markSeen', options);
    }
    
    // Handler for 'delivered' event
    socket.on('delivered', function(message) {
        chatMessages[MESSAGE_ID].delivered = true;
    });
    
    // Handler for 'markedSeen' event
    socket.on('markedSeen', function(message) {
        chatMessages[MESSAGE_ID].seen = true;
    });
    

    Server Side

    Pseudocode

    1. Register handler for 'received' event, this will emit 'delivered' event
    2. Register handler for 'markSeen' event, this will emit 'markedSeen' event
    

    Functions

    // Handler for 'received' event
    io.on('received', function(options) {
        var options = {
            timetoken: moment().valueOf(),
            userID: options.message.SENDER_ID,
            messageID: options.message.MESSAGE_ID
        };
    
        // Emit 'delivered' event
        socket.emit('delivered', options);
    });
    
    // Handler for 'markSeen' event
    io.on('markSeen', function(options) {
        var options = {
            timetoken: moment().valueOf(),
            userID: options.message.SENDER_ID,
            messageID: options.message.MESSAGE_ID
        };
    
        // Emit 'markedSeen' event
        socket.emit('markedSeen', options);
    });