diff --git a/src/Notifier.ts b/src/Notifier.ts index aa68b386a3..e502585df3 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -25,7 +25,11 @@ import { } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { type PermissionChanged as PermissionChangedEvent } from "@matrix-org/analytics-events/types/typescript/PermissionChanged"; -import { type IRTCNotificationContent, MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc"; +import { + DefaultCallApplicationSlot, + type IRTCNotificationContent, + MatrixRTCSession, +} from "matrix-js-sdk/src/matrixrtc"; import { MatrixClientPeg } from "./MatrixClientPeg"; import { PosthogAnalytics } from "./PosthogAnalytics"; @@ -487,7 +491,10 @@ class NotifierClass extends TypedEventEmitter m.sender === cli.getUserId()); + room && + MatrixRTCSession.sessionMembershipsForSlot(room, DefaultCallApplicationSlot).some( + (m) => m.sender === cli.getUserId(), + ); if (EventType.RTCNotification === ev.getType() && !thisUserHasConnectedDevice) { const content = ev.getContent() as IRTCNotificationContent; diff --git a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index a7e0e3755b..82f01d1525 100644 --- a/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -296,8 +296,12 @@ export default class RolesRoomSettingsTab extends React.Component { + const slotId = slotDescriptionToId({id: "", application: "m.call"}); const [maySendSlot, hasRoomSlot] = useRoomState(room, () => [ - room.currentState.mayClientSendStateEvent("org.matrix.msc4143.rtc.slot", room.client), + room.currentState.mayClientSendStateEvent(EventType.RTCSlot, room.client), // TODO: Replace with proper const - room.currentState.getStateEvents("org.matrix.msc4143.rtc.slot", "m.call#ROOM")?.getContent()?.application?.type === 'm.call', + room.currentState.getStateEvents(EventType.RTCSlot, slotId)?.getContent().application.type === DefaultCallApplicationSlot.application.type, ]); // TODO: Check that we are allowed to create audio/video calls, when the telephony PR lands. @@ -109,17 +112,14 @@ const useSlotsCallPermissions = ( return false; } await room.client.sendStateEvent(room.roomId, "org.matrix.msc4143.rtc.slot", { - "application": { - "type": "m.call", - // m.call.id is not specified here, as we want this slot to be general purpose - } - }, "m.call#ROOM"); + "application": DefaultCallApplicationSlot.application + }, slotId); return true; }, [room, hasRoomSlot]); const removeElementCallSlot = useCallback(async (): Promise => { if (hasRoomSlot) { - await room.client.sendStateEvent(room.roomId, "org.matrix.msc4143.rtc.slot", { }, "m.call#ROOM"); + await room.client.sendStateEvent(room.roomId, "org.matrix.msc4143.rtc.slot", { }, slotId); } }, [room, hasRoomSlot]); @@ -142,6 +142,6 @@ export function useElementCallPermissions (room: Room | LocalRoom): ElementCallP // We load both, to avoid conditional hook rendering on settings change. const slotsPerms = useSlotsCallPermissions(room); const legacyPerms = useLegacyCallPermissions(room); - const isMSC4354Enabled = useFeatureEnabled("feature_element_call_msc4354"); + const isMSC4354Enabled = useFeatureEnabled("feature_element_call_nextgen"); return isMSC4354Enabled ? slotsPerms : legacyPerms; } \ No newline at end of file diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index e6acd0129c..c2048f8b17 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1500,8 +1500,8 @@ "experimental_description": "Feeling experimental? Try out our latest ideas in development. These features are not finalised; they may be unstable, may change, or may be dropped altogether. Learn more.", "experimental_section": "Early previews", "extended_profiles_msc_support": "Requires your server to support MSC4133", - "feature_element_call_msc4354": "Use sticky events for Element Call", - "feature_element_call_msc4354_msc_support": "Requires your server to support MSC4354 (Sticky Events)", + "feature_element_call_nextgen": "Enable MultiSFU support for Element Call", + "feature_element_call_nextgen_msc_support": "Requires your server to support MSC4354 (Sticky Events)", "feature_disable_call_per_sender_encryption": "Disable per-sender encryption for Element Call", "feature_wysiwyg_composer_description": "Use rich text instead of Markdown in the message composer.", "group_calls": "New group call experience", @@ -2369,6 +2369,7 @@ "m.room.tombstone": "Upgrade the room", "m.room.topic": "Change topic", "m.room.topic_space": "Change description", + "m.rtc.slot": "Enable or disable %(brand)s calls", "m.space.child": "Manage rooms in this space", "m.widget": "Modify widgets", "muted_users_section": "Muted Users", diff --git a/src/models/Call.ts b/src/models/Call.ts index 9d483e7af7..e66ef55192 100644 --- a/src/models/Call.ts +++ b/src/models/Call.ts @@ -709,8 +709,8 @@ export class ElementCall extends Call { params.append("allowVoipWithNoMedia", "true"); } - if (SettingsStore.getValue("feature_element_call_msc4354")) { - params.append("preferStickyEvents", "true"); + if (SettingsStore.getValue("feature_element_call_nextgen")) { + params.append("multiSFU", "true"); } // Set custom fonts diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 158c6794ee..c69ba07579 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -222,7 +222,7 @@ export interface Settings { "feature_sliding_sync": IBaseSetting; "feature_simplified_sliding_sync": IFeature; "feature_element_call_video_rooms": IFeature; - "feature_element_call_msc4354": IFeature; + "feature_element_call_nextgen": IFeature; "feature_group_calls": IFeature; "feature_disable_call_per_sender_encryption": IFeature; "feature_allow_screen_share_only_mode": IFeature; @@ -630,18 +630,18 @@ export const SETTINGS: Settings = { controller: new ReloadOnChangeController(), default: false, }, - "feature_element_call_msc4354": { + "feature_element_call_nextgen": { isFeature: true, labsGroup: LabGroup.VoiceAndVideo, supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED, supportedLevelsAreOrdered: true, - displayName: _td("labs|feature_element_call_msc4354"), + displayName: _td("labs|feature_element_call_nextgen"), controller: new ServerSupportUnstableFeatureController( - "feature_element_call_msc4354", + "feature_element_call_nextgen", defaultWatchManager, [[UNSTABLE_MSC4354_STICKY_EVENTS]], undefined, - _td("labs|feature_element_call_msc4354_msc_support"), + _td("labs|feature_element_call_nextgen_msc_support"), false, ), default: false, diff --git a/test/unit-tests/Notifier-test.ts b/test/unit-tests/Notifier-test.ts index 5ff4b0bf77..87c724b114 100644 --- a/test/unit-tests/Notifier-test.ts +++ b/test/unit-tests/Notifier-test.ts @@ -433,7 +433,7 @@ describe("Notifier", () => { }); it("should not show toast when group call is already connected", () => { - const spyCallMemberships = jest.spyOn(MatrixRTCSession, "callMembershipsForRoom").mockReturnValue([ + const spyCallMemberships = jest.spyOn(MatrixRTCSession, "sessionMembershipsForSlot").mockReturnValue([ new CallMembership( mkEvent({ event: true, diff --git a/test/unit-tests/createRoom-test.ts b/test/unit-tests/createRoom-test.ts index 06fb43cb4c..133b47b985 100644 --- a/test/unit-tests/createRoom-test.ts +++ b/test/unit-tests/createRoom-test.ts @@ -125,7 +125,7 @@ describe("createRoom", () => { it("sets up Element video rooms correctly", async () => { const userId = client.getUserId()!; const createCallSpy = jest.spyOn(ElementCall, "create"); - const callMembershipSpy = jest.spyOn(MatrixRTCSession, "callMembershipsForRoom"); + const callMembershipSpy = jest.spyOn(MatrixRTCSession, "sessionMembershipsForSlot"); callMembershipSpy.mockReturnValue([]); const roomId = await createRoom(client, { roomType: RoomType.UnstableCall }); diff --git a/test/unit-tests/models/Call-test.ts b/test/unit-tests/models/Call-test.ts index 5d83aa335d..1f441da4b5 100644 --- a/test/unit-tests/models/Call-test.ts +++ b/test/unit-tests/models/Call-test.ts @@ -25,6 +25,7 @@ import { MatrixRTCSessionManagerEvents, MatrixRTCSession, MatrixRTCSessionEvent, + DefaultCallApplicationSlot, } from "matrix-js-sdk/src/matrixrtc"; import type { Mocked } from "jest-mock"; @@ -933,8 +934,8 @@ describe("ElementCall", () => { setRoomMembers(["@user:example.com", "@user2:example.com", "@user4:example.com"]); }); it("don't sent notify event if there are existing room call members", async () => { - jest.spyOn(MatrixRTCSession, "callMembershipsForRoom").mockReturnValue([ - { application: "m.call", callId: "" } as unknown as CallMembership, + jest.spyOn(MatrixRTCSession, "sessionMembershipsForSlot").mockReturnValue([ + DefaultCallApplicationSlot as unknown as CallMembership, ]); const sendEventSpy = jest.spyOn(room.client, "sendEvent"); ElementCall.create(room);