Forked from developerdza/Controllers--Livewire--Chat.php
Created
June 19, 2020 09:18
-
-
Save Salah856/a6bb1cafe8b6226ec098fd3b7e571195 to your computer and use it in GitHub Desktop.
Real Time Chat By Laravel And Livewire
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Livewire\Forum; | |
use Illuminate\Support\Facades\Auth; | |
use Illuminate\Support\Facades\DB; | |
use Livewire\WithPagination; | |
use Livewire\Component; | |
use App\Message; | |
use App\User; | |
class Chat extends Component | |
{ | |
use WithPagination; | |
protected $listeners = ['selected_users', 'selected_group', 'loadMore']; | |
public $message, $chat_id, $unreadedMessages, $search, $group_id , $paginate_var=10; | |
// get user unreaded messages | |
public function mount() | |
{ | |
$this->unreadedMessages = Auth::user()->unreadedMessages()->count(); | |
} | |
public function render() | |
{ | |
// get user unreaded messages | |
$unreadedMessages = $this->unreadedMessages; | |
// select the user I want to chat with | |
$id = $this->chat_id; | |
// get selected user Info --------------------------- | |
if (isset($this->chat_id)) { | |
$chat_user = User::find($id); | |
} | |
else { | |
$chat_user = ''; | |
} | |
//-------------------------------- | |
// get All user to select one of them | |
$users= User::all(); | |
// My id | |
$user_id = Auth::user()->id; | |
//------- Haldeling Messages between me and the selected user | |
// counting | |
$messages_count = Message::where('from_user',$user_id) | |
->where( 'to_user',$id) | |
->orWhere('from_user',$id) | |
->where('to_user',$user_id) | |
->count(); | |
// showing a special numer of messages firstly , then I can show more by scrolling to top | |
$messages = Message::where('from_user',$user_id) | |
->where( 'to_user',$id) | |
->orWhere('from_user',$id) | |
->where('to_user',$user_id) | |
->skip($messages_count - $this->paginate_var) | |
->take($this->paginate_var) | |
->get(); | |
// showing Recent conversations I have | |
$conversations = \App\Conversation::where('first_user',Auth::user()->id) | |
->orWhere('second_user',Auth::user()->id) | |
->orderBy('last_message_time','desc') | |
->get(); | |
return view('livewire.forum.chat',compact('messages','id','users','chat_user','unreadedMessages','conversations','paginate_var')); | |
} | |
// selecting the user I want to chat with by clicking his avatar | |
public function selected_users($id) | |
{ | |
$this->chat_id = $id; | |
//marking our messaeges as readed | |
Message::where('statu','unreaded') | |
->where('to_user',Auth::user()->id) | |
->where('from_user',$id) | |
->update(array('statu'=>'readed')); | |
// number of messages Iwant to show | |
$this->paginate_var = 10; | |
// scrollng to bottom | |
$this->emit('scroll'); | |
} | |
// sending messages | |
public function send($id) | |
{ | |
//--- | |
$message = new Message; | |
$message->body = $this->message; | |
$message->from_user = Auth::user()->id; | |
$message->to_user = $this->chat_id; | |
$message->save(); | |
//-- | |
//----------------------------Conversation------------------------ | |
//check if there is an old conversation between us | |
$conv_old = \App\Conversation::where('first_user',$message->from_user) | |
->where('second_user',$message->to_user) | |
->orWhere('first_user',$message->to_user) | |
->where('second_user',$message->from_user) | |
->get()->first(); | |
// if there is an old convesation between as , just link it to this message | |
if($conv_old) | |
{ | |
$conversation = \App\Conversation::find($conv_old->id); | |
$conversation->last_message_time = $message->created_at; | |
$conversation->save(); | |
$message->conversation_id = $conv_old->id; | |
$message->save(); | |
} | |
// else create a conversation and store our ids in it | |
else | |
{ | |
$conversation = new \App\Conversation; | |
$conversation->first_user = $message->from_user; | |
$conversation->second_user =$message->to_user; | |
$conversation->last_message_time = $message->created_at; | |
$conversation->save(); | |
$message->conversation_id = $conversation->id; | |
$message->save(); | |
} | |
//---------------------------- End Conversation------------------------ | |
// -------------------------------Event----------------- | |
//get Unreaded messages | |
$recivedUnreadedMessages =Message::where('statu','unreaded') | |
->where('from_user',Auth::user()->id) | |
->where('to_user', $this->chat_id) | |
->count(); | |
$this->message = ''; | |
$chat_user = User::find($this->chat_id); | |
//sending event with message content and the user Isend it to , and the numb of the Unreaded Messages | |
event(new \App\Events\Chat($this->chat_id,$message,$recivedUnreadedMessages,$chat_user)); | |
} | |
// Load more then 10 messaeges by scrolling to top | |
public function loadMore() | |
{ | |
$this->paginate_var = $this->paginate_var + 10; | |
$this->emit('load'); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Events; | |
use Illuminate\Broadcasting\Channel; | |
use Illuminate\Broadcasting\InteractsWithSockets; | |
use Illuminate\Broadcasting\PresenceChannel; | |
use Illuminate\Broadcasting\PrivateChannel; | |
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; | |
use Illuminate\Foundation\Events\Dispatchable; | |
use Illuminate\Queue\SerializesModels; | |
class Chat implements ShouldBroadcast | |
{ | |
use Dispatchable, InteractsWithSockets, SerializesModels; | |
/** | |
* Create a new event instance. | |
* | |
* @return void | |
*/ | |
public $user_id,$message,$recivedUnreadedMessages, $chat_user; | |
public function __construct($id,$message,$recivedUnreadedMessages,$chat_user) | |
{ | |
$this->user_id = $id; | |
$this->message = $message; | |
$this->recivedUnreadedMessages = $recivedUnreadedMessages; | |
$this->chat_user = $message->froom_user; | |
} | |
/** | |
* Get the channels the event should broadcast on. | |
* | |
* @return \Illuminate\Broadcasting\Channel|array | |
*/ | |
public function broadcastOn() | |
{ | |
create privete chat with his id | |
return new PrivateChannel('Chat.'.$this->user_id); | |
} | |
public function broadcastAs() | |
{ | |
return 'Chat'; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1----------------- | |
<script type="text/javascript"> | |
// when I scroll to top I fire the event load more to show more old messages | |
$('#messages').scroll(function() { | |
var top =$('#messages').scrollTop(); | |
if ( top == 0) { | |
window.livewire.emit('loadMore') | |
} | |
}); | |
</script> | |
2---------------- | |
<script type="text/javascript"> | |
// after selecting the user I fire the event scroll to scroll the messages box to bottom | |
window.livewire.on('scroll', function() { | |
$('#messages').animate({ | |
scrollTop: $('#messages')[0].scrollHeight}, "slow"); | |
}) | |
</script> | |
3---------------- | |
// after selecting user marking or messages as read | |
<script type="text/javascript"> | |
$(".user").click(function(){ | |
$(this).find('p').html(''); | |
}); | |
</script> | |
4------------------- | |
<script type="text/javascript"> | |
// storing my id | |
localStorage.setItem('uID',{{Auth::user()->id}}); | |
console.log (localStorage.getItem('uID')) ; | |
//lestening to the channel 'chat'.myId | |
window.Echo.private('Chat.'+localStorage.getItem('uID')) | |
.listen('.Chat', (e) => { | |
//--scrolling to bottom to see the new message | |
$('#messages').animate({ | |
scrollTop: $('#messages')[0].scrollHeight}, "slow"); | |
var id = @this.get('chat_id') | |
console.log(e); | |
// If the conversation betwwen my and the sender is open now .... | |
//-- appending the message tp messages box | |
$("."+ e.message.from_user).html(`${e.recivedUnreadedMessages}`); | |
if( e.message.from_user == id) | |
{ | |
$('#messages-boxx').append(` | |
<div class="media w-50 mb-3"> | |
<div class="media-body ml-3"> | |
<div class="bg-light rounded py-2 px-3 mb-2"> | |
<p class="text-small mb-0 text-muted">${e.message.body}</p> | |
</div> | |
<p class="small text-muted">${e.message.created_at}</p> | |
</div> | |
</div> | |
`); | |
} | |
//---- else increment the num of the enreded messages between us | |
else | |
{ | |
console.log("#user."+e.chat_user.id); | |
console.log(e.recivedUnreadedMessages); | |
} | |
}); | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// USERS SECTION | |
<div class="bg-white"> | |
//-----swching between users section and recent conversation section by alpine Js------- | |
<div class="messages-box" wire:ignore x-show.transition.in="tab === 'recent'"> | |
<button :class="{ 'active': tab === 'groups' }" @click="tab = 'all'"> | |
<img class="float-right" src="{{asset('icons/icons/group.png')}}" width="40" > | |
</button> | |
//-----End swching between users section and recent conversation section by alpine Js------- | |
// Conversations | |
<div class="list-group users rounded-0" > | |
@foreach($conversations as $conversation) | |
//---- If I started the chat betwwen us show me the avatar of the other user | |
@if(Auth::user()->id == $conversation->first_user) | |
<a class="list-group-item list-group-item-action text-white rounded-0" wire:click="$emit('selected_users',{{$conversation->second_user}})" > | |
<div class="media "> | |
<img src="{{Voyager::image($conversation->seecond_user->avatar)}}" alt="user" width="50" class="rounded-circle"> | |
<div class="media-body ml-4 user" > | |
<div class="d-flex align-items-center justify-content-between mb-1"> | |
<h6 class="mb-0" style="color: black">{{$conversation->seecond_user->name}}</h6><small class="small font-weight-bold" style="color: black"></small> | |
</div> | |
<p class="badge badge-danger {{$conversation->second_user}}" style="color: black" id="{{'user'.$conversation->first_user}}" > | |
{{\App\Message::where('statu','unreaded')->where('to_user',Auth::user()->id)->where('from_user',$conversation->seecond_user->id)->count()}} | |
</p> | |
</div> | |
</div> | |
</a> | |
//---- If I was not the one who started the chat betwwen us show me the avatar of the other userwho did it | |
@else | |
<div class="list-group-item list-group-item-action text-white rounded-0 user3" wire:click="$emit('selected_users',{{$conversation->first_user}})" > | |
<div class="media " > | |
<img src="{{Voyager::image($conversation->fiirst_user->avatar)}}" alt="user" width="50" class="rounded-circle"> | |
<div class="media-body ml-4 user"> | |
<div class="d-flex align-items-center justify-content-between mb-1" > | |
<h6 class="mb-0" style="color: black">{{$conversation->fiirst_user->name}}</h6><small class="small font-weight-bold" style="color: black"></small> | |
</div> | |
<p class="badge badge-danger {{$conversation->first_user}}" style="color: black" id="{{'user.'.$conversation->first_user}}"> | |
{{\App\Message::where('statu','unreaded')->where('to_user',Auth::user()->id)->where('from_user',$conversation->fiirst_user->id)->count()}}</p> | |
</div> | |
</div> | |
<p></p> | |
</div> | |
@endif | |
@endforeach | |
</div> | |
</div> | |
// users section | |
<div class="messages-box list-group users rounded-0" wire:ignore x-show.transition.in="tab === 'all'"> | |
<button class="btn" :class="{ 'active': tab === 'recent' }" @click="tab = 'recent'" style="border:none;"> | |
<img class="float-right" src="{{asset('icons/icons/back.png')}}" width="40" > | |
</button> | |
@foreach($users as $user) | |
<a class="list-group-item list-group-item-action text-white rounded-0" wire:click="$emit('selected_users',{{$user->id}})" > | |
<div class="media "> | |
<img src="{{Voyager::image($user->avatar)}}" alt="user" width="50" class="rounded-circle"> | |
<div class="media-body ml-4 user" > | |
<div class="d-flex align-items-center justify-content-between mb-1"> | |
<h6 class="mb-0" style="color: black">{{$user->name}}</h6><small class="small font-weight-bold" style="color: black"></small> | |
</div> | |
</div> | |
</div> | |
</a> | |
@endforeach | |
</div> | |
</div> | |
</div> | |
//------------------------------------------ | |
<!-- Chat Box--> | |
<div class="col-7 px-0"> | |
<div class="py-5 chat-box bg-white messages " id="messages"> | |
<!-- Messages--> | |
<div class="messages-boxx" id="messages-boxx" > | |
@foreach($messages as $message) | |
@if(Auth::user()->id == $message->from_user) | |
<!-- Reciever Message--> | |
<div class="media w-50 ml-auto mb-3"> | |
<div class="media-body"> | |
<div class="bg-primary rounded py-2 px-3 mb-2"> | |
<p class="text-small mb-0 text-white">{{$message->body}}</p> | |
</div> | |
<p class="small text-muted">{{$message->created_at}}</p> | |
</div> | |
</div> | |
@else | |
<!-- Sender Message--> | |
<div class="media w-50 mb-3"> | |
<img src="{{Voyager::image($message->froom_user->avatar)}}" alt="user" width="50" class="rounded-circle"> | |
<div class="media-body ml-3"> | |
<div class="bg-light rounded py-2 px-3 mb-2"> | |
<p class="text-small mb-0 text-muted">{{$message->body}}</p> | |
</div> | |
<p class="small text-muted">{{$message->created_at}}</p> | |
</div> | |
</div> | |
@endif | |
@endforeach | |
</div> | |
</div> | |
<div class="bg-light"> | |
<div class="input-group"> | |
<input type="text" placeholder="Type a message" aria-describedby="button-addon2" class="form-control rounded-0 border-0 py-4 bg-light" wire:model='message'> | |
<div class="input-group-append"> | |
<button id="button-addon2" type="submit" class="btn btn-link" wire:click='send'> <i class="fa fa-paper-plane" ></i></button> | |
</div> | |
</div> | |
</div> | |
</div> | |
vb
###
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
any guide steps like I need php artisan migrate something ? any documentation ?