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!