livekit-dgn/pages/rooms/[name].tsx
lukasIO 3fa395bbe1
Surface errors in PreJoin (#245)
* Don't use noSSR wrapper for prejoin

* wrap callbacks

* use client for room pages
2024-04-17 14:42:06 +02:00

196 lines
5.2 KiB
TypeScript

'use client';
import {
LiveKitRoom,
VideoConference,
formatChatMessageLinks,
useToken,
LocalUserChoices,
PreJoin,
} from '@livekit/components-react';
import {
DeviceUnsupportedError,
ExternalE2EEKeyProvider,
Room,
RoomConnectOptions,
RoomOptions,
VideoCodec,
VideoPresets,
setLogLevel,
} from 'livekit-client';
import type { NextPage } from 'next';
import Head from 'next/head';
import { useRouter } from 'next/router';
import * as React from 'react';
import { DebugMode } from '../../lib/Debug';
import { decodePassphrase, useServerUrl } from '../../lib/client-utils';
import { SettingsMenu } from '../../lib/SettingsMenu';
const Home: NextPage = () => {
const router = useRouter();
const { name: roomName } = router.query;
const [preJoinChoices, setPreJoinChoices] = React.useState<LocalUserChoices | undefined>(
undefined,
);
const preJoinDefaults = React.useMemo(() => {
return {
username: '',
videoEnabled: true,
audioEnabled: true,
};
}, []);
const handlePreJoinSubmit = React.useCallback((values: LocalUserChoices) => {
setPreJoinChoices(values);
}, []);
const onPreJoinError = React.useCallback((e: any) => {
console.error(e);
}, []);
const onLeave = React.useCallback(() => router.push('/'), []);
return (
<>
<Head>
<title>LiveKit Meet</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main data-lk-theme="default">
{roomName && !Array.isArray(roomName) && preJoinChoices ? (
<ActiveRoom
roomName={roomName}
userChoices={preJoinChoices}
onLeave={onLeave}
></ActiveRoom>
) : (
<div style={{ display: 'grid', placeItems: 'center', height: '100%' }}>
<PreJoin
onError={onPreJoinError}
defaults={preJoinDefaults}
onSubmit={handlePreJoinSubmit}
></PreJoin>
</div>
)}
</main>
</>
);
};
export default Home;
type ActiveRoomProps = {
userChoices: LocalUserChoices;
roomName: string;
region?: string;
onLeave?: () => void;
};
const ActiveRoom = ({ roomName, userChoices, onLeave }: ActiveRoomProps) => {
const tokenOptions = React.useMemo(() => {
return {
userInfo: {
identity: userChoices.username,
name: userChoices.username,
},
};
}, [userChoices.username]);
const token = useToken(process.env.NEXT_PUBLIC_LK_TOKEN_ENDPOINT, roomName, tokenOptions);
const router = useRouter();
const { region, hq, codec } = router.query;
const e2eePassphrase =
typeof window !== 'undefined' && decodePassphrase(location.hash.substring(1));
const liveKitUrl = useServerUrl(region as string | undefined);
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 roomOptions = React.useMemo((): RoomOptions => {
let videoCodec: VideoCodec | undefined = (
Array.isArray(codec) ? codec[0] : codec ?? 'vp9'
) as VideoCodec;
if (e2eeEnabled && (videoCodec === 'av1' || videoCodec === 'vp9')) {
videoCodec = undefined;
}
return {
videoCaptureDefaults: {
deviceId: userChoices.videoDeviceId ?? undefined,
resolution: hq === 'true' ? VideoPresets.h2160 : VideoPresets.h720,
},
publishDefaults: {
dtx: false,
videoSimulcastLayers:
hq === 'true'
? [VideoPresets.h1080, VideoPresets.h720]
: [VideoPresets.h540, VideoPresets.h216],
red: !e2eeEnabled,
videoCodec,
},
audioCaptureDefaults: {
deviceId: userChoices.audioDeviceId ?? undefined,
},
adaptiveStream: { pixelDensity: 'screen' },
dynacast: true,
e2ee: e2eeEnabled
? {
keyProvider,
worker,
}
: undefined,
};
// @ts-ignore
setLogLevel('debug', 'lk-e2ee');
}, [userChoices, hq, codec]);
const room = React.useMemo(() => new Room(roomOptions), []);
if (e2eeEnabled) {
keyProvider.setKey(decodePassphrase(e2eePassphrase));
room.setE2EEEnabled(true).catch((e) => {
if (e instanceof DeviceUnsupportedError) {
alert(
`You're trying to join an encrypted meeting, but your browser does not support it. Please update it to the latest version and try again.`,
);
console.error(e);
}
});
}
const connectOptions = React.useMemo((): RoomConnectOptions => {
return {
autoSubscribe: true,
};
}, []);
return (
<>
{liveKitUrl && (
<LiveKitRoom
room={room}
token={token}
serverUrl={liveKitUrl}
connectOptions={connectOptions}
video={userChoices.videoEnabled}
audio={userChoices.audioEnabled}
onDisconnected={onLeave}
>
<VideoConference
chatMessageFormatter={formatChatMessageLinks}
SettingsComponent={
process.env.NEXT_PUBLIC_SHOW_SETTINGS_MENU === 'true' ? SettingsMenu : undefined
}
/>
<DebugMode />
</LiveKitRoom>
)}
</>
);
};