Implement conference breakouts with meeting mode and programme lineup UI.
Deploy Ladill Meet / deploy (push) Successful in 1m3s
Deploy Ladill Meet / deploy (push) Successful in 1m3s
Attendees reconnect to breakout rooms with publish access while hosts stay on stage; poll and media-token endpoints drive LiveKit reconnection, and the live room shows Events-linked programme when available. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -263,30 +263,70 @@ class SessionService
|
||||
|
||||
public function generateMediaToken(Participant $participant): string
|
||||
{
|
||||
$session = $participant->session;
|
||||
$room = $session->room;
|
||||
$isHost = $participant->isHost();
|
||||
$breakoutService = app(BreakoutService::class);
|
||||
$webinarService = app(WebinarService::class);
|
||||
$spaceService = app(\App\Services\Meet\SpaceService::class);
|
||||
$mediaRoom = $breakoutService->mediaRoomForParticipant($participant);
|
||||
$canPublish = ($room->isSpace()
|
||||
? $spaceService->canPublish($room, $participant)
|
||||
: $webinarService->canPublish($room, $participant)) && $participant->canPublishMedia();
|
||||
$participant->loadMissing('breakoutRoom');
|
||||
$state = $this->mediaSessionState($participant);
|
||||
$mediaRoom = app(BreakoutService::class)->mediaRoomForParticipant($participant);
|
||||
|
||||
return $this->media->generateToken(
|
||||
$mediaRoom,
|
||||
$participant->uuid,
|
||||
$participant->display_name,
|
||||
[
|
||||
'can_publish' => $canPublish,
|
||||
'can_publish' => $state['can_publish'],
|
||||
'can_subscribe' => true,
|
||||
'can_publish_data' => true,
|
||||
'room_admin' => $isHost,
|
||||
'room_admin' => $participant->isHost(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/** @return array{can_publish: bool, uses_stage_layout: bool, in_breakout: bool, breakout_room_id: ?int, breakout: ?array{uuid: string, name: string, closes_at: ?string}} */
|
||||
public function mediaSessionState(Participant $participant): array
|
||||
{
|
||||
$participant->loadMissing(['breakoutRoom', 'session.room']);
|
||||
$room = $participant->session->room;
|
||||
$breakoutService = app(BreakoutService::class);
|
||||
$inBreakout = $breakoutService->isInActiveBreakout($participant);
|
||||
$usesStageLayout = app(StageLayoutService::class)->usesStageLayout($room) && ! $inBreakout;
|
||||
|
||||
$breakout = null;
|
||||
if ($inBreakout && $participant->breakoutRoom) {
|
||||
$breakout = [
|
||||
'uuid' => $participant->breakoutRoom->uuid,
|
||||
'name' => $participant->breakoutRoom->name,
|
||||
'closes_at' => $participant->breakoutRoom->closes_at?->toIso8601String(),
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'can_publish' => $this->canParticipantPublish($participant, $inBreakout),
|
||||
'uses_stage_layout' => $usesStageLayout,
|
||||
'in_breakout' => $inBreakout,
|
||||
'breakout_room_id' => $inBreakout ? $participant->breakout_room_id : null,
|
||||
'breakout' => $breakout,
|
||||
];
|
||||
}
|
||||
|
||||
public function canParticipantPublish(Participant $participant, ?bool $inBreakout = null): bool
|
||||
{
|
||||
$breakoutService = app(BreakoutService::class);
|
||||
$inBreakout ??= $breakoutService->isInActiveBreakout($participant);
|
||||
|
||||
if ($inBreakout) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$room = $participant->session->room;
|
||||
|
||||
if ($room->isSpace()) {
|
||||
return app(\App\Services\Meet\SpaceService::class)->canPublish($room, $participant)
|
||||
&& $participant->canPublishMedia();
|
||||
}
|
||||
|
||||
return app(WebinarService::class)->canPublish($room, $participant)
|
||||
&& $participant->canPublishMedia();
|
||||
}
|
||||
|
||||
public function getOrStartSession(Room $room, User $host): Session
|
||||
{
|
||||
if ($room->activeSession()) {
|
||||
|
||||
Reference in New Issue
Block a user