Compare commits

..

50 Commits

Author SHA1 Message Date
David Baker
e2abeba194 Merge pull request #1705 from vector-im/dbkr/use_secure_random
Generate call passwords with secure RNG
2023-10-06 16:20:50 +01:00
David Baker
e9798441f7 Merge remote-tracking branch 'origin/livekit' into dbkr/use_secure_random 2023-10-06 16:18:53 +01:00
David Baker
bc36acafc8 Merge pull request #1704 from vector-im/dbkr/refactor_room_create
Refactor room creation code a little
2023-10-06 16:18:18 +01:00
David Baker
f2435f1c31 More consistent variable naming 2023-10-06 16:15:16 +01:00
David Baker
715c5c73ca Merge remote-tracking branch 'origin/livekit' into dbkr/refactor_room_create 2023-10-06 15:15:30 +01:00
David Baker
be4afaeb7e Merge pull request #1687 from vector-im/dbkr/update_default_device
Switch capture devices if the default device changes
2023-10-06 12:01:46 +01:00
David Baker
44e604aaa1 Merge pull request #1703 from vector-im/dbkr/keep_password_in_url
Keep the password in the URL
2023-10-06 10:55:12 +01:00
David Baker
87d5062d34 Don't use js-sdk's base64 encode function
It uses the NodeJS Buffer global which presumably is provided by
Webpack in element-web but isn't here, apparently.
2023-10-05 17:57:23 +01:00
David Baker
d373081db1 Generate call passwords with secure RNG 2023-10-05 17:32:43 +01:00
David Baker
6481b2f67e Merge branch 'dbkr/keep_password_in_url' into dbkr/refactor_room_create 2023-10-05 17:27:03 +01:00
David Baker
b646b0ae56 Remove extra function
that was now doing exactly the same thing as the one above it.
2023-10-05 17:25:06 +01:00
David Baker
e63721acea Refactor room creation code a little
We c+ped the code to create room passwords between two places, but we
already had a createRoom utility function that knew about e2ee.
2023-10-05 16:44:31 +01:00
David Baker
4984bd630e Keep the password in the URL
We changed our minds: people do copy the URL from the bar and
give that to people and expect it to work: it doesn't make sense
to prioritise shorter URLs over this. There's no security advantage
unless we think there's a risk someone might steal your key by taking
a photo of your monitor over your shoulder and decrypting the calls
they can't already hear by standing behind you.
2023-10-05 16:13:56 +01:00
renovate[bot]
847789dcda Update dependency @sentry/vite-plugin to v2.8.0 (#1701)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-05 17:13:26 +02:00
renovate[bot]
d1cb6ee889 Update dependency vaul to ^0.7.0 (#1692)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-05 16:25:27 +02:00
renovate[bot]
7fbd84a63c Update dependency vite to v4.4.11 (#1699)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-10-05 16:24:29 +02:00
Timo
63a00eef2f await leave rtc session (#1648)
so that the widget is only getting the hangup even,
once the call has been cleaned up

Signed-off-by: Timo K <toger5@hotmail.de>
2023-10-04 18:27:07 +02:00
Timo
c18dce3617 Make sure roomAlias = null in widget mode (#1676)
Signed-off-by: Timo K <toger5@hotmail.de>
2023-10-04 15:56:57 +02:00
Stefan Ceriu
1eb2302060 Move apple-app-site-association to .well-known
https://developer.apple.com/videos/play/wwdc2019/717/

```
This file should be located at HTTPS://your domain name/.well-known/apple-app-site-association

Other paths are deprecated.
```
2023-10-04 16:40:49 +03:00
Stefan Ceriu
ad462f3d8e Fix apple-app-site-assoctiation no_universal_link query matching.
https://developer.apple.com/videos/play/wwdc2019/717/

```
You'll notice that I specify a question mark and an asterisk as the pattern from the query items value. A pattern consisting of a single asterisk matches any string, including the empty string. And a missing query item has a value equivalent to the empty string. So to match against the string that's at least one character long, I specify a question mark and then any additional characters are matched by the asterisk.
```
2023-10-04 16:40:49 +03:00
Robin
a3eb58f9fe Merge pull request #1688 from vector-im/renovate/vite-4.x-lockfile
Update dependency vite to v4.4.10
2023-10-03 16:29:34 -04:00
Robin
50b4d61fbd Merge pull request #1684 from RiotTranslateBot/weblate-element-call-element-call
Translations update from Weblate
2023-10-03 16:29:10 -04:00
Robin
d0eda79f27 Merge pull request #1691 from vector-im/renovate/vector-im-compound-web-0.x
Update dependency @vector-im/compound-web to ^0.5.0
2023-10-03 16:28:44 -04:00
Robin
a0cc7686b3 Merge pull request #1678 from vector-im/renovate/posthog-js-1.x-lockfile
Update dependency posthog-js to v1.81.3
2023-10-03 16:25:41 -04:00
renovate[bot]
20f96f17e4 Update dependency @vector-im/compound-web to ^0.5.0 2023-10-03 20:25:25 +00:00
random
1b109e1b3a Translated using Weblate (Italian)
Currently translated at 100.0% (121 of 121 strings)

Translation: Element Call/element-call
Translate-URL: https://translate.element.io/projects/element-call/element-call/it/
2023-10-03 19:43:00 +00:00
Jeff Huang
daa1fed0c0 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (121 of 121 strings)

Translation: Element Call/element-call
Translate-URL: https://translate.element.io/projects/element-call/element-call/zh_Hant/
2023-10-03 19:43:00 +00:00
Timo
01b2367f38 allow widget related params in the fragment (#1675)
Signed-off-by: Timo K <toger5@hotmail.de>
2023-10-03 21:35:28 +02:00
renovate[bot]
2961d588b6 Update dependency vite to v4.4.10 2023-10-03 19:29:34 +00:00
David Baker
c37b2924af Comment 2023-10-03 18:27:10 +01:00
David Baker
e0cabbc514 Switch capture devices if the default device changes
This is a bit of a hack, but is the only way I can see that we can
update to using the new default device when the OS-level default
changes. Hopefully the comments explain everything.
2023-10-03 18:22:56 +01:00
Robin
e54a1274bb Merge pull request #1679 from vector-im/renovate/livekit-components-react-1.x-lockfile
Update dependency @livekit/components-react to v1.3.0
2023-10-03 07:54:25 -04:00
Robin
e246f3f66b Merge pull request #1667 from vector-im/renovate/sentry-javascript-monorepo
Update sentry-javascript monorepo to v7.73.0
2023-10-03 07:52:31 -04:00
Robin
c769a1b86b Merge pull request #1671 from vector-im/renovate/typescript-eslint-monorepo
Update typescript-eslint monorepo to v6.7.4
2023-10-03 07:51:40 -04:00
renovate[bot]
bbc58502da Update dependency @livekit/components-react to v1.3.0 2023-10-03 11:51:28 +00:00
renovate[bot]
72ab839eff Update dependency posthog-js to v1.81.3 2023-10-03 11:49:11 +00:00
Robin
aea404588a Merge pull request #1677 from vector-im/renovate/node-18.x-lockfile
Update dependency @types/node to v18.18.3
2023-10-03 07:48:37 -04:00
renovate[bot]
b3c0a01429 Update dependency @types/node to v18.18.3 2023-10-02 21:25:51 +00:00
renovate[bot]
27fa35cbab Update typescript-eslint monorepo to v6.7.4 2023-10-02 17:32:32 +00:00
Robin
f779bc26cd Merge pull request #1666 from vector-im/renovate/i18next-parser-8.x-lockfile
Update dependency i18next-parser to v8.8.0
2023-10-02 10:36:30 -04:00
Robin
6b94e3553c Merge pull request #1665 from RiotTranslateBot/weblate-element-call-element-call
Translations update from Weblate
2023-10-02 10:35:33 -04:00
renovate[bot]
13579d5972 Update sentry-javascript monorepo to v7.73.0 2023-10-02 14:00:44 +00:00
renovate[bot]
47c1740504 Update dependency i18next-parser to v8.8.0 2023-10-01 17:49:06 +00:00
Ihor Hordiichuk
21789f7d22 Translated using Weblate (Ukrainian)
Currently translated at 100.0% (121 of 121 strings)

Translation: Element Call/element-call
Translate-URL: https://translate.element.io/projects/element-call/element-call/uk/
2023-10-01 04:26:55 +00:00
Robin
67ea390847 Merge pull request #1664 from vector-im/renovate/vite-plugin-svgr-4.x-lockfile
Update dependency vite-plugin-svgr to v4.1.0
2023-09-29 22:27:41 -04:00
Robin
e501c5305f Merge pull request #1662 from vector-im/renovate/node-18.x-lockfile
Update dependency @types/node to v18.18.1
2023-09-29 22:26:50 -04:00
renovate[bot]
d3704dab33 Update dependency vite-plugin-svgr to v4.1.0 2023-09-29 21:28:22 +00:00
renovate[bot]
a7a2adaf6b Update dependency @types/node to v18.18.1 2023-09-29 17:01:31 +00:00
Robin
516d365511 Merge pull request #1660 from RiotTranslateBot/weblate-element-call-element-call
Translations update from Weblate
2023-09-29 13:01:03 -04:00
Vri
4343ae588e Translated using Weblate (German)
Currently translated at 100.0% (121 of 121 strings)

Translation: Element Call/element-call
Translate-URL: https://translate.element.io/projects/element-call/element-call/de/
2023-09-29 14:22:14 +00:00
17 changed files with 501 additions and 488 deletions

View File

@@ -47,7 +47,7 @@
"@types/lodash": "^4.14.199",
"@use-gesture/react": "^10.2.11",
"@vector-im/compound-design-tokens": "^0.0.6",
"@vector-im/compound-web": "^0.4.0",
"@vector-im/compound-web": "^0.5.0",
"@vitejs/plugin-basic-ssl": "^1.0.1",
"@vitejs/plugin-react": "^4.0.1",
"buffer": "^6.0.3",
@@ -74,7 +74,7 @@
"tinyqueue": "^2.0.3",
"unique-names-generator": "^4.6.0",
"uuid": "9",
"vaul": "^0.6.1"
"vaul": "^0.7.0"
},
"devDependencies": {
"@babel/core": "^7.16.5",

View File

@@ -10,7 +10,7 @@
"components": [
{
"?": {
"no_universal_links": "*"
"no_universal_links": "?*"
},
"exclude": true,
"comment": "Opt out of universal links"

View File

@@ -114,5 +114,10 @@
"Start new call": "Neuen Anruf beginnen",
"Call not found": "Anruf nicht gefunden",
"Calls are now end-to-end encrypted and need to be created from the home page. This helps make sure everyone's using the same encryption key.": "Anrufe sind nun Ende-zu-Ende-verschlüsselt und müssen auf der Startseite erstellt werden. Damit stellen wir sicher, dass alle denselben Schlüssel verwenden.",
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117": "Dein Webbrowser unterstützt keine Medien-Ende-zu-Ende-Verschlüsselung. Unterstützte Browser sind Chrome, Safari, Firefox >=117"
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117": "Dein Webbrowser unterstützt keine Medien-Ende-zu-Ende-Verschlüsselung. Unterstützte Browser sind Chrome, Safari, Firefox >=117",
"Copy link": "Link kopieren",
"Invite": "Einladen",
"Invite to this call": "Zu diesem Anruf einladen",
"Link copied to clipboard": "Link in Zwischenablage kopiert",
"Participants": "Teilnehmende"
}

View File

@@ -23,7 +23,7 @@
"Debug log request": "Richiesta registro di debug",
"Developer": "Sviluppatore",
"Developer Settings": "Impostazioni per sviluppatori",
"Display name": "Nome da mostrare",
"Display name": "Il tuo nome",
"Element Call Home": "Inizio di Element Call",
"Enable end-to-end encryption (password protected calls)": "Attiva crittografia end-to-end (chiamate protette da password)",
"Encrypted": "Cifrata",

View File

@@ -114,5 +114,10 @@
"Back to recents": "Повернутися до недавніх",
"Call not found": "Виклик не знайдено",
"Calls are now end-to-end encrypted and need to be created from the home page. This helps make sure everyone's using the same encryption key.": "Відтепер виклики захищено наскрізним шифруванням, і їх потрібно створювати з домашньої сторінки. Це допомагає переконатися, що всі користувачі використовують один і той самий ключ шифрування.",
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117": "Ваш браузер не підтримує наскрізне шифрування мультимедійних даних. Підтримувані браузери: Chrome, Safari, Firefox >=117"
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117": "Ваш браузер не підтримує наскрізне шифрування мультимедійних даних. Підтримувані браузери: Chrome, Safari, Firefox >=117",
"Invite": "Запросити",
"Link copied to clipboard": "Посилання скопійовано до буфера обміну",
"Participants": "Учасники",
"Copy link": "Скопіювати посилання",
"Invite to this call": "Запросити до цього виклику"
}

View File

@@ -114,5 +114,10 @@
"Unmute microphone": "將麥克風取消靜音",
"Call not found": "找不到通話",
"Calls are now end-to-end encrypted and need to be created from the home page. This helps make sure everyone's using the same encryption key.": "通話現在是端對端加密的,必須從首頁建立。這有助於確保每個人都使用相同的加密金鑰。",
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117": "您的網路瀏覽器不支援媒體端到端加密。支援的瀏覽器包含了 Chrome、Safari、Firefox >=117"
"Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117": "您的網路瀏覽器不支援媒體端到端加密。支援的瀏覽器包含了 Chrome、Safari、Firefox >=117",
"Copy link": "複製連結",
"Invite": "邀請",
"Invite to this call": "邀請到此通話",
"Link copied to clipboard": "連結已複製到剪貼簿",
"Participants": "參與者"
}

View File

@@ -33,6 +33,9 @@ interface RoomIdentifier {
// clearer what each flag means, and helps us avoid coupling Element Call's
// behavior to the needs of specific consumers.
interface UrlParams {
// Widget api related params
widgetId: string | null;
parentUrl: string | null;
/**
* Anything about what room we're pointed to should be from useRoomIdentifier which
* parses the path and resolves alias with respect to the default server name, however
@@ -178,6 +181,9 @@ export const getUrlParams = (
const fontScale = parseFloat(parser.getParam("fontScale") ?? "");
return {
widgetId: parser.getParam("widgetId"),
parentUrl: parser.getParam("parentUrl"),
// NB. we don't validate roomId here as we do in getRoomIdentifierFromUrl:
// what would we do if it were invalid? If the widget API says that's what
// the room ID is, then that's what it is.
@@ -218,33 +224,39 @@ export function getRoomIdentifierFromUrl(
hash: string
): RoomIdentifier {
let roomAlias: string | null = null;
pathname = pathname.substring(1); // Strip the "/"
const pathComponents = pathname.split("/");
const pathHasRoom = pathComponents[0] == "room";
const hasRoomAlias = pathComponents.length > 1;
// Here we handle the beginning of the alias and make sure it starts with a "#"
// What type is our url: roomAlias in hash, room alias as the search path, roomAlias after /room/
if (hash === "" || hash.startsWith("#?")) {
roomAlias = pathname.substring(1); // Strip the "/"
// Delete "/room/", if present
if (roomAlias.startsWith("room/")) {
roomAlias = roomAlias.substring("room/".length);
if (hasRoomAlias && pathHasRoom) {
roomAlias = pathComponents[1];
}
// Add "#", if not present
if (!roomAlias.startsWith("#")) {
roomAlias = `#${roomAlias}`;
if (!pathHasRoom) {
roomAlias = pathComponents[0];
}
} else {
roomAlias = hash;
}
// Delete "?" and what comes afterwards
roomAlias = roomAlias.split("?")[0];
roomAlias = roomAlias?.split("?")[0] ?? null;
if (roomAlias.length <= 1) {
if (roomAlias) {
// Make roomAlias is null, if it only is a "#"
roomAlias = null;
} else {
// Add server part, if not present
if (!roomAlias.includes(":")) {
roomAlias = `${roomAlias}:${Config.defaultServerName()}`;
if (roomAlias.length <= 1) {
roomAlias = null;
} else {
// Add "#", if not present
if (!roomAlias.startsWith("#")) {
roomAlias = `#${roomAlias}`;
}
// Add server part, if not present
if (!roomAlias.includes(":")) {
roomAlias = `${roomAlias}:${Config.defaultServerName()}`;
}
}
}

View File

@@ -19,7 +19,7 @@ import { useEffect, useMemo } from "react";
import { useEnableE2EE } from "../settings/useSetting";
import { useLocalStorage } from "../useLocalStorage";
import { useClient } from "../ClientContext";
import { PASSWORD_STRING, useUrlParams } from "../UrlParams";
import { useUrlParams } from "../UrlParams";
import { widget } from "../widget";
export const getRoomSharedKeyLocalStorageKey = (roomId: string): string =>
@@ -60,29 +60,6 @@ export const useRoomSharedKey = (roomId: string): string | null => {
return useInternalRoomSharedKey(roomId)[0] ?? passwordFormUrl;
};
export const useManageRoomSharedKey = (roomId: string): string | null => {
const urlParams = useUrlParams();
const urlPassword = useKeyFromUrl(roomId);
const [e2eeSharedKey] = useInternalRoomSharedKey(roomId);
useEffect(() => {
const hash = location.hash;
if (!hash.includes("?")) return;
if (!hash.includes(PASSWORD_STRING)) return;
if (urlParams.password !== e2eeSharedKey) return;
const [hashStart, passwordStart] = hash.split(PASSWORD_STRING);
const hashEnd = passwordStart.split("&").slice(1).join("&");
location.replace((hashStart ?? "") + (hashEnd ?? ""));
}, [urlParams, e2eeSharedKey]);
return e2eeSharedKey ?? urlPassword;
};
export const useIsRoomE2EE = (roomId: string): boolean | null => {
const { client } = useClient();
const room = useMemo(() => client?.getRoom(roomId) ?? null, [roomId, client]);

View File

@@ -68,9 +68,11 @@ function CallTile({ name, avatarUrl, room }: CallTileProps) {
return (
<div className={styles.callTile}>
<Link
// note we explicitly omit the password here as we don't want it on this link because
// it's just for the user to navigate around and not for sharing
to={getRelativeRoomUrl(room.roomId, room.name)}
to={getRelativeRoomUrl(
room.roomId,
room.name,
roomSharedKey ?? undefined
)}
className={styles.callTileLink}
>
<Avatar id={room.roomId} name={name} size={Size.LG} src={avatarUrl} />

View File

@@ -17,7 +17,6 @@ limitations under the License.
import { useState, useCallback, FormEvent, FormEventHandler } from "react";
import { useHistory } from "react-router-dom";
import { MatrixClient } from "matrix-js-sdk/src/client";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { useTranslation } from "react-i18next";
import { Heading } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
@@ -42,8 +41,6 @@ import { Form } from "../form/Form";
import { useEnableE2EE, useOptInAnalytics } from "../settings/useSetting";
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
import { E2EEBanner } from "../E2EEBanner";
import { setLocalStorageItem } from "../useLocalStorage";
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement";
interface Props {
client: MatrixClient;
@@ -77,18 +74,19 @@ export function RegisteredView({ client }: Props) {
setError(undefined);
setLoading(true);
const roomId = (
await createRoom(client, roomName, e2eeEnabled ?? false)
)[1];
const createRoomResult = await createRoom(
client,
roomName,
e2eeEnabled ?? false
);
if (e2eeEnabled) {
setLocalStorageItem(
getRoomSharedKeyLocalStorageKey(roomId),
randomString(32)
);
}
history.push(getRelativeRoomUrl(roomId, roomName));
history.push(
getRelativeRoomUrl(
createRoomResult.roomId,
roomName,
createRoomResult.password
)
);
}
submit().catch((error) => {

View File

@@ -44,8 +44,6 @@ import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
import { useEnableE2EE, useOptInAnalytics } from "../settings/useSetting";
import { Config } from "../config/Config";
import { E2EEBanner } from "../E2EEBanner";
import { getRoomSharedKeyLocalStorageKey } from "../e2ee/sharedKeyManagement";
import { setLocalStorageItem } from "../useLocalStorage";
export const UnauthenticatedView: FC = () => {
const { setClient } = useClient();
@@ -87,18 +85,13 @@ export const UnauthenticatedView: FC = () => {
true
);
let roomId: string;
let createRoomResult;
try {
roomId = (
await createRoom(client, roomName, e2eeEnabled ?? false)
)[1];
if (e2eeEnabled) {
setLocalStorageItem(
getRoomSharedKeyLocalStorageKey(roomId),
randomString(32)
);
}
createRoomResult = await createRoom(
client,
roomName,
e2eeEnabled ?? false
);
} catch (error) {
if (!setClient) {
throw error;
@@ -127,7 +120,13 @@ export const UnauthenticatedView: FC = () => {
}
setClient({ client, session });
history.push(getRelativeRoomUrl(roomId, roomName));
history.push(
getRelativeRoomUrl(
createRoomResult.roomId,
roomName,
createRoomResult.password
)
);
}
submit().catch((error) => {

View File

@@ -20,6 +20,7 @@ import {
ExternalE2EEKeyProvider,
Room,
RoomOptions,
Track,
} from "livekit-client";
import { useLiveKitRoom } from "@livekit/components-react";
import { useEffect, useMemo, useRef, useState } from "react";
@@ -158,12 +159,54 @@ export function useLiveKit(
if (room !== undefined && connectionState === ConnectionState.Connected) {
const syncDevice = (kind: MediaDeviceKind, device: MediaDevice) => {
const id = device.selectedId;
if (id !== undefined && room.getActiveDevice(kind) !== id) {
room
.switchActiveDevice(kind, id)
.catch((e) =>
logger.error(`Failed to sync ${kind} device with LiveKit`, e)
);
// Detect if we're trying to use chrome's default device, in which case
// we need to to see if the default device has changed to a different device
// by comparing the group ID of the device we're using against the group ID
// of what the default device is *now*.
// This is special-cased for only audio inputs because we need to dig around
// in the LocalParticipant object for the track object and there's not a nice
// way to do that generically. There is usually no OS-level default video capture
// device anyway, and audio outputs work differently.
if (
id === "default" &&
kind === "audioinput" &&
room.options.audioCaptureDefaults?.deviceId === "default"
) {
const activeMicTrack = Array.from(
room.localParticipant.audioTracks.values()
).find((d) => d.source === Track.Source.Microphone)?.track;
const defaultDevice = device.available.find(
(d) => d.deviceId === "default"
);
if (
defaultDevice &&
activeMicTrack &&
// only restart if the stream is still running: LiveKit will detect
// when a track stops & restart appropriately, so this is not our job.
// Plus, we need to avoid restarting again if the track is already in
// the process of being restarted.
activeMicTrack.mediaStreamTrack.readyState !== "ended" &&
defaultDevice.groupId !==
activeMicTrack.mediaStreamTrack.getSettings().groupId
) {
// It's different, so restart the track, ie. cause Livekit to do another
// getUserMedia() call with deviceId: default to get the *new* default device.
// Note that room.switchActiveDevice() won't work: Livekit will ignore it because
// the deviceId hasn't changed (was & still is default).
room.localParticipant
.getTrack(Track.Source.Microphone)
?.audioTrack?.restartTrack();
}
} else {
if (id !== undefined && room.getActiveDevice(kind) !== id) {
room
.switchActiveDevice(kind, id)
.catch((e) =>
logger.error(`Failed to sync ${kind} device with LiveKit`, e)
);
}
}
};

View File

@@ -1,5 +1,5 @@
/*
Copyright 2022 New Vector Ltd
Copyright 2022-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.
@@ -35,6 +35,8 @@ import IndexedDBWorker from "./IndexedDBWorker?worker";
import { getUrlParams, PASSWORD_STRING } from "./UrlParams";
import { loadOlm } from "./olm";
import { Config } from "./config/Config";
import { setLocalStorageItem } from "./useLocalStorage";
import { getRoomSharedKeyLocalStorageKey } from "./e2ee/sharedKeyManagement";
export const fallbackICEServerAllowed =
import.meta.env.VITE_FALLBACK_STUN_ALLOWED === "true";
@@ -71,6 +73,14 @@ function waitForSync(client: MatrixClient) {
});
}
function secureRandomString(entropyBytes: number): string {
const key = new Uint8Array(entropyBytes);
crypto.getRandomValues(key);
return btoa(
key.reduce((acc, current) => acc + String.fromCharCode(current), "")
).replace(/=*$/, "");
}
/**
* Initialises and returns a new standalone Matrix Client.
* If true is passed for the 'restore' parameter, a check will be made
@@ -269,11 +279,17 @@ export function isLocalRoomId(roomId: string, client: MatrixClient): boolean {
return parts[1] === client.getDomain();
}
interface CreateRoomResult {
roomId: string;
alias?: string;
password?: string;
}
export async function createRoom(
client: MatrixClient,
name: string,
e2ee: boolean
): Promise<[string, string]> {
): Promise<CreateRoomResult> {
logger.log(`Creating room for group call`);
const createPromise = client.createRoom({
visibility: Visibility.Private,
@@ -336,7 +352,20 @@ export async function createRoom(
true
);
return [fullAliasFromRoomName(name, client), result.room_id];
let password;
if (e2ee) {
password = secureRandomString(16);
setLocalStorageItem(
getRoomSharedKeyLocalStorageKey(result.room_id),
password
);
}
return {
roomId: result.room_id,
alias: e2ee ? undefined : fullAliasFromRoomName(name, client),
password,
};
}
/**

View File

@@ -39,10 +39,7 @@ import { useMediaDevices, MediaDevices } from "../livekit/MediaDevicesContext";
import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships";
import { enterRTCSession, leaveRTCSession } from "../rtcSessionHelpers";
import { useMatrixRTCSessionJoinState } from "../useMatrixRTCSessionJoinState";
import {
useManageRoomSharedKey,
useIsRoomE2EE,
} from "../e2ee/sharedKeyManagement";
import { useIsRoomE2EE, useRoomSharedKey } from "../e2ee/sharedKeyManagement";
import { useEnableE2EE } from "../settings/useSetting";
import { useRoomAvatar } from "./useRoomAvatar";
import { useRoomName } from "./useRoomName";
@@ -75,7 +72,7 @@ export function GroupCallView({
const memberships = useMatrixRTCSessionMemberships(rtcSession);
const isJoined = useMatrixRTCSessionJoinState(rtcSession);
const e2eeSharedKey = useManageRoomSharedKey(rtcSession.room.roomId);
const e2eeSharedKey = useRoomSharedKey(rtcSession.room.roomId);
const isRoomE2EE = useIsRoomE2EE(rtcSession.room.roomId);
useEffect(() => {
@@ -217,13 +214,16 @@ export function GroupCallView({
sendInstantly
);
leaveRTCSession(rtcSession);
await leaveRTCSession(rtcSession);
if (widget) {
// we need to wait until the callEnded event is tracked on posthog.
// Otherwise the iFrame gets killed before the callEnded event got tracked.
await new Promise((resolve) => window.setTimeout(resolve, 10)); // 10ms
widget.api.setAlwaysOnScreen(false);
PosthogAnalytics.instance.logout();
// we will always send the hangup event after the memberships have been updated
// calling leaveRTCSession.
widget.api.transport.send(ElementWidgetActions.HangupCall, {});
}

View File

@@ -47,7 +47,9 @@ export function enterRTCSession(rtcSession: MatrixRTCSession) {
rtcSession.joinRoomSession([makeFocus(livekitAlias)]);
}
export function leaveRTCSession(rtcSession: MatrixRTCSession) {
export async function leaveRTCSession(
rtcSession: MatrixRTCSession
): Promise<void> {
//groupCallOTelMembership?.onLeaveCall();
rtcSession.leaveRoomSession();
await rtcSession.leaveRoomSession();
}

View File

@@ -70,9 +70,7 @@ interface WidgetHelpers {
*/
export const widget: WidgetHelpers | null = (() => {
try {
const query = new URLSearchParams(window.location.search);
const widgetId = query.get("widgetId");
const parentUrl = query.get("parentUrl");
const { widgetId, parentUrl } = getUrlParams();
if (widgetId && parentUrl) {
const parentOrigin = new URL(parentUrl).origin;

718
yarn.lock

File diff suppressed because it is too large Load Diff