Realtime Chat with laravel and pusher

34 Views Asked by At

So I would like to build a realtime chat in my website, but i have the chat system without the realtime. Indeed I have to refresh the page for the user who receive the messages.

So here the code

FIRST The view :

<div class="selected-conversation">
        {{-- Section pour afficher les messages --}}
        <div class="messages" id="message-container">
        <livewire:message-chat :conversationId="$conversation->id" :key="$conversation->id" id="chat-area"/>
</div>

    <script type="module" src="{{ asset('vendor/livewire/livewire/dist/livewire.js') }}" defer></script>
    <script src="https://js.pusher.com/7.0/pusher.min.js"></script>

    <script type="module">
        import Echo from 'https://cdn.jsdelivr.net/npm/[email protected]/dist/echo.js';

        Echo.private('conversation.' + {{ Auth::id() }})
            .listen('messageSent', (event) => {
                window.livewire.emit('messageSent');
            });

        const pusherKey = '{{ env("PUSHER_APP_KEY") }}';
        const pusherCluster = '{{ env("PUSHER_APP_CLUSTER") }}';

        window.Echo = new Echo({
            broadcaster: 'pusher',
            key: pusherKey,
            cluster: pusherCluster,
            encrypted: true,
        });
</script>

livewire component with his backend:

<div >
    @foreach ($messages as $message)
        @if ($message->user_id == Auth::id())
            <div class="sent-message">
                <strong class="you-message">Vous</strong><br>
                {{ $message->content }}<br>
                <div class="image-container">
                    @foreach ($message->images as $image)
                        <img class="message-image mr-2" src="{{ asset('storage/chatImages/' . $image->image_path) }}" alt="Message Image">
                    @endforeach
                </div>
                <span class="time">@if ($message->created_at)  {{ $message->created_at->diffForHumans() }} @endif</span>
            </div>
        @else
            <div class="received-message">
                <strong class="other-message">{{ $message->user->username }}</strong><br>
                {{ $message->content }}<br>
                <div class="image-container">
                    @foreach ($message->images as $image)
                        <img class="message-image mr-2" src="{{ asset('storage/chatImages/' . $image->image_path) }}" alt="Message Image">
                    @endforeach
                </div>
                <span class="time">@if ($message->created_at)  {{ $message->created_at->diffForHumans() }} @endif</span>
            </div>
        @endif
    @endforeach
</div>

BACKEND
<?php

namespace App\Livewire;

use App\Models\Message;
use Livewire\Component;

class MessageChat extends Component
{
    public $conversationId;

    public function mount($conversationId)
    {
        $this->conversationId = $conversationId;
    }

    public function getListeners()
    {
        return [
            "echo-private:conversation.{$this->conversationId},MessageSent" => 'messageSent',
        ];
    }

    public function render()
    {
        $messages = Message::where('conversation_id', $this->conversationId)->get();

        return view('livewire.message-chat', compact('messages'));
    }

    public function messageSent()
    {
      
        $this->render(); 
    }
}

Function in the controller

   public function sendMessage(Request $request, Conversation $conversation)
    {
        $user = Auth::user();
    
        $request->validate([
            'message' => 'required_without:image|string',
            'image' => 'required_with:message image|mimes:jpeg,png,jpg|max:2048',
        ]);
    
        $message = $conversation->messages()->create([
            'user_id' => $user->id,
            'content' => $request->input('message'),
        ]);
    
     
        if ($request->hasFile('images')) {
            foreach ($request->file('images') as $image) {
                $imageName = time() . '_' . $image->getClientOriginalName();
                $image->storeAs('chatImages', $imageName, 'public');
    
                $message->images()->create([
                    'image_path' => $imageName,
                ]);
            }
        }
    
      
        broadcast(new MessageSent($user, $message, $conversation));
        return response()->json(['status' => 'Message sent']);
        }

The event

<?php

namespace App\Events;

use App\Models\Conversation;
use App\Models\Message;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;

class MessageSent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $user;
    public $message;
    public $conversation;

    public function __construct(User $user, Message $message, Conversation $conversation)
    {
        $this->user = $user;
        $this->message = $message;
        $this->conversation = $conversation;
    }

    public function broadcastOn()
    {
        return new PrivateChannel('conversation.' . $this->message->conversation_id);
    }
    public function broadcastAs($message){
        return $message;
    }
}

The routes

    Route::post('/messagerie/{conversation?}/sendMessage', [App\Http\Controllers\MessageController::class, 'sendMessage'])->name('sendMessage');

If you can help me to find out the solution to have realtime, I'll appreciate it. Been a month stuck on this. Help is what I need xD

0

There are 0 best solutions below