@@ -28,7 +28,7 @@ import { MembershipManager } from "./NewMembershipManager.ts";
28
28
import { EncryptionManager , type IEncryptionManager } from "./EncryptionManager.ts" ;
29
29
import { LegacyMembershipManager } from "./LegacyMembershipManager.ts" ;
30
30
import { logDurationSync } from "../utils.ts" ;
31
- import { type Statistics } from "./types.ts" ;
31
+ import { type Statistics , type CallNotifyType , isMyMembership } from "./types.ts" ;
32
32
import { RoomKeyTransport } from "./RoomKeyTransport.ts" ;
33
33
import type { IMembershipManager } from "./IMembershipManager.ts" ;
34
34
import {
@@ -65,6 +65,15 @@ export type MatrixRTCSessionEventHandlerMap = {
65
65
) => void ;
66
66
[ MatrixRTCSessionEvent . MembershipManagerError ] : ( error : unknown ) => void ;
67
67
} ;
68
+
69
+ export interface SessionConfig {
70
+ /**
71
+ * What kind of notification to send when starting the session.
72
+ * @default `undefined` (no notification)
73
+ */
74
+ notifyType ?: CallNotifyType ;
75
+ }
76
+
68
77
// The names follow these principles:
69
78
// - we use the technical term delay if the option is related to delayed events.
70
79
// - we use delayedLeaveEvent if the option is related to the delayed leave event.
@@ -167,7 +176,7 @@ export interface EncryptionConfig {
167
176
*/
168
177
useKeyDelay ?: number ;
169
178
}
170
- export type JoinSessionConfig = MembershipConfig & EncryptionConfig ;
179
+ export type JoinSessionConfig = SessionConfig & MembershipConfig & EncryptionConfig ;
171
180
172
181
/**
173
182
* A MatrixRTCSession manages the membership & properties of a MatrixRTC session.
@@ -181,7 +190,15 @@ export class MatrixRTCSession extends TypedEventEmitter<
181
190
private encryptionManager ?: IEncryptionManager ;
182
191
// The session Id of the call, this is the call_id of the call Member event.
183
192
private _callId : string | undefined ;
193
+ private joinConfig ?: SessionConfig ;
184
194
private logger : Logger ;
195
+
196
+ /**
197
+ * Whether we're trying to join the session but still waiting for room state
198
+ * to reflect our own membership.
199
+ */
200
+ private joining = false ;
201
+
185
202
/**
186
203
* This timeout is responsible to track any expiration. We need to know when we have to start
187
204
* to ignore other call members. There is no callback for this. This timeout will always be configured to
@@ -429,6 +446,11 @@ export class MatrixRTCSession extends TypedEventEmitter<
429
446
) ;
430
447
}
431
448
449
+ this . joinConfig = joinConfig ;
450
+ const userId = this . client . getUserId ( ) ! ;
451
+ const deviceId = this . client . getDeviceId ( ) ! ;
452
+ this . joining = ! this . memberships . some ( ( m ) => isMyMembership ( m , userId , deviceId ) ) ;
453
+
432
454
// Join!
433
455
this . membershipManager ! . join ( fociPreferred , fociActive , ( e ) => {
434
456
this . logger . error ( "MembershipManager encountered an unrecoverable error: " , e ) ;
@@ -458,11 +480,11 @@ export class MatrixRTCSession extends TypedEventEmitter<
458
480
459
481
this . logger . info ( `Leaving call session in room ${ this . roomSubset . roomId } ` ) ;
460
482
483
+ this . joining = false ;
461
484
this . encryptionManager ! . leave ( ) ;
462
-
463
485
const leavePromise = this . membershipManager ! . leave ( timeout ) ;
464
- this . emit ( MatrixRTCSessionEvent . JoinStateChanged , false ) ;
465
486
487
+ this . emit ( MatrixRTCSessionEvent . JoinStateChanged , false ) ;
466
488
return await leavePromise ;
467
489
}
468
490
@@ -545,6 +567,22 @@ export class MatrixRTCSession extends TypedEventEmitter<
545
567
}
546
568
}
547
569
570
+ /**
571
+ * Sends a notification corresponding to the configured notify type.
572
+ */
573
+ private sendCallNotify ( ) : void {
574
+ if ( this . joinConfig ?. notifyType !== undefined ) {
575
+ this . client
576
+ . sendEvent ( this . roomSubset . roomId , EventType . CallNotify , {
577
+ "application" : "m.call" ,
578
+ "m.mentions" : { user_ids : [ ] , room : true } ,
579
+ "notify_type" : this . joinConfig . notifyType ,
580
+ "call_id" : this . callId ! ,
581
+ } )
582
+ . catch ( ( e ) => this . logger . error ( "Failed to send call notification" , e ) ) ;
583
+ }
584
+ }
585
+
548
586
/**
549
587
* Call this when the Matrix room members have changed.
550
588
*/
@@ -583,6 +621,15 @@ export class MatrixRTCSession extends TypedEventEmitter<
583
621
} ) ;
584
622
585
623
void this . membershipManager ?. onRTCSessionMemberUpdate ( this . memberships ) ;
624
+
625
+ const userId = this . client . getUserId ( ) ! ;
626
+ const deviceId = this . client . getDeviceId ( ) ! ;
627
+ if ( this . joining && this . memberships . some ( ( m ) => isMyMembership ( m , userId , deviceId ) ) ) {
628
+ this . joining = false ;
629
+ // If we're the first member in the call, we're responsible for
630
+ // sending the notification event
631
+ if ( oldMemberships . length === 0 ) this . sendCallNotify ( ) ;
632
+ }
586
633
}
587
634
// This also needs to be done if `changed` = false
588
635
// A member might have updated their fingerprint (created_ts)
0 commit comments