Skip to content

Commit 49ebb4a

Browse files
committed
simplify the useLivekit hook even more
This is possible because we concluded that we do not need to be able to hot reload the e2ee system.
1 parent f9ab5d8 commit 49ebb4a

File tree

1 file changed

+37
-78
lines changed

1 file changed

+37
-78
lines changed

src/livekit/useLivekit.ts

Lines changed: 37 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
type RoomOptions,
1515
Track,
1616
} from "livekit-client";
17-
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
17+
import { useEffect, useRef } from "react";
1818
import E2EEWorker from "livekit-client/e2ee-worker?worker";
1919
import { logger } from "matrix-js-sdk/lib/logger";
2020
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
@@ -24,11 +24,7 @@ import { map } from "rxjs";
2424
import { defaultLiveKitOptions } from "./options";
2525
import { type SFUConfig } from "./openIDSFU";
2626
import { type MuteStates } from "../room/MuteStates";
27-
import {
28-
type MediaDeviceHandle,
29-
type MediaDevices,
30-
useMediaDevices,
31-
} from "./MediaDevicesContext";
27+
import { type MediaDeviceHandle, useMediaDevices } from "./MediaDevicesContext";
3228
import {
3329
type ECConnectionState,
3430
useECConnectionState,
@@ -42,6 +38,7 @@ import {
4238
} from "./TrackProcessorContext";
4339
import { observeTrackReference$ } from "../state/MediaViewModel";
4440
import { useUrlParams } from "../UrlParams";
41+
import { useInitial } from "../useInitial";
4542

4643
interface UseLivekitResult {
4744
livekitRoom?: Room;
@@ -56,9 +53,10 @@ export function useLivekit(
5653
): UseLivekitResult {
5754
const { controlledAudioDevices } = useUrlParams();
5855

59-
const initialMuteStates = useRef<MuteStates>(muteStates);
56+
const initialMuteStates = useInitial(() => muteStates);
57+
6058
const devices = useMediaDevices();
61-
const initialDevices = useRef<MediaDevices>(devices);
59+
const initialDevices = useInitial(() => devices);
6260

6361
// Store if audio/video are currently updating. If to prohibit unnecessary calls
6462
// to setMicrophoneEnabled/setCameraEnabled
@@ -67,63 +65,59 @@ export function useLivekit(
6765
// Store the current button mute state that gets passed to this hook via props.
6866
// We need to store it for awaited code that relies on the current value.
6967
const buttonEnabled = useRef({
70-
audio: initialMuteStates.current.audio.enabled,
71-
video: initialMuteStates.current.video.enabled,
68+
audio: initialMuteStates.audio.enabled,
69+
video: initialMuteStates.video.enabled,
7270
});
7371

7472
const { processor } = useTrackProcessor();
7573

76-
const createRoom = (opt: RoomOptions, e2ee: EncryptionSystem): Room => {
77-
logger.info("[LivekitRoom] Create LiveKit room with options", opt);
78-
// We have to create the room manually here due to a bug inside
79-
// @livekit/components-react. JSON.stringify() is used in deps of a
80-
// useEffect() with an argument that references itself, if E2EE is enabled
81-
let newE2eeOptions: E2EEManagerOptions | undefined;
82-
if (e2ee.kind === E2eeType.PER_PARTICIPANT) {
74+
// Only ever create the room once via useInitial.
75+
const room = useInitial(() => {
76+
logger.info("[LivekitRoom] Create LiveKit room");
77+
78+
let e2ee: E2EEManagerOptions | undefined;
79+
if (e2eeSystem.kind === E2eeType.PER_PARTICIPANT) {
8380
logger.info("Created MatrixKeyProvider (per participant)");
84-
newE2eeOptions = {
81+
e2ee = {
8582
keyProvider: new MatrixKeyProvider(),
8683
worker: new E2EEWorker(),
8784
};
88-
} else if (e2ee.kind === E2eeType.SHARED_KEY && e2ee.secret) {
85+
} else if (e2eeSystem.kind === E2eeType.SHARED_KEY && e2eeSystem.secret) {
8986
logger.info("Created ExternalE2EEKeyProvider (shared key)");
90-
newE2eeOptions = {
87+
e2ee = {
9188
keyProvider: new ExternalE2EEKeyProvider(),
9289
worker: new E2EEWorker(),
9390
};
9491
}
95-
const r = new Room({ ...opt, e2ee: newE2eeOptions });
96-
r.setE2EEEnabled(e2ee.kind !== E2eeType.NONE).catch((e) => {
97-
logger.error("Failed to set E2EE enabled on room", e);
98-
});
9992

100-
return r;
101-
};
102-
103-
// Track the current room options in case we need to recreate the room if the encryption system changes
104-
// Only needed because we allow swapping the room in case the e2ee system changes.
105-
// otherwise this could become part of: `createRoom`
106-
const roomOptions = useMemo(
107-
(): RoomOptions => ({
93+
const roomOptions: RoomOptions = {
10894
...defaultLiveKitOptions,
10995
videoCaptureDefaults: {
11096
...defaultLiveKitOptions.videoCaptureDefaults,
111-
deviceId: devices.videoInput.selectedId,
112-
processor: processor,
97+
deviceId: initialDevices.videoInput.selectedId,
98+
processor,
11399
},
114100
audioCaptureDefaults: {
115101
...defaultLiveKitOptions.audioCaptureDefaults,
116-
deviceId: devices.audioInput.selectedId,
102+
deviceId: initialDevices.audioInput.selectedId,
117103
},
118104
audioOutput: {
119-
deviceId: devices.audioOutput.selectedId,
105+
deviceId: initialDevices.audioOutput.selectedId,
120106
},
121-
}),
122-
[processor, devices],
123-
);
124-
const [room, setRoom] = useState(() => createRoom(roomOptions, e2eeSystem));
107+
e2ee,
108+
};
109+
// We have to create the room manually here due to a bug inside
110+
// @livekit/components-react. JSON.stringify() is used in deps of a
111+
// useEffect() with an argument that references itself, if E2EE is enabled
112+
const room = new Room(roomOptions);
113+
room.setE2EEEnabled(e2eeSystem.kind !== E2eeType.NONE).catch((e) => {
114+
logger.error("Failed to set E2EE enabled on room", e);
115+
});
125116

126-
// Setup and update the already existing keyProvider
117+
return room;
118+
});
119+
120+
// Setup and update the keyProvider which was create by `createRoom`
127121
useEffect(() => {
128122
const e2eeOptions = room.options.e2ee;
129123
if (
@@ -143,41 +137,6 @@ export function useLivekit(
143137
}
144138
}, [room.options.e2ee, e2eeSystem, rtcSession]);
145139

146-
// Do we really allow hot swapping the e2ee system?
147-
// Will we ever reach this code?
148-
useEffect(() => {
149-
const e2eeOptions = room.options.e2ee;
150-
// Only do sth if our e2eeSystem has changed.
151-
if (
152-
// from non to sth else.
153-
(e2eeSystem.kind === E2eeType.NONE && e2eeOptions !== undefined) ||
154-
// from MatrixKeyProvider to sth else
155-
(e2eeSystem.kind === E2eeType.PER_PARTICIPANT &&
156-
!(
157-
e2eeOptions &&
158-
"keyProvider" in e2eeOptions &&
159-
e2eeOptions.keyProvider instanceof MatrixKeyProvider
160-
)) ||
161-
// from ExternalE2EEKeyProvider to sth else
162-
(e2eeSystem.kind === E2eeType.SHARED_KEY &&
163-
!(
164-
e2eeOptions &&
165-
"keyProvider" in e2eeOptions &&
166-
e2eeOptions.keyProvider instanceof ExternalE2EEKeyProvider
167-
))
168-
) {
169-
logger.warn(
170-
"[LivekitRoom] we cannot change the key provider after the room has been created, disconnecting and creating a new room",
171-
);
172-
const resetRoom = async (): Promise<void> => {
173-
await room.disconnect();
174-
const newRoom = createRoom(roomOptions, e2eeSystem);
175-
setRoom(newRoom);
176-
};
177-
void resetRoom();
178-
}
179-
}, [room, e2eeSystem, roomOptions, createRoom]);
180-
181140
// Sync the requested track processors with LiveKit
182141
useTrackProcessorSync(
183142
useObservableEagerState(
@@ -198,8 +157,8 @@ export function useLivekit(
198157
);
199158

200159
const connectionState = useECConnectionState(
201-
initialDevices.current.audioInput.selectedId,
202-
initialMuteStates.current.audio.enabled,
160+
initialDevices.audioInput.selectedId,
161+
initialMuteStates.audio.enabled,
203162
room,
204163
sfuConfig,
205164
);

0 commit comments

Comments
 (0)