diff --git a/components/CTA.tsx b/components/CTA.tsx index 3dc4ef2..b5a482b 100644 --- a/components/CTA.tsx +++ b/components/CTA.tsx @@ -1,5 +1,4 @@ import { Button } from "@/components/Button"; -import { OrganicBlob } from "@/components/OrganicBlob"; import { Container } from "@/components/Section"; type CTAProps = { @@ -20,9 +19,7 @@ export function CTA({ secondaryLabel = "Kontakt aufnehmen", }: CTAProps) { return ( -
- - +

{title} diff --git a/components/meeting/PreJoinScreen.tsx b/components/meeting/PreJoinScreen.tsx index b0ba99a..ee58fd1 100644 --- a/components/meeting/PreJoinScreen.tsx +++ b/components/meeting/PreJoinScreen.tsx @@ -1,6 +1,6 @@ "use client"; -import { useEffect, useRef, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { createLocalTracks, Track, type LocalTrack } from "livekit-client"; export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[]) => void }) { @@ -9,8 +9,10 @@ export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[ const [micOn, setMicOn] = useState(true); const [cameraOn, setCameraOn] = useState(true); const [speakerTested, setSpeakerTested] = useState(false); + const [requestingDevices, setRequestingDevices] = useState(false); const videoRef = useRef(null); const handedOffRef = useRef(false); + const initialDeviceRequestRef = useRef(false); const videoTrack = tracks.find((track) => track.kind === Track.Kind.Video); const audioTrack = tracks.find((track) => track.kind === Track.Kind.Audio); @@ -30,9 +32,11 @@ export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[ }; }, [tracks]); - async function requestDevices() { + const requestDevices = useCallback(async () => { + if (requestingDevices) return; tracks.forEach((track) => track.stop()); setError(null); + setRequestingDevices(true); try { const nextTracks = await createLocalTracks({ audio: true, video: true }); setTracks(nextTracks); @@ -40,8 +44,16 @@ export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[ setCameraOn(true); } catch { setError("Kamera oder Mikrofon konnten nicht freigegeben werden. Du kannst trotzdem ohne sie beitreten."); + } finally { + setRequestingDevices(false); } - } + }, [requestingDevices, tracks]); + + useEffect(() => { + if (initialDeviceRequestRef.current) return; + initialDeviceRequestRef.current = true; + void requestDevices(); + }, [requestDevices]); async function toggleMic() { if (!audioTrack) return; @@ -104,9 +116,10 @@ export function PreJoinScreen({ onContinue }: { onContinue: (tracks: LocalTrack[