12

I am using Laravel 5.6.7, Socket.IO and vue.js. I am not using Pusher and redis. Below is my code to send message to user chatting with me one to one.

var url = "http://localhost:6001/apps/My_appId/events?auth_key=My_Key";

var socketId = Echo.socketId();
var request = {
    "channel": "private-Send-Message-Channel.2",
    "name": "MessengerEvent",
    "data": {
        "msg": message
    },
    "socket_id": socketId
};
axios.post(url, JSON.stringify(request)).then((response) => {
    //Message Sent
});

I am trying to inform user who is chatting with me that I am still typing. Should I use the same above code which emits xhr on each char type? Is it the only way to inform user that the message typing is still in progress?

Update 1

Is there any better way to post xhr as mentioned above for each key press? I meant if user types 200 chars. will I post xhr 200 times?

or

Do we have an event called whisper and listenForWhisper as shown here https://laravel.com/docs/5.6/broadcasting#client-events ? I am using vue.js and laravel 5.6.7 without pusher and without redis

acdcjunior
  • 132,397
  • 37
  • 331
  • 304
Pankaj
  • 9,749
  • 32
  • 139
  • 283

4 Answers4

1

If you look at the broadcasting documentation you will see two code code snippets which you can use in your Vue.js application.

To broadcast client events, you may use Echo's whisper method:

Echo.private('chat')
    .whisper('typing', {
        name: this.user.name
    });

To listen for client events, you may use the listenForWhisper method:

Echo.private('chat')
    .listenForWhisper('typing', (e) => {
        console.log(e.name);
    });

While the user is typing, you can debounce the whisper method above.

If you don't wish to use another library like lodash, you can implement the debounce by simply wrapping whisper in a timeout. The following method would broadcast the whisper every 300ms:

isTyping() {
    let channel = Echo.private('chat');

    setTimeout(function() {
        channel.whisper('typing', {
            name: this.user.name,
            typing: true
        });
    }, 300);
}

The app needs to trigger isTyping() when an onkeydown event occurs in the chat application's input field.

You also need to listen for the whisper once the app is created. The following method will set the typing variable to true for 600ms after the event has been received.

created() {
    let _this = this;

    Echo.private('chat')
        .listenForWhisper('typing', (e) => {
            this.user = e.name;
            this.typing = e.typing;

            // remove is typing indicator after 0.6s
            setTimeout(function() {
                _this.typing = false
            }, 600);
        });
},
Dan Nagle
  • 4,384
  • 1
  • 16
  • 28
0

I am no Laravel expert, but I've faced this problem before.

First, let's define what "typing" means. The simplest way to define it is to say that a user is typing if and only if the input field to send a message is not empty.

This is not perfect, because the user can go away from keyboard in the middle of typing a message then not returning to complete and/or send it, but it is good enough.

More importantly, we now don't need to care about key strokes to know if the user is typing. In fact, "user is typing" now becomes as easy as chat_input_box.length > 0 to represent in code.

This boolean value is what needs to be synced across users/servers, not the act of hitting a key on the keyboard by the user. However, to keep the value up to date, we need to catch input events on chat_input_box and if the boolean value has changed since before this current event has occurred, socket.io should be able send a signal signifying whether the user has stopped or started typing.

On the receiving side, this signal toggles appropriate views to appear or disappear to indicate the state of the app to the user in human terms.

For the shortcoming of a user typing something then leaving, a timeout can be set so that when it is finished the boolean value "is typing" resets to false, while the act of typing something resets the timeout then starts it again automatically.

Rashad Saleh
  • 2,686
  • 1
  • 23
  • 28
0

You don't have to send an xhr request to your app. You can just broadcast events directly to the chat users without hitting your app.

From the Laravel docs:

Sometimes you may wish to broadcast an event to other connected clients without hitting your Laravel application at all. This can be particularly useful for things like "typing" notifications, where you want to alert users of your application that another user is typing a message on a given screen. To broadcast client events, you may use Echo's whisper method:

Echo.private('chat')
    .whisper('typing', {
        name: this.user.name
    });

To listen for client events, you may use the listenForWhisper method:

Echo.private('chat')
    .listenForWhisper('typing', (e) => {
        console.log(e.name);
    });
Paras
  • 9,258
  • 31
  • 55
  • Nope, this is Laravel Echo functionality. Echo is a wrapper library that supports both Pusher and Socket.io. – Paras Apr 02 '18 at 20:38
  • Both the methods whisper and listenForWhisper not supported for socket.io with vue.js and laravel – Pankaj Apr 02 '18 at 22:31
  • It works for private channels in socket.io. Where did you read it's not supported. I don't believe that is the case – Paras Apr 03 '18 at 04:49
-1

Yes you are right, it should not be emitting on every character change instead you could use debouncing to wait for a small time and then fire the function.

I would recommend using lodash library's debounce method. It should be something like this.

Kindly have a look at the documentation: https://lodash.com/docs/4.17.5#debounce

Laravel's Echo also sounds good, as you'll be doing nothing with typing action on the back-end thus just emitting from client to client is better than involving the server.

Farhan Tahir
  • 2,096
  • 1
  • 14
  • 27
  • Do you have any suggestions to check if the user is typing their message without the as mentioned in my question ? I am sorry this is not an answer. – Pankaj Mar 28 '18 at 06:33