You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-11-23 17:02:25 +03:00
Make a MatrixRTCSession emit once the RTCNotification is sent (#4976)
* MatrixRTCSession emits once the rtc notification is sent. Signed-off-by: Timo K <toger5@hotmail.de> * update correct type description Signed-off-by: Timo K <toger5@hotmail.de> * Add test Signed-off-by: Timo K <toger5@hotmail.de> * fix imports Signed-off-by: Timo K <toger5@hotmail.de> --------- Signed-off-by: Timo K <toger5@hotmail.de>
This commit is contained in:
@@ -309,8 +309,19 @@ describe("MatrixRTCSession", () => {
|
|||||||
expect(sess!.isJoined()).toEqual(true);
|
expect(sess!.isJoined()).toEqual(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("sends a notification when starting a call", async () => {
|
it("sends a notification when starting a call and emit DidSendCallNotification", async () => {
|
||||||
// Simulate a join, including the update to the room state
|
// Simulate a join, including the update to the room state
|
||||||
|
// Ensure sendEvent returns event IDs so the DidSendCallNotification payload includes them
|
||||||
|
sendEventMock
|
||||||
|
.mockResolvedValueOnce({ event_id: "legacy-evt" })
|
||||||
|
.mockResolvedValueOnce({ event_id: "new-evt" });
|
||||||
|
const didSendEventFn = jest.fn();
|
||||||
|
sess!.once(MatrixRTCSessionEvent.DidSendCallNotification, didSendEventFn);
|
||||||
|
// Create an additional listener to create a promise that resolves after the emission.
|
||||||
|
const didSendNotification = new Promise((resolve) => {
|
||||||
|
sess!.once(MatrixRTCSessionEvent.DidSendCallNotification, resolve);
|
||||||
|
});
|
||||||
|
|
||||||
sess!.joinRoomSession([mockFocus], mockFocus, { notificationType: "ring" });
|
sess!.joinRoomSession([mockFocus], mockFocus, { notificationType: "ring" });
|
||||||
await Promise.race([sentStateEvent, new Promise((resolve) => setTimeout(resolve, 5000))]);
|
await Promise.race([sentStateEvent, new Promise((resolve) => setTimeout(resolve, 5000))]);
|
||||||
mockRoomState(mockRoom, [{ ...membershipTemplate, user_id: client.getUserId()! }]);
|
mockRoomState(mockRoom, [{ ...membershipTemplate, user_id: client.getUserId()! }]);
|
||||||
@@ -335,6 +346,28 @@ describe("MatrixRTCSession", () => {
|
|||||||
"notify_type": "ring",
|
"notify_type": "ring",
|
||||||
"call_id": "",
|
"call_id": "",
|
||||||
});
|
});
|
||||||
|
await didSendNotification;
|
||||||
|
// And ensure we emitted the DidSendCallNotification event with both payloads
|
||||||
|
expect(didSendEventFn).toHaveBeenCalledWith(
|
||||||
|
{
|
||||||
|
"event_id": "new-evt",
|
||||||
|
"lifetime": 30000,
|
||||||
|
"m.mentions": { room: true, user_ids: [] },
|
||||||
|
"m.relates_to": {
|
||||||
|
event_id: expect.any(String),
|
||||||
|
rel_type: "org.matrix.msc4075.rtc.notification.parent",
|
||||||
|
},
|
||||||
|
"notification_type": "ring",
|
||||||
|
"sender_ts": expect.any(Number),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"application": "m.call",
|
||||||
|
"call_id": "",
|
||||||
|
"event_id": "legacy-evt",
|
||||||
|
"m.mentions": { room: true, user_ids: [] },
|
||||||
|
"notify_type": "ring",
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("doesn't send a notification when joining an existing call", async () => {
|
it("doesn't send a notification when joining an existing call", async () => {
|
||||||
|
|||||||
@@ -20,14 +20,21 @@ import { EventTimeline } from "../models/event-timeline.ts";
|
|||||||
import { type Room } from "../models/room.ts";
|
import { type Room } from "../models/room.ts";
|
||||||
import { type MatrixClient } from "../client.ts";
|
import { type MatrixClient } from "../client.ts";
|
||||||
import { EventType, RelationType } from "../@types/event.ts";
|
import { EventType, RelationType } from "../@types/event.ts";
|
||||||
|
import { KnownMembership } from "../@types/membership.ts";
|
||||||
|
import { type ISendEventResponse } from "../@types/requests.ts";
|
||||||
import { CallMembership } from "./CallMembership.ts";
|
import { CallMembership } from "./CallMembership.ts";
|
||||||
import { RoomStateEvent } from "../models/room-state.ts";
|
import { RoomStateEvent } from "../models/room-state.ts";
|
||||||
import { type Focus } from "./focus.ts";
|
import { type Focus } from "./focus.ts";
|
||||||
import { KnownMembership } from "../@types/membership.ts";
|
|
||||||
import { MembershipManager } from "./MembershipManager.ts";
|
import { MembershipManager } from "./MembershipManager.ts";
|
||||||
import { EncryptionManager, type IEncryptionManager } from "./EncryptionManager.ts";
|
import { EncryptionManager, type IEncryptionManager } from "./EncryptionManager.ts";
|
||||||
import { deepCompare, logDurationSync } from "../utils.ts";
|
import { deepCompare, logDurationSync } from "../utils.ts";
|
||||||
import { type Statistics, type RTCNotificationType, type Status } from "./types.ts";
|
import {
|
||||||
|
type Statistics,
|
||||||
|
type RTCNotificationType,
|
||||||
|
type Status,
|
||||||
|
type IRTCNotificationContent,
|
||||||
|
type ICallNotifyContent,
|
||||||
|
} from "./types.ts";
|
||||||
import { RoomKeyTransport } from "./RoomKeyTransport.ts";
|
import { RoomKeyTransport } from "./RoomKeyTransport.ts";
|
||||||
import {
|
import {
|
||||||
MembershipManagerEvent,
|
MembershipManagerEvent,
|
||||||
@@ -43,6 +50,9 @@ import {
|
|||||||
import { TypedReEmitter } from "../ReEmitter.ts";
|
import { TypedReEmitter } from "../ReEmitter.ts";
|
||||||
import { ToDeviceKeyTransport } from "./ToDeviceKeyTransport.ts";
|
import { ToDeviceKeyTransport } from "./ToDeviceKeyTransport.ts";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Events emitted by MatrixRTCSession
|
||||||
|
*/
|
||||||
export enum MatrixRTCSessionEvent {
|
export enum MatrixRTCSessionEvent {
|
||||||
// A member joined, left, or updated a property of their membership.
|
// A member joined, left, or updated a property of their membership.
|
||||||
MembershipsChanged = "memberships_changed",
|
MembershipsChanged = "memberships_changed",
|
||||||
@@ -54,6 +64,8 @@ export enum MatrixRTCSessionEvent {
|
|||||||
EncryptionKeyChanged = "encryption_key_changed",
|
EncryptionKeyChanged = "encryption_key_changed",
|
||||||
/** The membership manager had to shut down caused by an unrecoverable error */
|
/** The membership manager had to shut down caused by an unrecoverable error */
|
||||||
MembershipManagerError = "membership_manager_error",
|
MembershipManagerError = "membership_manager_error",
|
||||||
|
/** The RTCSession did send a call notification caused by joining the call as the first member */
|
||||||
|
DidSendCallNotification = "did_send_call_notification",
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MatrixRTCSessionEventHandlerMap = {
|
export type MatrixRTCSessionEventHandlerMap = {
|
||||||
@@ -68,6 +80,10 @@ export type MatrixRTCSessionEventHandlerMap = {
|
|||||||
participantId: string,
|
participantId: string,
|
||||||
) => void;
|
) => void;
|
||||||
[MatrixRTCSessionEvent.MembershipManagerError]: (error: unknown) => void;
|
[MatrixRTCSessionEvent.MembershipManagerError]: (error: unknown) => void;
|
||||||
|
[MatrixRTCSessionEvent.DidSendCallNotification]: (
|
||||||
|
notificationContentNew: { event_id: string } & IRTCNotificationContent,
|
||||||
|
notificationContentLegacy: { event_id: string } & ICallNotifyContent,
|
||||||
|
) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface SessionConfig {
|
export interface SessionConfig {
|
||||||
@@ -652,19 +668,24 @@ export class MatrixRTCSession extends TypedEventEmitter<
|
|||||||
* Sends a notification corresponding to the configured notify type.
|
* Sends a notification corresponding to the configured notify type.
|
||||||
*/
|
*/
|
||||||
private sendCallNotify(parentEventId: string, notificationType: RTCNotificationType): void {
|
private sendCallNotify(parentEventId: string, notificationType: RTCNotificationType): void {
|
||||||
// Send legacy event:
|
const sendLegacyNotificationEvent = async (): Promise<{
|
||||||
this.client
|
response: ISendEventResponse;
|
||||||
.sendEvent(this.roomSubset.roomId, EventType.CallNotify, {
|
content: ICallNotifyContent;
|
||||||
|
}> => {
|
||||||
|
const content: ICallNotifyContent = {
|
||||||
"application": "m.call",
|
"application": "m.call",
|
||||||
"m.mentions": { user_ids: [], room: true },
|
"m.mentions": { user_ids: [], room: true },
|
||||||
"notify_type": notificationType === "notification" ? "notify" : notificationType,
|
"notify_type": notificationType === "notification" ? "notify" : notificationType,
|
||||||
"call_id": this.callId!,
|
"call_id": this.callId!,
|
||||||
})
|
};
|
||||||
.catch((e) => this.logger.error("Failed to send call notification", e));
|
const response = await this.client.sendEvent(this.roomSubset.roomId, EventType.CallNotify, content);
|
||||||
|
return { response, content };
|
||||||
// Send new event:
|
};
|
||||||
this.client
|
const sendNewNotificationEvent = async (): Promise<{
|
||||||
.sendEvent(this.roomSubset.roomId, EventType.RTCNotification, {
|
response: ISendEventResponse;
|
||||||
|
content: IRTCNotificationContent;
|
||||||
|
}> => {
|
||||||
|
const content: IRTCNotificationContent = {
|
||||||
"m.mentions": { user_ids: [], room: true },
|
"m.mentions": { user_ids: [], room: true },
|
||||||
"notification_type": notificationType,
|
"notification_type": notificationType,
|
||||||
"m.relates_to": {
|
"m.relates_to": {
|
||||||
@@ -673,8 +694,21 @@ export class MatrixRTCSession extends TypedEventEmitter<
|
|||||||
},
|
},
|
||||||
"sender_ts": Date.now(),
|
"sender_ts": Date.now(),
|
||||||
"lifetime": 30_000, // 30 seconds
|
"lifetime": 30_000, // 30 seconds
|
||||||
|
};
|
||||||
|
const response = await this.client.sendEvent(this.roomSubset.roomId, EventType.RTCNotification, content);
|
||||||
|
return { response, content };
|
||||||
|
};
|
||||||
|
|
||||||
|
void Promise.all([sendLegacyNotificationEvent(), sendNewNotificationEvent()])
|
||||||
|
.then(([legacy, newNotification]) => {
|
||||||
|
// Join event_id and origin event content
|
||||||
|
const legacyResult = { ...legacy.response, ...legacy.content };
|
||||||
|
const newResult = { ...newNotification.response, ...newNotification.content };
|
||||||
|
this.emit(MatrixRTCSessionEvent.DidSendCallNotification, newResult, legacyResult);
|
||||||
})
|
})
|
||||||
.catch((e) => this.logger.error("Failed to send call notification", e));
|
.catch(([errorLegacy, errorNew]) =>
|
||||||
|
this.logger.error("Failed to send call notification", errorLegacy, errorNew),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user