Move e2ee options to index page (#155)
* Move e2ee options to index page * update readme * use localuserchoices
This commit is contained in:
parent
8fa50fd7d7
commit
789e994c3a
2 changed files with 53 additions and 25 deletions
|
@ -39,8 +39,14 @@ function Tabs(props: TabsProps) {
|
||||||
|
|
||||||
function DemoMeetingTab({ label }: { label: string }) {
|
function DemoMeetingTab({ label }: { label: string }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const [e2ee, setE2ee] = useState(false);
|
||||||
|
const [sharedPassphrase, setSharedPassphrase] = useState(randomString(64));
|
||||||
const startMeeting = () => {
|
const startMeeting = () => {
|
||||||
router.push(`/rooms/${generateRoomId()}`);
|
if (e2ee) {
|
||||||
|
router.push(`/rooms/${generateRoomId()}#${encodePassphrase(sharedPassphrase)}`);
|
||||||
|
} else {
|
||||||
|
router.push(`/rooms/${generateRoomId()}`);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className={styles.tabContent}>
|
<div className={styles.tabContent}>
|
||||||
|
@ -48,6 +54,28 @@ function DemoMeetingTab({ label }: { label: string }) {
|
||||||
<button style={{ marginTop: '1rem' }} className="lk-button" onClick={startMeeting}>
|
<button style={{ marginTop: '1rem' }} className="lk-button" onClick={startMeeting}>
|
||||||
Start Meeting
|
Start Meeting
|
||||||
</button>
|
</button>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row', gap: '1rem' }}>
|
||||||
|
<input
|
||||||
|
id="use-e2ee"
|
||||||
|
type="checkbox"
|
||||||
|
checked={e2ee}
|
||||||
|
onChange={(ev) => setE2ee(ev.target.checked)}
|
||||||
|
></input>
|
||||||
|
<label htmlFor="use-e2ee">Enable end-to-end encryption</label>
|
||||||
|
</div>
|
||||||
|
{e2ee && (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row', gap: '1rem' }}>
|
||||||
|
<label htmlFor="passphrase">Passphrase</label>
|
||||||
|
<input
|
||||||
|
id="passphrase"
|
||||||
|
type="password"
|
||||||
|
value={sharedPassphrase}
|
||||||
|
onChange={(ev) => setSharedPassphrase(ev.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
'use client';
|
'use client';
|
||||||
import {
|
import {
|
||||||
LiveKitRoom,
|
LiveKitRoom,
|
||||||
LocalUserChoices,
|
|
||||||
VideoConference,
|
VideoConference,
|
||||||
formatChatMessageLinks,
|
formatChatMessageLinks,
|
||||||
useToken,
|
useToken,
|
||||||
|
LocalUserChoices,
|
||||||
} from '@livekit/components-react';
|
} from '@livekit/components-react';
|
||||||
import {
|
import {
|
||||||
|
DeviceUnsupportedError,
|
||||||
ExternalE2EEKeyProvider,
|
ExternalE2EEKeyProvider,
|
||||||
LogLevel,
|
LogLevel,
|
||||||
Room,
|
Room,
|
||||||
|
@ -20,14 +21,9 @@ import type { NextPage } from 'next';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useMemo, useState } from 'react';
|
import * as React from 'react';
|
||||||
import { DebugMode } from '../../lib/Debug';
|
import { DebugMode } from '../../lib/Debug';
|
||||||
import {
|
import { decodePassphrase, useServerUrl } from '../../lib/client-utils';
|
||||||
decodePassphrase,
|
|
||||||
encodePassphrase,
|
|
||||||
randomString,
|
|
||||||
useServerUrl,
|
|
||||||
} from '../../lib/client-utils';
|
|
||||||
|
|
||||||
const PreJoinNoSSR = dynamic(
|
const PreJoinNoSSR = dynamic(
|
||||||
async () => {
|
async () => {
|
||||||
|
@ -39,15 +35,12 @@ const PreJoinNoSSR = dynamic(
|
||||||
const Home: NextPage = () => {
|
const Home: NextPage = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { name: roomName } = router.query;
|
const { name: roomName } = router.query;
|
||||||
const e2eePassphrase =
|
|
||||||
typeof window !== 'undefined' && decodePassphrase(location.hash.substring(1));
|
|
||||||
|
|
||||||
const [preJoinChoices, setPreJoinChoices] = useState<LocalUserChoices | undefined>(undefined);
|
const [preJoinChoices, setPreJoinChoices] = React.useState<LocalUserChoices | undefined>(
|
||||||
|
undefined,
|
||||||
|
);
|
||||||
|
|
||||||
function handlePreJoinSubmit(values: LocalUserChoices) {
|
function handlePreJoinSubmit(values: LocalUserChoices) {
|
||||||
if (values.e2ee) {
|
|
||||||
location.hash = encodePassphrase(values.sharedPassphrase);
|
|
||||||
}
|
|
||||||
setPreJoinChoices(values);
|
setPreJoinChoices(values);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
@ -74,11 +67,8 @@ const Home: NextPage = () => {
|
||||||
username: '',
|
username: '',
|
||||||
videoEnabled: true,
|
videoEnabled: true,
|
||||||
audioEnabled: true,
|
audioEnabled: true,
|
||||||
e2ee: !!e2eePassphrase,
|
|
||||||
sharedPassphrase: e2eePassphrase || randomString(64),
|
|
||||||
}}
|
}}
|
||||||
onSubmit={handlePreJoinSubmit}
|
onSubmit={handlePreJoinSubmit}
|
||||||
showE2EEOptions={true}
|
|
||||||
></PreJoinNoSSR>
|
></PreJoinNoSSR>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
@ -106,17 +96,20 @@ const ActiveRoom = ({ roomName, userChoices, onLeave }: ActiveRoomProps) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { region, hq, codec } = router.query;
|
const { region, hq, codec } = router.query;
|
||||||
|
|
||||||
|
const e2eePassphrase =
|
||||||
|
typeof window !== 'undefined' && decodePassphrase(location.hash.substring(1));
|
||||||
|
|
||||||
const liveKitUrl = useServerUrl(region as string | undefined);
|
const liveKitUrl = useServerUrl(region as string | undefined);
|
||||||
|
|
||||||
const worker =
|
const worker =
|
||||||
typeof window !== 'undefined' &&
|
typeof window !== 'undefined' &&
|
||||||
userChoices.e2ee &&
|
e2eePassphrase &&
|
||||||
new Worker(new URL('livekit-client/e2ee-worker', import.meta.url));
|
new Worker(new URL('livekit-client/e2ee-worker', import.meta.url));
|
||||||
|
|
||||||
const e2eeEnabled = !!(userChoices.e2ee && worker);
|
const e2eeEnabled = !!(e2eePassphrase && worker);
|
||||||
const keyProvider = new ExternalE2EEKeyProvider();
|
const keyProvider = new ExternalE2EEKeyProvider();
|
||||||
|
|
||||||
const roomOptions = useMemo((): RoomOptions => {
|
const roomOptions = React.useMemo((): RoomOptions => {
|
||||||
return {
|
return {
|
||||||
videoCaptureDefaults: {
|
videoCaptureDefaults: {
|
||||||
deviceId: userChoices.videoDeviceId ?? undefined,
|
deviceId: userChoices.videoDeviceId ?? undefined,
|
||||||
|
@ -145,13 +138,20 @@ const ActiveRoom = ({ roomName, userChoices, onLeave }: ActiveRoomProps) => {
|
||||||
};
|
};
|
||||||
}, [userChoices, hq, codec]);
|
}, [userChoices, hq, codec]);
|
||||||
|
|
||||||
const room = useMemo(() => new Room(roomOptions), []);
|
const room = React.useMemo(() => new Room(roomOptions), []);
|
||||||
|
|
||||||
if (e2eeEnabled) {
|
if (e2eeEnabled) {
|
||||||
keyProvider.setKey(decodePassphrase(userChoices.sharedPassphrase));
|
keyProvider.setKey(decodePassphrase(e2eePassphrase));
|
||||||
room.setE2EEEnabled(true);
|
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 = useMemo((): RoomConnectOptions => {
|
const connectOptions = React.useMemo((): RoomConnectOptions => {
|
||||||
return {
|
return {
|
||||||
autoSubscribe: true,
|
autoSubscribe: true,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue