mirror of
https://github.com/vector-im/element-call.git
synced 2026-09-01 21:25:18 +00:00
Merge branch 'livekit' into toger5/implement-media-device-switcher
This commit is contained in:
@@ -145,6 +145,7 @@
|
|||||||
},
|
},
|
||||||
"layout_grid_label": "Grid",
|
"layout_grid_label": "Grid",
|
||||||
"layout_spotlight_label": "Spotlight",
|
"layout_spotlight_label": "Spotlight",
|
||||||
|
"layout_switch_label": "Layout",
|
||||||
"lobby": {
|
"lobby": {
|
||||||
"ask_to_join": "Request to join call",
|
"ask_to_join": "Request to join call",
|
||||||
"join_as_guest": "Join as guest",
|
"join_as_guest": "Join as guest",
|
||||||
|
|||||||
@@ -142,9 +142,7 @@ export class TestHelpers {
|
|||||||
timeout: 15000,
|
timeout: 15000,
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.maybeDismissBrowserNotSupportedToast(page);
|
await this.dismissStartupToasts(page);
|
||||||
await this.maybeDismissServiceWorkerWarningToast(page);
|
|
||||||
await this.maybeDismissBackupChat(page);
|
|
||||||
|
|
||||||
await TestHelpers.setDevToolElementCallDevUrl(page);
|
await TestHelpers.setDevToolElementCallDevUrl(page);
|
||||||
|
|
||||||
@@ -155,73 +153,39 @@ export class TestHelpers {
|
|||||||
return { page, clientHandle, mxId };
|
return { page, clientHandle, mxId };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async maybeDismissBrowserNotSupportedToast(
|
// Dismisses any toasts that appear on startup, such as "Failed to load service worker" or "Back up your chats".
|
||||||
page: Page,
|
// Toast can be stacked, and only the top one can be dismiss, so just look at what is on top and
|
||||||
): Promise<void> {
|
// dismiss (if part of expected toats)
|
||||||
const browserUnsupportedToast = page
|
public static async dismissStartupToasts(page: Page): Promise<void> {
|
||||||
.getByText("Element does not support this browser")
|
const expectedToasts = [
|
||||||
.locator("..")
|
{ title: "Failed to load service worker", button: "OK" },
|
||||||
.locator("..");
|
{ title: "Back up your chats", button: "Dismiss" },
|
||||||
|
{ title: "Element does not support this browser", button: "Dismiss" },
|
||||||
|
];
|
||||||
|
|
||||||
// Dismiss incompatible browser toast
|
const toast = page.locator(".mx_Toast_toast");
|
||||||
const dismissButton = browserUnsupportedToast.getByRole("button", {
|
|
||||||
name: "Dismiss",
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
await expect(dismissButton).toBeVisible({ timeout: 700 });
|
|
||||||
await dismissButton.click();
|
|
||||||
} catch {
|
|
||||||
// dismissButton not visible, continue as normal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async maybeDismissServiceWorkerWarningToast(
|
// eslint-disable-next-line no-constant-condition
|
||||||
page: Page,
|
while (true) {
|
||||||
): Promise<void> {
|
try {
|
||||||
const toast = page
|
await toast.waitFor({ state: "visible", timeout: 700 });
|
||||||
.locator(".mx_Toast_toast")
|
const title = await toast.locator(".mx_Toast_title h2").textContent();
|
||||||
.getByText("Failed to load service worker");
|
|
||||||
|
|
||||||
try {
|
// Find the matching toast config
|
||||||
await expect(toast).toBeVisible({ timeout: 700 });
|
const toastConfig = expectedToasts.find((t) =>
|
||||||
await page
|
title?.includes(t.title),
|
||||||
.locator(".mx_Toast_toast")
|
);
|
||||||
.getByRole("button", { name: "OK" })
|
|
||||||
.click();
|
|
||||||
} catch {
|
|
||||||
// toast not visible, continue as normal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async maybeDismissBackupChat(page: Page): Promise<void> {
|
if (toastConfig) {
|
||||||
const toast = page
|
await toast.getByRole("button", { name: toastConfig.button }).click();
|
||||||
.locator(".mx_Toast_toast")
|
} else {
|
||||||
.getByText("Back up your chats");
|
// Unknown toast. We don't want to act on unknown toasts
|
||||||
|
break;
|
||||||
try {
|
}
|
||||||
await expect(toast).toBeVisible({ timeout: 700 });
|
} catch {
|
||||||
await page
|
// No toast visible, exit loop
|
||||||
.locator(".mx_Toast_toast")
|
break;
|
||||||
.getByRole("button", { name: "Dismiss" })
|
}
|
||||||
.click();
|
|
||||||
} catch {
|
|
||||||
// toast not visible, continue as normal
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async maybeDismissKeyBackupToast(page: Page): Promise<void> {
|
|
||||||
const toast = page
|
|
||||||
.locator(".mx_Toast_toast")
|
|
||||||
.getByText("Back up your chats");
|
|
||||||
|
|
||||||
try {
|
|
||||||
await expect(toast).toBeVisible({ timeout: 700 });
|
|
||||||
await page
|
|
||||||
.locator(".mx_Toast_toast")
|
|
||||||
.getByRole("button", { name: "Dismiss" })
|
|
||||||
.click();
|
|
||||||
} catch {
|
|
||||||
// toast not visible, continue as normal
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,7 +208,7 @@ export class TestHelpers {
|
|||||||
timeout: 10000,
|
timeout: 10000,
|
||||||
});
|
});
|
||||||
await expect(page.getByText("Encryption enabled")).toBeVisible();
|
await expect(page.getByText("Encryption enabled")).toBeVisible();
|
||||||
await TestHelpers.maybeDismissKeyBackupToast(page);
|
await TestHelpers.dismissStartupToasts(page);
|
||||||
|
|
||||||
// Invite users if any
|
// Invite users if any
|
||||||
if (andInvite.length > 0) {
|
if (andInvite.length > 0) {
|
||||||
@@ -283,7 +247,7 @@ export class TestHelpers {
|
|||||||
await expect(
|
await expect(
|
||||||
page.getByRole("main").getByRole("heading", { name: roomName }),
|
page.getByRole("main").getByRole("heading", { name: roomName }),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
await TestHelpers.maybeDismissKeyBackupToast(page);
|
await TestHelpers.dismissStartupToasts(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ widgetTest(
|
|||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
|
|
||||||
await expect(whistler.page.getByText("Incoming video call")).toBeVisible();
|
await expect(whistler.page.getByText("Incoming video call")).toBeVisible();
|
||||||
await whistler.page.getByRole("button", { name: "Ignore" }).click();
|
await whistler.page.getByRole("button", { name: "Decline" }).click();
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
whistler.page.locator('iframe[title="Element Call"]'),
|
whistler.page.locator('iframe[title="Element Call"]'),
|
||||||
|
|||||||
127
pnpm-lock.yaml
generated
127
pnpm-lock.yaml
generated
@@ -47,16 +47,16 @@ importers:
|
|||||||
version: 11.7.12
|
version: 11.7.12
|
||||||
'@livekit/components-core':
|
'@livekit/components-core':
|
||||||
specifier: ^0.12.0
|
specifier: ^0.12.0
|
||||||
version: 0.12.13(livekit-client@2.18.8(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)
|
version: 0.12.13(livekit-client@2.18.9(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)
|
||||||
'@livekit/components-react':
|
'@livekit/components-react':
|
||||||
specifier: ^2.0.0
|
specifier: ^2.0.0
|
||||||
version: 2.9.20(livekit-client@2.18.8(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)
|
version: 2.9.21(livekit-client@2.18.9(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)
|
||||||
'@livekit/protocol':
|
'@livekit/protocol':
|
||||||
specifier: ^1.42.2
|
specifier: ^1.42.2
|
||||||
version: 1.45.6
|
version: 1.45.6
|
||||||
'@livekit/track-processors':
|
'@livekit/track-processors':
|
||||||
specifier: ^0.7.1
|
specifier: ^0.7.1
|
||||||
version: 0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.8(@types/dom-mediacapture-record@1.0.22))
|
version: 0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.9(@types/dom-mediacapture-record@1.0.22))
|
||||||
'@mediapipe/tasks-vision':
|
'@mediapipe/tasks-vision':
|
||||||
specifier: ^0.10.18
|
specifier: ^0.10.18
|
||||||
version: 0.10.34
|
version: 0.10.34
|
||||||
@@ -236,7 +236,7 @@ importers:
|
|||||||
version: 5.88.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.2)(typescript@5.9.3)
|
version: 5.88.1(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)(@types/node@24.12.2)(typescript@5.9.3)
|
||||||
livekit-client:
|
livekit-client:
|
||||||
specifier: ^2.18.1
|
specifier: ^2.18.1
|
||||||
version: 2.18.8(@types/dom-mediacapture-record@1.0.22)
|
version: 2.18.9(@types/dom-mediacapture-record@1.0.22)
|
||||||
lodash-es:
|
lodash-es:
|
||||||
specifier: ^4.17.21
|
specifier: ^4.17.21
|
||||||
version: 4.18.1
|
version: 4.18.1
|
||||||
@@ -245,7 +245,7 @@ importers:
|
|||||||
version: 1.9.2
|
version: 1.9.2
|
||||||
matrix-js-sdk:
|
matrix-js-sdk:
|
||||||
specifier: matrix-org/matrix-js-sdk#develop
|
specifier: matrix-org/matrix-js-sdk#develop
|
||||||
version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/69985ee350a33ba75f1ad11f96468344f0c92a8d
|
version: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/349e8c5023b74b7ee17b2e9a0cba6dfce6818d68
|
||||||
matrix-widget-api:
|
matrix-widget-api:
|
||||||
specifier: ^1.16.1
|
specifier: ^1.16.1
|
||||||
version: 1.17.0
|
version: 1.17.0
|
||||||
@@ -1571,12 +1571,12 @@ packages:
|
|||||||
livekit-client: ^2.17.2
|
livekit-client: ^2.17.2
|
||||||
tslib: ^2.6.2
|
tslib: ^2.6.2
|
||||||
|
|
||||||
'@livekit/components-react@2.9.20':
|
'@livekit/components-react@2.9.21':
|
||||||
resolution: {integrity: sha512-hjkYOsJj9Jbghb7wM5cI8HoVisKeL6Zcy1VnRWTLm0sqVbto8GJp/17T4Udx85mCPY6Jgh8I1Cv0yVzgz7CQtg==}
|
resolution: {integrity: sha512-6hU9VucJJL+gAhilNGe4MBCDCZVk64qyjP9Ck86krvOIdVU76WeWksddg1MYUP10AlUwwrfD7davz41pJTcMJw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@livekit/krisp-noise-filter': ^0.2.12 || ^0.3.0
|
'@livekit/krisp-noise-filter': ^0.2.12 || ^0.3.0
|
||||||
livekit-client: ^2.17.2
|
livekit-client: ^2.18.2
|
||||||
react: '>=18'
|
react: '>=18'
|
||||||
react-dom: '>=18'
|
react-dom: '>=18'
|
||||||
tslib: ^2.6.2
|
tslib: ^2.6.2
|
||||||
@@ -3031,8 +3031,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/project-service@8.59.1':
|
'@typescript-eslint/project-service@8.59.2':
|
||||||
resolution: {integrity: sha512-+MuHQlHiEr00Of/IQbE/MmEoi44znZHbR/Pz7Opq4HryUOlRi+/44dro9Ycy8Fyo+/024IWtw8m4JUMCGTYxDg==}
|
resolution: {integrity: sha512-+2hqvEkeyf/0FBor67duF0Ll7Ot8jyKzDQOSrxazF/danillRq2DwR9dLptsXpoZQqxE1UisSmoZewrlPas9Vw==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
@@ -3049,8 +3049,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==}
|
resolution: {integrity: sha512-UzR16Ut8IpA3Mc4DbgAShlPPkVm8xXMWafXxB0BocaVRHs8ZGakAxGRskF7FId3sdk9lgGD73GSFaWmWFDE4dg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/scope-manager@8.59.1':
|
'@typescript-eslint/scope-manager@8.59.2':
|
||||||
resolution: {integrity: sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg==}
|
resolution: {integrity: sha512-JzfyEpEtOU89CcFSwyNS3mu4MLvLSXqnmX05+aKBDM+TdR5jzcGOEBwxwGNxrEQ7p/z6kK2WyioCGBf2zZBnvg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/tsconfig-utils@8.58.2':
|
'@typescript-eslint/tsconfig-utils@8.58.2':
|
||||||
@@ -3065,8 +3065,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/tsconfig-utils@8.59.1':
|
'@typescript-eslint/tsconfig-utils@8.59.2':
|
||||||
resolution: {integrity: sha512-/0nEyPbX7gRsk0Uwfe4ALwwgxuA66d/l2mhRDNlAvaj4U3juhUtJNq0DsY8M2AYwwb9rEq2hrC3IcIcEt++iJA==}
|
resolution: {integrity: sha512-BKK4alN7oi4C/zv4VqHQ+uRU+lTa6JGIZ7s1juw7b3RHo9OfKB+bKX3u0iVZetdsUCBBkSbdWbarJbmN0fTeSw==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
@@ -3094,6 +3094,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==}
|
resolution: {integrity: sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
|
'@typescript-eslint/types@8.59.2':
|
||||||
|
resolution: {integrity: sha512-e82GVOE8Ps3E++Egvb6Y3Dw0S10u8NkQ9KXmtRhCWJJ8kDhOJTvtMAWnFL16kB1583goCWXsr0NieKCZMs2/0Q==}
|
||||||
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@5.62.0':
|
'@typescript-eslint/typescript-estree@5.62.0':
|
||||||
resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
|
resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
@@ -3115,8 +3119,8 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.59.1':
|
'@typescript-eslint/typescript-estree@8.59.2':
|
||||||
resolution: {integrity: sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g==}
|
resolution: {integrity: sha512-o0XPGNwcWw+FIwStOWn+BwBuEmL6QXP0rsvAFg7ET1dey1Nr6Wb1ac8p5HEsK0ygO/6mUxlk+YWQD9xcb/nnXg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
@@ -3141,8 +3145,8 @@ packages:
|
|||||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||||
typescript: '>=4.8.4 <6.1.0'
|
typescript: '>=4.8.4 <6.1.0'
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.59.1':
|
'@typescript-eslint/utils@8.59.2':
|
||||||
resolution: {integrity: sha512-3pIeoXhCeYH9FSCBI8P3iNwJlGuzPlYKkTlen2O9T1DSeeg8UG8jstq6BLk+Mda0qup7mgk4z4XL4OzRaxZ8LA==}
|
resolution: {integrity: sha512-Juw3EinkXqjaffxz6roowvV7GZT/kET5vSKKZT6upl5TXdWkLkYmNPXwDDL2Vkt2DPn0nODIS4egC/0AGxKo/Q==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
|
||||||
@@ -3160,12 +3164,13 @@ packages:
|
|||||||
resolution: {integrity: sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==}
|
resolution: {integrity: sha512-/uejZt4dSere1bx12WLlPfv8GktzcaDtuJ7s42/HEZ5zGj9oxRaD4bj7qwSunXkf+pbAhFt2zjpHYUiT5lHf0Q==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@typescript-eslint/visitor-keys@8.59.1':
|
'@typescript-eslint/visitor-keys@8.59.2':
|
||||||
resolution: {integrity: sha512-LdDNl6C5iJExcM0Yh0PwAIBb9PrSiCsWamF/JyEZawm3kFDnRoaq3LGE4bpyRao/fWeGKKyw7icx0YxrLFC5Cg==}
|
resolution: {integrity: sha512-NwjLUnGy8/Zfx23fl50tRC8rYaYnM52xNRYFAXvmiil9yh1+K6aRVQMnzW6gQB/1DLgWt977lYQn7C+wtgXZiA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@ungap/structured-clone@1.3.0':
|
'@ungap/structured-clone@1.3.0':
|
||||||
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
|
resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==}
|
||||||
|
deprecated: Potential CWE-502 - Update to 1.3.1 or higher
|
||||||
|
|
||||||
'@use-gesture/core@10.3.1':
|
'@use-gesture/core@10.3.1':
|
||||||
resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==}
|
resolution: {integrity: sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==}
|
||||||
@@ -4892,9 +4897,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
jose@6.2.2:
|
|
||||||
resolution: {integrity: sha512-d7kPDd34KO/YnzaDOlikGpOurfF0ByC2sEV4cANCtdqLlTfBlw2p14O/5d/zv40gJPbIQxfES3nSx1/oYNyuZQ==}
|
|
||||||
|
|
||||||
jose@6.2.3:
|
jose@6.2.3:
|
||||||
resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==}
|
resolution: {integrity: sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==}
|
||||||
|
|
||||||
@@ -5076,8 +5078,8 @@ packages:
|
|||||||
lines-and-columns@1.2.4:
|
lines-and-columns@1.2.4:
|
||||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||||
|
|
||||||
livekit-client@2.18.8:
|
livekit-client@2.18.9:
|
||||||
resolution: {integrity: sha512-E+bSpnBVng/1xG4RfL1Q51dHUpBwL14Wix4sR5bS0djEzKMEtrxcUyhWLltdwQ0USf1t0PaxW6WL4oVb2s4Fsw==}
|
resolution: {integrity: sha512-l0cADcxxBCWCBMtU9eWY6RpdbRfgA5c1/05yngQXo08mcy3VOttmSE2pNZ74k2B2zQym149g5/Y1B3vq2FWwlw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/dom-mediacapture-record': ^1
|
'@types/dom-mediacapture-record': ^1
|
||||||
|
|
||||||
@@ -5151,8 +5153,8 @@ packages:
|
|||||||
matrix-events-sdk@0.0.1:
|
matrix-events-sdk@0.0.1:
|
||||||
resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==}
|
resolution: {integrity: sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA==}
|
||||||
|
|
||||||
matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/69985ee350a33ba75f1ad11f96468344f0c92a8d:
|
matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/349e8c5023b74b7ee17b2e9a0cba6dfce6818d68:
|
||||||
resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/69985ee350a33ba75f1ad11f96468344f0c92a8d}
|
resolution: {tarball: https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/349e8c5023b74b7ee17b2e9a0cba6dfce6818d68}
|
||||||
version: 41.4.0
|
version: 41.4.0
|
||||||
engines: {node: '>=22.0.0'}
|
engines: {node: '>=22.0.0'}
|
||||||
|
|
||||||
@@ -6058,6 +6060,11 @@ packages:
|
|||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
semver@7.8.0:
|
||||||
|
resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
set-blocking@2.0.0:
|
set-blocking@2.0.0:
|
||||||
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
|
||||||
|
|
||||||
@@ -8280,21 +8287,21 @@ snapshots:
|
|||||||
'@jridgewell/resolve-uri': 3.1.2
|
'@jridgewell/resolve-uri': 3.1.2
|
||||||
'@jridgewell/sourcemap-codec': 1.5.5
|
'@jridgewell/sourcemap-codec': 1.5.5
|
||||||
|
|
||||||
'@livekit/components-core@0.12.13(livekit-client@2.18.8(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)':
|
'@livekit/components-core@0.12.13(livekit-client@2.18.9(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@floating-ui/dom': 1.7.4
|
'@floating-ui/dom': 1.7.4
|
||||||
livekit-client: 2.18.8(@types/dom-mediacapture-record@1.0.22)
|
livekit-client: 2.18.9(@types/dom-mediacapture-record@1.0.22)
|
||||||
loglevel: 1.9.1
|
loglevel: 1.9.1
|
||||||
rxjs: 7.8.2
|
rxjs: 7.8.2
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@livekit/components-react@2.9.20(livekit-client@2.18.8(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)':
|
'@livekit/components-react@2.9.21(livekit-client@2.18.9(@types/dom-mediacapture-record@1.0.22))(react-dom@19.2.5(react@19.2.5))(react@19.2.5)(tslib@2.8.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@livekit/components-core': 0.12.13(livekit-client@2.18.8(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)
|
'@livekit/components-core': 0.12.13(livekit-client@2.18.9(@types/dom-mediacapture-record@1.0.22))(tslib@2.8.1)
|
||||||
clsx: 2.1.1
|
clsx: 2.1.1
|
||||||
events: 3.3.0
|
events: 3.3.0
|
||||||
jose: 6.2.2
|
jose: 6.2.3
|
||||||
livekit-client: 2.18.8(@types/dom-mediacapture-record@1.0.22)
|
livekit-client: 2.18.9(@types/dom-mediacapture-record@1.0.22)
|
||||||
react: 19.2.5
|
react: 19.2.5
|
||||||
react-dom: 19.2.5(react@19.2.5)
|
react-dom: 19.2.5(react@19.2.5)
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
@@ -8310,11 +8317,11 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@bufbuild/protobuf': 1.10.1
|
'@bufbuild/protobuf': 1.10.1
|
||||||
|
|
||||||
'@livekit/track-processors@0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.8(@types/dom-mediacapture-record@1.0.22))':
|
'@livekit/track-processors@0.7.2(@types/dom-mediacapture-transform@0.1.11)(livekit-client@2.18.9(@types/dom-mediacapture-record@1.0.22))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@mediapipe/tasks-vision': 0.10.34
|
'@mediapipe/tasks-vision': 0.10.34
|
||||||
'@types/dom-mediacapture-transform': 0.1.11
|
'@types/dom-mediacapture-transform': 0.1.11
|
||||||
livekit-client: 2.18.8(@types/dom-mediacapture-record@1.0.22)
|
livekit-client: 2.18.9(@types/dom-mediacapture-record@1.0.22)
|
||||||
|
|
||||||
'@matrix-org/matrix-sdk-crypto-wasm@18.2.0': {}
|
'@matrix-org/matrix-sdk-crypto-wasm@18.2.0': {}
|
||||||
|
|
||||||
@@ -9593,10 +9600,10 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/project-service@8.59.1(typescript@5.9.3)':
|
'@typescript-eslint/project-service@8.59.2(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/tsconfig-utils': 8.59.1(typescript@5.9.3)
|
'@typescript-eslint/tsconfig-utils': 8.59.2(typescript@5.9.3)
|
||||||
'@typescript-eslint/types': 8.59.1
|
'@typescript-eslint/types': 8.59.2
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -9617,10 +9624,10 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.59.0
|
'@typescript-eslint/types': 8.59.0
|
||||||
'@typescript-eslint/visitor-keys': 8.59.0
|
'@typescript-eslint/visitor-keys': 8.59.0
|
||||||
|
|
||||||
'@typescript-eslint/scope-manager@8.59.1':
|
'@typescript-eslint/scope-manager@8.59.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.59.1
|
'@typescript-eslint/types': 8.59.2
|
||||||
'@typescript-eslint/visitor-keys': 8.59.1
|
'@typescript-eslint/visitor-keys': 8.59.2
|
||||||
|
|
||||||
'@typescript-eslint/tsconfig-utils@8.58.2(typescript@5.9.3)':
|
'@typescript-eslint/tsconfig-utils@8.58.2(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9630,7 +9637,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
|
|
||||||
'@typescript-eslint/tsconfig-utils@8.59.1(typescript@5.9.3)':
|
'@typescript-eslint/tsconfig-utils@8.59.2(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
|
|
||||||
@@ -9654,6 +9661,8 @@ snapshots:
|
|||||||
|
|
||||||
'@typescript-eslint/types@8.59.1': {}
|
'@typescript-eslint/types@8.59.1': {}
|
||||||
|
|
||||||
|
'@typescript-eslint/types@8.59.2': {}
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)':
|
'@typescript-eslint/typescript-estree@5.62.0(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 5.62.0
|
'@typescript-eslint/types': 5.62.0
|
||||||
@@ -9698,15 +9707,15 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/typescript-estree@8.59.1(typescript@5.9.3)':
|
'@typescript-eslint/typescript-estree@8.59.2(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/project-service': 8.59.1(typescript@5.9.3)
|
'@typescript-eslint/project-service': 8.59.2(typescript@5.9.3)
|
||||||
'@typescript-eslint/tsconfig-utils': 8.59.1(typescript@5.9.3)
|
'@typescript-eslint/tsconfig-utils': 8.59.2(typescript@5.9.3)
|
||||||
'@typescript-eslint/types': 8.59.1
|
'@typescript-eslint/types': 8.59.2
|
||||||
'@typescript-eslint/visitor-keys': 8.59.1
|
'@typescript-eslint/visitor-keys': 8.59.2
|
||||||
debug: 4.4.3
|
debug: 4.4.3
|
||||||
minimatch: 10.2.5
|
minimatch: 10.2.5
|
||||||
semver: 7.7.4
|
semver: 7.8.0
|
||||||
tinyglobby: 0.2.16
|
tinyglobby: 0.2.16
|
||||||
ts-api-utils: 2.5.0(typescript@5.9.3)
|
ts-api-utils: 2.5.0(typescript@5.9.3)
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
@@ -9750,12 +9759,12 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.59.1(eslint@8.57.1)(typescript@5.9.3)':
|
'@typescript-eslint/utils@8.59.2(eslint@8.57.1)(typescript@5.9.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
|
'@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1)
|
||||||
'@typescript-eslint/scope-manager': 8.59.1
|
'@typescript-eslint/scope-manager': 8.59.2
|
||||||
'@typescript-eslint/types': 8.59.1
|
'@typescript-eslint/types': 8.59.2
|
||||||
'@typescript-eslint/typescript-estree': 8.59.1(typescript@5.9.3)
|
'@typescript-eslint/typescript-estree': 8.59.2(typescript@5.9.3)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
typescript: 5.9.3
|
typescript: 5.9.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -9776,9 +9785,9 @@ snapshots:
|
|||||||
'@typescript-eslint/types': 8.59.0
|
'@typescript-eslint/types': 8.59.0
|
||||||
eslint-visitor-keys: 5.0.1
|
eslint-visitor-keys: 5.0.1
|
||||||
|
|
||||||
'@typescript-eslint/visitor-keys@8.59.1':
|
'@typescript-eslint/visitor-keys@8.59.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/types': 8.59.1
|
'@typescript-eslint/types': 8.59.2
|
||||||
eslint-visitor-keys: 5.0.1
|
eslint-visitor-keys: 5.0.1
|
||||||
|
|
||||||
'@ungap/structured-clone@1.3.0': {}
|
'@ungap/structured-clone@1.3.0': {}
|
||||||
@@ -10982,7 +10991,7 @@ snapshots:
|
|||||||
|
|
||||||
eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.59.0(@typescript-eslint/parser@8.59.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3):
|
eslint-plugin-jest@29.15.2(@typescript-eslint/eslint-plugin@8.59.0(@typescript-eslint/parser@8.59.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/utils': 8.59.1(eslint@8.57.1)(typescript@5.9.3)
|
'@typescript-eslint/utils': 8.59.2(eslint@8.57.1)(typescript@5.9.3)
|
||||||
eslint: 8.57.1
|
eslint: 8.57.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 8.59.0(@typescript-eslint/parser@8.59.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)
|
'@typescript-eslint/eslint-plugin': 8.59.0(@typescript-eslint/parser@8.59.0(eslint@8.57.1)(typescript@5.9.3))(eslint@8.57.1)(typescript@5.9.3)
|
||||||
@@ -11873,8 +11882,6 @@ snapshots:
|
|||||||
|
|
||||||
jiti@2.6.1: {}
|
jiti@2.6.1: {}
|
||||||
|
|
||||||
jose@6.2.2: {}
|
|
||||||
|
|
||||||
jose@6.2.3: {}
|
jose@6.2.3: {}
|
||||||
|
|
||||||
js-tokens@10.0.0: {}
|
js-tokens@10.0.0: {}
|
||||||
@@ -12044,7 +12051,7 @@ snapshots:
|
|||||||
|
|
||||||
lines-and-columns@1.2.4: {}
|
lines-and-columns@1.2.4: {}
|
||||||
|
|
||||||
livekit-client@2.18.8(@types/dom-mediacapture-record@1.0.22):
|
livekit-client@2.18.9(@types/dom-mediacapture-record@1.0.22):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@livekit/mutex': 1.1.1
|
'@livekit/mutex': 1.1.1
|
||||||
'@livekit/protocol': 1.45.3
|
'@livekit/protocol': 1.45.3
|
||||||
@@ -12120,7 +12127,7 @@ snapshots:
|
|||||||
|
|
||||||
matrix-events-sdk@0.0.1: {}
|
matrix-events-sdk@0.0.1: {}
|
||||||
|
|
||||||
matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/69985ee350a33ba75f1ad11f96468344f0c92a8d:
|
matrix-js-sdk@https://codeload.github.com/matrix-org/matrix-js-sdk/tar.gz/349e8c5023b74b7ee17b2e9a0cba6dfce6818d68:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/runtime': 7.29.2
|
'@babel/runtime': 7.29.2
|
||||||
'@matrix-org/matrix-sdk-crypto-wasm': 18.2.0
|
'@matrix-org/matrix-sdk-crypto-wasm': 18.2.0
|
||||||
@@ -13201,6 +13208,8 @@ snapshots:
|
|||||||
|
|
||||||
semver@7.7.4: {}
|
semver@7.7.4: {}
|
||||||
|
|
||||||
|
semver@7.8.0: {}
|
||||||
|
|
||||||
set-blocking@2.0.0: {}
|
set-blocking@2.0.0: {}
|
||||||
|
|
||||||
set-cookie-parser@2.7.2: {}
|
set-cookie-parser@2.7.2: {}
|
||||||
|
|||||||
@@ -7,8 +7,13 @@ Please see LICENSE in the repository root for full details.
|
|||||||
|
|
||||||
import { type FC, type JSX, type Ref, useMemo } from "react";
|
import { type FC, type JSX, type Ref, useMemo } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
import {
|
||||||
|
SpotlightIcon,
|
||||||
|
GridIcon,
|
||||||
|
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||||
import { combineLatest, map } from "rxjs";
|
import { combineLatest, map } from "rxjs";
|
||||||
import { supportsBackgroundProcessors } from "@livekit/track-processors";
|
import { supportsBackgroundProcessors } from "@livekit/track-processors";
|
||||||
|
import { Switch } from "@vector-im/compound-web";
|
||||||
|
|
||||||
import LogoMark from "../icons/LogoMark.svg?react";
|
import LogoMark from "../icons/LogoMark.svg?react";
|
||||||
import LogoType from "../icons/LogoType.svg?react";
|
import LogoType from "../icons/LogoType.svg?react";
|
||||||
@@ -24,7 +29,6 @@ import {
|
|||||||
type ReactionData,
|
type ReactionData,
|
||||||
} from "../button";
|
} from "../button";
|
||||||
import styles from "./CallFooter.module.css";
|
import styles from "./CallFooter.module.css";
|
||||||
import { LayoutToggle } from "../room/LayoutToggle";
|
|
||||||
import {
|
import {
|
||||||
type CallViewModel,
|
type CallViewModel,
|
||||||
type GridMode,
|
type GridMode,
|
||||||
@@ -45,6 +49,7 @@ import type { ObservableScope } from "../state/ObservableScope";
|
|||||||
import { type MuteStates } from "../state/MuteStates";
|
import { type MuteStates } from "../state/MuteStates";
|
||||||
import { type ViewModel, useViewModel } from "../state/ViewModel";
|
import { type ViewModel, useViewModel } from "../state/ViewModel";
|
||||||
import { getUrlParams, HeaderStyle } from "../UrlParams";
|
import { getUrlParams, HeaderStyle } from "../UrlParams";
|
||||||
|
import { t } from "i18next";
|
||||||
|
|
||||||
export interface AudioOutputSwitcher {
|
export interface AudioOutputSwitcher {
|
||||||
targetOutput: string;
|
targetOutput: string;
|
||||||
@@ -554,10 +559,18 @@ export const CallFooter: FC<FooterProps> = ({ ref, children, vm }) => {
|
|||||||
</div>
|
</div>
|
||||||
{!hideControls && <div className={styles.buttons}>{buttons}</div>}
|
{!hideControls && <div className={styles.buttons}>{buttons}</div>}
|
||||||
{setLayoutMode && layoutMode && (
|
{setLayoutMode && layoutMode && (
|
||||||
<LayoutToggle
|
<Switch<"spotlight", "grid">
|
||||||
|
name="layoutMode"
|
||||||
|
aria-label={t("layout_switch_label")}
|
||||||
|
leftLabel={t("layout_spotlight_label")}
|
||||||
|
leftValue="spotlight"
|
||||||
|
leftIcon={SpotlightIcon}
|
||||||
|
rightLabel={t("layout_grid_label")}
|
||||||
|
rightValue="grid"
|
||||||
|
rightIcon={GridIcon}
|
||||||
className={styles.layout}
|
className={styles.layout}
|
||||||
layout={layoutMode}
|
value={layoutMode}
|
||||||
setLayout={setLayoutMode}
|
onChange={setLayoutMode}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -164,6 +164,14 @@ export interface ResolvedConfigOptions extends ConfigOptions {
|
|||||||
};
|
};
|
||||||
sync_disconnect_grace_period_ms: number;
|
sync_disconnect_grace_period_ms: number;
|
||||||
ssla: string;
|
ssla: string;
|
||||||
|
matrix_rtc_session: {
|
||||||
|
wait_for_key_rotation_ms?: number;
|
||||||
|
delayed_leave_event_delay_ms: number;
|
||||||
|
delayed_leave_event_restart_local_timeout_ms?: number;
|
||||||
|
delayed_leave_event_restart_ms?: number;
|
||||||
|
network_error_retry_ms: number;
|
||||||
|
membership_event_expiry_ms?: number;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_CONFIG: ResolvedConfigOptions = {
|
export const DEFAULT_CONFIG: ResolvedConfigOptions = {
|
||||||
@@ -178,4 +186,8 @@ export const DEFAULT_CONFIG: ResolvedConfigOptions = {
|
|||||||
},
|
},
|
||||||
sync_disconnect_grace_period_ms: 10000,
|
sync_disconnect_grace_period_ms: 10000,
|
||||||
ssla: "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf",
|
ssla: "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf",
|
||||||
|
matrix_rtc_session: {
|
||||||
|
delayed_leave_event_delay_ms: 10000,
|
||||||
|
network_error_retry_ms: 1000,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -84,6 +84,99 @@ describe("getSFUConfigWithOpenID", () => {
|
|||||||
expect.fail("Expected test to throw;");
|
expect.fail("Expected test to throw;");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should retry without delay params if the JWT service legacy endpoint returns M_BAD_JSON 400", async () => {
|
||||||
|
let callCount = 0;
|
||||||
|
|
||||||
|
fetchMock.post(
|
||||||
|
"https://sfu.example.org/sfu/get",
|
||||||
|
(url, opts) => {
|
||||||
|
callCount++;
|
||||||
|
const body = JSON.parse(opts.body as string);
|
||||||
|
|
||||||
|
// First call: check if it has delay parts and return 400
|
||||||
|
if (callCount === 1) {
|
||||||
|
expect(body).toHaveProperty("delay_id", "mock_delay_id");
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: { errcode: "M_BAD_JSON", error: "Unsupported parameters" },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second call: check if delay parts were stripped and return success
|
||||||
|
expect(body).not.toHaveProperty("delay_id");
|
||||||
|
expect(body).not.toHaveProperty("delay_timeout");
|
||||||
|
expect(body).not.toHaveProperty("delay_cs_api_url");
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: { url: sfuUrl, jwt: testJWTToken },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{ overwriteRoutes: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
// Note: Assuming getSFUConfigWithOpenID eventually calls getLiveKitJWT
|
||||||
|
const config = await getSFUConfigWithOpenID(
|
||||||
|
matrixClient,
|
||||||
|
ownMemberMock,
|
||||||
|
"https://sfu.example.org",
|
||||||
|
"!example_room_id",
|
||||||
|
{
|
||||||
|
delayEndpointBaseUrl: "https://matrix.homeserverserver.org",
|
||||||
|
delayId: "mock_delay_id",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(config.jwt).toBe(testJWTToken);
|
||||||
|
expect(callCount).toBe(2);
|
||||||
|
void (await fetchMock.flush());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should successfully send delay parameters to the JWT service legacy endpoint", async () => {
|
||||||
|
fetchMock.post(
|
||||||
|
"https://sfu.example.org/sfu/get",
|
||||||
|
(url, opts) => {
|
||||||
|
const body = JSON.parse(opts.body as string);
|
||||||
|
|
||||||
|
// Verify, that the request contains the expected delay parameters
|
||||||
|
if (
|
||||||
|
body.delay_id === "mock_delay_id" &&
|
||||||
|
body.delay_timeout === 10000 &&
|
||||||
|
body.delay_cs_api_url === "https://homeserverserver.org/cs_api"
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
status: 200,
|
||||||
|
body: { url: sfuUrl, jwt: testJWTToken },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
status: 400,
|
||||||
|
body: { error: "Missing expected delay params" },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
{ overwriteRoutes: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
const config = await getSFUConfigWithOpenID(
|
||||||
|
matrixClient,
|
||||||
|
ownMemberMock,
|
||||||
|
"https://sfu.example.org",
|
||||||
|
"!example_room_id",
|
||||||
|
{
|
||||||
|
delayEndpointBaseUrl: "https://homeserverserver.org/cs_api",
|
||||||
|
delayId: "mock_delay_id",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// Prüfe das Ergebnis
|
||||||
|
expect(config).toMatchObject({
|
||||||
|
jwt: testJWTToken,
|
||||||
|
url: sfuUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
void (await fetchMock.flush());
|
||||||
|
});
|
||||||
|
|
||||||
it("should try legacy and then new endpoint with delay delegation", async () => {
|
it("should try legacy and then new endpoint with delay delegation", async () => {
|
||||||
fetchMock.post("https://sfu.example.org/get_token", () => {
|
fetchMock.post("https://sfu.example.org/get_token", () => {
|
||||||
return {
|
return {
|
||||||
@@ -121,7 +214,7 @@ describe("getSFUConfigWithOpenID", () => {
|
|||||||
expect(calls[0][0]).toStrictEqual("https://sfu.example.org/get_token");
|
expect(calls[0][0]).toStrictEqual("https://sfu.example.org/get_token");
|
||||||
expect(calls[0][1]).toStrictEqual({
|
expect(calls[0][1]).toStrictEqual({
|
||||||
// check if it uses correct delayID!
|
// check if it uses correct delayID!
|
||||||
body: '{"room_id":"!example_room_id","slot_id":"m.call#ROOM","member":{"id":"@alice:example.org:DEVICE","claimed_user_id":"@alice:example.org","claimed_device_id":"DEVICE"},"delay_id":"mock_delay_id","delay_timeout":1000,"delay_cs_api_url":"https://matrix.homeserverserver.org"}',
|
body: '{"room_id":"!example_room_id","slot_id":"m.call#ROOM","member":{"id":"@alice:example.org:DEVICE","claimed_user_id":"@alice:example.org","claimed_device_id":"DEVICE"},"delay_id":"mock_delay_id","delay_timeout":10000,"delay_cs_api_url":"https://matrix.homeserverserver.org"}',
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@@ -131,7 +224,7 @@ describe("getSFUConfigWithOpenID", () => {
|
|||||||
expect(calls[1][0]).toStrictEqual("https://sfu.example.org/sfu/get");
|
expect(calls[1][0]).toStrictEqual("https://sfu.example.org/sfu/get");
|
||||||
|
|
||||||
expect(calls[1][1]).toStrictEqual({
|
expect(calls[1][1]).toStrictEqual({
|
||||||
body: '{"room":"!example_room_id","device_id":"DEVICE"}',
|
body: '{"room":"!example_room_id","device_id":"DEVICE","delay_id":"mock_delay_id","delay_timeout":10000,"delay_cs_api_url":"https://matrix.homeserverserver.org"}',
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
@@ -176,7 +269,7 @@ describe("getSFUConfigWithOpenID", () => {
|
|||||||
expect(calls[0][0]).toStrictEqual("https://sfu.example.org/get_token");
|
expect(calls[0][0]).toStrictEqual("https://sfu.example.org/get_token");
|
||||||
expect(calls[0][1]).toStrictEqual({
|
expect(calls[0][1]).toStrictEqual({
|
||||||
// check if it uses correct delayID!
|
// check if it uses correct delayID!
|
||||||
body: '{"room_id":"!example_room_id","slot_id":"m.call#ROOM","member":{"id":"@alice:example.org:DEVICE","claimed_user_id":"@alice:example.org","claimed_device_id":"DEVICE"},"delay_id":"mock_delay_id","delay_timeout":1000,"delay_cs_api_url":"https://matrix.homeserverserver.org"}',
|
body: '{"room_id":"!example_room_id","slot_id":"m.call#ROOM","member":{"id":"@alice:example.org:DEVICE","claimed_user_id":"@alice:example.org","claimed_device_id":"DEVICE"},"delay_id":"mock_delay_id","delay_timeout":10000,"delay_cs_api_url":"https://matrix.homeserverserver.org"}',
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|||||||
@@ -155,6 +155,8 @@ export async function getSFUConfigWithOpenID(
|
|||||||
serviceUrl,
|
serviceUrl,
|
||||||
roomId,
|
roomId,
|
||||||
openIdToken,
|
openIdToken,
|
||||||
|
opts?.delayEndpointBaseUrl,
|
||||||
|
opts?.delayId,
|
||||||
);
|
);
|
||||||
logger?.info(`Got JWT from call's active focus URL.`);
|
logger?.info(`Got JWT from call's active focus URL.`);
|
||||||
return extractFullConfigFromToken(sfuConfig);
|
return extractFullConfigFromToken(sfuConfig);
|
||||||
@@ -187,20 +189,62 @@ async function getLiveKitJWT(
|
|||||||
livekitServiceURL: string,
|
livekitServiceURL: string,
|
||||||
matrixRoomId: string,
|
matrixRoomId: string,
|
||||||
openIDToken: IOpenIDToken,
|
openIDToken: IOpenIDToken,
|
||||||
|
delayEndpointBaseUrl?: string,
|
||||||
|
delayId?: string,
|
||||||
): Promise<{ url: string; jwt: string }> {
|
): Promise<{ url: string; jwt: string }> {
|
||||||
const res = await doNetworkOperationWithRetry(async () => {
|
interface IDelayParams {
|
||||||
|
delay_id?: string;
|
||||||
|
delay_timeout?: number;
|
||||||
|
delay_cs_api_url?: string;
|
||||||
|
}
|
||||||
|
let bodyDalayParts: IDelayParams = {};
|
||||||
|
// Also check for empty string
|
||||||
|
if (delayId && delayEndpointBaseUrl) {
|
||||||
|
const delayTimeoutMs =
|
||||||
|
Config.get().matrix_rtc_session?.delayed_leave_event_delay_ms;
|
||||||
|
bodyDalayParts = {
|
||||||
|
delay_id: delayId,
|
||||||
|
delay_timeout: delayTimeoutMs,
|
||||||
|
delay_cs_api_url: delayEndpointBaseUrl,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const makeRequest = async (delayParts: IDelayParams): Promise<Response> => {
|
||||||
return await fetch(livekitServiceURL + "/sfu/get", {
|
return await fetch(livekitServiceURL + "/sfu/get", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
// This is the actual livekit room alias. For the legacy jwt endpoint simply the room id was used.
|
// The legacy JWT endpoint uses only the matrix room id to calculate the livekit room alias.
|
||||||
|
// However, the livekit room alias is provided as part of the JWT payload.
|
||||||
room: matrixRoomId,
|
room: matrixRoomId,
|
||||||
openid_token: openIDToken,
|
openid_token: openIDToken,
|
||||||
device_id: deviceId,
|
device_id: deviceId,
|
||||||
|
...delayParts,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await doNetworkOperationWithRetry(async () => {
|
||||||
|
let response = await makeRequest(bodyDalayParts);
|
||||||
|
|
||||||
|
// Old service compatibility check
|
||||||
|
const oldServiceDoesNotSupportDelayParts =
|
||||||
|
response.status === 400 && Object.keys(bodyDalayParts).length > 0;
|
||||||
|
// If http status 400 with M_BAD_JSON and we sent delay parts, retry without them
|
||||||
|
if (oldServiceDoesNotSupportDelayParts) {
|
||||||
|
try {
|
||||||
|
const errorBody = await response.json();
|
||||||
|
if (errorBody.errcode === "M_BAD_JSON") {
|
||||||
|
response = await makeRequest({});
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// If we can't parse the error, treat as real error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
@@ -241,7 +285,7 @@ export async function getLiveKitJWTWithDelayDelegation(
|
|||||||
// Also check for empty string
|
// Also check for empty string
|
||||||
if (delayId && delayEndpointBaseUrl) {
|
if (delayId && delayEndpointBaseUrl) {
|
||||||
const delayTimeoutMs =
|
const delayTimeoutMs =
|
||||||
Config.get().matrix_rtc_session?.delayed_leave_event_delay_ms ?? 1000;
|
Config.get().matrix_rtc_session?.delayed_leave_event_delay_ms;
|
||||||
bodyDalayParts = {
|
bodyDalayParts = {
|
||||||
delay_id: delayId,
|
delay_id: delayId,
|
||||||
delay_timeout: delayTimeoutMs,
|
delay_timeout: delayTimeoutMs,
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2023, 2024 New Vector Ltd.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.toggle {
|
|
||||||
padding: 2px;
|
|
||||||
border: 1px solid var(--cpd-color-border-interactive-secondary);
|
|
||||||
border-radius: var(--cpd-radius-pill-effect);
|
|
||||||
background: var(--cpd-color-bg-canvas-default);
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle input {
|
|
||||||
appearance: none;
|
|
||||||
/* Safari puts a margin on these, which is not removed via appearance: none */
|
|
||||||
margin: 0;
|
|
||||||
block-size: var(--cpd-space-11x);
|
|
||||||
inline-size: var(--cpd-space-11x);
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: var(--cpd-radius-pill-effect);
|
|
||||||
background: var(--cpd-color-bg-action-secondary-rest);
|
|
||||||
box-shadow: var(--small-drop-shadow);
|
|
||||||
transition: background-color 0.1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle svg {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
padding: calc(2.5 * var(--cpd-space-1x));
|
|
||||||
pointer-events: none;
|
|
||||||
color: var(--cpd-color-icon-primary);
|
|
||||||
transition: color 0.1s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle svg:nth-child(2) {
|
|
||||||
inset-inline-start: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle svg:nth-child(4) {
|
|
||||||
inset-inline-end: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (hover: hover) {
|
|
||||||
.toggle input:hover {
|
|
||||||
background: var(--cpd-color-bg-action-secondary-hovered);
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle input:active {
|
|
||||||
background: var(--cpd-color-bg-action-secondary-pressed);
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle input:checked {
|
|
||||||
background: var(--cpd-color-bg-action-primary-rest);
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle input:checked + svg {
|
|
||||||
color: var(--cpd-color-icon-on-solid-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (hover: hover) {
|
|
||||||
.toggle input:checked:hover {
|
|
||||||
background: var(--cpd-color-bg-action-primary-hovered);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle input:checked:active {
|
|
||||||
background: var(--cpd-color-bg-action-primary-pressed);
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle input:first-child {
|
|
||||||
margin-inline-end: 5px;
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2026 Element Creations Ltd.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { fn } from "storybook/test";
|
|
||||||
|
|
||||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
|
||||||
import { LayoutToggle } from "./LayoutToggle";
|
|
||||||
|
|
||||||
const meta = {
|
|
||||||
component: LayoutToggle,
|
|
||||||
} satisfies Meta<typeof LayoutToggle>;
|
|
||||||
|
|
||||||
export default meta;
|
|
||||||
type Story = StoryObj<typeof meta>;
|
|
||||||
|
|
||||||
export const Default: Story = {
|
|
||||||
args: {
|
|
||||||
layout: "grid",
|
|
||||||
setLayout: fn(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2023, 2024 New Vector Ltd.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
|
||||||
Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { type ChangeEvent, type FC, useCallback } from "react";
|
|
||||||
import { useTranslation } from "react-i18next";
|
|
||||||
import { Tooltip } from "@vector-im/compound-web";
|
|
||||||
import {
|
|
||||||
SpotlightIcon,
|
|
||||||
GridIcon,
|
|
||||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
|
||||||
import classNames from "classnames";
|
|
||||||
|
|
||||||
import styles from "./LayoutToggle.module.css";
|
|
||||||
|
|
||||||
export type Layout = "spotlight" | "grid";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
layout: Layout;
|
|
||||||
setLayout: (layout: Layout) => void;
|
|
||||||
className?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const LayoutToggle: FC<Props> = ({ layout, setLayout, className }) => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
|
|
||||||
const onChange = useCallback(
|
|
||||||
(e: ChangeEvent<HTMLInputElement>) => setLayout(e.target.value as Layout),
|
|
||||||
[setLayout],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form className={classNames(styles.toggle, className)}>
|
|
||||||
<Tooltip label={t("layout_spotlight_label")}>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="layout"
|
|
||||||
value="spotlight"
|
|
||||||
checked={layout === "spotlight"}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
<SpotlightIcon aria-hidden width={24} height={24} />
|
|
||||||
<Tooltip label={t("layout_grid_label")}>
|
|
||||||
<input
|
|
||||||
type="radio"
|
|
||||||
name="layout"
|
|
||||||
value="grid"
|
|
||||||
checked={layout === "grid"}
|
|
||||||
onChange={onChange}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
|
||||||
<GridIcon aria-hidden width={24} height={24} />
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -396,21 +396,23 @@ exports[`InCallView > rendering > renders 1`] = `
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<form
|
<fieldset
|
||||||
class="toggle layout"
|
aria-label="Layout"
|
||||||
|
class="_toggle_13rnk_9 layout"
|
||||||
|
data-size="lg"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
aria-labelledby="_r_11_"
|
aria-labelledby="_r_11_"
|
||||||
name="layout"
|
name="layoutMode"
|
||||||
type="radio"
|
type="radio"
|
||||||
value="spotlight"
|
value="spotlight"
|
||||||
/>
|
/>
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="24"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
@@ -420,23 +422,23 @@ exports[`InCallView > rendering > renders 1`] = `
|
|||||||
<input
|
<input
|
||||||
aria-labelledby="_r_16_"
|
aria-labelledby="_r_16_"
|
||||||
checked=""
|
checked=""
|
||||||
name="layout"
|
name="layoutMode"
|
||||||
type="radio"
|
type="radio"
|
||||||
value="grid"
|
value="grid"
|
||||||
/>
|
/>
|
||||||
<svg
|
<svg
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
height="24"
|
height="1em"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
>
|
>
|
||||||
<path
|
<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.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"
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</form>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -778,6 +778,19 @@ export function enterRTCSession(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculates `maximumNetworkErrorRetryCount`. The connection is failed if EITHER:
|
||||||
|
// - The /sync loop is unresponsive for > `gracePeriod` ms, or
|
||||||
|
// - A delayed leave event is emitted (after `leaveDelay` ms period).
|
||||||
|
// Note: Use leaveDelay >> gracePeriod for delegated leave events.
|
||||||
|
const gracePeriod = Config.get().sync_disconnect_grace_period_ms;
|
||||||
|
const leaveDelay = matrixRtcSessionConfig?.delayed_leave_event_delay_ms;
|
||||||
|
const retryInterval = matrixRtcSessionConfig?.network_error_retry_ms;
|
||||||
|
|
||||||
|
// Math.min is used to account for the respective worst case: /sync not available or leave event emitted.
|
||||||
|
const maxWaitTime = Math.min(gracePeriod, leaveDelay);
|
||||||
|
const maximumNetworkErrorRetryCount =
|
||||||
|
Math.ceil(maxWaitTime / retryInterval) + 1;
|
||||||
|
|
||||||
// Multi-sfu does not need a preferred foci list. just the focus that is actually used.
|
// Multi-sfu does not need a preferred foci list. just the focus that is actually used.
|
||||||
// TODO where/how do we track errors originating from the ongoing rtcSession?
|
// TODO where/how do we track errors originating from the ongoing rtcSession?
|
||||||
|
|
||||||
@@ -803,6 +816,7 @@ export function enterRTCSession(
|
|||||||
membershipEventExpiryMs:
|
membershipEventExpiryMs:
|
||||||
matrixRtcSessionConfig?.membership_event_expiry_ms,
|
matrixRtcSessionConfig?.membership_event_expiry_ms,
|
||||||
unstableSendStickyEvents: matrixRTCMode === MatrixRTCMode.Matrix_2_0,
|
unstableSendStickyEvents: matrixRTCMode === MatrixRTCMode.Matrix_2_0,
|
||||||
|
maximumNetworkErrorRetryCount: maximumNetworkErrorRetryCount,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user