Deploy Ladill Meet / deploy (push) Successful in 33s
Let attendees request host-granted microphone access with LiveKit reconnect, participant panel controls, and toolbar UI that only shows mic when allowed. Fix Events create URL, surface API key setup guidance, and align the Webinars sidebar icon with other nav items using currentColor strokes. Co-authored-by: Cursor <cursoragent@cursor.com>
84 lines
2.4 KiB
PHP
84 lines
2.4 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Meet;
|
|
|
|
use App\Models\Participant;
|
|
use App\Models\Room;
|
|
|
|
class SpeakAccessService
|
|
{
|
|
public function usesSpeakAccess(Room $room): bool
|
|
{
|
|
return $room->isWebinar() || $room->isConference();
|
|
}
|
|
|
|
public function canManageSpeakAccess(Participant $participant): bool
|
|
{
|
|
$room = $participant->session->room;
|
|
|
|
if (! $this->usesSpeakAccess($room)) {
|
|
return false;
|
|
}
|
|
|
|
return in_array($participant->role, ['host', 'co_host', 'panelist'], true);
|
|
}
|
|
|
|
public function requestSpeak(Participant $participant): Participant
|
|
{
|
|
$room = $participant->session->room;
|
|
abort_unless($this->usesSpeakAccess($room), 422);
|
|
abort_unless($participant->role === 'attendee', 422);
|
|
abort_unless(! $participant->speak_granted, 422, 'You already have speak access.');
|
|
|
|
$participant->update(['speak_requested' => true]);
|
|
|
|
return $participant->fresh();
|
|
}
|
|
|
|
public function cancelSpeakRequest(Participant $participant): Participant
|
|
{
|
|
$participant->update(['speak_requested' => false]);
|
|
|
|
return $participant->fresh();
|
|
}
|
|
|
|
public function grantSpeak(Participant $target, Participant $actor): Participant
|
|
{
|
|
abort_unless($this->canManageSpeakAccess($actor), 403);
|
|
abort_unless($target->session_id === $actor->session_id, 404);
|
|
abort_unless($target->status === 'joined', 422);
|
|
abort_unless($this->usesSpeakAccess($target->session->room), 422);
|
|
|
|
$target->update([
|
|
'speak_granted' => true,
|
|
'speak_requested' => false,
|
|
]);
|
|
|
|
return $target->fresh();
|
|
}
|
|
|
|
public function revokeSpeak(Participant $target, Participant $actor): Participant
|
|
{
|
|
abort_unless($this->canManageSpeakAccess($actor), 403);
|
|
abort_unless($target->session_id === $actor->session_id, 404);
|
|
|
|
$target->update([
|
|
'speak_granted' => false,
|
|
'speak_requested' => false,
|
|
'is_muted' => true,
|
|
]);
|
|
|
|
return $target->fresh();
|
|
}
|
|
|
|
public function dismissSpeakRequest(Participant $target, Participant $actor): Participant
|
|
{
|
|
abort_unless($this->canManageSpeakAccess($actor), 403);
|
|
abort_unless($target->session_id === $actor->session_id, 404);
|
|
|
|
$target->update(['speak_requested' => false]);
|
|
|
|
return $target->fresh();
|
|
}
|
|
}
|