Skip to content

Instantly share code, notes, and snippets.

@developerdza
Last active July 22, 2024 11:22
Show Gist options
  • Select an option

  • Save developerdza/dfca78f31a408e52806f11cbda2dc587 to your computer and use it in GitHub Desktop.

Select an option

Save developerdza/dfca78f31a408e52806f11cbda2dc587 to your computer and use it in GitHub Desktop.

Revisions

  1. developerdza revised this gist Jun 19, 2020. 3 changed files with 84 additions and 21 deletions.
    48 changes: 28 additions & 20 deletions Controllers--Livewire--Chat.php
    Original file line number Diff line number Diff line change
    @@ -10,26 +10,27 @@
    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
    // get user unreaded messages -- جلب الرسائل غير المقروءة المرسلة من طرف باقي المستخدمين
    public function mount()
    {
    $this->unreadedMessages = Auth::user()->unreadedMessages()->count();

    }
    public function render()
    {
    // get user unreaded messages
    // get user unreaded messages -- -- تخزين الرسائل غير المقروءة في متغير
    $unreadedMessages = $this->unreadedMessages;
    // select the user I want to chat with
    // جلب المستخدم الذي أود الحديث معه
    // select the user I want to chat with --
    $id = $this->chat_id;
    // get selected user Info ---------------------------
    // get selected user Info ------معلوماته
    if (isset($this->chat_id)) {
    $chat_user = User::find($id);
    }
    @@ -38,33 +39,36 @@ public function render()
    }
    //--------------------------------

    //جلب كل لامستخدمين كي أختار واحدا من بينهم أكلمه
    // 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)
    // counting حساب عدد الرسائل المرسلة من طرفه و غير مقروءة من طرفي
    $messages_count = Message::where('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
    // لكي لا يكون عليك انتظار كل الرسائل بينكما لتظهر ... سيظهر عدد محدد من الرسائل في البداية فقط و عندما تسحب لأعلى ستظهر الرسائل التي سبقتها
    //الكود يقوم بجلب عدد كل الرسائل بيني و بين المستخدم الاخر و يطرح منه العدد الذي أريد رؤيته و العدد الباقي من الرسائل يتخطاه
    // 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)
    {
    @@ -73,14 +77,15 @@ public function selected_users($id)
    Message::where('statu','unreaded')
    ->where('to_user',Auth::user()->id)
    ->where('from_user',$id)
    ->update(array('statu'=>'readed'));
    ->update(array('statu'=>'readed'));
    // يعود عدد الرسائل المرئية على أصله مع كل تحديد جديد للمستخدم
    // number of messages Iwant to show
    $this->paginate_var = 10;
    // scrollng to bottom
    // scrollng to bottom بمجرد الدخول لمحادثة مع مستخدم جديد سيقوم بالسحب لأسفل المحادثة مباشرة
    $this->emit('scroll');
    }

    // sending messages
    // sending messages -- إرسال الرسائل
    public function send($id)
    {
    //---
    @@ -91,8 +96,9 @@ public function send($id)
    $message->save();
    //--

    //----------------------------Conversation------------------------
    //check if there is an old conversation between us
    //----------------------------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)
    @@ -119,7 +125,8 @@ public function send($id)
    $message->conversation_id = $conversation->id;
    $message->save();
    }
    //---------------------------- End Conversation------------------------
    //---------------------------- End Conversation------------------------
    // إرسال الايفنت
    // -------------------------------Event-----------------
    //get Unreaded messages
    $recivedUnreadedMessages =Message::where('statu','unreaded')
    @@ -131,7 +138,8 @@ public function send($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));
    }

    // مع كل صعود تام لأعلى المحادثة ستزيد 10 رسائل

    // Load more then 10 messaeges by scrolling to top
    public function loadMore()
    {
    51 changes: 51 additions & 0 deletions Database
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,51 @@
    1 //---Tables--------

    1-users['name' , 'avatar' , .......],
    2-messages ['id' , 'body' , 'from_user' , 'to_user' , 'created_at' , 'updated_at'],
    3-conversations ['id' , 'first_user' , 'second_user' , 'date_of_last_message'],

    2 // ----------Relations---------

    **User Model ::
    public function messages()
    {
    return $this->hasMany(Message::Class);
    }

    **Convesation Model
    public function messages()
    {
    return $this->hasMany(Message::Class);
    }

    public function fiirst_user()
    {
    return $this->belongsTo('App\User','first_user');
    }

    public function seecond_user()
    {
    return $this->belongsTo('App\User','second_user');
    }

    **Message Model ::


    protected $fillable = array('statu');
    public function user()
    {
    return $this->belongsTo('App\User');
    }

    public function froom_user()
    {
    return $this->belongsTo('App\User','from_user');
    }

    public function too_user()
    {
    return $this->belongsTo('App\User','to_user');
    }



    6 changes: 5 additions & 1 deletion Js
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,6 @@
    1-----------------
    <script type="text/javascript">
    //عندما أصعد إلى أعلى أشغل الايفنت ليظهر عدد أكبر من الرسائل
    // when I scroll to top I fire the event load more to show more old messages
    $('#messages').scroll(function() {

    @@ -13,7 +14,7 @@
    </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() {
    @@ -36,14 +37,17 @@
    // 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
  2. developerdza renamed this gist Jun 19, 2020. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  3. developerdza revised this gist Jun 19, 2020. 5 changed files with 384 additions and 2 deletions.
    141 changes: 141 additions & 0 deletions Controllers--Livewire--Chat.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,141 @@
    <?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');
    }
    }
    46 changes: 46 additions & 0 deletions Events --- Chat
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    <?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';
    }
    }
    77 changes: 77 additions & 0 deletions Js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,77 @@
    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>
    120 changes: 120 additions & 0 deletions Views--Livewire--Chat.blade.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,120 @@
    // 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>

    2 changes: 0 additions & 2 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -1,2 +0,0 @@
    السلام عليكم

  4. developerdza created this gist Jun 19, 2020.
    2 changes: 2 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2 @@
    السلام عليكم