How to group chat messages per user? How to group chat messages per user? vue.js vue.js

How to group chat messages per user?


I solved this problem for myself pretty recently.Here's a full example.

The core business logic for grouping messages, in the above example, can be found under src/store.js in the addMessage function.

Unless your server is also storing all the messages and you have some mechanism to ensure causal ordering across all clients, I would recommend that you run the logic on each client. That way, you ensure that clients don't see messages jumping around under any circumstance. At worst, messages would appear ungrouped.

The algorithm to determine this is run when a new message is received, therefore it runs on each client, but you can tweak it to work for your use-case as well! It's shown below (I may have used the wrong flowchart elements..apologies).

addMessage({ state }, { msg, selfHash }) {  let addAsNewMsg = true;  const lastMessage = state.messages.slice(-1)[0];  if (lastMessage && lastMessage.userHash === msg.userHash) {    // The last message was also sent by the same user    // Check if it arrived within the grouping threshold duration (60s)    const lastMessageTime = moment(lastMessage.time);    const msgTime = moment(msg.time);    const diffSeconds = msgTime.diff(lastMessageTime, "seconds");    if (diffSeconds <= 60) {      addAsNewMsg = false; // We're going to be appending.. so      lastMessage.message.push(msg.message);      // We're going to now update the timestamp and (any) other fields.      delete msg.message; // Since, we've already added this above      Object.assign(lastMessage, msg); // Update with any remaining properties    }  }  if (addAsNewMsg) {    state.messages.push(msg);  }}


Seems like an ideal use case for computed properties. First sort the data by post_date

computed: {    sortedPosts() {        return this.posts.sort((a, b) => {            if (a.post_date < b.post_date) return -1;            else if (a.post_date > b.post_date) return +1;            return 0;        });    },

Then group by user.uid

    groupedPosts() {        const posts = this.sortedPosts.reduce((post, grouped) => {            if (grouped.length === 0)                 grouped.unshift([post]);            else if (grouped[0][0].user.uid === post.user.uid)                grouped[0].push(post);            else                grouped.unshift([post]);            return grouped;        }, []);        return posts.reverse();    }

Then used the computed property in a template

<div v-for="group in groupedPosts">    <div v-for="post in group">

(I haven't tested the code above, so watch for typos, etc.)


My approach would be to keep a reference to the div containing the last user's speech, and a variable representing the uid of the last user to speak. When a message comes in that matches the last uid, you'll simply add it to the div you're keeping track of; if the new uid doesn't match the previous one, you'll simply create a new div, add it to the DOM, and update the uid variable.

// initialize variableslet lastUid,curDiv;getData().forEach(msg => {  if (msg.user.uid !== lastUid) {    // new user is speaking!    curDiv = document.createElement("div");    document.body.appendChild(curDiv);    lastUid = msg.user.uid;  }  // add current message to the current div  curDiv.innerHTML += msg.message;});function getData() {  // really only put this in a function so that I could hoist it so that my logic can go above.  return [      {          "id":1,          "message":"<p>yo<\/p>",          "removed":"false",          "user":{              "uid":2,              "metadata":{                  "username":"Testing"              }          },          "post_date":"2018-02-24 14:30"      },      {          "id":2,          "message":"<p>test<\/p>",          "removed":"false",          "user":{              "uid":1,              "metadata":{                  "username":"Admin"              }          },          "post_date":"2018-02-24 22:31"      },      {          "id":3,          "message":"<p>Wassup?<\/p>",          "removed":"false",          "user":{              "uid":1,              "metadata":{                  "username":"Admin"              }          },          "post_date":"2018-02-24 22:40"      },      {          "id":12,          "message":"again for testing post date",          "removed":"false",          "user":{              "uid":1,              "metadata":{                  "username":"Admin"              }          },          "post_date":"2018-03-04 00:59"      },      {          "id":13,          "message":"Hello!",          "removed":"false",          "user":{              "uid":2,              "metadata":{                  "username":"Testing"              }          },          "post_date":"2018-03-04 11:13"      },      {          "id":13,          "message":"<p>Hi!</p>",          "removed":"false",          "user":{              "uid":2,              "metadata":{                  "username":"Testing"              }          },          "post_date":"2018-03-04 11:13"      },  ]}
div {  border: 1px solid black;  margin-bottom: 5px;}