parent
20a4e0bd09
commit
20c9c09258
2 changed files with 151 additions and 12 deletions
|
@ -16,7 +16,6 @@ limitations under the License.
|
||||||
|
|
||||||
import { ResizeObserver } from "@juggle/resize-observer";
|
import { ResizeObserver } from "@juggle/resize-observer";
|
||||||
import {
|
import {
|
||||||
useLiveKitRoom,
|
|
||||||
useLocalParticipant,
|
useLocalParticipant,
|
||||||
useParticipants,
|
useParticipants,
|
||||||
useToken,
|
useToken,
|
||||||
|
@ -79,6 +78,7 @@ import { InviteModal } from "./InviteModal";
|
||||||
import { useRageshakeRequestModal } from "../settings/submit-rageshake";
|
import { useRageshakeRequestModal } from "../settings/submit-rageshake";
|
||||||
import { RageshakeRequestModal } from "./RageshakeRequestModal";
|
import { RageshakeRequestModal } from "./RageshakeRequestModal";
|
||||||
import { VideoTile } from "../video-grid/VideoTile";
|
import { VideoTile } from "../video-grid/VideoTile";
|
||||||
|
import { useRoom } from "./useRoom";
|
||||||
|
|
||||||
const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
|
const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
|
||||||
// There is currently a bug in Safari our our code with cloning and sending MediaStreams
|
// There is currently a bug in Safari our our code with cloning and sending MediaStreams
|
||||||
|
@ -86,6 +86,16 @@ const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
|
||||||
// For now we can disable screensharing in Safari.
|
// For now we can disable screensharing in Safari.
|
||||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
|
||||||
|
const onConnectedCallback = (): void => {
|
||||||
|
console.log("connected to LiveKit room");
|
||||||
|
};
|
||||||
|
const onDisconnectedCallback = (): void => {
|
||||||
|
console.log("disconnected from LiveKit room");
|
||||||
|
};
|
||||||
|
const onErrorCallback = (err: Error): void => {
|
||||||
|
console.error("error connecting to LiveKit room", err);
|
||||||
|
};
|
||||||
|
|
||||||
interface LocalUserChoices {
|
interface LocalUserChoices {
|
||||||
videoMuted: boolean;
|
videoMuted: boolean;
|
||||||
audioMuted: boolean;
|
audioMuted: boolean;
|
||||||
|
@ -150,22 +160,16 @@ export function InCallView({
|
||||||
options
|
options
|
||||||
);
|
);
|
||||||
|
|
||||||
// Uses a hook to connect to the LiveKit room (on unmount the room will be left) and publish local media tracks (default).
|
useRoom({
|
||||||
useLiveKitRoom({
|
|
||||||
token,
|
token,
|
||||||
serverUrl: Config.get().livekit.server_url,
|
serverUrl: Config.get().livekit.server_url,
|
||||||
room: livekitRoom,
|
room: livekitRoom,
|
||||||
audio: !userChoices.audioMuted,
|
audio: !userChoices.audioMuted,
|
||||||
video: !userChoices.videoMuted,
|
video: !userChoices.videoMuted,
|
||||||
onConnected: () => {
|
simulateParticipants: 10,
|
||||||
console.log("connected to LiveKit room");
|
onConnected: onConnectedCallback,
|
||||||
},
|
onDisconnected: onDisconnectedCallback,
|
||||||
onDisconnected: () => {
|
onError: onErrorCallback,
|
||||||
console.log("disconnected from LiveKit room");
|
|
||||||
},
|
|
||||||
onError: (err) => {
|
|
||||||
console.error("error connecting to LiveKit room", err);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const screenSharingTracks = useTracks(
|
const screenSharingTracks = useTracks(
|
||||||
|
|
135
src/room/useRoom.ts
Normal file
135
src/room/useRoom.ts
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import {
|
||||||
|
ConnectionState,
|
||||||
|
MediaDeviceFailure,
|
||||||
|
Room,
|
||||||
|
RoomEvent,
|
||||||
|
} from "livekit-client";
|
||||||
|
import { LiveKitRoomProps } from "@livekit/components-react/src/components/LiveKitRoom";
|
||||||
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
const defaultRoomProps: Partial<LiveKitRoomProps> = {
|
||||||
|
connect: true,
|
||||||
|
audio: false,
|
||||||
|
video: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
export function useRoom(props: LiveKitRoomProps) {
|
||||||
|
const {
|
||||||
|
token,
|
||||||
|
serverUrl,
|
||||||
|
options,
|
||||||
|
room: passedRoom,
|
||||||
|
connectOptions,
|
||||||
|
connect,
|
||||||
|
audio,
|
||||||
|
video,
|
||||||
|
screen,
|
||||||
|
onConnected,
|
||||||
|
onDisconnected,
|
||||||
|
onError,
|
||||||
|
onMediaDeviceFailure,
|
||||||
|
} = { ...defaultRoomProps, ...props };
|
||||||
|
if (options && passedRoom) {
|
||||||
|
logger.warn(
|
||||||
|
"when using a manually created room, the options object will be ignored. set the desired options directly when creating the room instead."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const [room, setRoom] = React.useState<Room | undefined>();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
setRoom(passedRoom ?? new Room(options));
|
||||||
|
}, [options, passedRoom]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!room) return;
|
||||||
|
const onSignalConnected = () => {
|
||||||
|
const localP = room.localParticipant;
|
||||||
|
try {
|
||||||
|
logger.debug("trying to publish local tracks");
|
||||||
|
localP.setMicrophoneEnabled(
|
||||||
|
!!audio,
|
||||||
|
typeof audio !== "boolean" ? audio : undefined
|
||||||
|
);
|
||||||
|
localP.setCameraEnabled(
|
||||||
|
!!video,
|
||||||
|
typeof video !== "boolean" ? video : undefined
|
||||||
|
);
|
||||||
|
localP.setScreenShareEnabled(
|
||||||
|
!!screen,
|
||||||
|
typeof screen !== "boolean" ? screen : undefined
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
logger.warn(e);
|
||||||
|
onError?.(e as Error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const onMediaDeviceError = (e: Error) => {
|
||||||
|
const mediaDeviceFailure = MediaDeviceFailure.getFailure(e);
|
||||||
|
onMediaDeviceFailure?.(mediaDeviceFailure);
|
||||||
|
};
|
||||||
|
room.on(RoomEvent.SignalConnected, onSignalConnected);
|
||||||
|
room.on(RoomEvent.MediaDevicesError, onMediaDeviceError);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
room.off(RoomEvent.SignalConnected, onSignalConnected);
|
||||||
|
room.off(RoomEvent.MediaDevicesError, onMediaDeviceError);
|
||||||
|
};
|
||||||
|
}, [room, audio, video, screen, onError, onMediaDeviceFailure]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!room) return;
|
||||||
|
if (!token) {
|
||||||
|
logger.debug("no token yet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!serverUrl) {
|
||||||
|
logger.warn("no livekit url provided");
|
||||||
|
onError?.(Error("no livekit url provided"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (connect) {
|
||||||
|
logger.debug("connecting");
|
||||||
|
room.connect(serverUrl, token, connectOptions).catch((e) => {
|
||||||
|
logger.warn(e);
|
||||||
|
onError?.(e as Error);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
logger.debug("disconnecting because connect is false");
|
||||||
|
room.disconnect();
|
||||||
|
}
|
||||||
|
}, [connect, token, connectOptions, room, onError, serverUrl]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!room) return;
|
||||||
|
const connectionStateChangeListener = (state: ConnectionState) => {
|
||||||
|
switch (state) {
|
||||||
|
case ConnectionState.Disconnected:
|
||||||
|
if (onDisconnected) onDisconnected();
|
||||||
|
break;
|
||||||
|
case ConnectionState.Connected:
|
||||||
|
if (onConnected) onConnected();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
room.on(RoomEvent.ConnectionStateChanged, connectionStateChangeListener);
|
||||||
|
return () => {
|
||||||
|
room.off(RoomEvent.ConnectionStateChanged, connectionStateChangeListener);
|
||||||
|
};
|
||||||
|
}, [token, onConnected, onDisconnected, room]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!room) return;
|
||||||
|
return () => {
|
||||||
|
logger.info("disconnecting on onmount");
|
||||||
|
room.disconnect();
|
||||||
|
};
|
||||||
|
}, [room]);
|
||||||
|
|
||||||
|
return { room };
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue