Skip to content

Commit

Permalink
Merge pull request #15 from mohammed9895/main
Browse files Browse the repository at this point in the history
[Main] Add sort option config file and typing indicator
  • Loading branch information
199ocero authored Nov 28, 2024
2 parents 585ea4a + 8e0949f commit 959ea5b
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 28 deletions.
12 changes: 12 additions & 0 deletions config/filachat.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,18 @@
*/
'navigation_icon' => 'heroicon-o-chat-bubble-bottom-center',

/*
|--------------------------------------------------------------------------
| Navigation Sort
|--------------------------------------------------------------------------
|
| This option specifies the navigation sort used in the chat navigation. You can
| customize this if you have a different sort order in your application.
|
*/

'navigation_sort' => 1,

/*
|--------------------------------------------------------------------------
| Max Content Width
Expand Down
85 changes: 57 additions & 28 deletions resources/views/filachat/components/chat-box.blade.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
@props(['selectedConversation'])
<!-- Right Section (Chat Conversation) -->
<div
x-load-css="[@js(\Filament\Support\Facades\FilamentAsset::getStyleHref('filachat-styles', package: 'jaocero/filachat'))]"
class="flex flex-col w-full md:w-2/3 overflow-hidden">
x-load-css="[@js(\Filament\Support\Facades\FilamentAsset::getStyleHref('filachat-styles', package: 'jaocero/filachat'))]"
class="flex flex-col w-full md:w-2/3 overflow-hidden">
@if ($selectedConversation)
<!-- Chat Header -->
<div class="flex items-center h-20 gap-2 p-5 border-b dark:border-gray-800/60 border-gray-200/90">
Expand All @@ -29,26 +29,54 @@ class="flex flex-col w-full md:w-2/3 overflow-hidden">
</div>

<!-- Chat Messages -->
<div x-data="{ markAsRead: false }" x-init="
<div x-data="{ markAsRead: false, isTyping:false }" x-init="
Echo.channel('filachat')
.listen('.JaOcero\\FilaChat\\Events\\FilaChatMessageReadEvent', e => {
if (e.conversationId == @js($selectedConversation->id)) {
markAsRead = true;
}
})
.listen('.JaOcero\\FilaChat\\Events\\FilaChatMessageReceiverIsAwayEvent', e => {
if (e.conversationId == @js($selectedConversation->id)) {
markAsRead = false;
const channel = Echo.channel('filachat');
channel.listen('.JaOcero\\FilaChat\\Events\\FilaChatMessageReadEvent', e => {
if (e.conversationId == @js($selectedConversation->id)) {
markAsRead = true;
}
});
channel.listen('.JaOcero\\FilaChat\\Events\\FilaChatMessageReceiverIsAwayEvent', e => {
if (e.conversationId == @js($selectedConversation->id)) {
markAsRead = false;
}
});
// listen to typing event and reset the typing status after 3 seconds
channel.listen('.JaOcero\\FilaChat\\Events\\FilaChatUserTypingEvent', e => {
if (e.conversationId == @js($selectedConversation->id)) {
if(e.receiverId == @js(auth()->id())) {
isTyping = true;
setTimeout(() => {
isTyping = false;
}, 3000);
}
});
}
});
" id="chatContainer"
class="flex flex-col-reverse flex-1 p-5 overflow-y-auto">
class="flex flex-col-reverse flex-1 p-5 overflow-y-auto">
<!-- add the typing indicator to the bottom of the chat box -->
<div class="flex items-end gap-2 mb-2" x-show="isTyping">
<x-filament::avatar
src="https://ui-avatars.com/api/?name={{ urlencode($selectedConversation->other_person_name) }}"
alt="Profile" size="sm" />
<div class="max-w-md p-2 bg-gray-200 rounded-t-xl rounded-br-xl dark:bg-gray-800" >
<p class="text-sm">
<svg height="40" width="40" class="loader">
<circle class="dot" cx="10" cy="20" r="3" style="fill:grey;" />
<circle class="dot" cx="20" cy="20" r="3" style="fill:grey;" />
<circle class="dot" cx="30" cy="20" r="3" style="fill:grey;" />
</svg>
</p>
</div>
</div>
<!-- Message Item -->
@foreach ($conversationMessages as $index => $message)
<div wire:key="{{ $message->id }}">
@php
@php
$nextMessage = $conversationMessages[$index + 1] ?? null;
$nextMessageDate = $nextMessage ? \Carbon\Carbon::parse($nextMessage->created_at)->setTimezone(config('filachat.timezone', 'app.timezone'))->format('Y-m-d') : null;
$currentMessageDate = \Carbon\Carbon::parse($message->created_at)->setTimezone(config('filachat.timezone', 'app.timezone'))->format('Y-m-d');
Expand All @@ -75,7 +103,7 @@ class="flex flex-col-reverse flex-1 p-5 overflow-y-auto">
// Show avatar if the current message is the first in a consecutive sequence or a new day
$showAvatar = $message->senderable_id !== auth()->user()->id && ($message->senderable_id !== $previousSenderId || $currentMessageDate !== $previousMessageDate);
@endphp
<!-- Left Side -->
<!-- Left Side -->
<div class="flex items-end gap-2 mb-2">
@if ($showAvatar)
<x-filament::avatar
Expand Down Expand Up @@ -217,6 +245,7 @@ class="flex flex-col-reverse flex-1 p-5 overflow-y-auto">
<div class="w-full mb-6 text-center text-gray-500">{{__('Loading more messages...')}}</div>
</div>
@endif

</div>


Expand Down Expand Up @@ -247,18 +276,18 @@ class="flex flex-col-reverse flex-1 p-5 overflow-y-auto">

</div>
@script
<script>
$wire.on('chat-box-scroll-to-bottom', () => {
<script>
$wire.on('chat-box-scroll-to-bottom', () => {
chatContainer = document.getElementById('chatContainer');
chatContainer.scrollTo({
top: chatContainer.scrollHeight,
behavior: 'smooth',
});
setTimeout(() => {
chatContainer.scrollTop = chatContainer.scrollHeight;
}, 400);
chatContainer = document.getElementById('chatContainer');
chatContainer.scrollTo({
top: chatContainer.scrollHeight,
behavior: 'smooth',
});
</script>
setTimeout(() => {
chatContainer.scrollTop = chatContainer.scrollHeight;
}, 400);
});
</script>
@endscript
37 changes: 37 additions & 0 deletions src/Events/FilaChatUserTypingEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace JaOcero\FilaChat\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class FilaChatUserTypingEvent implements ShouldBroadcastNow
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

public string $type = FilaChatUserTypingEvent::class;

/**
* Create a new event instance.
*/
public function __construct(
public int $conversationId,
public bool $isTyping,
public int $receiverId,
) {}

/**
* Get the channels the event should broadcast on.
*
* @return Channel
*/
public function broadcastOn()
{
return new Channel('filachat');
}
}
14 changes: 14 additions & 0 deletions src/Livewire/ChatBox.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use JaOcero\FilaChat\Events\FilaChatMessageEvent;
use JaOcero\FilaChat\Events\FilaChatMessageReadEvent;
use JaOcero\FilaChat\Events\FilaChatMessageReceiverIsAwayEvent;
use JaOcero\FilaChat\Events\FilaChatUserTypingEvent;
use JaOcero\FilaChat\Models\FilaChatMessage;
use JaOcero\FilaChat\Traits\CanGetOriginalFileName;
use JaOcero\FilaChat\Traits\CanValidateAudio;
Expand Down Expand Up @@ -102,6 +103,19 @@ public function form(Form $form): Form
->grow(false),
Forms\Components\Textarea::make('message')
->hiddenLabel()
->live(debounce: 500)
->afterStateUpdated(function (?string $old, ?string $state) {
// check and set the receiver id
if (auth()->id() === $this->selectedConversation->receiverable_id) {
$receiverableId = $this->selectedConversation->senderable_id;
} else {
$receiverableId = $this->selectedConversation->receiverable_id;
}
// check if the user is typing by comparing the old state and the new state and broadcast the typing event
if ($state != $old) {
broadcast(new FilaChatUserTypingEvent($this->selectedConversation->id, true, $receiverableId));
}
})
->placeholder(function () use ($isRoleEnabled, $isAgent, $isOtherPersonAgent) {
if ($isRoleEnabled) {

Expand Down
5 changes: 5 additions & 0 deletions src/Pages/FilaChat.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ public static function getNavigationIcon(): string | Htmlable | null
return config('filachat.navigation_icon');
}

public static function getNavigationSort(): ?int
{
return config('filachat.navigation_sort');
}

public function mount(?int $id = null): void
{
if ($id) {
Expand Down

0 comments on commit 959ea5b

Please sign in to comment.