最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Show delivered and blue ticks like whats app - Stack Overflow

programmeradmin6浏览0评论

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,
        "isIning": { "$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!!!

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,
        "isIning": { "$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!!!

Share Improve this question edited Aug 26, 2018 at 9:01 Ashh asked Aug 17, 2018 at 5:13 AshhAshh 46.6k16 gold badges111 silver badges137 bronze badges 2
  • You'll have to send acknowledgements. Just client asking another client, have you received my message? Did you see it? You should always send a received message acknowledgements just to make sure messages have been send correctly. – user2879055 Commented Aug 27, 2018 at 6:51
  • @user2879055 Did not get you – Ashh Commented Aug 27, 2018 at 18:03
Add a ment  | 

3 Answers 3

Reset to default 3 +100

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);
});

After creating a new message entity and sending it to the recipient, recipient should emit a new delivered event as soon as this message is received. If this message is opened, send another event with read topic. Both events have to contain the message id.

In the server side, after receiving above events, check the sender of the message is that you got and pass proper events no notify sender about the current state of the message.

You'll need 2 distinct things you'll need to track. Once your server has received the message. in it's control when you're adding it to the database, this is when you're going to set the delivered tick to true. At this point you can emit a message back to the sending web-socket telling it that they're message has been delivered to the server, then the client sender can set their gray tick.

Similarly on the receiving side,once the receiver logs on, goes to the page where the message is/opens it. Basically as soon as it's visible for them, you can go through all the messages currently visible to them, if any do not have a "hasRead" checked to true, then you can send a call to to a controller that can set them to "hasRead=true". At this point your websocket can try update the sender(if they are online) that the message has been read. If they aren't online then you can just do the same thing i n reverse. E.G: If the sender es online, pass along the "hasRead" attribute with each message and you can set the blue ticks accordingly"

发布评论

评论列表(0)

  1. 暂无评论