瀏覽代碼

feat(silent): track if participant joined without audio (#2534)

* feat(silent): track if participant joined without audio

* Fix failing tests, use jitsi.org namespace

---------

Co-authored-by: Дамян Минков <damencho@jitsi.org>
release-8443
Nathan Beck 1 年之前
父節點
當前提交
fc115be599
沒有連結到貢獻者的電子郵件帳戶。

+ 28
- 0
JitsiConference.js 查看文件

@@ -1052,6 +1052,19 @@ JitsiConference.prototype.setDisplayName = function(name) {
1052 1052
     }
1053 1053
 };
1054 1054
 
1055
+/**
1056
+ * Set join without audio
1057
+ * @param silent whether user joined without audio
1058
+ */
1059
+JitsiConference.prototype.setIsSilent = function(silent) {
1060
+    if (this.room) {
1061
+        this.room.addOrReplaceInPresence('silent', {
1062
+            attributes: { xmlns: 'http://jitsi.org/protocol/silent' },
1063
+            value: silent
1064
+        }) && this.room.sendPresence();
1065
+    }
1066
+};
1067
+
1055 1068
 /**
1056 1069
  * Set new subject for this conference. (available only for moderator)
1057 1070
  * @param {string} subject new subject
@@ -1997,6 +2010,21 @@ JitsiConference.prototype.onDisplayNameChanged = function(jid, displayName) {
1997 2010
         displayName);
1998 2011
 };
1999 2012
 
2013
+JitsiConference.prototype.onSilentStatusChanged = function(jid, isSilent) {
2014
+    const id = Strophe.getResourceFromJid(jid);
2015
+    const participant = this.getParticipantById(id);
2016
+
2017
+    if (!participant) {
2018
+        return;
2019
+    }
2020
+
2021
+    participant.setIsSilent(isSilent);
2022
+    this.eventEmitter.emit(
2023
+        JitsiConferenceEvents.SILENT_STATUS_CHANGED,
2024
+        id,
2025
+        isSilent);
2026
+};
2027
+
2000 2028
 /**
2001 2029
  * Notifies this JitsiConference that a JitsiRemoteTrack was added to the conference.
2002 2030
  *

+ 3
- 0
JitsiConferenceEventManager.js 查看文件

@@ -345,6 +345,9 @@ JitsiConferenceEventManager.prototype.setupChatRoomListeners = function() {
345 345
     chatRoom.addListener(XMPPEvents.DISPLAY_NAME_CHANGED,
346 346
         conference.onDisplayNameChanged.bind(conference));
347 347
 
348
+    chatRoom.addListener(XMPPEvents.SILENT_STATUS_CHANGED,
349
+        conference.onSilentStatusChanged.bind(conference));
350
+
348 351
     chatRoom.addListener(XMPPEvents.LOCAL_ROLE_CHANGED, role => {
349 352
         conference.onLocalRoleChanged(role);
350 353
     });

+ 3
- 0
JitsiConferenceEvents.spec.ts 查看文件

@@ -85,6 +85,7 @@ describe( "/JitsiConferenceEvents members", () => {
85 85
         BREAKOUT_ROOMS_MOVE_TO_ROOM,
86 86
         BREAKOUT_ROOMS_UPDATED,
87 87
         METADATA_UPDATED,
88
+        SILENT_STATUS_CHANGED,
88 89
         JitsiConferenceEvents,
89 90
         ...others
90 91
     } = exported;
@@ -167,6 +168,7 @@ describe( "/JitsiConferenceEvents members", () => {
167 168
         expect( BREAKOUT_ROOMS_MOVE_TO_ROOM ).toBe( 'conference.breakout-rooms.move-to-room' );
168 169
         expect( BREAKOUT_ROOMS_UPDATED ).toBe( 'conference.breakout-rooms.updated' );
169 170
         expect( METADATA_UPDATED ).toBe( 'conference.metadata.updated' );
171
+        expect( SILENT_STATUS_CHANGED ).toBe( 'conference.silentStatusChanged' );
170 172
         expect( ENCODE_TIME_STATS_RECEIVED ).toBe( 'conference.encode_time_stats_received' );
171 173
 
172 174
         expect( JitsiConferenceEvents ).toBeDefined();
@@ -245,6 +247,7 @@ describe( "/JitsiConferenceEvents members", () => {
245 247
         expect( JitsiConferenceEvents.BREAKOUT_ROOMS_MOVE_TO_ROOM ).toBe( 'conference.breakout-rooms.move-to-room' );
246 248
         expect( JitsiConferenceEvents.BREAKOUT_ROOMS_UPDATED ).toBe( 'conference.breakout-rooms.updated' );
247 249
         expect( JitsiConferenceEvents.METADATA_UPDATED ).toBe( 'conference.metadata.updated' );
250
+        expect( JitsiConferenceEvents.SILENT_STATUS_CHANGED ).toBe( 'conference.silentStatusChanged' );
248 251
         expect( JitsiConferenceEvents.E2EE_VERIFICATION_READY ).toBe( 'conference.e2ee.verification.ready' );
249 252
         expect( JitsiConferenceEvents.E2EE_VERIFICATION_COMPLETED ).toBe( 'conference.e2ee.verification.completed' );
250 253
         expect( JitsiConferenceEvents.E2EE_VERIFICATION_AVAILABLE ).toBe( 'conference.e2ee.verification.available' );

+ 6
- 0
JitsiConferenceEvents.ts 查看文件

@@ -363,6 +363,11 @@ export enum JitsiConferenceEvents {
363 363
      */
364 364
     SERVER_REGION_CHANGED = 'conference.server_region_changed',
365 365
 
366
+    /**
367
+     * Indicates a user has joined without audio
368
+     */
369
+    SILENT_STATUS_CHANGED = 'conference.silentStatusChanged',
370
+
366 371
     /**
367 372
      * Indicates that start muted settings changed.
368 373
      */
@@ -550,6 +555,7 @@ export const PHONE_NUMBER_CHANGED = JitsiConferenceEvents.PHONE_NUMBER_CHANGED;
550 555
 export const PROPERTIES_CHANGED = JitsiConferenceEvents.PROPERTIES_CHANGED;
551 556
 export const RECORDER_STATE_CHANGED = JitsiConferenceEvents.RECORDER_STATE_CHANGED;
552 557
 export const SERVER_REGION_CHANGED = JitsiConferenceEvents.SERVER_REGION_CHANGED;
558
+export const SILENT_STATUS_CHANGED = JitsiConferenceEvents.SILENT_STATUS_CHANGED;
553 559
 export const START_MUTED_POLICY_CHANGED = JitsiConferenceEvents.START_MUTED_POLICY_CHANGED;
554 560
 export const STARTED_MUTED = JitsiConferenceEvents.STARTED_MUTED;
555 561
 export const SUBJECT_CHANGED = JitsiConferenceEvents.SUBJECT_CHANGED;

+ 18
- 1
JitsiParticipant.js 查看文件

@@ -26,8 +26,9 @@ export default class JitsiParticipant {
26 26
      * @param {object} identity - the xmpp identity
27 27
      * @param {boolean?} isReplacing - whether this is a participant replacing another into the meeting.
28 28
      * @param {boolean?} isReplaced - whether this is a participant to be kicked and replaced into the meeting.
29
+     * @param {boolean?} isSilent - whether participant has joined without audio
29 30
      */
30
-    constructor(jid, conference, displayName, hidden, statsID, status, identity, isReplacing, isReplaced) {
31
+    constructor(jid, conference, displayName, hidden, statsID, status, identity, isReplacing, isReplaced, isSilent) {
31 32
         this._jid = jid;
32 33
         this._id = Strophe.getResourceFromJid(jid);
33 34
         this._conference = conference;
@@ -42,6 +43,7 @@ export default class JitsiParticipant {
42 43
         this._identity = identity;
43 44
         this._isReplacing = isReplacing;
44 45
         this._isReplaced = isReplaced;
46
+        this._isSilent = isSilent;
45 47
         this._features = new Set();
46 48
 
47 49
         /**
@@ -276,6 +278,13 @@ export default class JitsiParticipant {
276 278
         return this._isReplacing;
277 279
     }
278 280
 
281
+    /**
282
+     * @returns {Boolean} Whether this participant has joined without audio.
283
+     */
284
+    isSilent() {
285
+        return this._isSilent;
286
+    }
287
+
279 288
     /**
280 289
      * @returns {Boolean} Whether this participant has muted their video.
281 290
      */
@@ -323,6 +332,14 @@ export default class JitsiParticipant {
323 332
         this._isReplacing = newIsReplacing;
324 333
     }
325 334
 
335
+    /**
336
+     * Sets whether participant has joined without audio.
337
+     * @param {boolean} newIsSilent - whether is silent.
338
+     */
339
+    setIsSilent(newIsSilent) {
340
+        this._isSilent = newIsSilent;
341
+    }
342
+
326 343
     /**
327 344
      * Sets the value of a property of this participant, and fires an event if
328 345
      * the value has changed.

+ 16
- 1
modules/xmpp/ChatRoom.js 查看文件

@@ -583,6 +583,9 @@ export default class ChatRoom extends Listenable {
583 583
             case 'nick':
584 584
                 member.nick = node.value;
585 585
                 break;
586
+            case 'silent':
587
+                member.isSilent = node.value;
588
+                break;
586 589
             case 'userId':
587 590
                 member.id = node.value;
588 591
                 break;
@@ -685,7 +688,8 @@ export default class ChatRoom extends Listenable {
685 688
                     member.botType,
686 689
                     member.jid,
687 690
                     member.features,
688
-                    member.isReplaceParticipant);
691
+                    member.isReplaceParticipant,
692
+                    member.isSilent);
689 693
 
690 694
                 // we are reporting the status with the join
691 695
                 // so we do not want a second event about status update
@@ -740,6 +744,11 @@ export default class ChatRoom extends Listenable {
740 744
                 memberOfThis.displayName = member.displayName;
741 745
             }
742 746
 
747
+            // join without audio
748
+            if (member.isSilent) {
749
+                memberOfThis.isSilent = member.isSilent;
750
+            }
751
+
743 752
             // update stored status message to be able to detect changes
744 753
             if (memberOfThis.status !== member.status) {
745 754
                 hasStatusUpdate = true;
@@ -776,6 +785,12 @@ export default class ChatRoom extends Listenable {
776 785
                         displayName);
777 786
                 }
778 787
                 break;
788
+            case 'silent':
789
+                this.eventEmitter.emit(
790
+                    XMPPEvents.SILENT_STATUS_CHANGED,
791
+                    from,
792
+                    member.isSilent);
793
+                break;
779 794
             case 'bridgeNotAvailable':
780 795
                 if (member.isFocus && !this.noBridgeAvailable) {
781 796
                     this.noBridgeAvailable = true;

+ 10
- 5
modules/xmpp/ChatRoom.spec.js 查看文件

@@ -185,7 +185,8 @@ describe('ChatRoom', () => {
185 185
                 undefined,
186 186
                 'fulljid',
187 187
                 undefined, // features
188
-                0 // isReplaceParticipant
188
+                0, // isReplaceParticipant
189
+                undefined // isSilent
189 190
             ]);
190 191
         });
191 192
 
@@ -220,7 +221,8 @@ describe('ChatRoom', () => {
220 221
                 undefined,
221 222
                 'jid=attr',
222 223
                 undefined, // features
223
-                0); // isReplaceParticipant
224
+                0, // isReplaceParticipant
225
+                undefined); // isSilent
224 226
         });
225 227
 
226 228
         it('parses muc user replacing other user correctly', () => {
@@ -254,7 +256,8 @@ describe('ChatRoom', () => {
254 256
               undefined,
255 257
               'jid=attr',
256 258
               undefined, // features
257
-              1); // isReplaceParticipant
259
+              1, // isReplaceParticipant
260
+              undefined); // isSilent
258 261
         });
259 262
 
260 263
         it('parses identity correctly', () => {
@@ -305,7 +308,8 @@ describe('ChatRoom', () => {
305 308
                 undefined,
306 309
                 'fulljid',
307 310
                 undefined, // features
308
-                0 // isReplaceParticipant
311
+                0, // isReplaceParticipant
312
+                undefined // isSilent
309 313
             ]);
310 314
         });
311 315
 
@@ -342,7 +346,8 @@ describe('ChatRoom', () => {
342 346
                 expectedBotType,
343 347
                 'fulljid',
344 348
                 undefined, // features
345
-                0 // isReplaceParticipant
349
+                0, // isReplaceParticipant
350
+                undefined // isSilent
346 351
             ]);
347 352
         });
348 353
 

+ 5
- 0
service/xmpp/XMPPEvents.ts 查看文件

@@ -266,6 +266,11 @@ export enum XMPPEvents {
266 266
      */
267 267
     SESSION_ACCEPT_TIMEOUT = 'xmpp.session_accept_timeout',
268 268
 
269
+    /**
270
+     * Event fired when participant joins a meeting without audio.
271
+     */
272
+    SILENT_STATUS_CHANGED = 'xmpp.silent_status_changed',
273
+
269 274
     /**
270 275
      * Event fired after successful sending of jingle source-add.
271 276
      */

Loading…
取消
儲存