Merge remote-tracking branch 'upstream/dbkr/openid' into SimonBrandner/feat/url
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
This commit is contained in:
commit
ce1671a117
9 changed files with 252 additions and 81 deletions
|
@ -15,41 +15,74 @@ type Handler struct {
|
||||||
key, secret string
|
key, secret string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OpenIDTokenType struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type SFURequest struct {
|
||||||
|
Room string `json:"room"`
|
||||||
|
OpenIDToken OpenIDTokenType `json:"openid_token"`
|
||||||
|
DeviceID string `json:"device_id"`
|
||||||
|
RemoveMeUserID string `json:"remove_me_user_id"` // we'll get this from OIDC
|
||||||
|
}
|
||||||
|
|
||||||
|
type SFUResponse struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
JWT string `json:"jwt"`
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Handler) handle(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) handle(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Printf("Request from %s", r.RemoteAddr)
|
log.Printf("Request from %s", r.RemoteAddr)
|
||||||
|
|
||||||
// Set the CORS headers
|
// Set the CORS headers
|
||||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||||
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
|
w.Header().Set("Access-Control-Allow-Methods", "POST")
|
||||||
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
|
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token")
|
||||||
|
|
||||||
// Handle preflight request (CORS)
|
// Handle preflight request (CORS)
|
||||||
if r.Method == "OPTIONS" {
|
if r.Method == "OPTIONS" {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
return
|
return
|
||||||
|
} else if r.Method == "POST" {
|
||||||
|
var body SFURequest
|
||||||
|
err := json.NewDecoder(r.Body).Decode(&body)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error decoding JSON: %v", err)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if body.Room == "" {
|
||||||
|
log.Printf("Request missing room")
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := getJoinToken(h.key, h.secret, body.Room, body.RemoveMeUserID+":"+body.DeviceID)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res := SFUResponse{URL: "http://localhost:7880/", JWT: token}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(res)
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
}
|
}
|
||||||
|
|
||||||
roomName := r.URL.Query().Get("roomName")
|
/*
|
||||||
name := r.URL.Query().Get("name")
|
roomName := r.URL.Query().Get("roomName")
|
||||||
identity := r.URL.Query().Get("identity")
|
name := r.URL.Query().Get("name")
|
||||||
|
identity := r.URL.Query().Get("identity")
|
||||||
|
|
||||||
log.Printf("roomName: %s, name: %s, identity: %s", roomName, name, identity)
|
log.Printf("roomName: %s, name: %s, identity: %s", roomName, name, identity)
|
||||||
|
|
||||||
if roomName == "" || name == "" || identity == "" {
|
if roomName == "" || name == "" || identity == "" {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
token, err := getJoinToken(h.key, h.secret, roomName, identity, name)
|
|
||||||
if err != nil {
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res := Response{token}
|
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
json.NewEncoder(w).Encode(res)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -68,15 +101,11 @@ func main() {
|
||||||
secret: secret,
|
secret: secret,
|
||||||
}
|
}
|
||||||
|
|
||||||
http.HandleFunc("/token", handler.handle)
|
http.HandleFunc("/sfu/get", handler.handle)
|
||||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Response struct {
|
func getJoinToken(apiKey, apiSecret, room, identity string) (string, error) {
|
||||||
Token string `json:"accessToken"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func getJoinToken(apiKey, apiSecret, room, identity, name string) (string, error) {
|
|
||||||
at := auth.NewAccessToken(apiKey, apiSecret)
|
at := auth.NewAccessToken(apiKey, apiSecret)
|
||||||
|
|
||||||
canPublish := true
|
canPublish := true
|
||||||
|
@ -91,8 +120,7 @@ func getJoinToken(apiKey, apiSecret, room, identity, name string) (string, error
|
||||||
|
|
||||||
at.AddGrant(grant).
|
at.AddGrant(grant).
|
||||||
SetIdentity(identity).
|
SetIdentity(identity).
|
||||||
SetValidFor(time.Hour).
|
SetValidFor(time.Hour)
|
||||||
SetName(name)
|
|
||||||
|
|
||||||
return at.ToJWT()
|
return at.ToJWT()
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"livekit": {
|
"livekit": {
|
||||||
"server_url": "wss://sfu.call.element.dev",
|
"livekit_service_url": "https://lk-jwt-service.lab.element.dev"
|
||||||
"jwt_service_url": "https://voip-sip-poc.element.io/lk/jwt_service"
|
|
||||||
},
|
},
|
||||||
"posthog": {
|
"posthog": {
|
||||||
"api_key": "phc_rXGHx9vDmyEvyRxPziYtdVIv0ahEv8A9uLWFcCi1WcU",
|
"api_key": "phc_rXGHx9vDmyEvyRxPziYtdVIv0ahEv8A9uLWFcCi1WcU",
|
||||||
|
|
|
@ -142,8 +142,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
||||||
const foci = livekit
|
const foci = livekit
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
url: livekit.server_url,
|
livekitServiceUrl: livekit.livekit_service_url,
|
||||||
jwtServiceUrl: livekit.jwt_service_url,
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
|
@ -55,10 +55,8 @@ export interface ConfigOptions {
|
||||||
|
|
||||||
// Describes the LiveKit configuration to be used.
|
// Describes the LiveKit configuration to be used.
|
||||||
livekit?: {
|
livekit?: {
|
||||||
// The LiveKit server URL to connect to.
|
// The link to the service that returns a livekit url and token to use it
|
||||||
server_url: string;
|
livekit_service_url: string;
|
||||||
// The link to the service that generates JWT tokens to join LiveKit rooms.
|
|
||||||
jwt_service_url: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
96
src/livekit/OpenIDLoader.tsx
Normal file
96
src/livekit/OpenIDLoader.tsx
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 New Vector Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
ReactNode,
|
||||||
|
createContext,
|
||||||
|
useContext,
|
||||||
|
useEffect,
|
||||||
|
useState,
|
||||||
|
} from "react";
|
||||||
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
import {
|
||||||
|
OpenIDClientParts,
|
||||||
|
SFUConfig,
|
||||||
|
getSFUConfigWithOpenID,
|
||||||
|
} from "./openIDSFU";
|
||||||
|
import { ErrorView, LoadingView } from "../FullScreenView";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
client: OpenIDClientParts;
|
||||||
|
livekitServiceURL: string;
|
||||||
|
roomName: string;
|
||||||
|
children: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SFUConfigContext = createContext<SFUConfig>(undefined);
|
||||||
|
|
||||||
|
export const useSFUConfig = () => useContext(SFUConfigContext);
|
||||||
|
|
||||||
|
export function OpenIDLoader({
|
||||||
|
client,
|
||||||
|
livekitServiceURL,
|
||||||
|
roomName,
|
||||||
|
children,
|
||||||
|
}: Props) {
|
||||||
|
const [state, setState] = useState<
|
||||||
|
SFUConfigLoading | SFUConfigLoaded | SFUConfigFailed
|
||||||
|
>({ kind: "loading" });
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const result = await getSFUConfigWithOpenID(
|
||||||
|
client,
|
||||||
|
livekitServiceURL,
|
||||||
|
roomName
|
||||||
|
);
|
||||||
|
setState({ kind: "loaded", sfuConfig: result });
|
||||||
|
} catch (e) {
|
||||||
|
logger.error("Failed to fetch SFU config: ", e);
|
||||||
|
setState({ kind: "failed", error: e });
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [client, livekitServiceURL, roomName]);
|
||||||
|
|
||||||
|
switch (state.kind) {
|
||||||
|
case "loading":
|
||||||
|
return <LoadingView />;
|
||||||
|
case "failed":
|
||||||
|
return <ErrorView error={state.error} />;
|
||||||
|
case "loaded":
|
||||||
|
return (
|
||||||
|
<SFUConfigContext.Provider value={state.sfuConfig}>
|
||||||
|
{children}
|
||||||
|
</SFUConfigContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type SFUConfigLoading = {
|
||||||
|
kind: "loading";
|
||||||
|
};
|
||||||
|
|
||||||
|
type SFUConfigLoaded = {
|
||||||
|
kind: "loaded";
|
||||||
|
sfuConfig: SFUConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SFUConfigFailed = {
|
||||||
|
kind: "failed";
|
||||||
|
error: Error;
|
||||||
|
};
|
54
src/livekit/openIDSFU.ts
Normal file
54
src/livekit/openIDSFU.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
Copyright 2023 New Vector Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { MatrixClient } from "matrix-js-sdk";
|
||||||
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
|
export interface SFUConfig {
|
||||||
|
url: string;
|
||||||
|
jwt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The bits we need from MatrixClient
|
||||||
|
export type OpenIDClientParts = Pick<
|
||||||
|
MatrixClient,
|
||||||
|
"getOpenIdToken" | "getDeviceId"
|
||||||
|
>;
|
||||||
|
|
||||||
|
export async function getSFUConfigWithOpenID(
|
||||||
|
client: OpenIDClientParts,
|
||||||
|
livekitServiceURL: string,
|
||||||
|
roomName: string
|
||||||
|
): Promise<SFUConfig> {
|
||||||
|
const openIdToken = await client.getOpenIdToken();
|
||||||
|
logger.debug("Got openID token", openIdToken);
|
||||||
|
|
||||||
|
const res = await fetch(livekitServiceURL + "/sfu/get", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
room: roomName,
|
||||||
|
openid_token: openIdToken,
|
||||||
|
device_id: client.getDeviceId(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error("SFO Config fetch failed with status code " + res.status);
|
||||||
|
}
|
||||||
|
return await res.json();
|
||||||
|
}
|
|
@ -1,8 +1,9 @@
|
||||||
import { Room, RoomOptions } from "livekit-client";
|
import { Room, RoomOptions } from "livekit-client";
|
||||||
import { useLiveKitRoom, useToken } from "@livekit/components-react";
|
import { useLiveKitRoom } from "@livekit/components-react";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
|
|
||||||
import { defaultLiveKitOptions } from "./options";
|
import { defaultLiveKitOptions } from "./options";
|
||||||
|
import { SFUConfig } from "./openIDSFU";
|
||||||
|
|
||||||
export type UserChoices = {
|
export type UserChoices = {
|
||||||
audio?: DeviceChoices;
|
audio?: DeviceChoices;
|
||||||
|
@ -14,29 +15,10 @@ export type DeviceChoices = {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LiveKitConfig = {
|
|
||||||
sfuUrl: string;
|
|
||||||
jwtUrl: string;
|
|
||||||
roomName: string;
|
|
||||||
userDisplayName: string;
|
|
||||||
userIdentity: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function useLiveKit(
|
export function useLiveKit(
|
||||||
userChoices: UserChoices,
|
userChoices: UserChoices,
|
||||||
config: LiveKitConfig
|
sfuConfig: SFUConfig
|
||||||
): Room | undefined {
|
): Room | undefined {
|
||||||
const tokenOptions = useMemo(
|
|
||||||
() => ({
|
|
||||||
userInfo: {
|
|
||||||
name: config.userDisplayName,
|
|
||||||
identity: config.userIdentity,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
[config.userDisplayName, config.userIdentity]
|
|
||||||
);
|
|
||||||
const token = useToken(config.jwtUrl, config.roomName, tokenOptions);
|
|
||||||
|
|
||||||
const roomOptions = useMemo((): RoomOptions => {
|
const roomOptions = useMemo((): RoomOptions => {
|
||||||
const options = defaultLiveKitOptions;
|
const options = defaultLiveKitOptions;
|
||||||
options.videoCaptureDefaults = {
|
options.videoCaptureDefaults = {
|
||||||
|
@ -51,8 +33,8 @@ export function useLiveKit(
|
||||||
}, [userChoices.video, userChoices.audio]);
|
}, [userChoices.video, userChoices.audio]);
|
||||||
|
|
||||||
const { room } = useLiveKitRoom({
|
const { room } = useLiveKitRoom({
|
||||||
token,
|
token: sfuConfig.jwt,
|
||||||
serverUrl: config.sfuUrl,
|
serverUrl: sfuConfig.url,
|
||||||
audio: userChoices.audio?.enabled ?? false,
|
audio: userChoices.audio?.enabled ?? false,
|
||||||
video: userChoices.video?.enabled ?? false,
|
video: userChoices.video?.enabled ?? false,
|
||||||
options: roomOptions,
|
options: roomOptions,
|
||||||
|
|
|
@ -28,13 +28,14 @@ import { useGroupCall } from "./useGroupCall";
|
||||||
import { ErrorView, FullScreenView } from "../FullScreenView";
|
import { ErrorView, FullScreenView } from "../FullScreenView";
|
||||||
import { LobbyView } from "./LobbyView";
|
import { LobbyView } from "./LobbyView";
|
||||||
import { MatrixInfo } from "./VideoPreview";
|
import { MatrixInfo } from "./VideoPreview";
|
||||||
import { ActiveCall } from "./InCallView";
|
|
||||||
import { CallEndedView } from "./CallEndedView";
|
import { CallEndedView } from "./CallEndedView";
|
||||||
import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler";
|
import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler";
|
||||||
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
|
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
|
||||||
import { useProfile } from "../profile/useProfile";
|
import { useProfile } from "../profile/useProfile";
|
||||||
import { UserChoices } from "../livekit/useLiveKit";
|
import { UserChoices } from "../livekit/useLiveKit";
|
||||||
import { findDeviceByName } from "../media-utils";
|
import { findDeviceByName } from "../media-utils";
|
||||||
|
import { OpenIDLoader } from "../livekit/OpenIDLoader";
|
||||||
|
import { ActiveCall } from "./InCallView";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
@ -218,21 +219,39 @@ export function GroupCallView({
|
||||||
undefined
|
undefined
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const [livekitServiceURL, setLivekitServiceURL] = useState<
|
||||||
|
string | undefined
|
||||||
|
>(groupCall.foci[0]?.livekitServiceUrl);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setLivekitServiceURL(groupCall.foci[0]?.livekitServiceUrl);
|
||||||
|
}, [setLivekitServiceURL, groupCall]);
|
||||||
|
|
||||||
|
if (!livekitServiceURL) {
|
||||||
|
return <ErrorView error={new Error("No livekit_service_url defined")} />;
|
||||||
|
}
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return <ErrorView error={error} />;
|
return <ErrorView error={error} />;
|
||||||
} else if (state === GroupCallState.Entered && userChoices) {
|
} else if (state === GroupCallState.Entered && userChoices) {
|
||||||
return (
|
return (
|
||||||
<ActiveCall
|
<OpenIDLoader
|
||||||
groupCall={groupCall}
|
|
||||||
client={client}
|
client={client}
|
||||||
participants={participants}
|
livekitServiceURL={livekitServiceURL}
|
||||||
onLeave={onLeave}
|
roomName={matrixInfo.roomName}
|
||||||
unencryptedEventsFromUsers={unencryptedEventsFromUsers}
|
>
|
||||||
hideHeader={hideHeader}
|
<ActiveCall
|
||||||
matrixInfo={matrixInfo}
|
client={client}
|
||||||
userChoices={userChoices}
|
groupCall={groupCall}
|
||||||
otelGroupCallMembership={otelGroupCallMembership}
|
participants={participants}
|
||||||
/>
|
onLeave={onLeave}
|
||||||
|
unencryptedEventsFromUsers={unencryptedEventsFromUsers}
|
||||||
|
hideHeader={hideHeader}
|
||||||
|
matrixInfo={matrixInfo}
|
||||||
|
userChoices={userChoices}
|
||||||
|
otelGroupCallMembership={otelGroupCallMembership}
|
||||||
|
/>
|
||||||
|
</OpenIDLoader>
|
||||||
);
|
);
|
||||||
} else if (left) {
|
} else if (left) {
|
||||||
// The call ended view is shown for two reasons: prompting guests to create
|
// The call ended view is shown for two reasons: prompting guests to create
|
||||||
|
|
|
@ -83,6 +83,7 @@ import { UserChoices, useLiveKit } from "../livekit/useLiveKit";
|
||||||
import { useMediaDevices } from "../livekit/useMediaDevices";
|
import { useMediaDevices } from "../livekit/useMediaDevices";
|
||||||
import { useFullscreen } from "./useFullscreen";
|
import { useFullscreen } from "./useFullscreen";
|
||||||
import { useLayoutStates } from "../video-grid/Layout";
|
import { useLayoutStates } from "../video-grid/Layout";
|
||||||
|
import { useSFUConfig } from "../livekit/OpenIDLoader";
|
||||||
|
|
||||||
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
|
||||||
|
@ -90,18 +91,13 @@ 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);
|
||||||
|
|
||||||
interface ActiveCallProps extends Omit<Props, "livekitRoom"> {
|
export interface ActiveCallProps extends Omit<InCallViewProps, "livekitRoom"> {
|
||||||
userChoices: UserChoices;
|
userChoices: UserChoices;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ActiveCall(props: ActiveCallProps) {
|
export function ActiveCall(props: ActiveCallProps) {
|
||||||
const livekitRoom = useLiveKit(props.userChoices, {
|
const sfuConfig = useSFUConfig();
|
||||||
sfuUrl: props.groupCall.foci[0]!.url,
|
const livekitRoom = useLiveKit(props.userChoices, sfuConfig);
|
||||||
jwtUrl: `${props.groupCall.foci[0]!.jwtServiceUrl}/token`,
|
|
||||||
roomName: props.matrixInfo.roomName,
|
|
||||||
userDisplayName: props.matrixInfo.displayName,
|
|
||||||
userIdentity: `${props.client.getUserId()}:${props.client.getDeviceId()}`,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
livekitRoom && (
|
livekitRoom && (
|
||||||
|
@ -112,7 +108,7 @@ export function ActiveCall(props: ActiveCallProps) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props {
|
export interface InCallViewProps {
|
||||||
client: MatrixClient;
|
client: MatrixClient;
|
||||||
groupCall: GroupCall;
|
groupCall: GroupCall;
|
||||||
livekitRoom: Room;
|
livekitRoom: Room;
|
||||||
|
@ -134,7 +130,7 @@ export function InCallView({
|
||||||
hideHeader,
|
hideHeader,
|
||||||
matrixInfo,
|
matrixInfo,
|
||||||
otelGroupCallMembership,
|
otelGroupCallMembership,
|
||||||
}: Props) {
|
}: InCallViewProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
usePreventScroll();
|
usePreventScroll();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue