javascript monitoring numerous socket channels for echoes

Currently, I am in the process of developing a chat application. On the server side, I am utilizing: php, laravel 5.4, and pusher. On the client side, I have incorporated vue.js along with laravel-echo.

Initially, I successfully created a "public chat room" which is essentially a chat group. My current focus lies in implementing private chat rooms.

My inquiry: What would be the most efficient approach (on the client side) to monitor all channels associated with the rooms that the user is part of?

End goal: To ensure that every channel within private and public rooms is monitored, similar to the functionality seen on the Facebook Messenger web page.

At this point, within the chat-window component, this is what I have:

created() {
  axios.get('/chatroom').then(response => {
      this.chatRooms = response.data;
      console.log('get /chatroom response: ' + response.data);
  });

  axios.get('/messages').then(response => {
      this.messages = response.data;
      console.log('get /messages response: ' + response.data);
  });

  Echo.join('chatroom')
      .here((users) => {
          this.usersInRoom = users;
      })
      .joining((user) => {
          this.usersInRoom.push(user);
      })
      .leaving((user) => {
          this.usersInRoom = this.usersInRoom.filter(u => u != user)
      })
      .listen('MessagePosted', (e) => {
          this.messages.push({
              message: e.message.message,
              user: e.user
          });
      });
  }
});

However, this setup only listens to the chatroom channel. How can the client listen to all the chatrooms stored in this.chatRooms ?

Appreciate any insights provided!

Answer №1

After realizing that each user needs to have their own channel, I made adjustments to my chat-window component:

<template lang="html">
  <div class="panel panel-default">
      <div class="panel-heading" style="height: 60px">
        <chat-room-picker :chatrooms="chatRooms" :newmessage="newmessage" :defaultchatroomid="pickedchatroomid" class="pull-left" v-on:chatroompicked="chatroompick"></chat-room-picker>
        <chat-room-creator class="pull-right"></chat-room-creator>
      </div>
        <chat-room :chatroomid="pickedchatroomid" :newmessage="newmessage"></chat-room>
  </div>
</template>

<script>
export default {
  data() {
    return {
     userId: loggedUserFS.id,
     userName: loggedUserFS.name,
     chatRooms: chatRoomsFS,
     pickedchatroomid: defaultChatRoomIdFS,
     newmessage: {},
    }
 },
 methods: {
   chatroompick(id) {
     this.pickedchatroomid = id;
   },
 },
 created() {
  // this.getCookiesParams();
  var tmp = this.chatRooms[0];
  this.pickedchatroomid = tmp.id;
   var channelName = 'chat-' + this.userId;
   console.debug(channelName + ", channel init.");
   window.Echo.join(channelName)
       .listen('NewMessageEvent', (e) => {
           console.debug("incoming message on " + channelName + ": " + JSON.stringify(e));
           console.debug(e.message.chatRoom_id + "==" + this.pickedchatroomid);
           console.debug(channelName +" : "+ e.message.chatRoom_id + "==" + this.pickedchatroomid);
           // TODO: finish it
           if(e.message.chatRoom_id == this.pickedchatroomid) { // if the received message is from the picked chat room
             console.debug("received message is from the picked chat room!");
             this.newmessage = e;
           } else { // if the received message is not from the picked chat room
             this.newmessage = e;
           }
       });
  }
}
</script>

<style lang="css">
</style>

I introduced a chat-room-picker, which is a dropdown for changing chatrooms, and a chat-room component for displaying messages in the current chat room. Both components utilize vue-watch to handle new messages - adding them to the chat room only if they belong to the current room, otherwise performing no action. The chat-room-picker will start blinking if the message belongs to a different room.

chat-room-picker watch:

  watch : {
    newmessage : function (value) {
      var message = value;
      var picker = $(".chatRoomPicker");
      //TODO: check if the message belongs to the current chat room
      picker.addClass("blink");
      picker.on("click", function() {
        picker.removeClass("blink");
      });
    }
  }

Watch part of the chat-room component:

  watch : {
    chatroomid : function (value) { // if chat-room is changed
      this.getChatRoomMessages();
    },
    newmessage : function(value) {  // TODO: here or parent component check the room of the message
      console.debug("new message received:" + JSON.stringify(value));
      var msgTmp = value.message;
      msgTmp.user = value.user;

      this.messages.push(msgTmp);
    }
  },

On the server side (in controller):

broadcast(new NewMessageEvent($message, $user, $usersOfChatRoom));

The broadcastOn method of the NewMessageEvent looks like this:

public function broadcastOn()
{
    $channels = [];
    foreach ($this->usersOfChatRoom as $addressee) {
      if($addressee->id != $this->user->id) {
        array_push($channels, new PresenceChannel('chat-' . $addressee->id));
      }
    }
    Log::debug("broadcastOn channels: " . json_encode($channels));
    return $channels;
  //
}

While it's not a fully complete solution, I have indicated where the code needs to be finalized. It may not be the most elegant approach, but it gets the job done. If anyone has alternative solutions, please feel free to share!

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Prevent input from being cleared when selecting an option with React-Select

Unfortunately, there was no satisfactory solution to this question so I will provide an answer: The issue arises when trying to utilize React-Select with a persistent input value that remains even after selection or blurring. Regrettably, this functionali ...

Which is more efficient for rendering performance: using images, CSS gradients, or box shadows with borders?

I'm curious about improving website scroll and animation performance. Which option would be better for your mobile webapp or website: Using a repeating thin image or CSS3 gradient? or Utilizing a repeating image instead of box shadow with a borde ...

processing an array using ajax form submission

Trying to manage an array that is returned from a PHP file after submitting form data. The value of the data after form submission is = ARRAY but I am unable to use this array in any way. Any suggestions on how to handle this array? Javascript: $(&apo ...

Is it common to encounter a "no such file or directory" error when running Docker-Compose with the command "ENTRYPOINT ['./init.sh']" in a Dockerfile?

Contemplate the docker-compose configuration : version: '3.0' volumes: data: driver: local networks: simple-network: driver: bridge services: postgres: container_name: postgres image: postgres ...

Verifying the presence of a popover

Utilizing bootstrap popover in my project, I am encountering an issue where the target variable may not always exist on the page. Currently, I am displaying the popover using the following code snippet - target = $('#' + currentPopoverId.data(& ...

Automatically populate input field values into a textarea using a separator with jQuery

There are multiple input fields to fill out: <input type="text" placeholder="name"> <input type="text" placeholder="age"> <input type="text" placeholder="gender"> <input type="text" placeholder="interest"> As I enter information i ...

Having trouble with a lengthy formula in your Google Sheets Apps Script function? You may encounter an error like `SyntaxError: missing ) after argument list line: 14 file: new line.gs`. Let

The Apps Script function being discussed: function insertNewRow() { var ss = SpreadsheetApp.openById("redactedforprivacy"); var sheet = ss.getSheetByName("Main"); sheet.insertRowBefore(2); var date = new Date(); var month = date.getMonth() + 1 ...

The value within the style.setProperty function does not get applied

I have a progress bar that dynamically increases based on user input: <div class="progressBarContainer percentBar"> <div class="progressBarPercent" style="--width:${gPercent}" id="${gName}-pbar">< ...

Why is it that methods lose their binding when they are returned from a ternary operator?

class TestClass { constructor() { this.prop = 5; } MethA() { console.log(this); console.log(this.prop); } MethB() { (true ? this.MethA : null)(); } } Test = new TestClass(); Test.MethB(); What is the ...

Error: The Stripe webhook payload must be submitted as either a string or a Buffer

I'm currently working on setting up a subscription system using Stripe. I have mostly followed the code from their documentation, but I keep encountering the following error: Webhook signature verification failed. Webhook payload must be provided as a ...

Unable to designate the drop-down option as the default selection

Can anyone help me with setting a default drop-down value using JavaScript? I have been struggling to achieve this. You can find my code on jsFiddle <div ng-controller="csrClrt"> <div ng:repeat="(key, item) in items track by $index"> ...

Is there a method to obtain specific props for focused tabBar badges to customize the background color accordingly?

Is there a way to specify focused props in tabBarBadgeStyle to customize the background color? options={{ tabBarLabel: "Teams", tabBarBadge: '3', tabBarBadgeStyle: { backgroundColor: ORANGE ...

Using the npm module to compile CoffeeScript tests

Searching high and low, I have yet to find a satisfactory answer on whether it is feasible to compile a string of CoffeeScript using the npm module. Can anyone shed some light on this? ...

Develop a Customized Notification System according to User Preferences

Currently, I am in the process of building a notification system and have some doubts about certain aspects. To simplify things, I'll be using generic names. This is how the system should function: A registered user has the ability to subscribe to ...

The attached event in my Nuxt.js project fails to fire during testing with Jest

I'm currently in the process of developing a web application using nuxt js + jest Here is an excerpt from my nuxt js component: export default { mounted () { document.addEventListener('click', this.eventClick) }, destroyed () { ...

Tips for assigning information from a react hook within a function or event

Currently, I am in the process of learning how to create hooks in order to efficiently reuse data that needs to be modified across different components. For my project, I am utilizing Material UI's Tabs and require the use of a custom hook called use ...

Redirecting pages using an Ajax script in JavaScript

Unfortunately, I am unable to use a *.php extension for my page due to unforeseen circumstances. This has led me to consider using *.html instead and implementing conditional redirection using javascript/Ajax to call a PHP script that can evaluate the cond ...

How to pass arguments to the `find` method in MongoDB collections

I've been attempting to pass arguments from a function to the MongoDB collection find method. Here's what I have so far: async find() { try { return await db.collection('users').find.apply(null, arguments); } catch(err) { c ...

Updating the variables of HTML components using JavaScript after making an AJAX request

I am using ajax to fetch a list of user data. But after this ajax call, I need to display the data in an HTML structure like a datasheet for each user. My question is how can I store the HTML code in a functional and elegant way to maintain readability and ...

Exploring Vue3: Implementing Highlight.js for Solidity code highlighting

Currently working on developing a webpage using Vue3. The goal is to display Solidity code in a visually pleasing and highlighted manner. After some research, I came across the Highlight.js library (link). Additionally, I found specific rules for highlight ...