Skip to content

Allow sending notification events when starting a call #4826

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
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
54 changes: 50 additions & 4 deletions src/matrixrtc/MatrixRTCSession.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { MembershipManager } from "./NewMembershipManager.ts";
import { EncryptionManager, type IEncryptionManager } from "./EncryptionManager.ts";
import { LegacyMembershipManager } from "./LegacyMembershipManager.ts";
import { logDurationSync } from "../utils.ts";
import { type Statistics } from "./types.ts";
import { type Statistics, type CallNotifyType, isMyMembership } from "./types.ts";
import { RoomKeyTransport } from "./RoomKeyTransport.ts";
import type { IMembershipManager } from "./IMembershipManager.ts";
import {
Expand Down Expand Up @@ -66,6 +66,14 @@ export type MatrixRTCSessionEventHandlerMap = {
[MatrixRTCSessionEvent.MembershipManagerError]: (error: unknown) => void;
};

export interface SessionConfig {
/**
* What kind of notification to send when starting the session.
* @default undefined (no notification)
*/
notifyType?: CallNotifyType;
}

export interface MembershipConfig {
/**
* Use the new Manager.
Expand Down Expand Up @@ -162,7 +170,7 @@ export interface EncryptionConfig {
*/
useKeyDelay?: number;
}
export type JoinSessionConfig = MembershipConfig & EncryptionConfig;
export type JoinSessionConfig = SessionConfig & MembershipConfig & EncryptionConfig;

/**
* A MatrixRTCSession manages the membership & properties of a MatrixRTC session.
Expand All @@ -176,7 +184,15 @@ export class MatrixRTCSession extends TypedEventEmitter<
private encryptionManager?: IEncryptionManager;
// The session Id of the call, this is the call_id of the call Member event.
private _callId: string | undefined;
private joinConfig?: SessionConfig;
private logger: Logger;

/**
* Whether we're trying to join the session but still waiting for room state
* to reflect our own membership.
*/
private joining = false;

/**
* This timeout is responsible to track any expiration. We need to know when we have to start
* to ignore other call members. There is no callback for this. This timeout will always be configured to
Expand Down Expand Up @@ -424,6 +440,11 @@ export class MatrixRTCSession extends TypedEventEmitter<
);
}

this.joinConfig = joinConfig;
const userId = this.client.getUserId()!;
const deviceId = this.client.getDeviceId()!;
this.joining = !this.memberships.some((m) => isMyMembership(m, userId, deviceId));

// Join!
this.membershipManager!.join(fociPreferred, fociActive, (e) => {
this.logger.error("MembershipManager encountered an unrecoverable error: ", e);
Expand Down Expand Up @@ -453,11 +474,11 @@ export class MatrixRTCSession extends TypedEventEmitter<

this.logger.info(`Leaving call session in room ${this.roomSubset.roomId}`);

this.joining = false;
this.encryptionManager!.leave();

const leavePromise = this.membershipManager!.leave(timeout);
this.emit(MatrixRTCSessionEvent.JoinStateChanged, false);

this.emit(MatrixRTCSessionEvent.JoinStateChanged, false);
return await leavePromise;
}

Expand Down Expand Up @@ -540,6 +561,22 @@ export class MatrixRTCSession extends TypedEventEmitter<
}
}

/**
* Sends a notification corresponding to the configured notify type.
*/
private sendCallNotify(): void {
if (this.joinConfig?.notifyType !== undefined) {
this.client
.sendEvent(this.roomSubset.roomId, EventType.CallNotify, {
"application": "m.call",
"m.mentions": { user_ids: [], room: true },
"notify_type": this.joinConfig.notifyType,
"call_id": this.callId!,
})
.catch((e) => this.logger.error("Failed to send call notification", e));
}
}

/**
* Call this when the Matrix room members have changed.
*/
Expand Down Expand Up @@ -578,6 +615,15 @@ export class MatrixRTCSession extends TypedEventEmitter<
});

void this.membershipManager?.onRTCSessionMemberUpdate(this.memberships);

const userId = this.client.getUserId()!;
const deviceId = this.client.getDeviceId()!;
if (this.joining && this.memberships.some((m) => isMyMembership(m, userId, deviceId))) {
this.joining = false;
// If we're the first member in the call, we're responsible for
// sending the notification event
if (oldMemberships.length === 0) this.sendCallNotify();
}
}
// This also needs to be done if `changed` = false
// A member might have updated their fingerprint (created_ts)
Expand Down