From cb30ecade9f5d433df247503fc0d3cd709f485e3 Mon Sep 17 00:00:00 2001 From: maro Date: Thu, 17 Sep 2026 01:13:07 +0200 Subject: [PATCH] fix: request media directly and expose host moderation --- components/meeting/CallRoom.tsx | 47 +++++++++++++--- components/meeting/PreJoinScreen.tsx | 80 ++++++++++++++++++---------- 2 files changed, 91 insertions(+), 36 deletions(-) diff --git a/components/meeting/CallRoom.tsx b/components/meeting/CallRoom.tsx index 0742ae0..9f1ff1d 100644 --- a/components/meeting/CallRoom.tsx +++ b/components/meeting/CallRoom.tsx @@ -1,7 +1,7 @@ "use client"; import { useEffect, useRef, useState } from "react"; -import { DisconnectReason, Room, RoomEvent, Track, type LocalTrack, type Participant } from "livekit-client"; +import { DisconnectReason, Room, RoomEvent, Track, type Participant } from "livekit-client"; import { PreJoinScreen } from "./PreJoinScreen"; import { SfuVideoTile } from "./SfuVideoTile"; import { MEETING_SESSION_KEY, type StoredMeetingSession } from "./JoinForm"; @@ -73,7 +73,7 @@ export function CallRoom({ slug }: { slug: string }) { const [callDurationMs, setCallDurationMs] = useState(null); const roomRef = useRef(null); - const localTracksRef = useRef([]); + const localTracksRef = useRef([]); const activeSpeakersRef = useRef>(new Set()); const intentionalCloseRef = useRef(false); const connectedAtRef = useRef(null); @@ -163,7 +163,7 @@ export function CallRoom({ slug }: { slug: string }) { setPhase("ended"); } - async function connectRoom(previewTracks: LocalTrack[]) { + async function connectRoom(previewTracks: MediaStreamTrack[]) { if (!session) return; setPhase("connecting"); setErrorMessage(null); @@ -225,12 +225,12 @@ export function CallRoom({ slug }: { slug: string }) { await room.connect(serverUrl, participantToken); for (const track of previewTracks) { await room.localParticipant.publishTrack(track, { - source: track.kind === Track.Kind.Audio ? Track.Source.Microphone : Track.Source.Camera, + source: track.kind === "audio" ? Track.Source.Microphone : Track.Source.Camera, }); } refresh(); - setMicOn(previewTracks.some((track) => track.kind === Track.Kind.Audio && track.mediaStreamTrack.enabled)); - setCamOn(previewTracks.some((track) => track.kind === Track.Kind.Video && track.mediaStreamTrack.enabled)); + setMicOn(previewTracks.some((track) => track.kind === "audio" && track.enabled)); + setCamOn(previewTracks.some((track) => track.kind === "video" && track.enabled)); connectedAtRef.current = Date.now(); setCallDurationMs(null); setPhase("connected"); @@ -366,7 +366,9 @@ export function CallRoom({ slug }: { slug: string }) {

{session.eventTitle}

LiveKit-SFU · {participants.length} Teilnehmer

{(["grid", "speaker", "screen"] as LayoutMode[]).map((mode) => )} - +
{errorMessage &&

{errorMessage}

} @@ -376,7 +378,36 @@ export function CallRoom({ slug }: { slug: string }) { {layout === "speaker" && activeSpeaker &&
{tile(activeSpeaker, { videoTrack: activeSpeaker.screenTrack ?? activeSpeaker.cameraTrack })}
{participants.filter((participant) => participant.identity !== activeSpeaker.identity).map((participant) => tile(participant, { compact: true }))}
} {layout === "screen" &&
{screenOwner ?
{tile(screenOwner, { videoTrack: screenOwner.screenTrack, name: `${screenOwner.name} · Bildschirm` })}
:
Noch niemand teilt den Bildschirm.
}
{participants.map((participant) => tile(participant, { compact: true }))}
} - {showParticipants && } + {showParticipants && ( + + )}