As well as broadcasting events from our Laravel application,
00:03
we can also whisper on a channel, which will only send this client to client. Let's just take a look at what that looks like when we get the typing event in.
00:13
So let's say channel and whisper. So rather than send a HTTP request to our back end to then broadcast to everyone that we're typing, using whisper, this is just going
00:25
to send this to all connected clients except ourselves. So let's go ahead and whisper a typing event, and let's just have an empty array of the data that we want to send first of all.
00:36
Let's make sure that we have our reverb server up here so we can check this event out, and let's go ahead and type something out. Let's go back over, and there we go.
00:46
So we now get a client typing event. We can ignore this client prefix, because when we pick this up with Laravel Echo, we can just use the typing event name,
00:57
and it contains a bunch of data. So this data at the moment is just an empty array, because we're not passing any data through to it. But what we can do in here is broadcast
01:06
which user is currently typing and whether they are typing. So we've just included a single event with a true or false value, but we could have split that up into two.
01:17
So let's pass some data down here to determine who's typing. Now, within Inertia, if we look at the handle Inertia requests middleware, this sends down to every single page
01:29
of the user who is currently authenticated. So what we can do is access page, props, auth, and user, and then grab the ID. If you're not using Inertia,
01:40
you could grab this from anywhere else that you have that available. Then we can send down whether they're typing or not, which is, we know just the event data
01:49
that we are emitting from here. Okay, let's look at the difference. So let's pull this up again, and we'll go over and just start typing.
01:57
Let's go back over to here, and there we go. User ID one is typing, and then eventually we'll get typing false. Now, what we can do with this is set this,
02:09
or listen for this, and then set it without store. So we know that when we are listening for all of these events, we're pushing to this user's store.
02:18
What we can do now is listen for a whisper. So we're gonna say listen for whisper. We know the event name, it is typing, and then we get exactly the same data
02:28
as we've already seen. So we can take the event data and just console log that out here. Now, this is gonna be broadcast to all other clients.
02:38
So if we just open up the console over this side and we type over this side like this, you can see that Mabel with an ID of two is typing, and then eventually she's not typing.
02:50
So we can use this for all clients to push this data to our store. Now, remember when we set up our channels earlier, if we just take a look at this,
02:58
these are the only two values that we're pushing. Now, what we could do with this is we could append onto this array that we get returned with only,
03:07
and we could always set typing to false, just so we've got another piece of data in there for when we eventually push this in. Okay, let's pull this in correctly, and we are good.
03:19
So now, if we just head over to our user component, we should see in here user typing. So that's always being broadcast within our presence channel.
03:32
Let's go over that and you can see we've got a false value here and a false value here. Let's start typing. And the goal is to set this to true
03:41
when Mabel is or isn't typing. So over to our room component, let's think about how we can do this. Once again, I'm gonna pull this up to one line
03:51
and let's take the event and let's say user store, and let's set a user to typing. And we'll just pass all of that event data in, or we could take specifically the user ID for that
04:04
and set it. So let's add this set typing event to our user store. So down here, let's say set user typing. Let's just check what we call that.
04:13
Call that set typing, so let's just keep the same name. And this is gonna take in the event, and we're gonna find that user and update their typing status.
04:24
So just so we're incredibly clear, if I console log this event out, that's just gonna give us the ID and typing. So the ID of the user and typing.
04:34
So let's find that user in our state. So you, we're gonna compare user ID to the event ID. We could have probably called that user ID, but it's fine. And then we're gonna set typing
04:49
to the event typing Boolean. So obviously that's either gonna be true or false. So find the user who is typing and set their typing status. Let's go over and see this in action.
04:59
So let's go ahead and type something over here. And yeah, let's just have a look here. Properties of undefined. And yeah, that's e.id, not event.
05:09
Okay, let's try that again. And there we go. You can see Mabel is typing and then eventually is not typing.
05:15
So we've successfully got this to work with the typing events and we've updated that value. Now we need to do is just visually represent this. And of course that just depends on whatever you want to do.
05:27
So let's go over to our chat users and let's update this to make this a bit better. So I'm gonna wrap this user name here in a span and then down here, I'm gonna add in an SVG.
05:39
Let's just add typing in there for now. And let's set this to flex with item center and justify between. So that should now give us a typing indicator
05:49
over this side. And I'm gonna go ahead and pull in an SVG from my notes here. And of course you can grab this from the GitHub repository. So all this is, is just an ellipsis here.
06:00
And what we wanna do is show this with maybe a little bit of animation when that user's typing. So the first thing that we'll do is go ahead
06:07
and set this with Tailwind to animate bounce. Completely optional, but let's try and make it as fun as possible. And we'll go ahead and by default set this
06:15
with an opacity of zero. And then we'll override this if the user is typing. We'll set a transition on the opacity as well. And we should be good.
06:24
So we shouldn't see that at the moment. What we can do though is bind in a class to this and set the opacity to 100 when that user is typing. So just use this to do anything, show a message,
06:38
go ahead and animate something based on that Boolean. Let's go over and try this out. So I'm gonna type hello and you can see Mabel is typing. Of course, three seconds later when she's stopped,
06:49
everything is good. So there's one more thing that we need to do over in our chat text area when we finish sending the message.
06:57
Let's take a look at what this looks like. So I'm gonna go ahead and type in hello. You can see that I'm typing here and I can continue to type.
07:03
When I hit enter though, we don't immediately see that the other user stopped typing even though they technically have because the message has been sent.
07:13
So to get around this, the first thing we're gonna do is just change the order of these around. We want this last, the order of these matters.
07:21
When we handle our enter, so if we just head over to the handle enter function, after we have sent the message and admitted this is valid, all we need to do here is re-invoke handle finish typing.
07:34
That will send off that event to our WebSocket server as soon as we finish typing and it's valid. And then of course it will broadcast that we're not typing anymore.
07:43
So let's head back over and try this out. So I'm going to type a message, hit enter, and you can see that immediately goes when we hit enter and send a message.
07:52
So there we go. All of our clients are now aware of who is typing and we fixed up that last little issue to immediately get rid of it once we send a message.
21 episodes•1 hr 41 mins•11 months ago
Overview
Using the power of Reverb, let’s build a realtime multi-room chat with Laravel and Vue with Inertia, pulling in Pinia for state management.
We’ll cover:
Using the Intersection Observer API to automatically load previous chat messages
State management with Pinia
Using presence channels to show online users for each room
Client-to client communication to show who’s typing
Using flexbox tricks to keep messages scrolled into view as they roll in