halloei's avatar

Broadcasting: Exclude current user from presence channel

In the frontend, I've got tasks in a table (/tasks). Multiple users should work on these tasks, until all are done.

To work on a task, a user visits the task's page (/tasks/3). Here, I'm using broadcasting presence channels to display a warning if another user is already on the same page.

I now like to display the "somebody is already working on that task" warning on the table view of all tasks (by coloring the table row of the respective tasks, for example). Letting the user join the presence channel of every shown task is not a solution because the user would obviously appear as if they was working on all of these tasks.

Is there a way to exclude the table-viewing user from the presence channel? Or is there another solution?

0 likes
1 reply
LaryAI's avatar
Level 58

One solution would be to create a separate presence channel for the table view and exclude the current user from that channel. Here's an example of how you could implement this:

  1. Create a new presence channel for the table view:
Broadcast::channel('table-view', function ($user) {
    return true;
});
  1. In your table view, join the table-view channel:
Echo.join('table-view')
    .here(users => {
        // handle initial presence data
    })
    .joining(user => {
        // handle new user joining
    })
    .leaving(user => {
        // handle user leaving
    });
  1. When a user visits a task page, join the task's presence channel as usual:
Echo.join(`task.${taskId}`)
    .here(users => {
        // handle initial presence data
    })
    .joining(user => {
        // handle new user joining
    })
    .leaving(user => {
        // handle user leaving
    });
  1. In your task page view, use the Echo instance to get the current user's ID:
let userId = Echo.socketId();
  1. When rendering the table view, pass the current user's ID to the view:
return view('table', [
    'currentUserId' => $currentUserId,
    // other data
]);
  1. In your table view, use the currentUserId to exclude the current user from the table-view channel:
Echo.join('table-view')
    .here(users => {
        // handle initial presence data
    })
    .joining(user => {
        // handle new user joining
    })
    .leaving(user => {
        // handle user leaving
    })
    .whisper('exclude', currentUserId);
  1. In your JavaScript code that handles the warning message, check if the current user's ID is in the presence data for the task channel. If it is, don't show the warning message for that task.
Echo.join(`task.${taskId}`)
    .here(users => {
        // handle initial presence data
        let isCurrentUserWorking = users.some(user => user.id === currentUserId);
        if (isCurrentUserWorking) {
            // don't show warning message
        } else {
            // show warning message
        }
    })
    .joining(user => {
        // handle new user joining
        if (user.id === currentUserId) {
            // don't show warning message
        } else {
            // show warning message
        }
    })
    .leaving(user => {
        // handle user leaving
        if (user.id === currentUserId) {
            // don't show warning message
        } else {
            // show warning message
        }
    });

This solution allows you to exclude the current user from the table-view channel while still using presence channels to display the warning message for individual tasks.

Please or to participate in this conversation.