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
2 changes: 2 additions & 0 deletions backend/dev_homeserver.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ experimental_features:
# MSC4222 needed for syncv2 state_after. This allow clients to
# correctly track the state of the room.
msc4222_enabled: true
# sticky events for matrixRTC user state
msc4354_enabled: true

# The maximum allowed duration by which sent events can be delayed, as
# per MSC4140. Must be a positive value if set. Defaults to no
Expand Down
2 changes: 1 addition & 1 deletion 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 Down
4 changes: 4 additions & 0 deletions locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@
"mute_all_audio": "Mute all audio (participants, reactions, join sounds)",
"show_connection_stats": "Show connection statistics",
"show_non_member_tiles": "Show tiles for non-member media",
"prefer_sticky_events": {
"label": "Prefer sticky events",
"description": "Improves reliability of calls (requires homeserver support)"
},
"url_params": "URL parameters",
"use_new_membership_manager": "Use the new implementation of the call MembershipManager",
"use_to_device_key_transport": "Use to device key transport. This will fallback to room key transport when another call member sent a room key"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,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=develop",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#d8feffd190ae834f050f5e709ae00ad7a24aced9",
"matrix-widget-api": "^1.13.0",
"normalize.css": "^8.0.1",
"observable-hooks": "^4.2.3",
Expand Down
44 changes: 33 additions & 11 deletions src/home/useGroupCallRooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,19 +113,41 @@ const roomIsJoinable = (room: Room): boolean => {
}
};

/**
* Determines if a given room has call events in it, and therefore
* is likely to be a call room.
* @param room The Matrix room instance.
* @returns `true` if the room has call events.
*/
const roomHasCallMembershipEvents = (room: Room): boolean => {
switch (room.getMyMembership()) {
case KnownMembership.Join:
return !!room
.getLiveTimeline()
.getState(EventTimeline.FORWARDS)
?.events?.get(EventType.GroupCallMemberPrefix);
case KnownMembership.Knock:
// Assume that a room you've knocked on is able to hold calls
return true;
default:
return false;
// Legacy events.
const myMembership = room.getMyMembership();
if (myMembership === KnownMembership.Knock) {
// Assume that a room you've knocked on is able to hold calls
return true;
} else if (myMembership !== KnownMembership.Join) {
// Otherwise, non-joined rooms should never show up.
return false;
}

const timeline = room.getLiveTimeline();

// Check legacy events first, because it's cheaper.
if (
timeline
.getState(EventTimeline.FORWARDS)
?.events?.has(EventType.GroupCallMemberPrefix)
) {
return true;
}

// There was call membership events at some point in the timeline.
return timeline.getEvents().some(
Copy link
Member

Choose a reason for hiding this comment

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

There is no API to get the sticky events? Having the sticky key doesn't make the event sticky.
I am a bit lost with what this method is expecting to do

Copy link
Member

Choose a reason for hiding this comment

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

What is this method exactly? Try some heuristic to see if a room is a call room? like type": "org.matrix.msc3417.call"?

Or if there might be an active call?
And now it is checking for possible past sticky events (but potentially not anymore sticky)?
I don't get what this doing and what for

(e) =>
// Membership events only count if both of these are true
e.unstableStickyInfo && e.getType() === EventType.GroupCallMemberPrefix,
);
// Otherwise, it's *unlikely* this room was ever a call.
};

export function useGroupCallRooms(client: MatrixClient): GroupCallRoom[] {
Expand Down
10 changes: 1 addition & 9 deletions src/room/GroupCallView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ import {
} from "../utils/errors.ts";
import { GroupCallErrorBoundary } from "./GroupCallErrorBoundary.tsx";
import {
useNewMembershipManager as useNewMembershipManagerSetting,
useExperimentalToDeviceTransport as useExperimentalToDeviceTransportSetting,
useSetting,
} from "../settings/settings";
Expand Down Expand Up @@ -185,7 +184,6 @@ export const GroupCallView: FC<Props> = ({
password: passwordFromUrl,
} = useUrlParams();
const e2eeSystem = useRoomEncryptionSystem(room.roomId);
const [useNewMembershipManager] = useSetting(useNewMembershipManagerSetting);
const [useExperimentalToDeviceTransport] = useSetting(
useExperimentalToDeviceTransportSetting,
);
Expand Down Expand Up @@ -226,7 +224,6 @@ export const GroupCallView: FC<Props> = ({
await enterRTCSession(
rtcSession,
perParticipantE2EE,
useNewMembershipManager,
useExperimentalToDeviceTransport,
);
} catch (e) {
Expand All @@ -241,11 +238,7 @@ export const GroupCallView: FC<Props> = ({
}
}
},
[
perParticipantE2EE,
useExperimentalToDeviceTransport,
useNewMembershipManager,
],
[perParticipantE2EE, useExperimentalToDeviceTransport],
);

useEffect(() => {
Expand Down Expand Up @@ -322,7 +315,6 @@ export const GroupCallView: FC<Props> = ({
mediaDevices,
latestMuteStates,
enterRTCSessionOrError,
useNewMembershipManager,
]);

const [left, setLeft] = useState(false);
Expand Down
1 change: 0 additions & 1 deletion src/rtcSessionHelpers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
}) as unknown as MatrixRTCSession;
await enterRTCSession(mockedSession, false);

expect(mockedSession.joinRoomSession).toHaveBeenLastCalledWith(

Check failure on line 90 in src/rtcSessionHelpers.test.ts

View workflow job for this annotation

GitHub Actions / Run unit tests

src/rtcSessionHelpers.test.ts > It joins the correct Session

AssertionError: expected last "spy" call to have been called with [ [ { …(3) }, { …(3) }, …(2) ], …(2) ] - Expected + Received @@ -24,10 +24,19 @@ { "focus_selection": "oldest_membership", "type": "livekit", }, { + "callIntent": undefined, + "delayedLeaveEventDelayMs": undefined, + "delayedLeaveEventRestartLocalTimeoutMs": undefined, + "delayedLeaveEventRestartMs": undefined, + "makeKeyDelay": undefined, "manageMediaKeys": false, + "membershipEventExpiryMs": undefined, + "networkErrorRetryMs": undefined, + "notificationType": undefined, + "unstableSendStickyEvents": false, "useExperimentalToDeviceTransport": false, "useLegacyMemberEvents": false, }, ] ❯ src/rtcSessionHelpers.test.ts:90:41
[
{
livekit_alias: "my-oldest-member-service-alias",
Expand Down Expand Up @@ -117,7 +117,6 @@
{
manageMediaKeys: false,
useLegacyMemberEvents: false,
useNewMembershipManager: true,
useExperimentalToDeviceTransport: false,
},
);
Expand Down
4 changes: 2 additions & 2 deletions src/rtcSessionHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ElementWidgetActions, widget, type WidgetHelpers } from "./widget";
import { MatrixRTCFocusMissingError } from "./utils/errors";
import { getUrlParams } from "./UrlParams";
import { getSFUConfigWithOpenID } from "./livekit/openIDSFU.ts";
import { preferStickyEvents } from "./settings/settings.ts";

const FOCI_WK_KEY = "org.matrix.msc4143.rtc_foci";

Expand Down Expand Up @@ -105,7 +106,6 @@ async function makePreferredLivekitFoci(
export async function enterRTCSession(
rtcSession: MatrixRTCSession,
encryptMedia: boolean,
useNewMembershipManager = true,
useExperimentalToDeviceTransport = false,
): Promise<void> {
PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date());
Expand All @@ -127,7 +127,6 @@ export async function enterRTCSession(
{
notificationType,
callIntent,
useNewMembershipManager,
manageMediaKeys: encryptMedia,
...(useDeviceSessionMemberEvents !== undefined && {
useLegacyMemberEvents: !useDeviceSessionMemberEvents,
Expand All @@ -143,6 +142,7 @@ export async function enterRTCSession(
membershipEventExpiryMs:
matrixRtcSessionConfig?.membership_event_expiry_ms,
useExperimentalToDeviceTransport,
unstableSendStickyEvents: preferStickyEvents.getValue(),
},
);
if (widget) {
Expand Down
60 changes: 43 additions & 17 deletions src/settings/DeveloperSettingsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,20 @@ 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, useMemo } from "react";
import {
type ChangeEvent,
type FC,
useCallback,
useEffect,
useMemo,
useState,
} from "react";
import { useTranslation } from "react-i18next";
import {
UNSTABLE_MSC4354_STICKY_EVENTS,
type MatrixClient,
} from "matrix-js-sdk";
import { logger } from "matrix-js-sdk/lib/logger";

import { FieldRow, InputField } from "../input/Input";
import {
Expand All @@ -15,15 +27,15 @@ import {
debugTileLayout as debugTileLayoutSetting,
showNonMemberTiles as showNonMemberTilesSetting,
showConnectionStats as showConnectionStatsSetting,
useNewMembershipManager as useNewMembershipManagerSetting,
useExperimentalToDeviceTransport as useExperimentalToDeviceTransportSetting,
muteAllAudio as muteAllAudioSetting,
alwaysShowIphoneEarpiece as alwaysShowIphoneEarpieceSetting,
preferStickyEvents as preferStickyEventsSetting,
} from "./settings";
import type { MatrixClient } from "matrix-js-sdk";
import type { Room as LivekitRoom } from "livekit-client";
import styles from "./DeveloperSettingsTab.module.css";
import { useUrlParams } from "../UrlParams";

interface Props {
client: MatrixClient;
livekitRoom?: LivekitRoom;
Expand All @@ -39,12 +51,24 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
showNonMemberTilesSetting,
);

const [showConnectionStats, setShowConnectionStats] = useSetting(
showConnectionStatsSetting,
const [stickyEventsSupported, setStickyEventsSupported] = useState(false);
useEffect(() => {
client
.doesServerSupportUnstableFeature(UNSTABLE_MSC4354_STICKY_EVENTS)
.then((result) => {
setStickyEventsSupported(result);
})
.catch((ex) => {
logger.warn("Failed to check if sticky events are supported", ex);
});
}, [client]);

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

const [useNewMembershipManager, setNewMembershipManager] = useSetting(
useNewMembershipManagerSetting,
const [showConnectionStats, setShowConnectionStats] = useSetting(
showConnectionStatsSetting,
);

const [alwaysShowIphoneEarpiece, setAlwaysShowIphoneEarpiece] = useSetting(
Expand Down Expand Up @@ -143,29 +167,31 @@ export const DeveloperSettingsTab: FC<Props> = ({ client, livekitRoom }) => {
</FieldRow>
<FieldRow>
<InputField
id="showConnectionStats"
id="preferStickyEvents"
type="checkbox"
label={t("developer_mode.show_connection_stats")}
checked={!!showConnectionStats}
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 => {
setShowConnectionStats(event.target.checked);
setPreferStickyEvents(event.target.checked);
},
[setShowConnectionStats],
[setPreferStickyEvents],
)}
/>
</FieldRow>
<FieldRow>
<InputField
id="useNewMembershipManager"
id="showConnectionStats"
type="checkbox"
label={t("developer_mode.use_new_membership_manager")}
checked={!!useNewMembershipManager}
label={t("developer_mode.show_connection_stats")}
checked={!!showConnectionStats}
onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
setNewMembershipManager(event.target.checked);
setShowConnectionStats(event.target.checked);
},
[setNewMembershipManager],
[setShowConnectionStats],
)}
/>
</FieldRow>
Expand Down
10 changes: 5 additions & 5 deletions src/settings/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ 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 Expand Up @@ -119,11 +124,6 @@ export const soundEffectVolume = new Setting<number>(
0.5,
);

export const useNewMembershipManager = new Setting<boolean>(
"new-membership-manager",
true,
);

export const useExperimentalToDeviceTransport = new Setting<boolean>(
"experimental-to-device-transport",
true,
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7537,7 +7537,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=develop"
matrix-js-sdk: "github:matrix-org/matrix-js-sdk#d8feffd190ae834f050f5e709ae00ad7a24aced9"
matrix-widget-api: "npm:^1.13.0"
normalize.css: "npm:^8.0.1"
observable-hooks: "npm:^4.2.3"
Expand Down Expand Up @@ -10297,9 +10297,9 @@ __metadata:
languageName: node
linkType: hard

"matrix-js-sdk@github:matrix-org/matrix-js-sdk#head=develop":
"matrix-js-sdk@github:matrix-org/matrix-js-sdk#d8feffd190ae834f050f5e709ae00ad7a24aced9":
version: 38.3.0
resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=41d70d0b5d3f0eba92686f8089cb329d875b26b5"
resolution: "matrix-js-sdk@https://github.com/matrix-org/matrix-js-sdk.git#commit=d8feffd190ae834f050f5e709ae00ad7a24aced9"
dependencies:
"@babel/runtime": "npm:^7.12.5"
"@matrix-org/matrix-sdk-crypto-wasm": "npm:^15.3.0"
Expand All @@ -10315,7 +10315,7 @@ __metadata:
sdp-transform: "npm:^2.14.1"
unhomoglyph: "npm:^1.0.6"
uuid: "npm:13"
checksum: 10c0/b48528fec573f3e14d1297f360a56d52d7f313da0d4cf82ab51e4c29798b86995b8a6bd72409779746e7bcf02949bc2788bffa9aba276bfb1a76dbcbe89900a0
checksum: 10c0/0a588a8c8f7fcc8b56b7c409eb74e7876dcf2d546866176c3d75c2e6a96badce39e1a7bc4712e27a16f9d20db2385e24f08b2a336f6055ab5a9d9f4b4ff399e4
languageName: node
linkType: hard

Expand Down
Loading