diff --git a/app/custom/VideoConferenceClientImpl.tsx b/app/custom/VideoConferenceClientImpl.tsx index fc4f12a..97b6c37 100644 --- a/app/custom/VideoConferenceClientImpl.tsx +++ b/app/custom/VideoConferenceClientImpl.tsx @@ -11,24 +11,22 @@ import { type VideoCodec, } from 'livekit-client'; import { DebugMode } from '@/lib/Debug'; -import { useEffect, useMemo } from 'react'; -import { decodePassphrase } from '@/lib/client-utils'; +import { useEffect, useMemo, useState } from 'react'; import { KeyboardShortcuts } from '@/lib/KeyboardShortcuts'; import { SettingsMenu } from '@/lib/SettingsMenu'; +import { useSetupE2EE } from '@/lib/useSetupE2EE'; export function VideoConferenceClientImpl(props: { liveKitUrl: string; token: string; codec: VideoCodec | undefined; }) { - const worker = - typeof window !== 'undefined' && - new Worker(new URL('livekit-client/e2ee-worker', import.meta.url)); const keyProvider = new ExternalE2EEKeyProvider(); - - const e2eePassphrase = - typeof window !== 'undefined' ? decodePassphrase(window.location.hash.substring(1)) : undefined; + const { worker, e2eePassphrase } = useSetupE2EE(); const e2eeEnabled = !!(e2eePassphrase && worker); + + const [e2eeSetupComplete, setE2eeSetupComplete] = useState(false); + const roomOptions = useMemo((): RoomOptions => { return { publishDefaults: { @@ -45,13 +43,10 @@ export function VideoConferenceClientImpl(props: { } : undefined, }; - }, [e2eeEnabled, props.codec]); + }, [e2eeEnabled, props.codec, keyProvider, worker]); + + const room = useMemo(() => new Room(roomOptions), [roomOptions]); - const room = useMemo(() => new Room(roomOptions), []); - if (e2eeEnabled) { - keyProvider.setKey(e2eePassphrase); - room.setE2EEEnabled(true); - } const connectOptions = useMemo((): RoomConnectOptions => { return { autoSubscribe: true, @@ -59,13 +54,27 @@ export function VideoConferenceClientImpl(props: { }, []); useEffect(() => { - room.connect(props.liveKitUrl, props.token, connectOptions).catch((error) => { - console.error(error); - }); - room.localParticipant.enableCameraAndMicrophone().catch((error) => { - console.error(error); - }); - }, [room, props.liveKitUrl, props.token, connectOptions]); + if (e2eeEnabled) { + keyProvider.setKey(e2eePassphrase).then(() => { + room.setE2EEEnabled(true).then(() => { + setE2eeSetupComplete(true); + }); + }); + } else { + setE2eeSetupComplete(true); + } + }, [e2eeEnabled, e2eePassphrase, keyProvider, room, setE2eeSetupComplete]); + + useEffect(() => { + if (e2eeSetupComplete) { + room.connect(props.liveKitUrl, props.token, connectOptions).catch((error) => { + console.error(error); + }); + room.localParticipant.enableCameraAndMicrophone().catch((error) => { + console.error(error); + }); + } + }, [room, props.liveKitUrl, props.token, connectOptions, e2eeSetupComplete]); return (
diff --git a/app/rooms/[roomName]/PageClientImpl.tsx b/app/rooms/[roomName]/PageClientImpl.tsx index 9413df6..3a88002 100644 --- a/app/rooms/[roomName]/PageClientImpl.tsx +++ b/app/rooms/[roomName]/PageClientImpl.tsx @@ -25,6 +25,7 @@ import { RoomEvent, } from 'livekit-client'; import { useRouter } from 'next/navigation'; +import { useSetupE2EE } from '@/lib/useSetupE2EE'; const CONN_DETAILS_ENDPOINT = process.env.NEXT_PUBLIC_CONN_DETAILS_ENDPOINT ?? '/api/connection-details'; @@ -93,15 +94,10 @@ function VideoConferenceComponent(props: { codec: VideoCodec; }; }) { - const e2eePassphrase = - typeof window !== 'undefined' && decodePassphrase(location.hash.substring(1)); - - const worker = - typeof window !== 'undefined' && - e2eePassphrase && - new Worker(new URL('livekit-client/e2ee-worker', import.meta.url)); - const e2eeEnabled = !!(e2eePassphrase && worker); const keyProvider = new ExternalE2EEKeyProvider(); + const { worker, e2eePassphrase } = useSetupE2EE(); + const e2eeEnabled = !!(e2eePassphrase && worker); + const [e2eeSetupComplete, setE2eeSetupComplete] = React.useState(false); const roomOptions = React.useMemo((): RoomOptions => { @@ -127,12 +123,7 @@ function VideoConferenceComponent(props: { }, adaptiveStream: { pixelDensity: 'screen' }, dynacast: true, - e2ee: e2eeEnabled - ? { - keyProvider, - worker, - } - : undefined, + e2ee: keyProvider && worker && e2eeEnabled ? { keyProvider, worker } : undefined, }; }, [props.userChoices, props.options.hq, props.options.codec]); diff --git a/lib/useSetupE2EE.ts b/lib/useSetupE2EE.ts new file mode 100644 index 0000000..280582e --- /dev/null +++ b/lib/useSetupE2EE.ts @@ -0,0 +1,15 @@ +import React from 'react'; +import { ExternalE2EEKeyProvider } from 'livekit-client'; +import { decodePassphrase } from './client-utils'; + +export function useSetupE2EE() { + const e2eePassphrase = + typeof window !== 'undefined' ? decodePassphrase(location.hash.substring(1)) : undefined; + + const worker: Worker | undefined = + typeof window !== 'undefined' && e2eePassphrase + ? new Worker(new URL('livekit-client/e2ee-worker', import.meta.url)) + : undefined; + + return { worker, e2eePassphrase }; +}