Step 5: Real-time broadcasting (NewEmailReceived event, channel routes, Livewire listener)

This commit is contained in:
idevakk
2026-03-05 14:14:04 +05:30
parent dc5029e8cb
commit ac9e7227e6
3 changed files with 104 additions and 3 deletions

View File

@@ -0,0 +1,68 @@
<?php
namespace App\Events;
use App\Models\Email;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NewEmailReceived implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*/
public function __construct(
public Email $email,
) {}
/**
* Get the channels the event should broadcast on.
*
* Broadcasts on a public channel keyed by domain.
* Private user channels will be added when user-mailbox assignment is implemented.
*
* @return array<int, Channel>
*/
public function broadcastOn(): array
{
return [
new Channel('mailbox.'.$this->email->domain),
];
}
/**
* The event's broadcast name.
*/
public function broadcastAs(): string
{
return 'new.email';
}
/**
* Get the data to broadcast.
*
* @return array<string, mixed>
*/
public function broadcastWith(): array
{
return [
'id' => $this->email->id,
'unique_id_hash' => $this->email->unique_id_hash,
'recipient_email' => $this->email->recipient_email,
'sender_email' => $this->email->sender_email,
'sender_name' => $this->email->sender_name,
'domain' => $this->email->domain,
'subject' => $this->email->subject,
'preview' => $this->email->preview,
'attachments_json' => $this->email->attachments_json,
'attachment_size' => $this->email->attachment_size,
'is_read' => $this->email->is_read,
'received_at' => $this->email->received_at?->toISOString(),
];
}
}

View File

@@ -40,6 +40,37 @@ class Mailbox extends Component
public $availableDomains = ['imail.com', 'devmail.ai', 'temp-inbox.net'];
/**
* Get Reverb/Echo event listeners for the current mailbox domain.
*
* @return array<string, string>
*/
public function getListeners(): array
{
$currentMailbox = collect($this->activeMailboxes)->firstWhere('id', $this->currentMailboxId);
$domain = $currentMailbox ? explode('@', $currentMailbox['address'])[1] ?? '' : '';
if (empty($domain)) {
return [];
}
return [
"echo:mailbox.{$domain},.new.email" => 'onNewEmail',
];
}
/**
* Handle a new email broadcast event from Reverb.
*
* @param array<string, mixed> $eventData The email data from the broadcast.
*/
public function onNewEmail(array $eventData): void
{
// TODO: When real data integration is complete, prepend the new email to the list.
// For now, trigger a component refresh to pick up new data.
$this->dispatch('$refresh');
}
public function getEmailsProperty()
{
// Mock emails based on mailbox ID

View File

@@ -2,6 +2,8 @@
use Illuminate\Support\Facades\Broadcast;
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
return (int) $user->id === (int) $id;
});
// Private channel: authenticated user can only listen to their own channel
Broadcast::channel('user.{id}', fn ($user, $id) => (int) $user->id === (int) $id);
// Public channel: mailbox.{domain} — no auth needed for temp email service
// The domain channel is public so guests can receive real-time updates