@webex/plugin-meetings 3.9.0-webinar5k.1 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.js +24 -0
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/index.js +22 -5
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +7 -0
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interceptors/locusRouteToken.js +116 -0
- package/dist/interceptors/locusRouteToken.js.map +1 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +11 -2
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +76 -322
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/parser.js +4 -1
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/media/properties.js +53 -5
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +14 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +467 -277
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +177 -14
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/type.js +7 -0
- package/dist/meeting/type.js.map +1 -0
- package/dist/meeting/util.js +100 -3
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +29 -21
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +20 -16
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js +9 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +10 -0
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +10 -7
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +7 -2
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +2 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -1
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +34 -5
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +42 -2
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/reachability/index.js +3 -3
- package/dist/reachability/index.js.map +1 -1
- package/dist/types/constants.d.ts +23 -0
- package/dist/types/controls-options-manager/index.d.ts +9 -1
- package/dist/types/interceptors/index.d.ts +2 -1
- package/dist/types/interceptors/locusRouteToken.d.ts +38 -0
- package/dist/types/locus-info/index.d.ts +9 -54
- package/dist/types/media/properties.d.ts +21 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +14 -0
- package/dist/types/meeting/index.d.ts +64 -29
- package/dist/types/meeting/request.d.ts +42 -0
- package/dist/types/meeting/type.d.ts +9 -0
- package/dist/types/meeting/util.d.ts +13 -0
- package/dist/types/meeting-info/meeting-info-v2.d.ts +6 -3
- package/dist/types/meetings/index.d.ts +3 -1
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/util.d.ts +5 -0
- package/dist/types/members/index.d.ts +12 -11
- package/dist/types/members/util.d.ts +8 -4
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/multistream/remoteMedia.d.ts +20 -1
- package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +25 -27
- package/src/constants.ts +26 -2
- package/src/controls-options-manager/index.ts +26 -5
- package/src/index.ts +2 -1
- package/src/interceptors/index.ts +2 -1
- package/src/interceptors/locusRouteToken.ts +80 -0
- package/src/locus-info/controlsUtils.ts +18 -0
- package/src/locus-info/index.ts +69 -357
- package/src/locus-info/parser.ts +5 -1
- package/src/media/properties.ts +43 -0
- package/src/meeting/in-meeting-actions.ts +29 -0
- package/src/meeting/index.ts +296 -87
- package/src/meeting/request.ts +141 -0
- package/src/meeting/type.ts +9 -0
- package/src/meeting/util.ts +107 -3
- package/src/meeting-info/meeting-info-v2.ts +24 -5
- package/src/meetings/index.ts +15 -22
- package/src/member/index.ts +10 -0
- package/src/member/util.ts +14 -0
- package/src/members/index.ts +20 -10
- package/src/members/util.ts +20 -3
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +7 -7
- package/src/multistream/remoteMedia.ts +34 -4
- package/src/multistream/remoteMediaGroup.ts +37 -2
- package/src/reachability/index.ts +3 -3
- package/test/unit/spec/common/browser-detection.js +0 -24
- package/test/unit/spec/controls-options-manager/index.js +47 -0
- package/test/unit/spec/fixture/locus.js +1 -0
- package/test/unit/spec/interceptors/locusRouteToken.ts +87 -0
- package/test/unit/spec/locus-info/index.js +80 -361
- package/test/unit/spec/locus-info/parser.js +3 -2
- package/test/unit/spec/media/properties.ts +137 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +14 -0
- package/test/unit/spec/meeting/index.js +637 -53
- package/test/unit/spec/meeting/muteState.js +32 -6
- package/test/unit/spec/meeting/request.js +21 -0
- package/test/unit/spec/meeting/utils.js +171 -18
- package/test/unit/spec/meeting-info/meetinginfov2.js +8 -3
- package/test/unit/spec/meetings/index.js +12 -5
- package/test/unit/spec/member/util.js +24 -0
- package/test/unit/spec/members/collection.js +120 -0
- package/test/unit/spec/members/index.js +107 -2
- package/test/unit/spec/members/request.js +55 -0
- package/test/unit/spec/members/utils.js +116 -14
- package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
- package/test/unit/spec/multistream/remoteMedia.ts +66 -2
- package/test/unit/spec/reachability/index.ts +158 -3
- package/test/unit/spec/roap/turnDiscovery.ts +3 -3
- package/dist/hashTree/constants.js +0 -23
- package/dist/hashTree/constants.js.map +0 -1
- package/dist/hashTree/hashTree.js +0 -516
- package/dist/hashTree/hashTree.js.map +0 -1
- package/dist/hashTree/hashTreeParser.js +0 -521
- package/dist/hashTree/hashTreeParser.js.map +0 -1
- package/dist/types/hashTree/constants.d.ts +0 -8
- package/dist/types/hashTree/hashTree.d.ts +0 -128
- package/dist/types/hashTree/hashTreeParser.d.ts +0 -152
- package/src/hashTree/constants.ts +0 -12
- package/src/hashTree/hashTree.ts +0 -460
- package/src/hashTree/hashTreeParser.ts +0 -556
- package/test/unit/spec/hashTree/hashTree.ts +0 -394
- package/test/unit/spec/hashTree/hashTreeParser.ts +0 -156
package/src/locus-info/index.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable class-methods-use-this */
|
|
2
1
|
import {isEqual, assignWith, cloneDeep, isEmpty, forEach} from 'lodash';
|
|
3
2
|
|
|
4
3
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
@@ -31,21 +30,6 @@ import MediaSharesUtils from './mediaSharesUtils';
|
|
|
31
30
|
import LocusDeltaParser from './parser';
|
|
32
31
|
import Metrics from '../metrics';
|
|
33
32
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
34
|
-
import HashTreeParser, {
|
|
35
|
-
DataSet,
|
|
36
|
-
HashTreeMessage,
|
|
37
|
-
HashTreeObject,
|
|
38
|
-
HtMeta,
|
|
39
|
-
LocusInfoUpdateType,
|
|
40
|
-
ObjectType,
|
|
41
|
-
} from '../hashTree/hashTreeParser';
|
|
42
|
-
|
|
43
|
-
export type LocusLLMEvent = {
|
|
44
|
-
data: {
|
|
45
|
-
eventType: 'locus.state_message';
|
|
46
|
-
stateElementsMessage: HashTreeMessage;
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
33
|
|
|
50
34
|
export type LocusDTO = {
|
|
51
35
|
controls?: any;
|
|
@@ -67,11 +51,7 @@ export type LocusDTO = {
|
|
|
67
51
|
name: string;
|
|
68
52
|
orgId: string;
|
|
69
53
|
};
|
|
70
|
-
htMeta?: HtMeta;
|
|
71
54
|
info?: any;
|
|
72
|
-
jsSdkMeta?: {
|
|
73
|
-
removedParticipantIds: string[]; // list of ids of participants that are removed in the last update
|
|
74
|
-
};
|
|
75
55
|
links?: any;
|
|
76
56
|
mediaShares?: any[];
|
|
77
57
|
meetings?: any[];
|
|
@@ -93,26 +73,9 @@ export type LocusDTO = {
|
|
|
93
73
|
};
|
|
94
74
|
|
|
95
75
|
export type LocusApiResponseBody = {
|
|
96
|
-
dataSets?: DataSet[];
|
|
97
76
|
locus: LocusDTO; // this LocusDTO here might not be the full one (for example it won't have all the participants, but it should have self)
|
|
98
77
|
};
|
|
99
78
|
|
|
100
|
-
const LocusDtoTopLevelKeys = [
|
|
101
|
-
'controls',
|
|
102
|
-
'fullState',
|
|
103
|
-
'host',
|
|
104
|
-
'info',
|
|
105
|
-
'links',
|
|
106
|
-
'mediaShares',
|
|
107
|
-
'meetings',
|
|
108
|
-
'participants',
|
|
109
|
-
'replaces',
|
|
110
|
-
'self',
|
|
111
|
-
'sequence',
|
|
112
|
-
'syncUrl',
|
|
113
|
-
'url',
|
|
114
|
-
];
|
|
115
|
-
|
|
116
79
|
/**
|
|
117
80
|
* @description LocusInfo extends ChildEmitter to convert locusInfo info a private emitter to parent object
|
|
118
81
|
* @export
|
|
@@ -130,7 +93,6 @@ export default class LocusInfo extends EventsScope {
|
|
|
130
93
|
aclUrl: any;
|
|
131
94
|
baseSequence: any;
|
|
132
95
|
created: any;
|
|
133
|
-
deltaParticipants: any;
|
|
134
96
|
identities: any;
|
|
135
97
|
membership: any;
|
|
136
98
|
participants: any;
|
|
@@ -152,9 +114,6 @@ export default class LocusInfo extends EventsScope {
|
|
|
152
114
|
resources: any;
|
|
153
115
|
mainSessionLocusCache: any;
|
|
154
116
|
self: any;
|
|
155
|
-
hashTreeParser?: HashTreeParser;
|
|
156
|
-
hashTreeObjectId2ParticipantId: Map<number, string>; // mapping of hash tree object ids to participant ids
|
|
157
|
-
|
|
158
117
|
/**
|
|
159
118
|
* Constructor
|
|
160
119
|
* @param {function} updateMeeting callback to update the meeting object from an object
|
|
@@ -173,26 +132,32 @@ export default class LocusInfo extends EventsScope {
|
|
|
173
132
|
this.meetingId = meetingId;
|
|
174
133
|
this.updateMeeting = updateMeeting;
|
|
175
134
|
this.locusParser = new LocusDeltaParser();
|
|
176
|
-
this.hashTreeObjectId2ParticipantId = new Map();
|
|
177
135
|
}
|
|
178
136
|
|
|
179
137
|
/**
|
|
180
138
|
* Does a Locus sync. It tries to get the latest delta DTO or if it can't, it falls back to getting the full Locus DTO.
|
|
181
139
|
*
|
|
182
140
|
* @param {Meeting} meeting
|
|
141
|
+
* @param {boolean} isLocusUrlChanged
|
|
142
|
+
* @param {Locus} locus
|
|
183
143
|
* @returns {undefined}
|
|
184
144
|
*/
|
|
185
|
-
private doLocusSync(meeting: any) {
|
|
186
|
-
let isDelta;
|
|
145
|
+
private doLocusSync(meeting: any, isLocusUrlChanged: boolean, locus: any) {
|
|
187
146
|
let url;
|
|
147
|
+
let isDelta = false;
|
|
188
148
|
let meetingDestroyed = false;
|
|
189
149
|
|
|
190
|
-
if (
|
|
150
|
+
if (isLocusUrlChanged) {
|
|
151
|
+
// for the locus url changed case from breakout to main session, we should always do a full sync, in this case, the url from locus is always on main session,
|
|
152
|
+
// so use the main session locus url to get the full locus(full participants list in the response).
|
|
153
|
+
// for the locus url changed case from main session to breakout, we don't need to care about it here,
|
|
154
|
+
// because it is a USE_INCOMING case, it will not be executed here.
|
|
155
|
+
url = locus.url;
|
|
156
|
+
} else if (this.locusParser.workingCopy?.syncUrl) {
|
|
191
157
|
url = this.locusParser.workingCopy.syncUrl;
|
|
192
158
|
isDelta = true;
|
|
193
159
|
} else {
|
|
194
160
|
url = meeting.locusUrl;
|
|
195
|
-
isDelta = false;
|
|
196
161
|
}
|
|
197
162
|
|
|
198
163
|
LoggerProxy.logger.info(
|
|
@@ -261,7 +226,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
261
226
|
|
|
262
227
|
if (isDelta) {
|
|
263
228
|
if (res.body.baseSequence) {
|
|
264
|
-
meeting.locusInfo.handleLocusDelta(res.body, meeting);
|
|
229
|
+
meeting.locusInfo.handleLocusDelta(res.body, meeting);
|
|
265
230
|
|
|
266
231
|
return;
|
|
267
232
|
}
|
|
@@ -304,6 +269,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
304
269
|
*/
|
|
305
270
|
applyLocusDeltaData(action: string, locus: any, meeting: any) {
|
|
306
271
|
const {DESYNC, USE_CURRENT, USE_INCOMING, WAIT, LOCUS_URL_CHANGED} = LocusDeltaParser.loci;
|
|
272
|
+
const isLocusUrlChanged = action === LOCUS_URL_CHANGED;
|
|
307
273
|
|
|
308
274
|
switch (action) {
|
|
309
275
|
case USE_INCOMING:
|
|
@@ -315,7 +281,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
315
281
|
break;
|
|
316
282
|
case DESYNC:
|
|
317
283
|
case LOCUS_URL_CHANGED:
|
|
318
|
-
this.doLocusSync(meeting);
|
|
284
|
+
this.doLocusSync(meeting, isLocusUrlChanged, locus);
|
|
319
285
|
break;
|
|
320
286
|
default:
|
|
321
287
|
LoggerProxy.logger.info(
|
|
@@ -370,17 +336,6 @@ export default class LocusInfo extends EventsScope {
|
|
|
370
336
|
* @property {Object} person - Contains person data.
|
|
371
337
|
*/
|
|
372
338
|
|
|
373
|
-
/**
|
|
374
|
-
* Stored participant changes between the last event and the current event.
|
|
375
|
-
* All previously stored events are overwritten between events.
|
|
376
|
-
*
|
|
377
|
-
* @instance
|
|
378
|
-
* @type {Array<DeltaParticipant>}
|
|
379
|
-
* @private
|
|
380
|
-
* @member LocusInfo
|
|
381
|
-
*/
|
|
382
|
-
this.deltaParticipants = [];
|
|
383
|
-
|
|
384
339
|
this.updateLocusCache(locus);
|
|
385
340
|
// above section only updates the locusInfo object
|
|
386
341
|
// The below section makes sure it updates the locusInfo as well as updates the meeting object
|
|
@@ -388,7 +343,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
388
343
|
// For 1:1 space meeting the conversation Url does not exist in locus.conversation
|
|
389
344
|
this.updateConversationUrl(locus.conversationUrl, locus.info);
|
|
390
345
|
this.updateControls(locus.controls, locus.self);
|
|
391
|
-
this.updateLocusUrl(locus.url);
|
|
346
|
+
this.updateLocusUrl(locus.url, ControlsUtils.isMainSessionDTO(locus));
|
|
392
347
|
this.updateFullState(locus.fullState);
|
|
393
348
|
this.updateMeetingInfo(locus.info);
|
|
394
349
|
this.updateEmbeddedApps(locus.embeddedApps);
|
|
@@ -402,188 +357,25 @@ export default class LocusInfo extends EventsScope {
|
|
|
402
357
|
|
|
403
358
|
/**
|
|
404
359
|
* @param {Object} locus
|
|
405
|
-
* @param {DataSet[]} [dataSets=[]] - Array of data sets
|
|
406
360
|
* @returns {undefined}
|
|
407
361
|
* @memberof LocusInfo
|
|
408
362
|
*/
|
|
409
|
-
initialSetup(locus: object
|
|
363
|
+
initialSetup(locus: object) {
|
|
410
364
|
this.updateLocusCache(locus);
|
|
411
|
-
this.onFullLocus(locus
|
|
365
|
+
this.onFullLocus(locus);
|
|
412
366
|
|
|
413
367
|
// Change it to true after it receives it first locus object
|
|
414
368
|
this.emitChange = true;
|
|
415
369
|
}
|
|
416
370
|
|
|
417
371
|
/**
|
|
418
|
-
*
|
|
419
|
-
* @param {HashTreeObject} object data set object
|
|
420
|
-
* @param {any} locus
|
|
421
|
-
* @returns {void}
|
|
422
|
-
*/
|
|
423
|
-
updateHashTreeObjectInLocus(object: HashTreeObject, locus: LocusDTO): LocusDTO {
|
|
424
|
-
const type = object.htMeta.elementId.type.toLowerCase();
|
|
425
|
-
|
|
426
|
-
switch (type) {
|
|
427
|
-
case ObjectType.locus: {
|
|
428
|
-
if (!object.data) {
|
|
429
|
-
LoggerProxy.logger.warn(
|
|
430
|
-
`Locus-info:index#updateHashTreeObjectInLocus --> received LOCUS object without data, this is not supported!`
|
|
431
|
-
);
|
|
432
|
-
|
|
433
|
-
return locus;
|
|
434
|
-
}
|
|
435
|
-
// replace the main locus
|
|
436
|
-
|
|
437
|
-
// The Locus object from MAIN dataset has empty participants, so removing them to avoid it overriding the ones in our current locus object
|
|
438
|
-
// Also, it doesn't have "self". That's OK as it won't override existing locus.self and also existing SDK code can handle that missing self in Locus updates
|
|
439
|
-
const locusObjectFromData = object.data;
|
|
440
|
-
delete locusObjectFromData.participants;
|
|
441
|
-
|
|
442
|
-
locus = {...locus, ...locusObjectFromData};
|
|
443
|
-
locus.htMeta = object.htMeta;
|
|
444
|
-
break;
|
|
445
|
-
}
|
|
446
|
-
case ObjectType.participant:
|
|
447
|
-
LoggerProxy.logger.info(
|
|
448
|
-
`Locus-info:index#updateHashTreeObjectInLocus --> participant id=${
|
|
449
|
-
object.htMeta.elementId.id
|
|
450
|
-
} ${object.data ? 'updated' : 'removed'}`
|
|
451
|
-
);
|
|
452
|
-
console.log(
|
|
453
|
-
'marcin: hashTreeObjectId2ParticipantId=',
|
|
454
|
-
cloneDeep(this.hashTreeObjectId2ParticipantId)
|
|
455
|
-
);
|
|
456
|
-
if (object.data) {
|
|
457
|
-
if (!locus.participants) {
|
|
458
|
-
locus.participants = [];
|
|
459
|
-
}
|
|
460
|
-
const participantObject = object.data;
|
|
461
|
-
participantObject.htMeta = object.htMeta;
|
|
462
|
-
locus.participants.push(participantObject);
|
|
463
|
-
this.hashTreeObjectId2ParticipantId.set(object.htMeta.elementId.id, participantObject.id);
|
|
464
|
-
} else {
|
|
465
|
-
const participantId = this.hashTreeObjectId2ParticipantId.get(object.htMeta.elementId.id);
|
|
466
|
-
|
|
467
|
-
if (!locus.jsSdkMeta) {
|
|
468
|
-
locus.jsSdkMeta = {removedParticipantIds: []};
|
|
469
|
-
}
|
|
470
|
-
locus.jsSdkMeta.removedParticipantIds.push(participantId);
|
|
471
|
-
this.hashTreeObjectId2ParticipantId.delete(object.htMeta.elementId.id);
|
|
472
|
-
}
|
|
473
|
-
break;
|
|
474
|
-
case ObjectType.self:
|
|
475
|
-
if (!object.data) {
|
|
476
|
-
LoggerProxy.logger.warn(
|
|
477
|
-
`Locus-info:index#updateHashTreeObjectInLocus --> received SELF object without data, this is not supported!`
|
|
478
|
-
);
|
|
479
|
-
|
|
480
|
-
return locus;
|
|
481
|
-
}
|
|
482
|
-
locus.self = object.data;
|
|
483
|
-
break;
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
return locus;
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
/**
|
|
490
|
-
* Handles HTTP response from Locus API call when hash tree update.
|
|
372
|
+
* Handles HTTP response from Locus API call.
|
|
491
373
|
* @param {Meeting} meeting meeting object
|
|
492
|
-
* @param {LocusApiResponseBody} responseBody body of the http
|
|
374
|
+
* @param {LocusApiResponseBody} responseBody body of the http response from Locus API call
|
|
493
375
|
* @returns {void}
|
|
494
376
|
*/
|
|
495
377
|
handleLocusAPIResponse(meeting, responseBody: LocusApiResponseBody): void {
|
|
496
|
-
|
|
497
|
-
if (responseBody.dataSets) {
|
|
498
|
-
if (!this.hashTreeParser) {
|
|
499
|
-
LoggerProxy.logger.warn(
|
|
500
|
-
`Locus-info:index#handleLocusAPIResponse --> received response with hash tree info from Locus API, but we don't have the hashTreeParser created`
|
|
501
|
-
);
|
|
502
|
-
|
|
503
|
-
return;
|
|
504
|
-
}
|
|
505
|
-
// Locus is using the new hash tree mechanism
|
|
506
|
-
// so update our data in the hash tree parser
|
|
507
|
-
this.hashTreeParser.handleLocusUpdate(responseBody);
|
|
508
|
-
|
|
509
|
-
// but the Locus object we receive in this case looks same like classic delta, so we can use existing delta method to process it
|
|
510
|
-
this.onDeltaLocus(responseBody.locus);
|
|
511
|
-
} else {
|
|
512
|
-
// classic Locus delta
|
|
513
|
-
this.handleLocusDelta(responseBody.locus, meeting);
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Handles a hash tree message received from Locus.
|
|
519
|
-
*
|
|
520
|
-
* @param {Meeting} meeting - The meeting object
|
|
521
|
-
* @param {HashTreeMessage} message incoming hash tree message
|
|
522
|
-
* @returns {void}
|
|
523
|
-
*/
|
|
524
|
-
private handleHashTreeMessage(meeting: any, message: HashTreeMessage) {
|
|
525
|
-
if (!this.hashTreeParser) {
|
|
526
|
-
LoggerProxy.logger.warn(
|
|
527
|
-
`Locus-info:index#handleHashTreeMessage --> received hash tree message, but we don't have the hashTreeParser`
|
|
528
|
-
);
|
|
529
|
-
|
|
530
|
-
return;
|
|
531
|
-
}
|
|
532
|
-
if (message.locusStateElements === undefined) {
|
|
533
|
-
// todo: need to see in practice how exactly the heartbeat messages look like
|
|
534
|
-
this.hashTreeParser.handleRootHashHeartBeatMessage(message);
|
|
535
|
-
} else {
|
|
536
|
-
this.hashTreeParser.handleMessage(message);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* Updates our locus info based on the data parsed by the hash tree parser.
|
|
542
|
-
*
|
|
543
|
-
* @param {LocusInfoUpdateType} updateType - The type of update received.
|
|
544
|
-
* @param {Object} [data] - Additional data for the update, if applicable.
|
|
545
|
-
* @returns {void}
|
|
546
|
-
*/
|
|
547
|
-
private updateFromHashTree(
|
|
548
|
-
updateType: LocusInfoUpdateType,
|
|
549
|
-
data?: {updatedObjects: HashTreeObject[]}
|
|
550
|
-
) {
|
|
551
|
-
switch (updateType) {
|
|
552
|
-
case LocusInfoUpdateType.OBJECTS_UPDATED: {
|
|
553
|
-
// initialize the main locus with what we currently have
|
|
554
|
-
// but with empty participants array
|
|
555
|
-
let locus: LocusDTO = {
|
|
556
|
-
participants: [],
|
|
557
|
-
jsSdkMeta: {removedParticipantIds: []},
|
|
558
|
-
};
|
|
559
|
-
|
|
560
|
-
LocusDtoTopLevelKeys.forEach((key) => {
|
|
561
|
-
if (key === 'participants') {
|
|
562
|
-
locus[key] = [];
|
|
563
|
-
} else {
|
|
564
|
-
locus[key] = cloneDeep(this[key]);
|
|
565
|
-
}
|
|
566
|
-
});
|
|
567
|
-
|
|
568
|
-
// apply the updates from the hash tree onto the locus
|
|
569
|
-
data.updatedObjects.forEach((object) => {
|
|
570
|
-
locus = this.updateHashTreeObjectInLocus(object, locus);
|
|
571
|
-
});
|
|
572
|
-
|
|
573
|
-
// update our locus info with the new locus
|
|
574
|
-
this.onDeltaLocus(locus);
|
|
575
|
-
|
|
576
|
-
break;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
case LocusInfoUpdateType.MEETING_ENDED: {
|
|
580
|
-
LoggerProxy.logger.info(
|
|
581
|
-
`Locus-info:index#updateFromHashTree --> received signal that meeting ended, destroying meeting ${this.meetingId}`
|
|
582
|
-
);
|
|
583
|
-
const meeting = this.webex.meetings.meetingCollection.get(this.meetingId);
|
|
584
|
-
this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
378
|
+
this.handleLocusDelta(responseBody.locus, meeting);
|
|
587
379
|
}
|
|
588
380
|
|
|
589
381
|
/**
|
|
@@ -593,43 +385,38 @@ export default class LocusInfo extends EventsScope {
|
|
|
593
385
|
* @memberof LocusInfo
|
|
594
386
|
*/
|
|
595
387
|
parse(meeting: any, data: any) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
default:
|
|
629
|
-
// Why will there be a event with no eventType ????
|
|
630
|
-
// we may not need this, we can get full locus
|
|
631
|
-
this.handleLocusDelta(locus, meeting);
|
|
632
|
-
}
|
|
388
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
389
|
+
const {eventType} = data;
|
|
390
|
+
const locus = this.getTheLocusToUpdate(data.locus);
|
|
391
|
+
LoggerProxy.logger.info(`Locus-info:index#parse --> received locus data: ${eventType}`);
|
|
392
|
+
|
|
393
|
+
locus.jsSdkMeta = {removedParticipantIds: []};
|
|
394
|
+
|
|
395
|
+
switch (eventType) {
|
|
396
|
+
case LOCUSEVENT.PARTICIPANT_JOIN:
|
|
397
|
+
case LOCUSEVENT.PARTICIPANT_LEFT:
|
|
398
|
+
case LOCUSEVENT.CONTROLS_UPDATED:
|
|
399
|
+
case LOCUSEVENT.PARTICIPANT_AUDIO_MUTED:
|
|
400
|
+
case LOCUSEVENT.PARTICIPANT_AUDIO_UNMUTED:
|
|
401
|
+
case LOCUSEVENT.PARTICIPANT_VIDEO_MUTED:
|
|
402
|
+
case LOCUSEVENT.PARTICIPANT_VIDEO_UNMUTED:
|
|
403
|
+
case LOCUSEVENT.SELF_CHANGED:
|
|
404
|
+
case LOCUSEVENT.PARTICIPANT_UPDATED:
|
|
405
|
+
case LOCUSEVENT.PARTICIPANT_CONTROLS_UPDATED:
|
|
406
|
+
case LOCUSEVENT.PARTICIPANT_ROLES_UPDATED:
|
|
407
|
+
case LOCUSEVENT.PARTICIPANT_DECLINED:
|
|
408
|
+
case LOCUSEVENT.FLOOR_GRANTED:
|
|
409
|
+
case LOCUSEVENT.FLOOR_RELEASED:
|
|
410
|
+
this.onFullLocus(locus, eventType);
|
|
411
|
+
break;
|
|
412
|
+
case LOCUSEVENT.DIFFERENCE:
|
|
413
|
+
this.handleLocusDelta(locus, meeting);
|
|
414
|
+
break;
|
|
415
|
+
|
|
416
|
+
default:
|
|
417
|
+
// Why will there be a event with no eventType ????
|
|
418
|
+
// we may not need this, we can get full locus
|
|
419
|
+
this.handleLocusDelta(locus, meeting);
|
|
633
420
|
}
|
|
634
421
|
}
|
|
635
422
|
|
|
@@ -648,46 +435,17 @@ export default class LocusInfo extends EventsScope {
|
|
|
648
435
|
* updates the locus with full locus object
|
|
649
436
|
* @param {object} locus locus object
|
|
650
437
|
* @param {string} eventType particulat locus event
|
|
651
|
-
* @param {DataSet[]} dataSets
|
|
652
438
|
* @returns {object} null
|
|
653
439
|
* @memberof LocusInfo
|
|
654
440
|
*/
|
|
655
|
-
onFullLocus(locus: any, eventType?: string
|
|
441
|
+
onFullLocus(locus: any, eventType?: string) {
|
|
656
442
|
if (!locus) {
|
|
657
443
|
LoggerProxy.logger.error(
|
|
658
444
|
'Locus-info:index#onFullLocus --> object passed as argument was invalid, continuing.'
|
|
659
445
|
);
|
|
660
446
|
}
|
|
661
447
|
|
|
662
|
-
if (
|
|
663
|
-
// this is the new hashmap Locus DTO format (only applicable to webinars for now)
|
|
664
|
-
if (!this.hashTreeParser) {
|
|
665
|
-
LoggerProxy.logger.info(`Locus-info:index#onFullLocus --> creating hash tree parser`);
|
|
666
|
-
LoggerProxy.logger.info(
|
|
667
|
-
'Locus-info:index#onFullLocus --> dataSets:',
|
|
668
|
-
dataSets,
|
|
669
|
-
' and locus:',
|
|
670
|
-
locus
|
|
671
|
-
);
|
|
672
|
-
this.hashTreeParser = new HashTreeParser({
|
|
673
|
-
initialLocus: {locus, dataSets},
|
|
674
|
-
webexRequest: this.webex.request.bind(this.webex),
|
|
675
|
-
locusInfoUpdateCallback: this.updateFromHashTree.bind(this),
|
|
676
|
-
debugId: `HT-${this.meetingId.substring(0, 4)}`,
|
|
677
|
-
});
|
|
678
|
-
} else {
|
|
679
|
-
// in this case the Locus we're getting is not necessarily the full one
|
|
680
|
-
// so treat it like if we just got it in a message
|
|
681
|
-
console.log('marcin: !!!!!!!! full DTO - this is not fully implemented/tested yet');
|
|
682
|
-
|
|
683
|
-
LoggerProxy.logger.warn(
|
|
684
|
-
'Locus-info:index#onFullLocus --> full DTO - this is not fully implemented/tested yet!!!!!!!!'
|
|
685
|
-
);
|
|
686
|
-
this.handleLocusAPIResponse(undefined, {dataSets, locus});
|
|
687
|
-
|
|
688
|
-
return;
|
|
689
|
-
}
|
|
690
|
-
} else if (!this.locusParser.isNewFullLocus(locus)) {
|
|
448
|
+
if (!this.locusParser.isNewFullLocus(locus)) {
|
|
691
449
|
LoggerProxy.logger.info(
|
|
692
450
|
`Locus-info:index#onFullLocus --> ignoring old full locus DTO, eventType=${eventType}`
|
|
693
451
|
);
|
|
@@ -695,12 +453,8 @@ export default class LocusInfo extends EventsScope {
|
|
|
695
453
|
return;
|
|
696
454
|
}
|
|
697
455
|
|
|
698
|
-
this.updateParticipantDeltas(locus.participants);
|
|
699
456
|
this.scheduledMeeting = locus.meeting || null;
|
|
700
457
|
this.participants = locus.participants;
|
|
701
|
-
this.participants?.forEach((participant) => {
|
|
702
|
-
this.hashTreeObjectId2ParticipantId.set(participant.htMeta.elementId.id, participant.id);
|
|
703
|
-
});
|
|
704
458
|
const isReplaceMembers = ControlsUtils.isNeedReplaceMembers(this.controls, locus.controls);
|
|
705
459
|
this.updateLocusInfo(locus);
|
|
706
460
|
this.updateParticipants(
|
|
@@ -795,7 +549,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
795
549
|
this.updateCreated(locus.created);
|
|
796
550
|
this.updateFullState(locus.fullState);
|
|
797
551
|
this.updateHostInfo(locus.host);
|
|
798
|
-
this.updateLocusUrl(locus.url);
|
|
552
|
+
this.updateLocusUrl(locus.url, ControlsUtils.isMainSessionDTO(locus));
|
|
799
553
|
this.updateMeetingInfo(locus.info, locus.self);
|
|
800
554
|
this.updateMediaShares(locus.mediaShares);
|
|
801
555
|
this.updateParticipantsUrl(locus.participantsUrl);
|
|
@@ -1061,55 +815,6 @@ export default class LocusInfo extends EventsScope {
|
|
|
1061
815
|
}
|
|
1062
816
|
}
|
|
1063
817
|
|
|
1064
|
-
/**
|
|
1065
|
-
* Update the deltaParticipants property of this object based on a list of
|
|
1066
|
-
* provided participants.
|
|
1067
|
-
*
|
|
1068
|
-
* @param {Array} [participants] - The participants to update against.
|
|
1069
|
-
* @returns {void}
|
|
1070
|
-
*/
|
|
1071
|
-
updateParticipantDeltas(participants: Array<any> = []) {
|
|
1072
|
-
// Used to find a participant within a participants collection.
|
|
1073
|
-
const findParticipant = (participant, collection) =>
|
|
1074
|
-
collection.find((item) => item.person.id === participant.person.id);
|
|
1075
|
-
|
|
1076
|
-
// Generates an object that indicates which state properties have changed.
|
|
1077
|
-
const generateDelta = (prevState: any = {}, newState: any = {}) => {
|
|
1078
|
-
// Setup deltas.
|
|
1079
|
-
const deltas = {
|
|
1080
|
-
audioStatus: prevState.audioStatus !== newState.audioStatus,
|
|
1081
|
-
videoSlidesStatus: prevState.videoSlidesStatus !== newState.videoSlidesStatus,
|
|
1082
|
-
videoStatus: prevState.videoStatus !== newState.videoStatus,
|
|
1083
|
-
};
|
|
1084
|
-
|
|
1085
|
-
// Clean the object
|
|
1086
|
-
Object.keys(deltas).forEach((key) => {
|
|
1087
|
-
if (deltas[key] !== true) {
|
|
1088
|
-
delete deltas[key];
|
|
1089
|
-
}
|
|
1090
|
-
});
|
|
1091
|
-
|
|
1092
|
-
return deltas;
|
|
1093
|
-
};
|
|
1094
|
-
|
|
1095
|
-
this.deltaParticipants = participants.reduce((collection, participant) => {
|
|
1096
|
-
const existingParticipant = findParticipant(participant, this.participants || []) || {};
|
|
1097
|
-
|
|
1098
|
-
const delta = generateDelta(existingParticipant.status, participant.status);
|
|
1099
|
-
|
|
1100
|
-
const changed = Object.keys(delta).length > 0;
|
|
1101
|
-
|
|
1102
|
-
if (changed) {
|
|
1103
|
-
collection.push({
|
|
1104
|
-
person: participant.person,
|
|
1105
|
-
delta,
|
|
1106
|
-
});
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
return collection;
|
|
1110
|
-
}, []);
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1113
818
|
/**
|
|
1114
819
|
* update meeting's members
|
|
1115
820
|
* @param {Object} participants new participants object
|
|
@@ -1118,7 +823,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1118
823
|
* @returns {Array} updatedParticipants
|
|
1119
824
|
* @memberof LocusInfo
|
|
1120
825
|
*/
|
|
1121
|
-
updateParticipants(participants: object, removedParticipantIds
|
|
826
|
+
updateParticipants(participants: object, removedParticipantIds?: string[], isReplace?: boolean) {
|
|
1122
827
|
this.emitScoped(
|
|
1123
828
|
{
|
|
1124
829
|
file: 'locus-info',
|
|
@@ -1190,6 +895,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1190
895
|
hasAnnotationControlChanged,
|
|
1191
896
|
hasRemoteDesktopControlChanged,
|
|
1192
897
|
hasPollingQAControlChanged,
|
|
898
|
+
hasAutoEndMeetingChanged,
|
|
1193
899
|
},
|
|
1194
900
|
current,
|
|
1195
901
|
} = ControlsUtils.getControls(this.controls, controls);
|
|
@@ -1464,6 +1170,14 @@ export default class LocusInfo extends EventsScope {
|
|
|
1464
1170
|
);
|
|
1465
1171
|
}
|
|
1466
1172
|
|
|
1173
|
+
if (hasAutoEndMeetingChanged) {
|
|
1174
|
+
this.emitScoped(
|
|
1175
|
+
{file: 'locus-info', function: 'updateControls'},
|
|
1176
|
+
LOCUSINFO.EVENTS.CONTROLS_AUTO_END_MEETING_WARNING_CHANGED,
|
|
1177
|
+
{state: current.autoEndMeetingWarning}
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1467
1181
|
this.controls = controls;
|
|
1468
1182
|
}
|
|
1469
1183
|
}
|
|
@@ -1624,10 +1338,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1624
1338
|
*/
|
|
1625
1339
|
updateMeetingInfo(info: object, self?: object) {
|
|
1626
1340
|
const roles = self ? SelfUtils.getRoles(self) : this.parsedLocus.self?.roles || [];
|
|
1627
|
-
if (
|
|
1628
|
-
(info && !isEqual(this.info, info)) ||
|
|
1629
|
-
(roles.length && !isEqual(this.roles, roles) && info)
|
|
1630
|
-
) {
|
|
1341
|
+
if ((info && !isEqual(this.info, info)) || (!isEqual(this.roles, roles) && info)) {
|
|
1631
1342
|
const isJoined = SelfUtils.isJoined(self || this.parsedLocus.self);
|
|
1632
1343
|
const parsedInfo = InfoUtils.getInfos(this.parsedLocus.info, info, roles, isJoined);
|
|
1633
1344
|
|
|
@@ -2030,10 +1741,11 @@ export default class LocusInfo extends EventsScope {
|
|
|
2030
1741
|
/**
|
|
2031
1742
|
* handles when the locus.url is updated
|
|
2032
1743
|
* @param {String} url
|
|
1744
|
+
* @param {Boolean} isMainLocus
|
|
2033
1745
|
* @returns {undefined}
|
|
2034
1746
|
* emits internal event locus_info_update_url
|
|
2035
1747
|
*/
|
|
2036
|
-
updateLocusUrl(url: string) {
|
|
1748
|
+
updateLocusUrl(url: string, isMainLocus = true) {
|
|
2037
1749
|
if (url && this.url !== url) {
|
|
2038
1750
|
this.url = url;
|
|
2039
1751
|
this.updateMeeting({locusUrl: url});
|
|
@@ -2043,7 +1755,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
2043
1755
|
function: 'updateLocusUrl',
|
|
2044
1756
|
},
|
|
2045
1757
|
EVENTS.LOCUS_INFO_UPDATE_URL,
|
|
2046
|
-
url
|
|
1758
|
+
{url, isMainLocus}
|
|
2047
1759
|
);
|
|
2048
1760
|
}
|
|
2049
1761
|
}
|
package/src/locus-info/parser.ts
CHANGED
|
@@ -728,13 +728,17 @@ export default class Parser {
|
|
|
728
728
|
break;
|
|
729
729
|
|
|
730
730
|
case USE_INCOMING:
|
|
731
|
-
case LOCUS_URL_CHANGED:
|
|
732
731
|
// update working copy for future comparisons.
|
|
733
732
|
// Note: The working copy of parser gets updated in .onFullLocus()
|
|
734
733
|
// and here when USE_INCOMING or LOCUS_URL_CHANGED locus.
|
|
735
734
|
this.workingCopy = newLoci;
|
|
736
735
|
break;
|
|
737
736
|
|
|
737
|
+
case LOCUS_URL_CHANGED:
|
|
738
|
+
// clear the working copy completely, do a full locus sync
|
|
739
|
+
this.workingCopy = null;
|
|
740
|
+
break;
|
|
741
|
+
|
|
738
742
|
case WAIT:
|
|
739
743
|
// we've taken newLoci from the front of the queue, so put it back there as we have to wait
|
|
740
744
|
// for the one that should be in front of it, before we can process it
|