Step 5: Real-time broadcasting (NewEmailReceived event, channel routes, Livewire listener)
This commit is contained in:
68
app/Events/NewEmailReceived.php
Normal file
68
app/Events/NewEmailReceived.php
Normal 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(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,6 +40,37 @@ class Mailbox extends Component
|
|||||||
|
|
||||||
public $availableDomains = ['imail.com', 'devmail.ai', 'temp-inbox.net'];
|
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()
|
public function getEmailsProperty()
|
||||||
{
|
{
|
||||||
// Mock emails based on mailbox ID
|
// Mock emails based on mailbox ID
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
use Illuminate\Support\Facades\Broadcast;
|
use Illuminate\Support\Facades\Broadcast;
|
||||||
|
|
||||||
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
|
// Private channel: authenticated user can only listen to their own channel
|
||||||
return (int) $user->id === (int) $id;
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user