mirror of
https://github.com/vector-im/element-call.git
synced 2026-08-29 21:15:19 +00:00
Compare commits
10 Commits
toger5/med
...
v0.12.0-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24cb61c24b | ||
|
|
8f424452fc | ||
|
|
c2ce1fd382 | ||
|
|
52895ed599 | ||
|
|
0719320ceb | ||
|
|
593a50289a | ||
|
|
60881d7b11 | ||
|
|
5f65c51cf3 | ||
|
|
4876bddea4 | ||
|
|
a5a737f830 |
2
.github/workflows/blocked.yaml
vendored
2
.github/workflows/blocked.yaml
vendored
@@ -1,7 +1,7 @@
|
||||
name: Prevent blocked
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, labeled, unlabeled, synchronize]
|
||||
types: [opened, labeled, unlabeled]
|
||||
jobs:
|
||||
prevent-blocked:
|
||||
name: Prevent blocked
|
||||
|
||||
3
.github/workflows/test.yaml
vendored
3
.github/workflows/test.yaml
vendored
@@ -46,8 +46,7 @@ jobs:
|
||||
run: yarn playwright install --with-deps
|
||||
- name: Run backend components
|
||||
run: |
|
||||
docker compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml pull
|
||||
docker compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml up -d
|
||||
docker compose -f playwright-backend-docker-compose.yml up -d
|
||||
docker ps
|
||||
- name: Copy config file
|
||||
run: cp config/config.devenv.json public/config.json
|
||||
|
||||
@@ -43,11 +43,6 @@ server {
|
||||
# MatrixRTC reverse proxy
|
||||
# - MatrixRTC Authorization Service
|
||||
# - LiveKit SFU websocket signaling connection
|
||||
upstream jwt-auth-services {
|
||||
server auth-server:6080;
|
||||
server host.docker.internal:6080;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
@@ -67,9 +62,8 @@ server {
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
|
||||
# JWT Service running at port 6080
|
||||
proxy_pass http://jwt-auth-services/;
|
||||
|
||||
# JWT Service running at port 8080
|
||||
proxy_pass http://auth-server:8080/;
|
||||
}
|
||||
|
||||
location ^~ /livekit/sfu/ {
|
||||
|
||||
@@ -6,7 +6,7 @@ services:
|
||||
image: ghcr.io/element-hq/lk-jwt-service:latest-ci
|
||||
hostname: auth-server
|
||||
environment:
|
||||
- LIVEKIT_JWT_PORT=6080
|
||||
- LK_JWT_PORT=8080
|
||||
- LIVEKIT_URL=wss://matrix-rtc.m.localhost/livekit/sfu
|
||||
- LIVEKIT_KEY=devkey
|
||||
- LIVEKIT_SECRET=secret
|
||||
@@ -18,7 +18,7 @@ services:
|
||||
condition: on-failure
|
||||
ports:
|
||||
# HOST_PORT:CONTAINER_PORT
|
||||
- 6080:6080
|
||||
- 8080:8080
|
||||
networks:
|
||||
- ecbackend
|
||||
|
||||
|
||||
19
package.json
19
package.json
@@ -22,7 +22,6 @@
|
||||
"test": "vitest",
|
||||
"test:coverage": "vitest --coverage",
|
||||
"backend": "docker-compose -f dev-backend-docker-compose.yml up",
|
||||
"backend-playwright": "docker-compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml up",
|
||||
"test:playwright": "playwright test",
|
||||
"test:playwright:open": "yarn test:playwright --ui",
|
||||
"links:enable": "mv .links.disabled.yaml .links.yaml & touch .links.yaml",
|
||||
@@ -44,11 +43,11 @@
|
||||
"@livekit/track-processors": "^0.5.5",
|
||||
"@mediapipe/tasks-vision": "^0.10.18",
|
||||
"@opentelemetry/api": "^1.4.0",
|
||||
"@opentelemetry/core": "^2.0.0",
|
||||
"@opentelemetry/exporter-trace-otlp-http": "^0.201.0",
|
||||
"@opentelemetry/resources": "^2.0.0",
|
||||
"@opentelemetry/sdk-trace-base": "^2.0.0",
|
||||
"@opentelemetry/sdk-trace-web": "^2.0.0",
|
||||
"@opentelemetry/core": "^1.25.1",
|
||||
"@opentelemetry/exporter-trace-otlp-http": "^0.57.0",
|
||||
"@opentelemetry/resources": "^1.25.1",
|
||||
"@opentelemetry/sdk-trace-base": "^1.25.1",
|
||||
"@opentelemetry/sdk-trace-web": "^1.9.1",
|
||||
"@opentelemetry/semantic-conventions": "^1.25.1",
|
||||
"@playwright/test": "^1.52.0",
|
||||
"@radix-ui/react-dialog": "^1.0.4",
|
||||
@@ -77,8 +76,8 @@
|
||||
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
||||
"@typescript-eslint/parser": "^8.31.0",
|
||||
"@use-gesture/react": "^10.2.11",
|
||||
"@vector-im/compound-design-tokens": "^4.0.0",
|
||||
"@vector-im/compound-web": "^7.12.0",
|
||||
"@vector-im/compound-design-tokens": "^3.0.0",
|
||||
"@vector-im/compound-web": "^7.2.0",
|
||||
"@vitejs/plugin-react": "^4.0.1",
|
||||
"@vitest/coverage-v8": "^3.0.0",
|
||||
"babel-plugin-transform-vite-meta-env": "^1.0.3",
|
||||
@@ -89,7 +88,7 @@
|
||||
"eslint-plugin-deprecate": "^0.8.2",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.5.1",
|
||||
"eslint-plugin-matrix-org": "2.1.0",
|
||||
"eslint-plugin-matrix-org": "^2.0.0",
|
||||
"eslint-plugin-react": "^7.29.4",
|
||||
"eslint-plugin-react-hooks": "^5.0.0",
|
||||
"eslint-plugin-rxjs": "^5.0.3",
|
||||
@@ -126,7 +125,7 @@
|
||||
"unique-names-generator": "^4.6.0",
|
||||
"vaul": "^1.0.0",
|
||||
"vite": "^6.0.0",
|
||||
"vite-plugin-generate-file": "^0.3.0",
|
||||
"vite-plugin-generate-file": "^0.2.0",
|
||||
"vite-plugin-html": "^3.2.2",
|
||||
"vite-plugin-svgr": "^4.0.0",
|
||||
"vitest": "^3.0.0",
|
||||
|
||||
@@ -5,13 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import {
|
||||
type Browser,
|
||||
type Page,
|
||||
test,
|
||||
expect,
|
||||
type JSHandle,
|
||||
} from "@playwright/test";
|
||||
import { type Page, test, expect, type JSHandle } from "@playwright/test";
|
||||
|
||||
import type { MatrixClient } from "matrix-js-sdk";
|
||||
|
||||
@@ -36,8 +30,8 @@ const PASSWORD = "foobarbaz1!";
|
||||
const CONFIG_JSON = {
|
||||
default_server_config: {
|
||||
"m.homeserver": {
|
||||
base_url: "https://synapse.m.localhost",
|
||||
server_name: "synapse.m.localhost",
|
||||
base_url: "http://synapse.localhost:8008",
|
||||
server_name: "synapse.localhost",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -80,52 +74,6 @@ async function setDevToolElementCallDevUrl(page: Page): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new user and returns page, clientHandle and mxId.
|
||||
*/
|
||||
async function registerUser(
|
||||
browser: Browser,
|
||||
username: string,
|
||||
): Promise<{ page: Page; clientHandle: JSHandle<MatrixClient>; mxId: string }> {
|
||||
const userContext = await browser.newContext({
|
||||
reducedMotion: "reduce",
|
||||
});
|
||||
const page = await userContext.newPage();
|
||||
await page.goto("http://localhost:8081/#/welcome");
|
||||
await page.getByRole("link", { name: "Create Account" }).click();
|
||||
await page.getByRole("textbox", { name: "Username" }).fill(username);
|
||||
await page
|
||||
.getByRole("textbox", { name: "Password", exact: true })
|
||||
.fill(PASSWORD);
|
||||
await page.getByRole("textbox", { name: "Confirm password" }).click();
|
||||
await page.getByRole("textbox", { name: "Confirm password" }).fill(PASSWORD);
|
||||
await page.getByRole("button", { name: "Register" }).click();
|
||||
const continueButton = page.getByRole("button", { name: "Continue" });
|
||||
try {
|
||||
await expect(continueButton).toBeVisible({ timeout: 5000 });
|
||||
await page
|
||||
.getByRole("textbox", { name: "Password", exact: true })
|
||||
.fill(PASSWORD);
|
||||
await continueButton.click();
|
||||
} catch {
|
||||
// continueButton not visible, continue as normal
|
||||
}
|
||||
await expect(
|
||||
page.getByRole("heading", { name: `Welcome ${username}` }),
|
||||
).toBeVisible();
|
||||
await setDevToolElementCallDevUrl(page);
|
||||
|
||||
const clientHandle = await page.evaluateHandle(() =>
|
||||
window.mxMatrixClientPeg.get(),
|
||||
);
|
||||
const mxId = (await clientHandle.evaluate(
|
||||
(cli: MatrixClient) => cli.getUserId(),
|
||||
clientHandle,
|
||||
))!;
|
||||
|
||||
return { page, clientHandle, mxId };
|
||||
}
|
||||
|
||||
export const widgetTest = test.extend<MyFixtures>({
|
||||
asWidget: async ({ browser, context }, pUse) => {
|
||||
await context.route(`http://localhost:8081/config.json*`, async (route) => {
|
||||
@@ -135,17 +83,61 @@ export const widgetTest = test.extend<MyFixtures>({
|
||||
const userA = `brooks_${Date.now()}`;
|
||||
const userB = `whistler_${Date.now()}`;
|
||||
|
||||
// Register users
|
||||
const {
|
||||
page: ewPage1,
|
||||
clientHandle: brooksClientHandle,
|
||||
mxId: brooksMxId,
|
||||
} = await registerUser(browser, userA);
|
||||
const {
|
||||
page: ewPage2,
|
||||
clientHandle: whistlerClientHandle,
|
||||
mxId: whistlerMxId,
|
||||
} = await registerUser(browser, userB);
|
||||
const user1Context = await browser.newContext({
|
||||
reducedMotion: "reduce",
|
||||
});
|
||||
const ewPage1 = await user1Context.newPage();
|
||||
// Register the first user
|
||||
await ewPage1.goto("http://localhost:8081/#/welcome");
|
||||
await ewPage1.getByRole("link", { name: "Create Account" }).click();
|
||||
await ewPage1.getByRole("textbox", { name: "Username" }).fill(userA);
|
||||
await ewPage1
|
||||
.getByRole("textbox", { name: "Password", exact: true })
|
||||
.fill(PASSWORD);
|
||||
await ewPage1.getByRole("textbox", { name: "Confirm password" }).click();
|
||||
await ewPage1
|
||||
.getByRole("textbox", { name: "Confirm password" })
|
||||
.fill(PASSWORD);
|
||||
await ewPage1.getByRole("button", { name: "Register" }).click();
|
||||
await expect(
|
||||
ewPage1.getByRole("heading", { name: `Welcome ${userA}` }),
|
||||
).toBeVisible();
|
||||
await setDevToolElementCallDevUrl(ewPage1);
|
||||
|
||||
const brooksClientHandle = await ewPage1.evaluateHandle(() =>
|
||||
window.mxMatrixClientPeg.get(),
|
||||
);
|
||||
const brooksMxId = (await brooksClientHandle.evaluate((cli) => {
|
||||
return cli.getUserId();
|
||||
}, brooksClientHandle))!;
|
||||
|
||||
const user2Context = await browser.newContext({
|
||||
reducedMotion: "reduce",
|
||||
});
|
||||
const ewPage2 = await user2Context.newPage();
|
||||
// Register the second user
|
||||
await ewPage2.goto("http://localhost:8081/#/welcome");
|
||||
await ewPage2.getByRole("link", { name: "Create Account" }).click();
|
||||
await ewPage2.getByRole("textbox", { name: "Username" }).fill(userB);
|
||||
await ewPage2
|
||||
.getByRole("textbox", { name: "Password", exact: true })
|
||||
.fill(PASSWORD);
|
||||
await ewPage2.getByRole("textbox", { name: "Confirm password" }).click();
|
||||
await ewPage2
|
||||
.getByRole("textbox", { name: "Confirm password" })
|
||||
.fill(PASSWORD);
|
||||
await ewPage2.getByRole("button", { name: "Register" }).click();
|
||||
await expect(
|
||||
ewPage2.getByRole("heading", { name: `Welcome ${userB}` }),
|
||||
).toBeVisible();
|
||||
await setDevToolElementCallDevUrl(ewPage2);
|
||||
|
||||
const whistlerClientHandle = await ewPage2.evaluateHandle(() =>
|
||||
window.mxMatrixClientPeg.get(),
|
||||
);
|
||||
const whistlerMxId = (await whistlerClientHandle.evaluate((cli) => {
|
||||
return cli.getUserId();
|
||||
}, whistlerClientHandle))!;
|
||||
|
||||
// Invite the second user
|
||||
await ewPage1.getByRole("button", { name: "Add room" }).click();
|
||||
|
||||
@@ -9,14 +9,11 @@ import { expect, test } from "@playwright/test";
|
||||
|
||||
import { widgetTest } from "../fixtures/widget-user.ts";
|
||||
|
||||
// Skip test, including Fixtures
|
||||
widgetTest.skip(
|
||||
({ browserName }) => browserName === "firefox",
|
||||
"This test is not working on firefox, after hangup brooks is locked in a strange state with a blank widget",
|
||||
);
|
||||
|
||||
widgetTest("Start a new call as widget", async ({ asWidget, browserName }) => {
|
||||
test.slow(); // Triples the timeout
|
||||
test.skip(
|
||||
browserName === "firefox",
|
||||
"This test is not working on firefox, after hangup brooks is locked in a strange state with a blank widget",
|
||||
);
|
||||
|
||||
const { brooks, whistler } = asWidget;
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
}
|
||||
],
|
||||
"semanticCommits": "disabled",
|
||||
"ignoreDeps": ["posthog-js", "eslint-plugin-matrix-org"],
|
||||
"ignoreDeps": ["posthog-js"],
|
||||
"vulnerabilityAlerts": {
|
||||
"schedule": ["at any time"],
|
||||
"prHourlyLimit": 0,
|
||||
|
||||
@@ -10,7 +10,7 @@ import classNames from "classnames";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import * as Sentry from "@sentry/react";
|
||||
import { logger } from "matrix-js-sdk/lib/logger";
|
||||
import { ErrorSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
import { ErrorIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import { Header, HeaderLogo, LeftNav, RightNav } from "./Header";
|
||||
import styles from "./FullScreenView.module.css";
|
||||
@@ -67,7 +67,7 @@ export const ErrorPage = ({ error, widget }: ErrorPageProps): ReactElement => {
|
||||
) : (
|
||||
<ErrorView
|
||||
widget={widget}
|
||||
Icon={ErrorSolidIcon}
|
||||
Icon={ErrorIcon}
|
||||
title={t("error.generic")}
|
||||
rageshake
|
||||
fatal
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
exports[`the content is rendered when the modal is open 1`] = `
|
||||
<div
|
||||
aria-labelledby="radix-:r4:"
|
||||
class="overlay animate modal dialog _glass_sepwu_8"
|
||||
class="overlay animate modal dialog _glass_1x9g9_17"
|
||||
data-state="open"
|
||||
id="radix-:r3:"
|
||||
role="dialog"
|
||||
@@ -17,7 +17,7 @@ exports[`the content is rendered when the modal is open 1`] = `
|
||||
class="header"
|
||||
>
|
||||
<h2
|
||||
class="_typography_6v6n8_153 _font-heading-md-semibold_6v6n8_112"
|
||||
class="_typography_yh5dq_162 _font-heading-md-semibold_yh5dq_121"
|
||||
id="radix-:r4:"
|
||||
>
|
||||
My modal
|
||||
|
||||
@@ -12,7 +12,7 @@ exports[`Toast > renders 1`] = `
|
||||
type="button"
|
||||
>
|
||||
<h3
|
||||
class="_typography_6v6n8_153 _font-body-sm-semibold_6v6n8_36"
|
||||
class="_typography_yh5dq_162 _font-body-sm-semibold_yh5dq_45"
|
||||
id="radix-:r4:"
|
||||
>
|
||||
Hello world!
|
||||
|
||||
@@ -107,13 +107,13 @@ export class RageshakeSpanProcessor implements SpanProcessor {
|
||||
startTime,
|
||||
duration,
|
||||
references:
|
||||
span.parentSpanContext?.spanId === undefined
|
||||
span.parentSpanId === undefined
|
||||
? []
|
||||
: [
|
||||
{
|
||||
refType: "CHILD_OF",
|
||||
traceID: traceId,
|
||||
spanID: span.parentSpanContext?.spanId,
|
||||
spanID: span.parentSpanId,
|
||||
},
|
||||
],
|
||||
tags: dumpAttributes(span.attributes),
|
||||
|
||||
@@ -10,7 +10,7 @@ exports[`Can close reaction dialog 1`] = `
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-labelledby=":rb5:"
|
||||
class="_button_vczzf_8 _has-icon_vczzf_57 _icon-only_vczzf_50"
|
||||
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -26,7 +26,7 @@ exports[`Can close reaction dialog 1`] = `
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10m3.536-6.464a1 1 0 0 0-1.415-1.415A3 3 0 0 1 12 15a3 3 0 0 1-2.121-.879 1 1 0 1 0-1.414 1.415A5 5 0 0 0 12 17c1.38 0 2.632-.56 3.536-1.464M10 10.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m5.5 1.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3"
|
||||
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Zm3.536-6.464a1 1 0 0 0-1.415-1.415A2.988 2.988 0 0 1 12 15a2.988 2.988 0 0 1-2.121-.879 1 1 0 1 0-1.414 1.415A4.987 4.987 0 0 0 12 17c1.38 0 2.632-.56 3.536-1.464ZM10 10.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Zm5.5 1.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
@@ -44,7 +44,7 @@ exports[`Can fully expand emoji picker 1`] = `
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-labelledby=":r7m:"
|
||||
class="_button_vczzf_8 _has-icon_vczzf_57 _icon-only_vczzf_50"
|
||||
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -60,7 +60,7 @@ exports[`Can fully expand emoji picker 1`] = `
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10m3.536-6.464a1 1 0 0 0-1.415-1.415A3 3 0 0 1 12 15a3 3 0 0 1-2.121-.879 1 1 0 1 0-1.414 1.415A5 5 0 0 0 12 17c1.38 0 2.632-.56 3.536-1.464M10 10.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m5.5 1.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3"
|
||||
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Zm3.536-6.464a1 1 0 0 0-1.415-1.415A2.988 2.988 0 0 1 12 15a2.988 2.988 0 0 1-2.121-.879 1 1 0 1 0-1.414 1.415A4.987 4.987 0 0 0 12 17c1.38 0 2.632-.56 3.536-1.464ZM10 10.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Zm5.5 1.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
@@ -75,7 +75,7 @@ exports[`Can lower hand 1`] = `
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-labelledby=":r36:"
|
||||
class="_button_vczzf_8 _has-icon_vczzf_57 _icon-only_vczzf_50"
|
||||
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
|
||||
data-kind="secondary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -91,7 +91,7 @@ exports[`Can lower hand 1`] = `
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10m3.536-6.464a1 1 0 0 0-1.415-1.415A3 3 0 0 1 12 15a3 3 0 0 1-2.121-.879 1 1 0 1 0-1.414 1.415A5 5 0 0 0 12 17c1.38 0 2.632-.56 3.536-1.464M10 10.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m5.5 1.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3"
|
||||
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Zm3.536-6.464a1 1 0 0 0-1.415-1.415A2.988 2.988 0 0 1 12 15a2.988 2.988 0 0 1-2.121-.879 1 1 0 1 0-1.414 1.415A4.987 4.987 0 0 0 12 17c1.38 0 2.632-.56 3.536-1.464ZM10 10.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Zm5.5 1.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
@@ -109,7 +109,7 @@ exports[`Can open menu 1`] = `
|
||||
aria-expanded="true"
|
||||
aria-haspopup="true"
|
||||
aria-labelledby=":r0:"
|
||||
class="_button_vczzf_8 _has-icon_vczzf_57 _icon-only_vczzf_50"
|
||||
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -125,7 +125,7 @@ exports[`Can open menu 1`] = `
|
||||
>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10m3.536-6.464a1 1 0 0 0-1.415-1.415A3 3 0 0 1 12 15a3 3 0 0 1-2.121-.879 1 1 0 1 0-1.414 1.415A5 5 0 0 0 12 17c1.38 0 2.632-.56 3.536-1.464M10 10.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0m5.5 1.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3"
|
||||
d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10Zm3.536-6.464a1 1 0 0 0-1.415-1.415A2.988 2.988 0 0 1 12 15a2.988 2.988 0 0 1-2.121-.879 1 1 0 1 0-1.414 1.415A4.987 4.987 0 0 0 12 17c1.38 0 2.632-.56 3.536-1.464ZM10 10.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Zm5.5 1.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
@@ -140,7 +140,7 @@ exports[`Can raise hand 1`] = `
|
||||
aria-expanded="false"
|
||||
aria-haspopup="true"
|
||||
aria-labelledby=":r1j:"
|
||||
class="_button_vczzf_8 raisedButton _has-icon_vczzf_57 _icon-only_vczzf_50"
|
||||
class="_button_i91xf_17 raisedButton _has-icon_i91xf_66 _icon-only_i91xf_59"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -155,7 +155,7 @@ exports[`Can raise hand 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M11 3a1 1 0 1 1 2 0v8.5a.5.5 0 0 0 1 0V4a1 1 0 1 1 2 0v10.2l3.284-2.597a1.081 1.081 0 0 1 1.47 1.577c-.613.673-1.214 1.367-1.818 2.064-1.267 1.463-2.541 2.934-3.943 4.235A6 6 0 0 1 5 15V7a1 1 0 0 1 1.999 0v5.5a.5.5 0 0 0 1 0V4a1 1 0 0 1 2 0v7.5a.5.5 0 0 0 1 0z"
|
||||
d="M11 3a1 1 0 1 1 2 0v8.5a.5.5 0 0 0 1 0V4a1 1 0 1 1 2 0v10.2l3.284-2.597a1.081 1.081 0 0 1 1.47 1.577c-.613.673-1.214 1.367-1.818 2.064-1.267 1.463-2.541 2.934-3.944 4.235A6 6 0 0 1 5 15V7a1 1 0 0 1 2 0v5.5a.5.5 0 0 0 1 0V4a1 1 0 0 1 2 0v7.5a.5.5 0 0 0 1 0V3Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
@@ -21,7 +21,7 @@ const getRoomSharedKeyLocalStorageKey = (roomId: string): string =>
|
||||
|
||||
const useInternalRoomSharedKey = (roomId: string): string | null => {
|
||||
const key = getRoomSharedKeyLocalStorageKey(roomId);
|
||||
const [roomSharedKey] = useLocalStorage(key);
|
||||
const roomSharedKey = useLocalStorage(key)[0];
|
||||
|
||||
return roomSharedKey;
|
||||
};
|
||||
|
||||
@@ -8,14 +8,16 @@ Please see LICENSE in the repository root for full details.
|
||||
import {
|
||||
type FC,
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
type JSX,
|
||||
} from "react";
|
||||
import { createMediaDeviceObserver } from "@livekit/components-core";
|
||||
import { combineLatest, filter, map, pairwise, startWith } from "rxjs";
|
||||
import { combineLatest, map, startWith } from "rxjs";
|
||||
import { useObservable, useObservableEagerState } from "observable-hooks";
|
||||
import { logger } from "matrix-js-sdk/lib/logger";
|
||||
|
||||
@@ -64,6 +66,9 @@ export interface MediaDeviceHandle {
|
||||
interface InputDevices {
|
||||
audioInput: MediaDeviceHandle;
|
||||
videoInput: MediaDeviceHandle;
|
||||
startUsingDeviceNames: () => void;
|
||||
stopUsingDeviceNames: () => void;
|
||||
usingNames: boolean;
|
||||
}
|
||||
|
||||
export interface MediaDevices extends Omit<InputDevices, "usingNames"> {
|
||||
@@ -115,7 +120,14 @@ function useSelectedId(
|
||||
function useMediaDeviceHandle(
|
||||
kind: MediaDeviceKind,
|
||||
setting: Setting<string | undefined>,
|
||||
usingNames: boolean,
|
||||
): MediaDeviceHandle {
|
||||
const hasRequestedPermissions = useRef(false);
|
||||
const requestPermissions = usingNames || hasRequestedPermissions.current;
|
||||
// Make sure we don't needlessly reset to a device observer without names,
|
||||
// once permissions are already given
|
||||
hasRequestedPermissions.current ||= usingNames;
|
||||
|
||||
// We use a bare device observer here rather than one of the fancy device
|
||||
// selection hooks from @livekit/components-react, because
|
||||
// useMediaDeviceSelect expects a room or track, which we don't have here, and
|
||||
@@ -124,34 +136,13 @@ function useMediaDeviceHandle(
|
||||
// kind, which then results in multiple permissions requests.
|
||||
const deviceObserver$ = useMemo(
|
||||
() =>
|
||||
createMediaDeviceObserver(kind, () =>
|
||||
logger.error("Error creating MediaDeviceObserver"),
|
||||
).pipe(
|
||||
startWith(undefined, []),
|
||||
// Convert to a tuple of previous and next value.
|
||||
pairwise(),
|
||||
// Filter out consecutive updates that don't change the available devices.
|
||||
// createMediaDeviceObserver can will emit each time, 'devicechange' is emitted.
|
||||
// On safari this happens each time we call `getUserMedia`.
|
||||
filter(([prev, n]) => {
|
||||
// The only way to get undefined is with startWith for `prev`.
|
||||
const next = n!;
|
||||
if (prev === undefined) return true;
|
||||
if (prev.length !== next.length) return true;
|
||||
if (prev.length === 0) return false;
|
||||
return !next.every(
|
||||
(d, i) =>
|
||||
d.deviceId === prev[i].deviceId && d.label === prev[i].label,
|
||||
);
|
||||
}),
|
||||
// Convert back to non-pairwise observable
|
||||
map(([, next]) => next!),
|
||||
// Use startWith at the end to ensure that the observable
|
||||
// always emits an initial value that does not get filtered out.
|
||||
),
|
||||
[kind],
|
||||
createMediaDeviceObserver(
|
||||
kind,
|
||||
() => logger.error("Error creating MediaDeviceObserver"),
|
||||
requestPermissions,
|
||||
).pipe(startWith([])),
|
||||
[kind, requestPermissions],
|
||||
);
|
||||
|
||||
const available = useObservableEagerState(
|
||||
useMemo(
|
||||
() =>
|
||||
@@ -182,13 +173,6 @@ function useMediaDeviceHandle(
|
||||
["", { type: "default", name: availableRaw[0]?.label || null }],
|
||||
...available,
|
||||
]);
|
||||
const availablePrint = Array.from(available.entries()).map(
|
||||
([id, label]) =>
|
||||
`id:${id === "" ? '""' : id} label:${(label as { name?: string }).name}\n`,
|
||||
);
|
||||
logger.info(
|
||||
`Media devices changed.\nkind ${kind}\n(deviceObserver$ updated): ${availablePrint}`,
|
||||
);
|
||||
// Note: creating virtual default input devices would be another problem
|
||||
// entirely, because requesting a media stream from deviceId "" won't
|
||||
// automatically track the default device.
|
||||
@@ -239,19 +223,43 @@ export const devicesStub: MediaDevices = {
|
||||
audioInput: deviceStub,
|
||||
audioOutput: deviceStub,
|
||||
videoInput: deviceStub,
|
||||
startUsingDeviceNames: () => {},
|
||||
stopUsingDeviceNames: () => {},
|
||||
};
|
||||
|
||||
export const MediaDevicesContext = createContext<MediaDevices>(devicesStub);
|
||||
|
||||
function useInputDevices(): InputDevices {
|
||||
// Counts the number of callers currently using device names.
|
||||
const [numCallersUsingNames, setNumCallersUsingNames] = useState(0);
|
||||
const usingNames = numCallersUsingNames > 0;
|
||||
|
||||
const audioInput = useMediaDeviceHandle("audioinput", audioInputSetting);
|
||||
const videoInput = useMediaDeviceHandle("videoinput", videoInputSetting);
|
||||
const audioInput = useMediaDeviceHandle(
|
||||
"audioinput",
|
||||
audioInputSetting,
|
||||
usingNames,
|
||||
);
|
||||
const videoInput = useMediaDeviceHandle(
|
||||
"videoinput",
|
||||
videoInputSetting,
|
||||
usingNames,
|
||||
);
|
||||
|
||||
const startUsingDeviceNames = useCallback(
|
||||
() => setNumCallersUsingNames((n) => n + 1),
|
||||
[setNumCallersUsingNames],
|
||||
);
|
||||
const stopUsingDeviceNames = useCallback(
|
||||
() => setNumCallersUsingNames((n) => n - 1),
|
||||
[setNumCallersUsingNames],
|
||||
);
|
||||
|
||||
return {
|
||||
audioInput,
|
||||
videoInput,
|
||||
startUsingDeviceNames,
|
||||
stopUsingDeviceNames,
|
||||
usingNames,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -260,13 +268,20 @@ interface Props {
|
||||
}
|
||||
|
||||
export const MediaDevicesProvider: FC<Props> = ({ children }) => {
|
||||
const { audioInput, videoInput } = useInputDevices();
|
||||
const {
|
||||
audioInput,
|
||||
videoInput,
|
||||
startUsingDeviceNames,
|
||||
stopUsingDeviceNames,
|
||||
usingNames,
|
||||
} = useInputDevices();
|
||||
|
||||
const { controlledAudioDevices } = useUrlParams();
|
||||
|
||||
const webViewAudioOutput = useMediaDeviceHandle(
|
||||
"audiooutput",
|
||||
audioOutputSetting,
|
||||
usingNames,
|
||||
);
|
||||
const controlledAudioOutput = useControlledOutput();
|
||||
|
||||
@@ -277,6 +292,8 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
|
||||
? controlledAudioOutput
|
||||
: webViewAudioOutput,
|
||||
videoInput,
|
||||
startUsingDeviceNames,
|
||||
stopUsingDeviceNames,
|
||||
}),
|
||||
[
|
||||
audioInput,
|
||||
@@ -284,6 +301,8 @@ export const MediaDevicesProvider: FC<Props> = ({ children }) => {
|
||||
controlledAudioOutput,
|
||||
webViewAudioOutput,
|
||||
videoInput,
|
||||
startUsingDeviceNames,
|
||||
stopUsingDeviceNames,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -377,6 +396,17 @@ export const useMediaDevices = (): MediaDevices =>
|
||||
* default because it may involve requesting additional permissions from the
|
||||
* user.
|
||||
*/
|
||||
export const useMediaDeviceNames = (
|
||||
context: MediaDevices,
|
||||
enabled = true,
|
||||
): void =>
|
||||
useEffect(() => {
|
||||
if (enabled) {
|
||||
context.startUsingDeviceNames();
|
||||
return context.stopUsingDeviceNames;
|
||||
}
|
||||
}, [context, enabled]);
|
||||
|
||||
/**
|
||||
* A convenience hook to get the audio node configuration for the earpiece.
|
||||
* It will check the `useAsEarpiece` of the `audioOutput` device and return
|
||||
|
||||
@@ -131,7 +131,6 @@ export function useLivekit(
|
||||
// @livekit/components-react. JSON.stringify() is used in deps of a
|
||||
// useEffect() with an argument that references itself, if E2EE is enabled
|
||||
const room = useMemo(() => {
|
||||
logger.info("[LivekitRooms] Create LiveKit room with options", roomOptions);
|
||||
const r = new Room(roomOptions);
|
||||
r.setE2EEEnabled(e2eeSystem.kind !== E2eeType.NONE).catch((e) => {
|
||||
logger.error("Failed to set E2EE enabled on room", e);
|
||||
|
||||
@@ -29,7 +29,7 @@ window.setLKLogLevel = setLKLogLevel;
|
||||
initRageshake().catch((e) => {
|
||||
logger.error("Failed to initialize rageshake", e);
|
||||
});
|
||||
setLKLogLevel("info");
|
||||
setLKLogLevel("warn");
|
||||
setLKLogExtension((level, msg, context) => {
|
||||
// we pass a synthetic logger name of "livekit" to the rageshake to make it easier to read
|
||||
global.mx_rage_logger.log(level, "livekit", msg, context);
|
||||
|
||||
@@ -5,15 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
Please see LICENSE in the repository root for full details.
|
||||
*/
|
||||
|
||||
import {
|
||||
SimpleSpanProcessor,
|
||||
type SpanProcessor,
|
||||
} from "@opentelemetry/sdk-trace-base";
|
||||
import { SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
||||
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
||||
import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
|
||||
import opentelemetry, { type Tracer } from "@opentelemetry/api";
|
||||
import { resourceFromAttributes } from "@opentelemetry/resources";
|
||||
import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
|
||||
import { Resource } from "@opentelemetry/resources";
|
||||
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
|
||||
import { logger } from "matrix-js-sdk/lib/logger";
|
||||
|
||||
import { PosthogSpanProcessor } from "../analytics/PosthogSpanProcessor";
|
||||
@@ -62,34 +59,34 @@ export class ElementCallOpenTelemetry {
|
||||
collectorUrl: string | undefined,
|
||||
rageshakeUrl: string | undefined,
|
||||
) {
|
||||
const spanProcessors: SpanProcessor[] = [];
|
||||
// This is how we can make Jaeger show a reasonable service in the dropdown on the left.
|
||||
const providerConfig = {
|
||||
resource: new Resource({
|
||||
[SemanticResourceAttributes.SERVICE_NAME]: SERVICE_NAME,
|
||||
}),
|
||||
};
|
||||
this._provider = new WebTracerProvider(providerConfig);
|
||||
|
||||
if (collectorUrl) {
|
||||
logger.info("Enabling OTLP collector with URL " + collectorUrl);
|
||||
this.otlpExporter = new OTLPTraceExporter({
|
||||
url: collectorUrl,
|
||||
});
|
||||
spanProcessors.push(new SimpleSpanProcessor(this.otlpExporter));
|
||||
this._provider.addSpanProcessor(
|
||||
new SimpleSpanProcessor(this.otlpExporter),
|
||||
);
|
||||
} else {
|
||||
logger.info("OTLP collector disabled");
|
||||
}
|
||||
|
||||
if (rageshakeUrl) {
|
||||
this.rageshakeProcessor = new RageshakeSpanProcessor();
|
||||
spanProcessors.push(this.rageshakeProcessor);
|
||||
this._provider.addSpanProcessor(this.rageshakeProcessor);
|
||||
}
|
||||
|
||||
spanProcessors.push(new PosthogSpanProcessor());
|
||||
|
||||
this._provider = new WebTracerProvider({
|
||||
resource: resourceFromAttributes({
|
||||
// This is how we can make Jaeger show a reasonable service in the dropdown on the left.
|
||||
[ATTR_SERVICE_NAME]: SERVICE_NAME,
|
||||
}),
|
||||
spanProcessors,
|
||||
});
|
||||
|
||||
this._provider.addSpanProcessor(new PosthogSpanProcessor());
|
||||
opentelemetry.trace.setGlobalTracerProvider(this._provider);
|
||||
|
||||
this._tracer = opentelemetry.trace.getTracer(
|
||||
// This is not the serviceName shown in jaeger
|
||||
"my-element-call-otl-tracer",
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
} from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import {
|
||||
ErrorSolidIcon,
|
||||
ErrorIcon,
|
||||
HostIcon,
|
||||
OfflineIcon,
|
||||
WebBrowserIcon,
|
||||
@@ -63,7 +63,7 @@ const ErrorPage: FC<ErrorPageProps> = ({
|
||||
icon = WebBrowserIcon;
|
||||
break;
|
||||
default:
|
||||
icon = ErrorSolidIcon;
|
||||
icon = ErrorIcon;
|
||||
}
|
||||
|
||||
const actions: { label: string; onClick: () => void }[] = [];
|
||||
|
||||
@@ -106,6 +106,8 @@ function mockMediaDevices(
|
||||
videoInput: mockDevices(
|
||||
camera ? new Map([[mockCamera.deviceId, mockCamera]]) : new Map(),
|
||||
),
|
||||
startUsingDeviceNames: (): void => {},
|
||||
stopUsingDeviceNames: (): void => {},
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ exports[`ConnectionLostError: Action handling should reset error state 1`] = `
|
||||
class="error"
|
||||
>
|
||||
<div
|
||||
class="_content_o77nw_8 icon"
|
||||
class="_content_md016_17 icon"
|
||||
data-size="large"
|
||||
>
|
||||
<svg
|
||||
@@ -119,12 +119,12 @@ exports[`ConnectionLostError: Action handling should reset error state 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M3.5 3.5a1 1 0 1 0-1.414 1.414l4.113 4.114a5.5 5.5 0 0 0-.184 1.07A5.002 5.002 0 0 0 7 20h10.172l1.914 1.914A1 1 0 1 0 20.5 20.5l-.979-.979.004-.001L7.145 7.14l-.002.003zm18.5 12a4.48 4.48 0 0 1-.928 2.738L8.637 5.803A5.47 5.47 0 0 1 11.5 5a5.49 5.49 0 0 1 4.25 2.008 4 4 0 0 1 4.187 4.708A4.5 4.5 0 0 1 22 15.5"
|
||||
d="M3.5 3.5a1 1 0 1 0-1.414 1.414l4.113 4.114a5.484 5.484 0 0 0-.184 1.069A5.002 5.002 0 0 0 7 20h10.172l1.914 1.914A1 1 0 0 0 20.5 20.5l-.979-.979.004-.002L7.145 7.14l-.002.004L3.5 3.5Zm18.5 12a4.48 4.48 0 0 1-.928 2.738L8.637 5.803A5.474 5.474 0 0 1 11.5 5a5.49 5.49 0 0 1 4.25 2.008 4 4 0 0 1 4.187 4.708A4.497 4.497 0 0 1 22 15.5Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1
|
||||
class="_typography_6v6n8_153 _font-heading-md-semibold_6v6n8_112"
|
||||
class="_typography_yh5dq_162 _font-heading-md-semibold_yh5dq_121"
|
||||
>
|
||||
Connection lost
|
||||
</h1>
|
||||
@@ -135,7 +135,7 @@ exports[`ConnectionLostError: Action handling should reset error state 1`] = `
|
||||
Reconnect
|
||||
</button>
|
||||
<button
|
||||
class="_button_vczzf_8 homeLink"
|
||||
class="_button_i91xf_17 homeLink"
|
||||
data-kind="tertiary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -258,7 +258,7 @@ exports[`should have a close button in widget mode 1`] = `
|
||||
class="error"
|
||||
>
|
||||
<div
|
||||
class="_content_o77nw_8 icon"
|
||||
class="_content_md016_17 icon"
|
||||
data-size="large"
|
||||
>
|
||||
<svg
|
||||
@@ -269,17 +269,17 @@ exports[`should have a close button in widget mode 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.713 6.713A.97.97 0 0 1 16 7a.97.97 0 0 1-.713-.287A.97.97 0 0 1 15 6q0-.424.287-.713A.97.97 0 0 1 16 5q.424 0 .712.287Q17 5.576 17 6t-.288.713"
|
||||
d="M16.712 6.713A.968.968 0 0 1 16 7a.968.968 0 0 1-.713-.287A.967.967 0 0 1 15 6c0-.283.096-.52.287-.713A.968.968 0 0 1 16 5a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713Z"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2zm12 2H6v4h12zM6 12v-2h12v2zm0 2v2h12v-2zm0 6v-2h12v2z"
|
||||
d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H6Zm12 2H6v4h12V4ZM6 12v-2h12v2H6Zm0 2v2h12v-2H6Zm0 6v-2h12v2H6Z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1
|
||||
class="_typography_6v6n8_153 _font-heading-md-semibold_6v6n8_112"
|
||||
class="_typography_yh5dq_162 _font-heading-md-semibold_yh5dq_121"
|
||||
>
|
||||
Call is not supported
|
||||
</h1>
|
||||
@@ -287,7 +287,7 @@ exports[`should have a close button in widget mode 1`] = `
|
||||
The server is not configured to work with Element Call. Please contact your server admin (Domain: example.com, Error Code: MISSING_MATRIX_RTC_FOCUS).
|
||||
</p>
|
||||
<button
|
||||
class="_button_vczzf_8"
|
||||
class="_button_i91xf_17"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -410,7 +410,7 @@ exports[`should render the error page with link back to home 1`] = `
|
||||
class="error"
|
||||
>
|
||||
<div
|
||||
class="_content_o77nw_8 icon"
|
||||
class="_content_md016_17 icon"
|
||||
data-size="large"
|
||||
>
|
||||
<svg
|
||||
@@ -421,17 +421,17 @@ exports[`should render the error page with link back to home 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.713 6.713A.97.97 0 0 1 16 7a.97.97 0 0 1-.713-.287A.97.97 0 0 1 15 6q0-.424.287-.713A.97.97 0 0 1 16 5q.424 0 .712.287Q17 5.576 17 6t-.288.713"
|
||||
d="M16.712 6.713A.968.968 0 0 1 16 7a.968.968 0 0 1-.713-.287A.967.967 0 0 1 15 6c0-.283.096-.52.287-.713A.968.968 0 0 1 16 5a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713Z"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2zm12 2H6v4h12zM6 12v-2h12v2zm0 2v2h12v-2zm0 6v-2h12v2z"
|
||||
d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H6Zm12 2H6v4h12V4ZM6 12v-2h12v2H6Zm0 2v2h12v-2H6Zm0 6v-2h12v2H6Z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1
|
||||
class="_typography_6v6n8_153 _font-heading-md-semibold_6v6n8_112"
|
||||
class="_typography_yh5dq_162 _font-heading-md-semibold_yh5dq_121"
|
||||
>
|
||||
Call is not supported
|
||||
</h1>
|
||||
@@ -439,7 +439,7 @@ exports[`should render the error page with link back to home 1`] = `
|
||||
The server is not configured to work with Element Call. Please contact your server admin (Domain: example.com, Error Code: MISSING_MATRIX_RTC_FOCUS).
|
||||
</p>
|
||||
<button
|
||||
class="_button_vczzf_8 homeLink"
|
||||
class="_button_i91xf_17 homeLink"
|
||||
data-kind="tertiary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -562,7 +562,7 @@ exports[`should report correct error for 'Call is not supported' 1`] = `
|
||||
class="error"
|
||||
>
|
||||
<div
|
||||
class="_content_o77nw_8 icon"
|
||||
class="_content_md016_17 icon"
|
||||
data-size="large"
|
||||
>
|
||||
<svg
|
||||
@@ -573,17 +573,17 @@ exports[`should report correct error for 'Call is not supported' 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M16.713 6.713A.97.97 0 0 1 16 7a.97.97 0 0 1-.713-.287A.97.97 0 0 1 15 6q0-.424.287-.713A.97.97 0 0 1 16 5q.424 0 .712.287Q17 5.576 17 6t-.288.713"
|
||||
d="M16.712 6.713A.968.968 0 0 1 16 7a.968.968 0 0 1-.713-.287A.967.967 0 0 1 15 6c0-.283.096-.52.287-.713A.968.968 0 0 1 16 5a.97.97 0 0 1 .712.287c.192.192.288.43.288.713s-.096.52-.288.713Z"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2zm12 2H6v4h12zM6 12v-2h12v2zm0 2v2h12v-2zm0 6v-2h12v2z"
|
||||
d="M6 2a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H6Zm12 2H6v4h12V4ZM6 12v-2h12v2H6Zm0 2v2h12v-2H6Zm0 6v-2h12v2H6Z"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1
|
||||
class="_typography_6v6n8_153 _font-heading-md-semibold_6v6n8_112"
|
||||
class="_typography_yh5dq_162 _font-heading-md-semibold_yh5dq_121"
|
||||
>
|
||||
Call is not supported
|
||||
</h1>
|
||||
@@ -591,7 +591,7 @@ exports[`should report correct error for 'Call is not supported' 1`] = `
|
||||
The server is not configured to work with Element Call. Please contact your server admin (Domain: example.com, Error Code: MISSING_MATRIX_RTC_FOCUS).
|
||||
</p>
|
||||
<button
|
||||
class="_button_vczzf_8 homeLink"
|
||||
class="_button_i91xf_17 homeLink"
|
||||
data-kind="tertiary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -714,7 +714,7 @@ exports[`should report correct error for 'Connection lost' 1`] = `
|
||||
class="error"
|
||||
>
|
||||
<div
|
||||
class="_content_o77nw_8 icon"
|
||||
class="_content_md016_17 icon"
|
||||
data-size="large"
|
||||
>
|
||||
<svg
|
||||
@@ -725,12 +725,12 @@ exports[`should report correct error for 'Connection lost' 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M3.5 3.5a1 1 0 1 0-1.414 1.414l4.113 4.114a5.5 5.5 0 0 0-.184 1.07A5.002 5.002 0 0 0 7 20h10.172l1.914 1.914A1 1 0 1 0 20.5 20.5l-.979-.979.004-.001L7.145 7.14l-.002.003zm18.5 12a4.48 4.48 0 0 1-.928 2.738L8.637 5.803A5.47 5.47 0 0 1 11.5 5a5.49 5.49 0 0 1 4.25 2.008 4 4 0 0 1 4.187 4.708A4.5 4.5 0 0 1 22 15.5"
|
||||
d="M3.5 3.5a1 1 0 1 0-1.414 1.414l4.113 4.114a5.484 5.484 0 0 0-.184 1.069A5.002 5.002 0 0 0 7 20h10.172l1.914 1.914A1 1 0 0 0 20.5 20.5l-.979-.979.004-.002L7.145 7.14l-.002.004L3.5 3.5Zm18.5 12a4.48 4.48 0 0 1-.928 2.738L8.637 5.803A5.474 5.474 0 0 1 11.5 5a5.49 5.49 0 0 1 4.25 2.008 4 4 0 0 1 4.187 4.708A4.497 4.497 0 0 1 22 15.5Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1
|
||||
class="_typography_6v6n8_153 _font-heading-md-semibold_6v6n8_112"
|
||||
class="_typography_yh5dq_162 _font-heading-md-semibold_yh5dq_121"
|
||||
>
|
||||
Connection lost
|
||||
</h1>
|
||||
@@ -741,7 +741,7 @@ exports[`should report correct error for 'Connection lost' 1`] = `
|
||||
Reconnect
|
||||
</button>
|
||||
<button
|
||||
class="_button_vczzf_8 homeLink"
|
||||
class="_button_i91xf_17 homeLink"
|
||||
data-kind="tertiary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -864,7 +864,7 @@ exports[`should report correct error for 'Incompatible browser' 1`] = `
|
||||
class="error"
|
||||
>
|
||||
<div
|
||||
class="_content_o77nw_8 icon"
|
||||
class="_content_md016_17 icon"
|
||||
data-size="large"
|
||||
>
|
||||
<svg
|
||||
@@ -875,12 +875,12 @@ exports[`should report correct error for 'Incompatible browser' 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M4 20q-.824 0-1.412-.587A1.93 1.93 0 0 1 2 18V6q0-.824.587-1.412A1.93 1.93 0 0 1 4 4h16q.824 0 1.413.588Q22 5.175 22 6v12q0 .824-.587 1.413A1.93 1.93 0 0 1 20 20zm0-2h16V8H4z"
|
||||
d="M4 20c-.55 0-1.02-.196-1.413-.587A1.926 1.926 0 0 1 2 18V6c0-.55.196-1.02.587-1.412A1.926 1.926 0 0 1 4 4h16c.55 0 1.02.196 1.413.588.391.391.587.862.587 1.412v12c0 .55-.196 1.02-.587 1.413A1.926 1.926 0 0 1 20 20H4Zm0-2h16V8H4v10Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1
|
||||
class="_typography_6v6n8_153 _font-heading-md-semibold_6v6n8_112"
|
||||
class="_typography_yh5dq_162 _font-heading-md-semibold_yh5dq_121"
|
||||
>
|
||||
Incompatible browser
|
||||
</h1>
|
||||
@@ -888,7 +888,7 @@ exports[`should report correct error for 'Incompatible browser' 1`] = `
|
||||
Your web browser does not support encrypted calls. Supported browsers include Chrome, Safari, and Firefox 117+.
|
||||
</p>
|
||||
<button
|
||||
class="_button_vczzf_8 homeLink"
|
||||
class="_button_i91xf_17 homeLink"
|
||||
data-kind="tertiary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -1011,7 +1011,7 @@ exports[`should report correct error for 'Insufficient capacity' 1`] = `
|
||||
class="error"
|
||||
>
|
||||
<div
|
||||
class="_content_o77nw_8 icon"
|
||||
class="_content_md016_17 icon"
|
||||
data-size="large"
|
||||
>
|
||||
<svg
|
||||
@@ -1022,12 +1022,12 @@ exports[`should report correct error for 'Insufficient capacity' 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 17q.424 0 .713-.288A.97.97 0 0 0 13 16a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 15a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 16q0 .424.287.712.288.288.713.288m0-4q.424 0 .713-.287A.97.97 0 0 0 13 12V8a.97.97 0 0 0-.287-.713A.97.97 0 0 0 12 7a.97.97 0 0 0-.713.287A.97.97 0 0 0 11 8v4q0 .424.287.713.288.287.713.287m0 9a9.7 9.7 0 0 1-3.9-.788 10.1 10.1 0 0 1-3.175-2.137q-1.35-1.35-2.137-3.175A9.7 9.7 0 0 1 2 12q0-2.075.788-3.9a10.1 10.1 0 0 1 2.137-3.175q1.35-1.35 3.175-2.137A9.7 9.7 0 0 1 12 2q2.075 0 3.9.788a10.1 10.1 0 0 1 3.175 2.137q1.35 1.35 2.137 3.175A9.7 9.7 0 0 1 22 12a9.7 9.7 0 0 1-.788 3.9 10.1 10.1 0 0 1-2.137 3.175q-1.35 1.35-3.175 2.137A9.7 9.7 0 0 1 12 22"
|
||||
d="M12 17a.97.97 0 0 0 .713-.288A.968.968 0 0 0 13 16a.968.968 0 0 0-.287-.713A.968.968 0 0 0 12 15a.968.968 0 0 0-.713.287A.968.968 0 0 0 11 16c0 .283.096.52.287.712.192.192.43.288.713.288Zm0-4c.283 0 .52-.096.713-.287A.968.968 0 0 0 13 12V8a.967.967 0 0 0-.287-.713A.968.968 0 0 0 12 7a.968.968 0 0 0-.713.287A.967.967 0 0 0 11 8v4c0 .283.096.52.287.713.192.191.43.287.713.287Zm0 9a9.738 9.738 0 0 1-3.9-.788 10.099 10.099 0 0 1-3.175-2.137c-.9-.9-1.612-1.958-2.137-3.175A9.738 9.738 0 0 1 2 12a9.74 9.74 0 0 1 .788-3.9 10.099 10.099 0 0 1 2.137-3.175c.9-.9 1.958-1.612 3.175-2.137A9.738 9.738 0 0 1 12 2a9.74 9.74 0 0 1 3.9.788 10.098 10.098 0 0 1 3.175 2.137c.9.9 1.613 1.958 2.137 3.175A9.738 9.738 0 0 1 22 12a9.738 9.738 0 0 1-.788 3.9 10.098 10.098 0 0 1-2.137 3.175c-.9.9-1.958 1.613-3.175 2.137A9.738 9.738 0 0 1 12 22Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<h1
|
||||
class="_typography_6v6n8_153 _font-heading-md-semibold_6v6n8_112"
|
||||
class="_typography_yh5dq_162 _font-heading-md-semibold_yh5dq_121"
|
||||
>
|
||||
Insufficient capacity
|
||||
</h1>
|
||||
@@ -1035,7 +1035,7 @@ exports[`should report correct error for 'Insufficient capacity' 1`] = `
|
||||
The server has reached its maximum capacity and you cannot join the call at this time. Try again later, or contact your server admin if the problem persists.
|
||||
</p>
|
||||
<button
|
||||
class="_button_vczzf_8 homeLink"
|
||||
class="_button_i91xf_17 homeLink"
|
||||
data-kind="tertiary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
|
||||
@@ -47,7 +47,7 @@ exports[`InCallView > rendering > renders 1`] = `
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-labelledby=":r0:"
|
||||
class="_button_vczzf_8 _has-icon_vczzf_57 _icon-only_vczzf_50"
|
||||
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
data-testid="incall_mute"
|
||||
@@ -63,14 +63,14 @@ exports[`InCallView > rendering > renders 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 8v-.006l6.831 6.832-.002.002 1.414 1.415.003-.003 1.414 1.414-.003.003L20.5 20.5a1 1 0 0 1-1.414 1.414l-3.022-3.022A7.95 7.95 0 0 1 13 19.938V21a1 1 0 0 1-2 0v-1.062A8 8 0 0 1 4 12a1 1 0 1 1 2 0 6 6 0 0 0 8.587 5.415l-1.55-1.55A4.005 4.005 0 0 1 8 12v-1.172L2.086 4.914A1 1 0 0 1 3.5 3.5zm9.417 6.583 1.478 1.477A7.96 7.96 0 0 0 20 12a1 1 0 0 0-2 0c0 .925-.21 1.8-.583 2.583M8.073 5.238l7.793 7.793q.132-.495.134-1.031V6a4 4 0 0 0-7.927-.762"
|
||||
d="M8 8v-.006l6.831 6.832-.002.002 1.414 1.415.003-.003 1.414 1.414-.003.003L20.5 20.5a1 1 0 0 1-1.414 1.414l-3.022-3.022A7.949 7.949 0 0 1 13 19.938V21a1 1 0 0 1-2 0v-1.062A8.001 8.001 0 0 1 4 12a1 1 0 1 1 2 0 6 6 0 0 0 8.587 5.415l-1.55-1.55A4.005 4.005 0 0 1 8 12v-1.172L2.086 4.914A1 1 0 0 1 3.5 3.5L8 8Zm9.417 6.583 1.478 1.477A7.963 7.963 0 0 0 20 12a1 1 0 0 0-2 0c0 .925-.21 1.8-.583 2.583ZM8.073 5.238l7.793 7.793c.087-.329.134-.674.134-1.031V6a4 4 0 0 0-7.927-.762Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
aria-labelledby=":r5:"
|
||||
class="_button_vczzf_8 _has-icon_vczzf_57 _icon-only_vczzf_50"
|
||||
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
data-testid="incall_videomute"
|
||||
@@ -86,13 +86,13 @@ exports[`InCallView > rendering > renders 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M2.747 2.753 4.35 4.355l.007-.003L18 17.994v.012l3.247 3.247a1 1 0 0 1-1.414 1.414l-2.898-2.898A2 2 0 0 1 16 20H6a4 4 0 0 1-4-4V8c0-.892.292-1.715.785-2.38L1.333 4.166a1 1 0 0 1 1.414-1.414M18 15.166 6.834 4H16a2 2 0 0 1 2 2v4.286l3.35-2.871a1 1 0 0 1 1.65.76v7.65a1 1 0 0 1-1.65.76L18 13.715z"
|
||||
d="M2.747 2.753 4.35 4.355l.007-.003L18 17.994v.012l3.247 3.247a1 1 0 0 1-1.414 1.414l-2.898-2.898A1.992 1.992 0 0 1 16 20H6a4 4 0 0 1-4-4V8c0-.892.292-1.715.785-2.38L1.333 4.166a1 1 0 0 1 1.414-1.414ZM18 15.166 6.834 4H16a2 2 0 0 1 2 2v4.286l3.35-2.871a1 1 0 0 1 1.65.76v7.65a1 1 0 0 1-1.65.76L18 13.715v1.45Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-labelledby=":ra:"
|
||||
class="_button_vczzf_8 _has-icon_vczzf_57 _icon-only_vczzf_50"
|
||||
class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59"
|
||||
data-kind="secondary"
|
||||
data-size="lg"
|
||||
role="button"
|
||||
@@ -107,13 +107,13 @@ exports[`InCallView > rendering > renders 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12.731 2C13.432 2 14 2.568 14 3.269c0 .578.396 1.074.935 1.286q.128.052.253.106c.531.23 1.162.16 1.572-.25a1.27 1.27 0 0 1 1.794 0l1.034 1.035a1.27 1.27 0 0 1 0 1.794c-.41.41-.48 1.04-.248 1.572l.105.253c.212.539.708.935 1.286.935.701 0 1.269.568 1.269 1.269v1.462c0 .701-.568 1.269-1.269 1.269-.578 0-1.074.396-1.287.935q-.05.128-.104.253c-.232.531-.161 1.162.248 1.572a1.27 1.27 0 0 1 0 1.794l-1.034 1.034a1.27 1.27 0 0 1-1.794 0c-.41-.41-1.04-.48-1.572-.248a8 8 0 0 1-.253.105c-.539.212-.935.708-.935 1.286 0 .701-.568 1.269-1.269 1.269H11.27c-.702 0-1.27-.568-1.27-1.269 0-.578-.396-1.074-.935-1.287a8 8 0 0 1-.253-.104c-.531-.232-1.162-.161-1.572.248a1.27 1.27 0 0 1-1.794 0l-1.034-1.034a1.27 1.27 0 0 1 0-1.794c.41-.41.48-1.04.249-1.572a8 8 0 0 1-.106-.253C4.343 14.396 3.847 14 3.27 14 2.568 14 2 13.432 2 12.731V11.27c0-.702.568-1.27 1.269-1.27.578 0 1.074-.396 1.286-.935q.052-.128.106-.253c.23-.531.16-1.162-.25-1.572a1.27 1.27 0 0 1 0-1.794l1.035-1.034a1.27 1.27 0 0 1 1.794 0c.41.41 1.04.48 1.572.249a8 8 0 0 1 .253-.106c.539-.212.935-.708.935-1.286C10 2.568 10.568 2 11.269 2zM12 16a4 4 0 1 0 0-8 4 4 0 0 0 0 8"
|
||||
d="M12.731 2C13.432 2 14 2.568 14 3.269c0 .578.396 1.074.935 1.286.085.034.17.07.253.106.531.23 1.162.16 1.572-.25a1.269 1.269 0 0 1 1.794 0l1.034 1.035a1.269 1.269 0 0 1 0 1.794c-.41.41-.48 1.04-.248 1.572.036.084.07.168.105.253.212.539.708.935 1.286.935.701 0 1.269.568 1.269 1.269v1.462c0 .701-.568 1.269-1.269 1.269-.578 0-1.074.396-1.287.935-.033.085-.068.17-.104.253-.232.531-.161 1.162.248 1.572a1.269 1.269 0 0 1 0 1.794l-1.034 1.034a1.269 1.269 0 0 1-1.794 0c-.41-.41-1.04-.48-1.572-.248a7.935 7.935 0 0 1-.253.105c-.539.212-.935.708-.935 1.286 0 .701-.568 1.269-1.269 1.269H11.27c-.702 0-1.27-.568-1.27-1.269 0-.578-.396-1.074-.935-1.287a7.975 7.975 0 0 1-.253-.104c-.531-.232-1.162-.161-1.572.248a1.269 1.269 0 0 1-1.794 0l-1.034-1.034a1.269 1.269 0 0 1 0-1.794c.41-.41.48-1.04.249-1.572a7.89 7.89 0 0 1-.106-.253C4.343 14.396 3.847 14 3.27 14 2.568 14 2 13.432 2 12.731V11.27c0-.702.568-1.27 1.269-1.27.578 0 1.074-.396 1.286-.935.034-.085.07-.17.106-.253.23-.531.16-1.162-.25-1.572a1.269 1.269 0 0 1 0-1.794l1.035-1.034a1.269 1.269 0 0 1 1.794 0c.41.41 1.04.48 1.572.249a7.93 7.93 0 0 1 .253-.106c.539-.212.935-.708.935-1.286C10 2.568 10.568 2 11.269 2h1.462ZM12 16a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
aria-labelledby=":rf:"
|
||||
class="_button_vczzf_8 endCall _has-icon_vczzf_57 _icon-only_vczzf_50 _destructive_vczzf_107"
|
||||
class="_button_i91xf_17 endCall _has-icon_i91xf_66 _icon-only_i91xf_59 _destructive_i91xf_116"
|
||||
data-kind="primary"
|
||||
data-size="lg"
|
||||
data-testid="incall_leave"
|
||||
@@ -129,7 +129,7 @@ exports[`InCallView > rendering > renders 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="m2.765 16.02-2.47-2.416A1.02 1.02 0 0 1 0 12.852q0-.456.295-.751a15.6 15.6 0 0 1 5.316-3.786A15.9 15.9 0 0 1 12 7q3.355 0 6.39 1.329a16 16 0 0 1 5.315 3.772q.295.294.295.751t-.295.752l-2.47 2.416a1.047 1.047 0 0 1-1.396.108l-3.114-2.363a1.1 1.1 0 0 1-.322-.376 1.1 1.1 0 0 1-.108-.483v-2.27a13.6 13.6 0 0 0-2.12-.524C13.459 9.996 12 9.937 12 9.937s-1.459.059-2.174.175q-1.074.174-2.121.523v2.271q0 .268-.108.483a1.1 1.1 0 0 1-.322.376l-3.114 2.363a1.047 1.047 0 0 1-1.396-.107"
|
||||
d="m2.765 16.02-2.47-2.416A1.018 1.018 0 0 1 0 12.852c0-.304.098-.555.295-.751a15.64 15.64 0 0 1 5.316-3.786A15.89 15.89 0 0 1 12 7c2.237 0 4.367.443 6.39 1.329a15.977 15.977 0 0 1 5.315 3.772c.197.196.295.447.295.751 0 .305-.098.555-.295.752l-2.47 2.416a1.047 1.047 0 0 1-1.396.108l-3.114-2.363a1.067 1.067 0 0 1-.322-.376 1.066 1.066 0 0 1-.108-.483v-2.27a13.593 13.593 0 0 0-2.12-.524C13.459 9.996 12 9.937 12 9.937s-1.459.059-2.175.175c-.715.116-1.422.29-2.12.523v2.271c0 .179-.036.34-.108.483a1.066 1.066 0 0 1-.322.376l-3.114 2.363a1.047 1.047 0 0 1-1.396-.107Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
@@ -152,7 +152,7 @@ exports[`InCallView > rendering > renders 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M5 5h14v8h-5a1 1 0 0 0-1 1v5H5zm10 14v-4h4v4zM5 21h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2"
|
||||
d="M5 5h14v8h-5a1 1 0 0 0-1 1v5H5V5Zm10 14v-4h4v4h-4ZM5 21h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2Z"
|
||||
/>
|
||||
</svg>
|
||||
<input
|
||||
@@ -171,7 +171,7 @@ exports[`InCallView > rendering > renders 1`] = `
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M4 11a.97.97 0 0 1-.712-.287A.97.97 0 0 1 3 10V4q0-.424.288-.712A.97.97 0 0 1 4 3h6q.424 0 .713.288Q11 3.575 11 4v6q0 .424-.287.713A.97.97 0 0 1 10 11zm5-2V5H5v4zm5 12a.97.97 0 0 1-.713-.288A.97.97 0 0 1 13 20v-6q0-.424.287-.713A.97.97 0 0 1 14 13h6q.424 0 .712.287.288.288.288.713v6q0 .424-.288.712A.97.97 0 0 1 20 21zm5-2v-4h-4v4zM4 21a.97.97 0 0 1-.712-.288A.97.97 0 0 1 3 20v-6q0-.424.288-.713A.97.97 0 0 1 4 13h6q.424 0 .713.287.287.288.287.713v6q0 .424-.287.712A.97.97 0 0 1 10 21zm5-2v-4H5v4zm5-8a.97.97 0 0 1-.713-.287A.97.97 0 0 1 13 10V4q0-.424.287-.712A.97.97 0 0 1 14 3h6q.424 0 .712.288Q21 3.575 21 4v6q0 .424-.288.713A.97.97 0 0 1 20 11zm5-2V5h-4v4z"
|
||||
d="M4 11a.967.967 0 0 1-.712-.287A.968.968 0 0 1 3 10V4c0-.283.096-.52.288-.712A.968.968 0 0 1 4 3h6a.97.97 0 0 1 .713.288A.968.968 0 0 1 11 4v6c0 .283-.096.52-.287.713A.968.968 0 0 1 10 11H4Zm5-2V5H5v4h4Zm5 12a.968.968 0 0 1-.713-.288A.968.968 0 0 1 13 20v-6c0-.283.096-.52.287-.713A.968.968 0 0 1 14 13h6a.97.97 0 0 1 .712.287c.192.192.288.43.288.713v6c0 .283-.096.52-.288.712A.968.968 0 0 1 20 21h-6Zm5-2v-4h-4v4h4ZM4 21a.967.967 0 0 1-.712-.288A.968.968 0 0 1 3 20v-6a.97.97 0 0 1 .288-.713A.967.967 0 0 1 4 13h6c.283 0 .52.096.713.287.191.192.287.43.287.713v6a.97.97 0 0 1-.287.712A.968.968 0 0 1 10 21H4Zm5-2v-4H5v4h4Zm5-8a.968.968 0 0 1-.713-.287A.968.968 0 0 1 13 10V4a.97.97 0 0 1 .287-.712A.968.968 0 0 1 14 3h6c.283 0 .52.096.712.288A.965.965 0 0 1 21 4v6a.97.97 0 0 1-.288.713A.968.968 0 0 1 20 11h-6Zm5-2V5h-4v4h4Z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
@@ -19,6 +19,7 @@ import { ProfileSettingsTab } from "./ProfileSettingsTab";
|
||||
import { FeedbackSettingsTab } from "./FeedbackSettingsTab";
|
||||
import {
|
||||
useMediaDevices,
|
||||
useMediaDeviceNames,
|
||||
iosDeviceMenu$,
|
||||
} from "../livekit/MediaDevicesContext";
|
||||
import { widget } from "../widget";
|
||||
@@ -97,6 +98,7 @@ export const SettingsModal: FC<Props> = ({
|
||||
};
|
||||
|
||||
const devices = useMediaDevices();
|
||||
useMediaDeviceNames(devices, open);
|
||||
const [soundVolume, setSoundVolume] = useSetting(soundEffectVolumeSetting);
|
||||
const [soundVolumeRaw, setSoundVolumeRaw] = useState(soundVolume);
|
||||
const [showDeveloperSettingsTab] = useSetting(developerMode);
|
||||
@@ -127,7 +129,7 @@ export const SettingsModal: FC<Props> = ({
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{iosDeviceMenu && controlledAudioDevices && (
|
||||
{iosDeviceMenu && (
|
||||
<Button
|
||||
onClick={(e): void => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -13,7 +13,7 @@ import { useTranslation } from "react-i18next";
|
||||
import classNames from "classnames";
|
||||
import { VideoTrack } from "@livekit/components-react";
|
||||
import { Text, Tooltip } from "@vector-im/compound-web";
|
||||
import { ErrorSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
import { ErrorIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import styles from "./MediaView.module.css";
|
||||
import { Avatar } from "../Avatar";
|
||||
@@ -168,7 +168,7 @@ export const MediaView = forwardRef<HTMLDivElement, Props>(
|
||||
placement="bottom"
|
||||
isTriggerInteractive={false}
|
||||
>
|
||||
<ErrorSolidIcon
|
||||
<ErrorIcon
|
||||
width={20}
|
||||
height={20}
|
||||
className={styles.errorIcon}
|
||||
|
||||
@@ -126,6 +126,8 @@ test("will use the correct device", () => {
|
||||
useAsEarpiece: false,
|
||||
},
|
||||
videoInput: deviceStub,
|
||||
startUsingDeviceNames: () => {},
|
||||
stopUsingDeviceNames: () => {},
|
||||
}}
|
||||
>
|
||||
<TestComponentWrapper />
|
||||
@@ -159,6 +161,8 @@ test("will use the pan if earpiece is selected", async () => {
|
||||
useAsEarpiece: true,
|
||||
},
|
||||
videoInput: deviceStub,
|
||||
startUsingDeviceNames: () => {},
|
||||
stopUsingDeviceNames: () => {},
|
||||
}}
|
||||
>
|
||||
<TestComponentWrapper />
|
||||
|
||||
@@ -42,14 +42,6 @@ export const useLocalStorage = (
|
||||
};
|
||||
|
||||
export const setLocalStorageItem = (key: string, value: string): void => {
|
||||
// Avoid unnecessary updates. Not avoiding them so can cause unexpected state updates across hooks.
|
||||
// For instance:
|
||||
// - In call view uses useRoomEncryptionSystem
|
||||
// - This will set the key again.
|
||||
// - All other instances of useRoomEncryptionSystem will now do a useMemo update of the e2eeSystem
|
||||
// - because the dependency `storedPassword = useInternalRoomSharedKey(roomId);` would change.
|
||||
if (localStorage.getItem(key) === value) return;
|
||||
|
||||
localStorage.setItem(key, value);
|
||||
localStorageBus.emit(key, value);
|
||||
};
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
// These imports within @livekit/components-core and
|
||||
// @livekit/components-react are broken under the "bundler" module
|
||||
// resolution mode, so we need to resolve them manually
|
||||
"livekit-client/dist/src/room/types": [
|
||||
"./node_modules/livekit-client/dist/src/room/types.d.ts"
|
||||
],
|
||||
"livekit-client/dist/src/room/Room": [
|
||||
"./node_modules/livekit-client/dist/src/room/Room.d.ts"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user