Auto-join host into live session when going live from green room.
Deploy Ladill Meet / deploy (push) Successful in 2m1s

Green room poll was racing go-live and sending the host to the ended page; carry participant session into the new live session instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-02 06:57:33 +00:00
co-authored by Cursor
parent eadb77dd5b
commit 8162827957
6 changed files with 248 additions and 7 deletions
@@ -15,6 +15,7 @@ use App\Services\Meet\FileSharingService;
use App\Services\Meet\LiveStreamService;
use App\Services\Meet\PollService;
use App\Services\Meet\QaService;
use App\Services\Meet\SessionService;
use App\Services\Meet\StageLayoutService;
use App\Services\Meet\TownHallService;
use App\Services\Meet\WhiteboardService;
@@ -34,6 +35,7 @@ class MeetingFeaturesController extends Controller
protected LiveStreamService $liveStreams,
protected TownHallService $townHall,
protected StageLayoutService $stageLayout,
protected SessionService $sessions,
) {}
// --- Q&A ---
@@ -282,13 +284,24 @@ class MeetingFeaturesController extends Controller
public function goLiveTownHall(Request $request, Session $session): JsonResponse
{
$this->hostOnly($request, $session);
$live = $this->townHall->goLive($session, $request->user());
$participant = app(SessionService::class)->joinedParticipantForUser($live, $request->user());
$hostParticipant = $this->hostOnly($request, $session);
if ($participant) {
app(SessionService::class)->rememberParticipantSession($request, $participant, $live);
}
$user = $request->user()
?? ($hostParticipant->user_ref ? \App\Models\User::where('public_id', $hostParticipant->user_ref)->first() : null);
abort_unless($user, 403);
$live = $this->townHall->goLive($session, $user);
$this->sessions->ensureJoinedParticipant(
$request,
$live,
$user,
'host',
$hostParticipant->display_name,
$hostParticipant->email,
);
$request->session()->forget("meet.participant.{$session->uuid}");
return response()->json([
'session_uuid' => $live->uuid,
@@ -16,6 +16,7 @@ use App\Services\Meet\SecurityPolicyService;
use App\Services\Meet\SessionService;
use App\Services\Meet\SpaceService;
use App\Services\Meet\StageLayoutService;
use App\Services\Meet\TownHallService;
use App\Services\Meet\TranscriptService;
use App\Services\Meet\WebinarService;
use Illuminate\Http\JsonResponse;
@@ -44,6 +45,12 @@ class MeetingRoomController extends Controller
$kind = $room->isConference() ? 'conference' : 'meeting';
$participantUuid = $request->session()->get("meet.participant.{$session->uuid}");
if (! $participantUuid && $request->user() && $request->user()->ownerRef() === $room->host_user_ref) {
$hostParticipant = $this->sessions->ensureJoinedParticipant($request, $session, $request->user(), 'host');
$participantUuid = $hostParticipant->uuid;
}
abort_unless($participantUuid, 403, "Please join the {$kind} first.");
$participant = Participant::where('uuid', $participantUuid)
@@ -227,6 +234,27 @@ class MeetingRoomController extends Controller
public function poll(Request $request, Session $session): JsonResponse
{
if (! $session->isLive()) {
$townHall = app(TownHallService::class);
$liveSession = $townHall->successorLiveSession($session);
if ($liveSession) {
$participantUuid = $request->session()->get("meet.participant.{$session->uuid}");
if ($participantUuid) {
$greenParticipant = Participant::where('uuid', $participantUuid)
->where('session_id', $session->id)
->first();
if ($greenParticipant && $this->sessions->transitionGreenRoomParticipant($request, $greenParticipant, $liveSession)) {
return response()->json([
'ended' => true,
'redirect' => route('meet.room', $liveSession),
'transition' => 'go_live',
]);
}
}
}
return response()->json([
'ended' => true,
'redirect' => route('meet.ended', $session),
+62
View File
@@ -233,6 +233,68 @@ class SessionService
$request->session()->put("meet.participant.{$session->uuid}", $participant->uuid);
}
public function ensureJoinedParticipant(
Request $request,
Session $session,
?User $user,
string $role,
?string $displayName = null,
?string $email = null,
): Participant {
if ($user) {
$existing = $this->joinedParticipantForUser($session, $user);
if ($existing) {
$this->rememberParticipantSession($request, $existing, $session);
return $existing;
}
}
$participant = $this->joinParticipant($session, $user, $role, $displayName, $email);
$this->rememberParticipantSession($request, $participant, $session);
return $participant;
}
public function transitionGreenRoomParticipant(
Request $request,
Participant $greenParticipant,
Session $liveSession,
): ?Participant {
$presenters = (array) $liveSession->presenter_refs;
$isPresenter = in_array($greenParticipant->role, ['host', 'co_host', 'panelist'], true)
|| ($greenParticipant->user_ref && in_array($greenParticipant->user_ref, $presenters, true));
if (! $isPresenter) {
return null;
}
$user = $greenParticipant->user_ref
? User::where('public_id', $greenParticipant->user_ref)->first()
: null;
$role = $greenParticipant->role;
if ($user && $user->ownerRef() === $liveSession->room->host_user_ref) {
$role = 'host';
} elseif (! in_array($role, ['host', 'co_host', 'panelist'], true)) {
$role = 'panelist';
}
$greenSession = $greenParticipant->session;
$participant = $this->ensureJoinedParticipant(
$request,
$liveSession,
$user,
$role,
$greenParticipant->display_name,
$greenParticipant->email,
);
$request->session()->forget("meet.participant.{$greenSession->uuid}");
return $participant;
}
public function joinedParticipantForUser(Session $session, User $user): ?Participant
{
return $session->participants()
+14
View File
@@ -66,6 +66,20 @@ class TownHallService
return $liveSession;
}
public function successorLiveSession(Session $greenRoomSession): ?Session
{
if ($greenRoomSession->session_mode !== 'green_room' || $greenRoomSession->isLive()) {
return null;
}
return $greenRoomSession->room->sessions()
->where('status', 'live')
->where('session_mode', 'live')
->where('id', '!=', $greenRoomSession->id)
->latest('started_at')
->first();
}
public function handoffCoHost(Session $session, Participant $from, string $toUserRef): Participant
{
abort_unless(in_array($from->role, ['host', 'co_host'], true), 403);