Merge remote-tracking branch 'upstream/livekit' into SimonBrandner/feat/friendly-url
This commit is contained in:
6
.github/workflows/netlify-livekit.yaml
vendored
6
.github/workflows/netlify-livekit.yaml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
deployments: write
|
||||
# Important: the 'branches' filter above will match the 'livekit-experiment' branch on forks,
|
||||
# Important: the 'branches' filter above will match the 'livekit' branch on forks,
|
||||
# so we need to check the head repo too in order to not run on PRs from forks
|
||||
# We check the branch name again too just for completeness
|
||||
# (Is there a nicer way to see if a PR is from a fork?)
|
||||
@@ -53,10 +53,10 @@ jobs:
|
||||
|
||||
- name: Add redirects file
|
||||
# We fetch from github directly as we don't bother checking out the repo
|
||||
run: curl -s https://raw.githubusercontent.com/vector-im/element-call/livekit-experiment/config/netlify_redirects > dist/_redirects
|
||||
run: curl -s https://raw.githubusercontent.com/vector-im/element-call/livekit/config/netlify_redirects > dist/_redirects
|
||||
|
||||
- name: Add config file
|
||||
run: curl -s https://raw.githubusercontent.com/vector-im/element-call/livekit-experiment/config/element_io_preview.json > dist/config.json
|
||||
run: curl -s https://raw.githubusercontent.com/vector-im/element-call/livekit/config/element_io_preview.json > dist/config.json
|
||||
|
||||
- name: Deploy to Netlify
|
||||
id: netlify
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
}
|
||||
},
|
||||
"livekit": {
|
||||
"server_url": "wss://sfu.call.element.dev",
|
||||
"jwt_service_url": "https://voip-sip-poc.element.io/lk/jwt_service"
|
||||
"livekit_service_url": "https://livekit.element.dev"
|
||||
},
|
||||
"posthog": {
|
||||
"api_key": "phc_rXGHx9vDmyEvyRxPziYtdVIv0ahEv8A9uLWFcCi1WcU",
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"i18next-http-backend": "^1.4.4",
|
||||
"livekit-client": "^1.9.7",
|
||||
"lodash": "^4.17.21",
|
||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#af10b0c44b4a427c8d2224bfd6feb03a12cfd27e",
|
||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#426d29d6b9a9d71a3c0d7fe6f7bac3473cd10832",
|
||||
"matrix-widget-api": "^1.3.1",
|
||||
"mermaid": "^8.13.8",
|
||||
"normalize.css": "^8.0.1",
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.": "Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.",
|
||||
"Audio": "Audio",
|
||||
"Avatar": "Avatar",
|
||||
"By clicking \"Go\", you agree to our <2>Terms and conditions</2>": "By clicking \"Go\", you agree to our <2>Terms and conditions</2>",
|
||||
"By clicking \"Join call now\", you agree to our <2>Terms and conditions</2>": "By clicking \"Join call now\", you agree to our <2>Terms and conditions</2>",
|
||||
"By clicking \"Go\", you agree to our <2>End User Licensing Agreement (EULA)</2>": "By clicking \"Go\", you agree to our <2>End User Licensing Agreement (EULA)</2>",
|
||||
"By clicking \"Join call now\", you agree to our <2>End User Licensing Agreement (EULA)</2>": "By clicking \"Join call now\", you agree to our <2>End User Licensing Agreement (EULA)</2>",
|
||||
"By participating in this beta, you consent to the collection of anonymous data, which we use to improve the product. You can find more information about which data we track in our <2>Privacy Policy</2> and our <5>Cookie Policy</5>.": "By participating in this beta, you consent to the collection of anonymous data, which we use to improve the product. You can find more information about which data we track in our <2>Privacy Policy</2> and our <5>Cookie Policy</5>.",
|
||||
"Call link copied": "Call link copied",
|
||||
"Call type menu": "Call type menu",
|
||||
@@ -99,7 +99,7 @@
|
||||
"Thanks, we received your feedback!": "Thanks, we received your feedback!",
|
||||
"Thanks! We'll get right on it.": "Thanks! We'll get right on it.",
|
||||
"This call already exists, would you like to join?": "This call already exists, would you like to join?",
|
||||
"This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>Terms and conditions</12>": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>Terms and conditions</12>",
|
||||
"This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)</12>": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)</12>",
|
||||
"Turn off camera": "Turn off camera",
|
||||
"Turn on camera": "Turn on camera",
|
||||
"Unmute microphone": "Unmute microphone",
|
||||
|
||||
@@ -113,5 +113,7 @@
|
||||
"{{displayName}}, your call has ended.": "{{displayName}}, Twoje połączenie zostało zakończone.",
|
||||
"<0>Thanks for your feedback!</0>": "<0>Dziękujemy za Twoją opinię!</0>",
|
||||
"<0>We'd love to hear your feedback so we can improve your experience.</0>": "<0>Z przyjemnością wysłuchamy Twojej opinii, aby poprawić Twoje doświadczenia.</0>",
|
||||
"How did it go?": "Jak poszło?"
|
||||
"How did it go?": "Jak poszło?",
|
||||
"{{displayName}} is presenting": "{{displayName}} prezentuje",
|
||||
"Show connection stats": "Pokaż statystyki połączenia"
|
||||
}
|
||||
|
||||
@@ -95,11 +95,25 @@
|
||||
"Audio": "Аудио",
|
||||
"Element Call Home": "Главная Element Call",
|
||||
"Copy": "Копировать",
|
||||
"<0>Join call now</0><1>Or</1><2>Copy call link and join later</2>": "<0>Присоединиться сейчас к звонку</0><1>или<1><2>Скопировать ссылку на звонок и присоединиться позже</2>",
|
||||
"<0>Join call now</0><1>Or</1><2>Copy call link and join later</2>": "<0>Присоединиться сейчас</0><1>или<1><2>Скопировать ссылку и присоединиться позже</2>",
|
||||
"<0>Submitting debug logs will help us track down the problem.</0>": "<0>Отправка журналов поможет нам найти и устранить проблему.</0>",
|
||||
"<0>Oops, something's gone wrong.</0>": "<0>Упс, что-то пошло не так.</0>",
|
||||
"Expose developer settings in the settings window.": "Раскрыть настройки разработчика в окне настроек.",
|
||||
"Developer Settings": "Настройки Разработчика",
|
||||
"By participating in this beta, you consent to the collection of anonymous data, which we use to improve the product. You can find more information about which data we track in our <2>Privacy Policy</2> and our <5>Cookie Policy</5>.": "Участвуя в этой бета-версии, вы соглашаетесь на сбор анонимных данных, которые мы используем для улучшения продукта. Более подробную информацию о том, какие данные мы отслеживаем, вы можете найти в нашей <2> Политике конфиденциальности</2> и нашей <5> Политике использования файлов cookie</5>.",
|
||||
"<0></0><1></1>You may withdraw consent by unchecking this box. If you are currently in a call, this setting will take effect at the end of the call.": "<0></0><1></1>Вы можете отозвать согласие, сняв этот флажок. Если вы в данный момент находитесь в разговоре, эта настройка вступит в силу по окончании разговора."
|
||||
"<0></0><1></1>You may withdraw consent by unchecking this box. If you are currently in a call, this setting will take effect at the end of the call.": "<0></0><1></1>Вы можете отозвать согласие, сняв этот флажок. Если вы в данный момент находитесь в разговоре, эта настройка вступит в силу по окончании разговора.",
|
||||
"{{displayName}} is presenting": "{{displayName}} представляет",
|
||||
"<0>We'd love to hear your feedback so we can improve your experience.</0>": "<0>Мы будем рады видеть ваши отзывы, чтобы мы могли улучшить ваш опыт.</0>",
|
||||
"Thanks, we received your feedback!": "Спасибо. Мы получили ваш отзыв!",
|
||||
"Feedback": "Отзыв",
|
||||
"Submit": "Отправить",
|
||||
"Submitting…": "Отправляем…",
|
||||
"{{count}} stars|one": "{{count}} отмечен",
|
||||
"{{count}} stars|other": "{{count}} отмеченных",
|
||||
"{{displayName}}, your call has ended.": "{{displayName}}, ваш звонок окончен.",
|
||||
"<0>Thanks for your feedback!</0>": "<0>Спасибо за обратную связь!</0>",
|
||||
"Your feedback": "Ваш отзыв",
|
||||
"How did it go?": "Как всё прошло?",
|
||||
"If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.": "Если у вас возникли проблемы или вы просто хотите оставить отзыв, отправьте нам краткое описание ниже.",
|
||||
"Show connection stats": "Показать статистику соединения"
|
||||
}
|
||||
|
||||
@@ -78,5 +78,10 @@
|
||||
"Debug log request": "Yêu cầu nhật ký gỡ lỗi",
|
||||
"By clicking \"Join call now\", you agree to our <2>Terms and conditions</2>": "Khi nhấn vào \"Tham gia cuộc gọi\", bạn đồng ý với <2>Điều khoản và điều kiện</2> của chúng tôi",
|
||||
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.": "Một người dùng khác trong cuộc gọi đang gặp vấn đề. Để có thể chẩn đoán tốt hơn chúng tôi muốn thu thập nhật ký gỡ lỗi.",
|
||||
"<0>Why not finish by setting up a password to keep your account?</0><1>You'll be able to keep your name and set an avatar for use on future calls</1>": "<0>Tại sao lại không hoàn thiện bằng cách đặt mật khẩu để giữ tài khoản của bạn?</0><1>Bạn sẽ có thể giữ tên và đặt ảnh đại diện cho những cuộc gọi tiếp theo.</1>"
|
||||
"<0>Why not finish by setting up a password to keep your account?</0><1>You'll be able to keep your name and set an avatar for use on future calls</1>": "<0>Tại sao lại không hoàn thiện bằng cách đặt mật khẩu để giữ tài khoản của bạn?</0><1>Bạn sẽ có thể giữ tên và đặt ảnh đại diện cho những cuộc gọi tiếp theo.</1>",
|
||||
"<0>Oops, something's gone wrong.</0>": "<0>Ối, có cái gì đó sai.</0>",
|
||||
"{{displayName}} is presenting": "{{displayName}} đang trình bày",
|
||||
"{{displayName}}, your call has ended.": "{{displayName}}, cuộc gọi đã kết thúc.",
|
||||
"<0>We'd love to hear your feedback so we can improve your experience.</0>": "<0>Chúng tôi muốn nghe phản hồi của bạn để còn cải thiện trải nghiệm cho bạn.</0>",
|
||||
"<0>Thanks for your feedback!</0>": "<0>Cảm hơn vì đã phản hồi!</0>"
|
||||
}
|
||||
|
||||
@@ -138,6 +138,15 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
||||
const { user_id, device_id, access_token, passwordlessUser } =
|
||||
session;
|
||||
|
||||
const livekit = Config.get().livekit;
|
||||
const foci = livekit
|
||||
? [
|
||||
{
|
||||
livekitServiceUrl: livekit.livekit_service_url,
|
||||
},
|
||||
]
|
||||
: undefined;
|
||||
|
||||
try {
|
||||
return {
|
||||
client: await initClient(
|
||||
@@ -147,6 +156,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
||||
userId: user_id,
|
||||
deviceId: device_id,
|
||||
fallbackICEServerAllowed: fallbackICEServerAllowed,
|
||||
foci,
|
||||
},
|
||||
true
|
||||
),
|
||||
@@ -163,6 +173,7 @@ export const ClientProvider: FC<Props> = ({ children }) => {
|
||||
userId: user_id,
|
||||
deviceId: device_id,
|
||||
fallbackICEServerAllowed: fallbackICEServerAllowed,
|
||||
foci,
|
||||
},
|
||||
false // Don't need the crypto store just to log out
|
||||
);
|
||||
|
||||
@@ -211,7 +211,9 @@ export const RegisterPage: FC = () => {
|
||||
apply.
|
||||
<br />
|
||||
By clicking "Register", you agree to our{" "}
|
||||
<Link href={privacyPolicyUrl}>Terms and conditions</Link>
|
||||
<Link href={privacyPolicyUrl}>
|
||||
End User Licensing Agreement (EULA)
|
||||
</Link>
|
||||
</Trans>
|
||||
</Caption>
|
||||
{error && (
|
||||
|
||||
@@ -55,10 +55,8 @@ export interface ConfigOptions {
|
||||
|
||||
// Describes the LiveKit configuration to be used.
|
||||
livekit?: {
|
||||
// The LiveKit server URL to connect to.
|
||||
server_url: string;
|
||||
// The link to the service that generates JWT tokens to join LiveKit rooms.
|
||||
jwt_service_url: string;
|
||||
// The link to the service that returns a livekit url and token to use it
|
||||
livekit_service_url: string;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -164,7 +164,9 @@ export const UnauthenticatedView: FC = () => {
|
||||
<Caption className={styles.notice}>
|
||||
<Trans>
|
||||
By clicking "Go", you agree to our{" "}
|
||||
<Link href={privacyPolicyUrl}>Terms and conditions</Link>
|
||||
<Link href={privacyPolicyUrl}>
|
||||
End User Licensing Agreement (EULA)
|
||||
</Link>
|
||||
</Trans>
|
||||
</Caption>
|
||||
{error && (
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -15,7 +15,11 @@ const defaultLiveKitPublishOptions: TrackPublishDefaults = {
|
||||
forceStereo: false,
|
||||
simulcast: true,
|
||||
videoSimulcastLayers: [VideoPresets.h180, VideoPresets.h216] as VideoPreset[],
|
||||
screenShareEncoding: ScreenSharePresets.h1080fps15.encoding,
|
||||
screenShareEncoding: ScreenSharePresets.h1080fps30.encoding,
|
||||
screenShareSimulcastLayers: [
|
||||
new VideoPreset(1920, 1080, 1_500_000, 5, "medium"),
|
||||
ScreenSharePresets.h1080fps15,
|
||||
] as VideoPreset[],
|
||||
stopMicTrackOnMute: false,
|
||||
videoCodec: "vp8",
|
||||
videoEncoding: VideoPresets.h360.encoding,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { Room, RoomOptions } from "livekit-client";
|
||||
import { useLiveKitRoom, useToken } from "@livekit/components-react";
|
||||
import { useLiveKitRoom } from "@livekit/components-react";
|
||||
import { useMemo } from "react";
|
||||
|
||||
import { defaultLiveKitOptions } from "./options";
|
||||
import { SFUConfig } from "./openIDSFU";
|
||||
|
||||
export type UserChoices = {
|
||||
audio?: DeviceChoices;
|
||||
@@ -14,29 +15,10 @@ export type DeviceChoices = {
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type LiveKitConfig = {
|
||||
sfuUrl: string;
|
||||
jwtUrl: string;
|
||||
roomName: string;
|
||||
userDisplayName: string;
|
||||
userIdentity: string;
|
||||
};
|
||||
|
||||
export function useLiveKit(
|
||||
userChoices: UserChoices,
|
||||
config: LiveKitConfig
|
||||
sfuConfig: SFUConfig
|
||||
): 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 options = defaultLiveKitOptions;
|
||||
options.videoCaptureDefaults = {
|
||||
@@ -51,8 +33,8 @@ export function useLiveKit(
|
||||
}, [userChoices.video, userChoices.audio]);
|
||||
|
||||
const { room } = useLiveKitRoom({
|
||||
token,
|
||||
serverUrl: config.sfuUrl,
|
||||
token: sfuConfig.jwt,
|
||||
serverUrl: sfuConfig.url,
|
||||
audio: userChoices.audio?.enabled ?? false,
|
||||
video: userChoices.video?.enabled ?? false,
|
||||
options: roomOptions,
|
||||
|
||||
@@ -28,13 +28,14 @@ import { useGroupCall } from "./useGroupCall";
|
||||
import { ErrorView, FullScreenView } from "../FullScreenView";
|
||||
import { LobbyView } from "./LobbyView";
|
||||
import { MatrixInfo } from "./VideoPreview";
|
||||
import { ActiveCall } from "./InCallView";
|
||||
import { CallEndedView } from "./CallEndedView";
|
||||
import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler";
|
||||
import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
|
||||
import { useProfile } from "../profile/useProfile";
|
||||
import { UserChoices } from "../livekit/useLiveKit";
|
||||
import { findDeviceByName } from "../media-utils";
|
||||
import { OpenIDLoader } from "../livekit/OpenIDLoader";
|
||||
import { ActiveCall } from "./InCallView";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@@ -218,21 +219,39 @@ export function GroupCallView({
|
||||
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) {
|
||||
return <ErrorView error={error} />;
|
||||
} else if (state === GroupCallState.Entered && userChoices) {
|
||||
return (
|
||||
<ActiveCall
|
||||
groupCall={groupCall}
|
||||
<OpenIDLoader
|
||||
client={client}
|
||||
participants={participants}
|
||||
onLeave={onLeave}
|
||||
unencryptedEventsFromUsers={unencryptedEventsFromUsers}
|
||||
hideHeader={hideHeader}
|
||||
matrixInfo={matrixInfo}
|
||||
userChoices={userChoices}
|
||||
otelGroupCallMembership={otelGroupCallMembership}
|
||||
/>
|
||||
livekitServiceURL={livekitServiceURL}
|
||||
roomName={matrixInfo.roomName}
|
||||
>
|
||||
<ActiveCall
|
||||
client={client}
|
||||
groupCall={groupCall}
|
||||
participants={participants}
|
||||
onLeave={onLeave}
|
||||
unencryptedEventsFromUsers={unencryptedEventsFromUsers}
|
||||
hideHeader={hideHeader}
|
||||
matrixInfo={matrixInfo}
|
||||
userChoices={userChoices}
|
||||
otelGroupCallMembership={otelGroupCallMembership}
|
||||
/>
|
||||
</OpenIDLoader>
|
||||
);
|
||||
} else if (left) {
|
||||
// The call ended view is shown for two reasons: prompting guests to create
|
||||
|
||||
@@ -72,7 +72,6 @@ import { MatrixInfo } from "./VideoPreview";
|
||||
import { useJoinRule } from "./useJoinRule";
|
||||
import { ParticipantInfo } from "./useGroupCall";
|
||||
import { ItemData, TileContent } from "../video-grid/VideoTile";
|
||||
import { Config } from "../config/Config";
|
||||
import { NewVideoGrid } from "../video-grid/NewVideoGrid";
|
||||
import { OTelGroupCallMembership } from "../otel/OTelGroupCallMembership";
|
||||
import { SettingsModal } from "../settings/SettingsModal";
|
||||
@@ -84,6 +83,7 @@ import { UserChoices, useLiveKit } from "../livekit/useLiveKit";
|
||||
import { useMediaDevices } from "../livekit/useMediaDevices";
|
||||
import { useFullscreen } from "./useFullscreen";
|
||||
import { useLayoutStates } from "../video-grid/Layout";
|
||||
import { useSFUConfig } from "../livekit/OpenIDLoader";
|
||||
|
||||
const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
|
||||
// There is currently a bug in Safari our our code with cloning and sending MediaStreams
|
||||
@@ -91,18 +91,13 @@ const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {});
|
||||
// For now we can disable screensharing in Safari.
|
||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||
|
||||
interface ActiveCallProps extends Omit<Props, "livekitRoom"> {
|
||||
export interface ActiveCallProps extends Omit<InCallViewProps, "livekitRoom"> {
|
||||
userChoices: UserChoices;
|
||||
}
|
||||
|
||||
export function ActiveCall(props: ActiveCallProps) {
|
||||
const livekitRoom = useLiveKit(props.userChoices, {
|
||||
sfuUrl: Config.get().livekit!.server_url,
|
||||
jwtUrl: `${Config.get().livekit!.jwt_service_url}/token`,
|
||||
roomName: props.matrixInfo.roomName,
|
||||
userDisplayName: props.matrixInfo.displayName,
|
||||
userIdentity: `${props.client.getUserId()}:${props.client.getDeviceId()}`,
|
||||
});
|
||||
const sfuConfig = useSFUConfig();
|
||||
const livekitRoom = useLiveKit(props.userChoices, sfuConfig);
|
||||
|
||||
return (
|
||||
livekitRoom && (
|
||||
@@ -113,7 +108,7 @@ export function ActiveCall(props: ActiveCallProps) {
|
||||
);
|
||||
}
|
||||
|
||||
interface Props {
|
||||
export interface InCallViewProps {
|
||||
client: MatrixClient;
|
||||
groupCall: GroupCall;
|
||||
livekitRoom: Room;
|
||||
@@ -135,7 +130,7 @@ export function InCallView({
|
||||
hideHeader,
|
||||
matrixInfo,
|
||||
otelGroupCallMembership,
|
||||
}: Props) {
|
||||
}: InCallViewProps) {
|
||||
const { t } = useTranslation();
|
||||
usePreventScroll();
|
||||
|
||||
|
||||
@@ -83,7 +83,9 @@ export function RoomAuthView() {
|
||||
<Caption>
|
||||
<Trans>
|
||||
By clicking "Join call now", you agree to our{" "}
|
||||
<Link href={privacyPolicyUrl}>Terms and conditions</Link>
|
||||
<Link href={privacyPolicyUrl}>
|
||||
End User Licensing Agreement (EULA)
|
||||
</Link>
|
||||
</Trans>
|
||||
</Caption>
|
||||
{error && (
|
||||
|
||||
Reference in New Issue
Block a user