Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dev-backend-docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ services:

synapse:
hostname: homeserver
image: docker.io/matrixdotorg/synapse:latest
image: ghcr.io/element-hq/synapse:msc4354-5
pull_policy: always
environment:
- SYNAPSE_CONFIG_PATH=/data/cfg/homeserver.yaml
Expand All @@ -106,7 +106,7 @@ services:

synapse-1:
hostname: homeserver-1
image: docker.io/matrixdotorg/synapse:latest
image: ghcr.io/element-hq/synapse:msc4354-5
pull_policy: always
environment:
- SYNAPSE_CONFIG_PATH=/data/cfg/homeserver.yaml
Expand Down
1 change: 1 addition & 0 deletions docs/url-params.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ These parameters are relevant to both [widget](./embedded-standalone.md) and [st
| `sendNotificationType` | `ring` or `notification` | No | No | Will send a "ring" or "notification" `m.rtc.notification` event if the user is the first one in the call. |
| `autoLeaveWhenOthersLeft` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Whether the app should automatically leave the call when there is no one left in the call. |
| `waitForCallPickup` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | When sending a notification, show UI that the app is awaiting an answer, play a dial tone, and (in widget mode) auto-close the widget once the notification expires. |
| `multiSFU` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Enables experimental new multiSFU support. |

### Widget-only parameters

Expand Down
9 changes: 4 additions & 5 deletions locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,11 @@
"livekit_server_info": "LiveKit Server Info",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}",
"multi_sfu": "Multi-SFU media transport",
"mute_all_audio": "Mute all audio (participants, reactions, join sounds)",
"prefer_sticky_events": {
"description": "Improves reliability of calls (requires homeserver support)",
"label": "Prefer sticky events"
"multi_sfu": {
"description": "Allows multiple SFUs to be present in a call (requires homeserver support)",
"label": "Multi-SFU media transport"
},
"mute_all_audio": "Mute all audio (participants, reactions, join sounds)",
"show_connection_stats": "Show connection statistics",
"url_params": "URL parameters"
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@
"livekit-client": "^2.13.0",
"lodash-es": "^4.17.21",
"loglevel": "^1.9.1",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=toger5/sticky-events&commit=e7f5bec51b6f70501a025b79fe5021c933385b21",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#head=hs/rtc-slots&commit=c56fe525aa4dcb8c3b8629dc303b95f4dd4988bd",
"matrix-widget-api": "^1.13.0",
"normalize.css": "^8.0.1",
"observable-hooks": "^4.2.3",
Expand Down
6 changes: 6 additions & 0 deletions src/UrlParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,11 @@ export interface UrlProperties {
* can be "light", "dark", "light-high-contrast" or "dark-high-contrast".
*/
theme: string | null;
/**
* Whether or not the call should be held using the sticky event implementation,
* where possible.
*/
multiSFU: boolean;
}

/**
Expand Down Expand Up @@ -501,6 +506,7 @@ export const computeUrlParams = (search = "", hash = ""): UrlParams => {
sentryDsn: parser.getParam("sentryDsn"),
sentryEnvironment: parser.getParam("sentryEnvironment"),
e2eEnabled: parser.getFlagParam("enableE2EE", true),
multiSFU: parser.getFlagParam("multiSFU", false),
};

const configuration: Partial<UrlConfiguration> = {
Expand Down
29 changes: 4 additions & 25 deletions src/settings/DeveloperSettingsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
multiSfu as multiSfuSetting,
muteAllAudio as muteAllAudioSetting,
alwaysShowIphoneEarpiece as alwaysShowIphoneEarpieceSetting,
preferStickyEvents as preferStickyEventsSetting,
} from "./settings";
import type { Room as LivekitRoom } from "livekit-client";
import styles from "./DeveloperSettingsTab.module.css";
Expand Down Expand Up @@ -59,10 +58,6 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRooms }) => {
});
}, [client]);

const [preferStickyEvents, setPreferStickyEvents] = useSetting(
preferStickyEventsSetting,
);

const [showConnectionStats, setShowConnectionStats] = useSetting(
showConnectionStatsSetting,
);
Expand Down Expand Up @@ -146,22 +141,6 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRooms }) => {
}
/>
</FieldRow>
<FieldRow>
<InputField
id="preferStickyEvents"
type="checkbox"
label={t("developer_mode.prefer_sticky_events.label")}
disabled={!stickyEventsSupported}
description={t("developer_mode.prefer_sticky_events.description")}
checked={!!preferStickyEvents}
onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
setPreferStickyEvents(event.target.checked);
},
[setPreferStickyEvents],
)}
/>
</FieldRow>
<FieldRow>
<InputField
id="showConnectionStats"
Expand All @@ -180,10 +159,10 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRooms }) => {
<InputField
id="multiSfu"
type="checkbox"
label={t("developer_mode.multi_sfu")}
// If using sticky events we implicitly prefer use multi-sfu
checked={multiSfu || preferStickyEvents}
disabled={preferStickyEvents}
label={t("developer_mode.multi_sfu.label")}
description={t("developer_mode.multi_sfu.description")}
checked={multiSfu}
disabled={!stickyEventsSupported}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, we should have been checking this. MSFU can't be enabled without sticky event support by the homeserver.

onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
setMultiSfu(event.target.checked);
Expand Down
5 changes: 0 additions & 5 deletions src/settings/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,6 @@ export const showConnectionStats = new Setting<boolean>(
false,
);

export const preferStickyEvents = new Setting<boolean>(
"prefer-sticky-events",
false,
);

export const audioInput = new Setting<string | undefined>(
"audio-input",
undefined,
Expand Down
21 changes: 4 additions & 17 deletions src/state/CallViewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ import {
duplicateTiles,
multiSfu,
playReactionsSound,
preferStickyEvents,
showReactions,
} from "../settings/settings";
import { isFirefox } from "../Platform";
Expand Down Expand Up @@ -282,22 +281,13 @@ export class CallViewModel {
remote: { membership: CallMembership; transport: LivekitTransport }[];
preferred: Async<LivekitTransport>;
multiSfu: boolean;
preferStickyEvents: boolean;
} | null> = this.scope.behavior(
this.joined$.pipe(
switchMap((joined) =>
joined
? combineLatest(
[
this.preferredTransport$,
this.memberships$,
multiSfu.value$,
preferStickyEvents.value$,
],
(preferred, memberships, preferMultiSfu, preferStickyEvents) => {
// Multi-SFU must be implicitly enabled when using sticky events
const multiSfu = preferStickyEvents || preferMultiSfu;

[this.preferredTransport$, this.memberships$, multiSfu.value$],
(preferred, memberships, multiSfu) => {
const oldestMembership =
this.matrixRTCSession.getOldestMembership();
const remote = memberships.flatMap((m) => {
Expand Down Expand Up @@ -333,7 +323,6 @@ export class CallViewModel {
remote,
preferred,
multiSfu,
preferStickyEvents,
};
},
)
Expand Down Expand Up @@ -368,7 +357,6 @@ export class CallViewModel {
*/
private readonly advertisedTransport$: Behavior<{
multiSfu: boolean;
preferStickyEvents: boolean;
transport: LivekitTransport;
} | null> = this.scope.behavior(
this.transports$.pipe(
Expand All @@ -377,7 +365,6 @@ export class CallViewModel {
transports.preferred.state === "ready"
? {
multiSfu: transports.multiSfu,
preferStickyEvents: transports.preferStickyEvents,
// In non-multi-SFU mode we should always advertise the preferred
// SFU to minimize the number of membership updates
transport: transports.multiSfu
Expand All @@ -388,7 +375,6 @@ export class CallViewModel {
),
distinctUntilChanged<{
multiSfu: boolean;
preferStickyEvents: boolean;
transport: LivekitTransport;
} | null>(deepCompare),
),
Expand Down Expand Up @@ -1834,7 +1820,8 @@ export class CallViewModel {
await enterRTCSession(this.matrixRTCSession, advertised.transport, {
encryptMedia: this.options.encryptionSystem.kind !== E2eeType.NONE,
useMultiSfu: advertised.multiSfu,
preferStickyEvents: advertised.preferStickyEvents,
// Multi-SFU enables sticky events.
preferStickyEvents: advertised.multiSfu ?? this.urlParams.multiSFU,
});
} catch (e) {
logger.error("Error entering RTC session", e);
Expand Down
15 changes: 15 additions & 0 deletions src/utils/matrix.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
MemoryStore,
Preset,
Visibility,
EventType,
} from "matrix-js-sdk";
import { type ISyncStateData, type SyncState } from "matrix-js-sdk/lib/sync";
import { logger } from "matrix-js-sdk/lib/logger";
Expand All @@ -24,10 +25,14 @@
import { generateUrlSearchParams, getUrlParams } from "../UrlParams";
import { Config } from "../config/Config";
import { E2eeType } from "../e2ee/e2eeType";
import {

Check failure on line 28 in src/utils/matrix.ts

View workflow job for this annotation

GitHub Actions / Lint, format & type check

There should be at least one empty line between import groups
type EncryptionSystem,
saveKeyForRoom,
} from "../e2ee/sharedKeyManagement";
import {

Check failure on line 32 in src/utils/matrix.ts

View workflow job for this annotation

GitHub Actions / Lint, format & type check

`matrix-js-sdk/lib/matrixrtc` import should occur before type import of `matrix-js-sdk`

Check failure on line 32 in src/utils/matrix.ts

View workflow job for this annotation

GitHub Actions / Lint, format & type check

Imports "RtcSlotEventContent" are only used as type
DefaultCallApplicationSlot,
RtcSlotEventContent,
} from "matrix-js-sdk/lib/matrixrtc";

export const fallbackICEServerAllowed =
import.meta.env.VITE_FALLBACK_STUN_ALLOWED === "true";
Expand Down Expand Up @@ -236,6 +241,16 @@
preset: Preset.PublicChat,
name,
room_alias_name: e2ee ? undefined : roomAliasLocalpartFromRoomName(name),
initial_state: [
// Always create a slot
{
type: EventType.RTCSlot,
content: {
slot_id: DefaultCallApplicationSlot.slot_id,
application: { ...DefaultCallApplicationSlot.application },
} satisfies RtcSlotEventContent,
},
],
power_level_content_override: {
invite: 100,
kick: 100,
Expand Down
23 changes: 16 additions & 7 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7545,7 +7545,7 @@ __metadata:
livekit-client: "npm:^2.13.0"
lodash-es: "npm:^4.17.21"
loglevel: "npm:^1.9.1"
matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=toger5/sticky-events&commit=e7f5bec51b6f70501a025b79fe5021c933385b21"
matrix-js-sdk: "github:matrix-org/matrix-js-sdk#head=hs/rtc-slots&commit=c56fe525aa4dcb8c3b8629dc303b95f4dd4988bd"
matrix-widget-api: "npm:^1.13.0"
normalize.css: "npm:^8.0.1"
observable-hooks: "npm:^4.2.3"
Expand Down Expand Up @@ -10343,9 +10343,9 @@ __metadata:
languageName: node
linkType: hard

"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=toger5/sticky-events&commit=e7f5bec51b6f70501a025b79fe5021c933385b21":
version: 38.4.0
resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=e7f5bec51b6f70501a025b79fe5021c933385b21"
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=hs/rtc-slots&commit=c56fe525aa4dcb8c3b8629dc303b95f4dd4988bd":
version: 39.0.0
resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=c56fe525aa4dcb8c3b8629dc303b95f4dd4988bd"
dependencies:
"@babel/runtime": "npm:^7.12.5"
"@matrix-org/matrix-sdk-crypto-wasm": "npm:^15.3.0"
Expand All @@ -10358,10 +10358,10 @@ __metadata:
matrix-widget-api: "npm:^1.10.0"
oidc-client-ts: "npm:^3.0.1"
p-retry: "npm:7"
sdp-transform: "npm:^2.14.1"
sdp-transform: "npm:^3.0.0"
unhomoglyph: "npm:^1.0.6"
uuid: "npm:13"
checksum: 10c0/7adffdc183affd2d3ee1e8497cad6ca7904a37f98328ff7bc15aa6c1829dc9f9a92f8e1bd6260432a33626ff2a839644de938270163e73438b7294675cd954e4
checksum: 10c0/f8267c2a1fac67076400f886259d9b58b597f975865ce49aefe774d2f56a5c7caef66307f02fe24dcad35829e747bd7e563ecbb9a694d1f80b2439eebe0724fa
languageName: node
linkType: hard

Expand Down Expand Up @@ -12544,7 +12544,7 @@ __metadata:
languageName: node
linkType: hard

"sdp-transform@npm:^2.14.1, sdp-transform@npm:^2.15.0":
"sdp-transform@npm:^2.15.0":
version: 2.15.0
resolution: "sdp-transform@npm:2.15.0"
bin:
Expand All @@ -12553,6 +12553,15 @@ __metadata:
languageName: node
linkType: hard

"sdp-transform@npm:^3.0.0":
version: 3.0.0
resolution: "sdp-transform@npm:3.0.0"
bin:
sdp-verify: checker.js
checksum: 10c0/828a4595041ba64c86b29075aa4007ab384519b1fa29882db59ccb83b54b2b2a33b60848293f8da537fe151c52f5844fc17c8325396cac309fb19e2e81ec5bf4
languageName: node
linkType: hard

"sdp@npm:^3.2.0":
version: 3.2.0
resolution: "sdp@npm:3.2.0"
Expand Down
Loading