@webex/plugin-meetings 3.10.0-next.1 → 3.10.0-next.11
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/annotation/annotation.types.js.map +1 -1
- package/dist/annotation/constants.js.map +1 -1
- package/dist/annotation/index.js +19 -22
- package/dist/annotation/index.js.map +1 -1
- package/dist/breakouts/breakout.js +6 -6
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/collection.js.map +1 -1
- package/dist/breakouts/edit-lock-error.js +9 -11
- package/dist/breakouts/edit-lock-error.js.map +1 -1
- package/dist/breakouts/events.js.map +1 -1
- package/dist/breakouts/index.js +126 -127
- package/dist/breakouts/index.js.map +1 -1
- package/dist/breakouts/request.js +6 -8
- package/dist/breakouts/request.js.map +1 -1
- package/dist/breakouts/utils.js.map +1 -1
- package/dist/common/browser-detection.js.map +1 -1
- package/dist/common/collection.js +1 -2
- package/dist/common/collection.js.map +1 -1
- package/dist/common/config.js.map +1 -1
- package/dist/common/errors/captcha-error.js +9 -11
- package/dist/common/errors/captcha-error.js.map +1 -1
- package/dist/common/errors/intent-to-join.js +10 -12
- package/dist/common/errors/intent-to-join.js.map +1 -1
- package/dist/common/errors/join-forbidden-error.js +10 -12
- package/dist/common/errors/join-forbidden-error.js.map +1 -1
- package/dist/common/errors/join-meeting.js +10 -12
- package/dist/common/errors/join-meeting.js.map +1 -1
- package/dist/common/errors/join-webinar-error.js +9 -11
- package/dist/common/errors/join-webinar-error.js.map +1 -1
- package/dist/common/errors/media.js +9 -11
- package/dist/common/errors/media.js.map +1 -1
- package/dist/common/errors/multistream-not-supported-error.js +9 -11
- package/dist/common/errors/multistream-not-supported-error.js.map +1 -1
- package/dist/common/errors/no-meeting-info.js +9 -11
- package/dist/common/errors/no-meeting-info.js.map +1 -1
- package/dist/common/errors/parameter.js +11 -14
- package/dist/common/errors/parameter.js.map +1 -1
- package/dist/common/errors/password-error.js +9 -11
- package/dist/common/errors/password-error.js.map +1 -1
- package/dist/common/errors/permission.js +9 -11
- package/dist/common/errors/permission.js.map +1 -1
- package/dist/common/errors/reclaim-host-role-errors.js +32 -38
- package/dist/common/errors/reclaim-host-role-errors.js.map +1 -1
- package/dist/common/errors/reconnection-not-started.js +5 -6
- package/dist/common/errors/reconnection-not-started.js.map +1 -1
- package/dist/common/errors/reconnection.js +9 -11
- package/dist/common/errors/reconnection.js.map +1 -1
- package/dist/common/errors/stats.js +9 -11
- package/dist/common/errors/stats.js.map +1 -1
- package/dist/common/errors/webex-errors.js +38 -27
- package/dist/common/errors/webex-errors.js.map +1 -1
- package/dist/common/errors/webex-meetings-error.js +9 -12
- package/dist/common/errors/webex-meetings-error.js.map +1 -1
- package/dist/common/events/events-scope.js +9 -10
- package/dist/common/events/events-scope.js.map +1 -1
- package/dist/common/events/events.js +9 -10
- package/dist/common/events/events.js.map +1 -1
- package/dist/common/events/trigger-proxy.js.map +1 -1
- package/dist/common/events/util.js.map +1 -1
- package/dist/common/logs/logger-config.js.map +1 -1
- package/dist/common/logs/logger-proxy.js.map +1 -1
- package/dist/common/logs/request.js +17 -17
- package/dist/common/logs/request.js.map +1 -1
- package/dist/common/queue.js +1 -2
- package/dist/common/queue.js.map +1 -1
- package/dist/config.js +0 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +12 -8
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.js +1 -2
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +1 -2
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +165 -0
- package/dist/hashTree/hashTreeParser.js.map +1 -0
- package/dist/hashTree/types.js +15 -0
- package/dist/hashTree/types.js.map +1 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interceptors/locusRetry.js +6 -8
- package/dist/interceptors/locusRetry.js.map +1 -1
- package/dist/interceptors/locusRouteToken.js +6 -8
- package/dist/interceptors/locusRouteToken.js.map +1 -1
- package/dist/interpretation/collection.js.map +1 -1
- package/dist/interpretation/index.js +1 -2
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/interpretation/siLanguage.js.map +1 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
- package/dist/locus-info/fullState.js.map +1 -1
- package/dist/locus-info/hostUtils.js.map +1 -1
- package/dist/locus-info/index.js +532 -94
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/mediaSharesUtils.js.map +1 -1
- package/dist/locus-info/parser.js +3 -4
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.js.map +1 -1
- package/dist/locus-info/types.js +7 -0
- package/dist/locus-info/types.js.map +1 -0
- package/dist/media/MediaConnectionAwaiter.js +1 -2
- package/dist/media/MediaConnectionAwaiter.js.map +1 -1
- package/dist/media/index.js +5 -2
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +15 -17
- package/dist/media/properties.js.map +1 -1
- package/dist/media/util.js.map +1 -1
- package/dist/meeting/brbState.js +8 -9
- package/dist/meeting/brbState.js.map +1 -1
- package/dist/meeting/connectionStateHandler.js +10 -13
- package/dist/meeting/connectionStateHandler.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1556 -1528
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +13 -17
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +11 -12
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +101 -104
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/state.js.map +1 -1
- package/dist/meeting/type.js.map +1 -1
- package/dist/meeting/util.js +24 -23
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting/voicea-meeting.js +3 -3
- package/dist/meeting/voicea-meeting.js.map +1 -1
- package/dist/meeting-info/collection.js +7 -10
- package/dist/meeting-info/collection.js.map +1 -1
- package/dist/meeting-info/index.js +1 -2
- package/dist/meeting-info/index.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +135 -146
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.js +1 -2
- package/dist/meeting-info/request.js.map +1 -1
- package/dist/meeting-info/util.js +36 -37
- package/dist/meeting-info/util.js.map +1 -1
- package/dist/meeting-info/utilv2.js +30 -31
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.js +6 -8
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.js +179 -141
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js.map +1 -1
- package/dist/meetings/request.js +6 -8
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +25 -23
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +1 -2
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js +6 -3
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js.map +1 -1
- package/dist/members/collection.js +1 -2
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +18 -21
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +8 -11
- package/dist/members/request.js.map +1 -1
- package/dist/members/types.js.map +1 -1
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +3 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.js +3 -4
- package/dist/metrics/index.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -2
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +34 -45
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/multistream/receiveSlotManager.js +8 -9
- package/dist/multistream/receiveSlotManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +12 -15
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +1 -2
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/multistream/remoteMediaManager.js +122 -123
- package/dist/multistream/remoteMediaManager.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +29 -30
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/personal-meeting-room/index.js +16 -19
- package/dist/personal-meeting-room/index.js.map +1 -1
- package/dist/personal-meeting-room/request.js +7 -10
- package/dist/personal-meeting-room/request.js.map +1 -1
- package/dist/personal-meeting-room/util.js.map +1 -1
- package/dist/reachability/clusterReachability.js +36 -39
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +203 -205
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js.map +1 -1
- package/dist/reachability/request.js.map +1 -1
- package/dist/reachability/util.js.map +1 -1
- package/dist/reactions/constants.js.map +1 -1
- package/dist/reactions/reactions.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/reconnection-manager/index.js +178 -176
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.js.map +1 -1
- package/dist/recording-controller/index.js +1 -2
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js +12 -15
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/request.js +24 -26
- package/dist/roap/request.js.map +1 -1
- package/dist/roap/turnDiscovery.js +75 -76
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/types.js.map +1 -1
- package/dist/transcription/index.js +4 -5
- package/dist/transcription/index.js.map +1 -1
- package/dist/types/common/errors/webex-errors.d.ts +12 -0
- package/dist/types/constants.d.ts +26 -21
- package/dist/types/hashTree/hashTreeParser.d.ts +109 -0
- package/dist/types/hashTree/types.d.ts +16 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/locus-info/index.d.ts +91 -42
- package/dist/types/locus-info/types.d.ts +45 -0
- package/dist/types/meeting/index.d.ts +22 -9
- package/dist/types/meetings/index.d.ts +9 -2
- package/dist/types/metrics/constants.d.ts +2 -0
- package/dist/webinar/collection.js +1 -2
- package/dist/webinar/collection.js.map +1 -1
- package/dist/webinar/index.js +148 -158
- package/dist/webinar/index.js.map +1 -1
- package/package.json +16 -16
- package/src/common/errors/webex-errors.ts +19 -0
- package/src/constants.ts +14 -2
- package/src/hashTree/hashTreeParser.ts +146 -0
- package/src/hashTree/types.ts +20 -0
- package/src/index.ts +2 -0
- package/src/locus-info/index.ts +534 -85
- package/src/locus-info/types.ts +46 -0
- package/src/media/index.ts +6 -0
- package/src/meeting/index.ts +61 -27
- package/src/meeting/util.ts +1 -0
- package/src/meetings/index.ts +104 -51
- package/src/metrics/constants.ts +2 -0
- package/test/unit/spec/locus-info/index.js +576 -1
- package/test/unit/spec/media/index.ts +140 -9
- package/test/unit/spec/meeting/index.js +178 -94
- package/test/unit/spec/meeting/utils.js +77 -0
- package/test/unit/spec/meetings/index.js +71 -28
package/src/locus-info/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {isEqual, assignWith, cloneDeep, isEmpty
|
|
1
|
+
import {isEqual, assignWith, cloneDeep, isEmpty} from 'lodash';
|
|
2
2
|
|
|
3
3
|
import LoggerProxy from '../common/logs/logger-proxy';
|
|
4
4
|
import EventsScope from '../common/events/events-scope';
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
MEETING_REMOVED_REASON,
|
|
18
18
|
CALL_REMOVED_REASON,
|
|
19
19
|
RECORDING_STATE,
|
|
20
|
-
|
|
20
|
+
Enum,
|
|
21
21
|
} from '../constants';
|
|
22
22
|
|
|
23
23
|
import InfoUtils from './infoUtils';
|
|
@@ -30,52 +30,53 @@ import MediaSharesUtils from './mediaSharesUtils';
|
|
|
30
30
|
import LocusDeltaParser from './parser';
|
|
31
31
|
import Metrics from '../metrics';
|
|
32
32
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
host?: {
|
|
48
|
-
id: string;
|
|
49
|
-
incomingCallProtocols: any[];
|
|
50
|
-
isExternal: boolean;
|
|
51
|
-
name: string;
|
|
52
|
-
orgId: string;
|
|
33
|
+
import HashTreeParser, {
|
|
34
|
+
DataSet,
|
|
35
|
+
HashTreeMessage,
|
|
36
|
+
HashTreeObject,
|
|
37
|
+
isSelf,
|
|
38
|
+
LocusInfoUpdateType,
|
|
39
|
+
} from '../hashTree/hashTreeParser';
|
|
40
|
+
import {ObjectType} from '../hashTree/types';
|
|
41
|
+
import {LocusDTO} from './types';
|
|
42
|
+
|
|
43
|
+
export type LocusLLMEvent = {
|
|
44
|
+
data: {
|
|
45
|
+
eventType: typeof LOCUSEVENT.HASH_TREE_DATA_UPDATED;
|
|
46
|
+
stateElementsMessage: HashTreeMessage;
|
|
53
47
|
};
|
|
54
|
-
info?: any;
|
|
55
|
-
links?: any;
|
|
56
|
-
mediaShares?: any[];
|
|
57
|
-
meetings?: any[];
|
|
58
|
-
participants: any[];
|
|
59
|
-
replaces?: any[];
|
|
60
|
-
self?: any;
|
|
61
|
-
sequence?: {
|
|
62
|
-
dirtyParticipants: number;
|
|
63
|
-
entries: number[];
|
|
64
|
-
rangeEnd: number;
|
|
65
|
-
rangeStart: number;
|
|
66
|
-
sequenceHash: number;
|
|
67
|
-
sessionToken: string;
|
|
68
|
-
since: string;
|
|
69
|
-
totalParticipants: number;
|
|
70
|
-
};
|
|
71
|
-
syncUrl?: string;
|
|
72
|
-
url?: string;
|
|
73
48
|
};
|
|
74
49
|
|
|
50
|
+
const LocusDtoTopLevelKeys = [
|
|
51
|
+
'controls',
|
|
52
|
+
'fullState',
|
|
53
|
+
'host',
|
|
54
|
+
'info',
|
|
55
|
+
'links',
|
|
56
|
+
'mediaShares',
|
|
57
|
+
'meetings',
|
|
58
|
+
'participants',
|
|
59
|
+
'replaces',
|
|
60
|
+
'self',
|
|
61
|
+
'sequence',
|
|
62
|
+
'syncUrl',
|
|
63
|
+
'url',
|
|
64
|
+
'htMeta', // only exists when hash trees are used
|
|
65
|
+
];
|
|
66
|
+
|
|
75
67
|
export type LocusApiResponseBody = {
|
|
68
|
+
dataSets?: DataSet[];
|
|
76
69
|
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)
|
|
77
70
|
};
|
|
78
71
|
|
|
72
|
+
const LocusObjectStateAfterUpdates = {
|
|
73
|
+
unchanged: 'unchanged',
|
|
74
|
+
removed: 'removed',
|
|
75
|
+
updated: 'updated',
|
|
76
|
+
} as const;
|
|
77
|
+
|
|
78
|
+
type LocusObjectStateAfterUpdates = Enum<typeof LocusObjectStateAfterUpdates>;
|
|
79
|
+
|
|
79
80
|
/**
|
|
80
81
|
* @description LocusInfo extends ChildEmitter to convert locusInfo info a private emitter to parent object
|
|
81
82
|
* @export
|
|
@@ -114,6 +115,10 @@ export default class LocusInfo extends EventsScope {
|
|
|
114
115
|
resources: any;
|
|
115
116
|
mainSessionLocusCache: any;
|
|
116
117
|
self: any;
|
|
118
|
+
hashTreeParser?: HashTreeParser;
|
|
119
|
+
hashTreeObjectId2ParticipantId: Map<number, string>; // mapping of hash tree object ids to participant ids
|
|
120
|
+
classicVsHashTreeMismatchMetricCounter = 0;
|
|
121
|
+
|
|
117
122
|
/**
|
|
118
123
|
* Constructor
|
|
119
124
|
* @param {function} updateMeeting callback to update the meeting object from an object
|
|
@@ -132,10 +137,12 @@ export default class LocusInfo extends EventsScope {
|
|
|
132
137
|
this.meetingId = meetingId;
|
|
133
138
|
this.updateMeeting = updateMeeting;
|
|
134
139
|
this.locusParser = new LocusDeltaParser();
|
|
140
|
+
this.hashTreeObjectId2ParticipantId = new Map();
|
|
135
141
|
}
|
|
136
142
|
|
|
137
143
|
/**
|
|
138
144
|
* 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.
|
|
145
|
+
* WARNING: This function must not be used for hash tree based Locus meetings.
|
|
139
146
|
*
|
|
140
147
|
* @param {Meeting} meeting
|
|
141
148
|
* @param {boolean} isLocusUrlChanged
|
|
@@ -356,14 +363,109 @@ export default class LocusInfo extends EventsScope {
|
|
|
356
363
|
}
|
|
357
364
|
|
|
358
365
|
/**
|
|
359
|
-
*
|
|
366
|
+
* Creates the HashTreeParser instance.
|
|
367
|
+
* @param {Object} initial locus data
|
|
368
|
+
* @returns {void}
|
|
369
|
+
*/
|
|
370
|
+
private createHashTreeParser({
|
|
371
|
+
initialLocus,
|
|
372
|
+
}: {
|
|
373
|
+
initialLocus: {
|
|
374
|
+
dataSets: Array<DataSet>;
|
|
375
|
+
locus: any;
|
|
376
|
+
};
|
|
377
|
+
}) {
|
|
378
|
+
return new HashTreeParser({
|
|
379
|
+
initialLocus,
|
|
380
|
+
webexRequest: this.webex.request.bind(this.webex),
|
|
381
|
+
locusInfoUpdateCallback: this.updateFromHashTree.bind(this),
|
|
382
|
+
debugId: `HT-${this.meetingId.substring(0, 4)}`,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* @param {Object} data - data to initialize locus info with. It may be from a join or GET /loci response or from a Mercury event that triggers a creation of meeting object
|
|
360
388
|
* @returns {undefined}
|
|
361
389
|
* @memberof LocusInfo
|
|
362
390
|
*/
|
|
363
|
-
initialSetup(
|
|
364
|
-
|
|
365
|
-
|
|
391
|
+
async initialSetup(
|
|
392
|
+
data:
|
|
393
|
+
| {
|
|
394
|
+
trigger: 'join-response';
|
|
395
|
+
locus: LocusDTO;
|
|
396
|
+
dataSets?: DataSet[];
|
|
397
|
+
}
|
|
398
|
+
| {
|
|
399
|
+
trigger: 'locus-message';
|
|
400
|
+
locus?: LocusDTO;
|
|
401
|
+
hashTreeMessage?: HashTreeMessage;
|
|
402
|
+
}
|
|
403
|
+
| {
|
|
404
|
+
trigger: 'get-loci-response';
|
|
405
|
+
locus?: LocusDTO;
|
|
406
|
+
}
|
|
407
|
+
) {
|
|
408
|
+
switch (data.trigger) {
|
|
409
|
+
case 'locus-message':
|
|
410
|
+
if (data.hashTreeMessage) {
|
|
411
|
+
// we need the SELF object to be in the received message, because it contains visibleDataSets
|
|
412
|
+
// and these are needed to initialize all the hash trees
|
|
413
|
+
const selfObject = data.hashTreeMessage.locusStateElements?.find((el) => isSelf(el));
|
|
414
|
+
|
|
415
|
+
if (!selfObject?.data?.visibleDataSets) {
|
|
416
|
+
LoggerProxy.logger.warn(
|
|
417
|
+
`Locus-info:index#initialSetup --> cannot initialize HashTreeParser, SELF object with visibleDataSets is missing in the message`
|
|
418
|
+
);
|
|
419
|
+
|
|
420
|
+
throw new Error('SELF object with visibleDataSets is missing in the message');
|
|
421
|
+
}
|
|
366
422
|
|
|
423
|
+
LoggerProxy.logger.info(
|
|
424
|
+
'Locus-info:index#initialSetup --> creating HashTreeParser from message'
|
|
425
|
+
);
|
|
426
|
+
// first create the HashTreeParser, but don't initialize it with any data yet
|
|
427
|
+
// pass just a fake locus that contains only the visibleDataSets
|
|
428
|
+
this.hashTreeParser = this.createHashTreeParser({
|
|
429
|
+
initialLocus: {
|
|
430
|
+
locus: {self: {visibleDataSets: selfObject.data.visibleDataSets}},
|
|
431
|
+
dataSets: [], // empty, because they will be populated in initializeFromMessage() call // dataSets: data.hashTreeMessage.dataSets,
|
|
432
|
+
},
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
// now handle the message - that should populate all the visible datasets
|
|
436
|
+
await this.hashTreeParser.initializeFromMessage(data.hashTreeMessage);
|
|
437
|
+
} else {
|
|
438
|
+
// "classic" Locus case, no hash trees involved
|
|
439
|
+
this.updateLocusCache(data.locus);
|
|
440
|
+
this.onFullLocus(data.locus, undefined);
|
|
441
|
+
}
|
|
442
|
+
break;
|
|
443
|
+
case 'join-response':
|
|
444
|
+
this.updateLocusCache(data.locus);
|
|
445
|
+
this.onFullLocus(data.locus, undefined, data.dataSets);
|
|
446
|
+
break;
|
|
447
|
+
case 'get-loci-response':
|
|
448
|
+
if (data.locus?.links?.resources?.visibleDataSets?.url) {
|
|
449
|
+
LoggerProxy.logger.info(
|
|
450
|
+
'Locus-info:index#initialSetup --> creating HashTreeParser from get-loci-response'
|
|
451
|
+
);
|
|
452
|
+
// first create the HashTreeParser, but don't initialize it with any data yet
|
|
453
|
+
// pass just a fake locus that contains only the visibleDataSets
|
|
454
|
+
this.hashTreeParser = this.createHashTreeParser({
|
|
455
|
+
initialLocus: {
|
|
456
|
+
locus: {self: {visibleDataSets: data.locus?.self?.visibleDataSets}},
|
|
457
|
+
dataSets: [], // empty, because we don't have them yet
|
|
458
|
+
},
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
// now initialize all the data
|
|
462
|
+
await this.hashTreeParser.initializeFromGetLociResponse(data.locus);
|
|
463
|
+
} else {
|
|
464
|
+
// "classic" Locus case, no hash trees involved
|
|
465
|
+
this.updateLocusCache(data.locus);
|
|
466
|
+
this.onFullLocus(data.locus, undefined);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
367
469
|
// Change it to true after it receives it first locus object
|
|
368
470
|
this.emitChange = true;
|
|
369
471
|
}
|
|
@@ -375,7 +477,276 @@ export default class LocusInfo extends EventsScope {
|
|
|
375
477
|
* @returns {void}
|
|
376
478
|
*/
|
|
377
479
|
handleLocusAPIResponse(meeting, responseBody: LocusApiResponseBody): void {
|
|
378
|
-
this.
|
|
480
|
+
if (this.hashTreeParser) {
|
|
481
|
+
// API responses with hash tree are a bit problematic and not fully confirmed how they will look like
|
|
482
|
+
// we don't really need them, because all updates are guaranteed to come via Mercury or LLM messages anyway
|
|
483
|
+
// so it's OK to skip them for now
|
|
484
|
+
LoggerProxy.logger.info(
|
|
485
|
+
'Locus-info:index#handleLocusAPIResponse: skipping handling of API http response with hashTreeParser'
|
|
486
|
+
);
|
|
487
|
+
} else {
|
|
488
|
+
if (responseBody.dataSets) {
|
|
489
|
+
this.sendClassicVsHashTreeMismatchMetric(
|
|
490
|
+
meeting,
|
|
491
|
+
`unexpected hash tree dataSets in API response`
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
// classic Locus delta
|
|
495
|
+
this.handleLocusDelta(responseBody.locus, meeting);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
*
|
|
501
|
+
* @param {HashTreeObject} object data set object
|
|
502
|
+
* @param {any} locus
|
|
503
|
+
* @returns {void}
|
|
504
|
+
*/
|
|
505
|
+
updateLocusFromHashTreeObject(object: HashTreeObject, locus: LocusDTO): LocusDTO {
|
|
506
|
+
const type = object.htMeta.elementId.type.toLowerCase();
|
|
507
|
+
|
|
508
|
+
switch (type) {
|
|
509
|
+
case ObjectType.locus: {
|
|
510
|
+
if (!object.data) {
|
|
511
|
+
// not doing anything here, as we need Locus to always be there (at least some fields)
|
|
512
|
+
// and that's already taken care of in updateFromHashTree()
|
|
513
|
+
LoggerProxy.logger.info(
|
|
514
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> LOCUS object removed`
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
return locus;
|
|
518
|
+
}
|
|
519
|
+
// replace the main locus
|
|
520
|
+
|
|
521
|
+
// The Locus object we receive from backend has empty participants, so removing them to avoid it overriding the ones in our current locus object
|
|
522
|
+
// Also, other fields like mediaShares are managed by other ObjectType updates, so removing them too
|
|
523
|
+
// BTW, it also 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
|
|
524
|
+
const locusObjectFromData = object.data;
|
|
525
|
+
delete locusObjectFromData.participants;
|
|
526
|
+
delete locusObjectFromData.mediaShares;
|
|
527
|
+
|
|
528
|
+
locus = {...locus, ...locusObjectFromData};
|
|
529
|
+
LoggerProxy.logger.info(
|
|
530
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> LOCUS object updated`
|
|
531
|
+
);
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
case ObjectType.mediaShare:
|
|
535
|
+
if (object.data) {
|
|
536
|
+
LoggerProxy.logger.info(
|
|
537
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> mediaShare id=${
|
|
538
|
+
object.htMeta.elementId.id
|
|
539
|
+
} name='${object.data.name}' updated ${
|
|
540
|
+
object.data.name === 'content'
|
|
541
|
+
? `floor=${object.data.floor?.disposition}, ${object.data.floor?.beneficiary?.id}`
|
|
542
|
+
: ''
|
|
543
|
+
}`
|
|
544
|
+
);
|
|
545
|
+
const existingMediaShare = locus.mediaShares?.find(
|
|
546
|
+
(ms) => ms.htMeta.elementId.id === object.htMeta.elementId.id
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
if (existingMediaShare) {
|
|
550
|
+
Object.assign(existingMediaShare, object.data);
|
|
551
|
+
} else {
|
|
552
|
+
locus.mediaShares = locus.mediaShares || [];
|
|
553
|
+
locus.mediaShares.push(object.data);
|
|
554
|
+
}
|
|
555
|
+
} else {
|
|
556
|
+
LoggerProxy.logger.info(
|
|
557
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> mediaShare id=${object.htMeta.elementId.id} removed`
|
|
558
|
+
);
|
|
559
|
+
locus.mediaShares = locus.mediaShares?.filter(
|
|
560
|
+
(ms) => ms.htMeta.elementId.id !== object.htMeta.elementId.id
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
break;
|
|
564
|
+
case ObjectType.participant:
|
|
565
|
+
LoggerProxy.logger.info(
|
|
566
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> participant id=${
|
|
567
|
+
object.htMeta.elementId.id
|
|
568
|
+
} ${object.data ? 'updated' : 'removed'}`
|
|
569
|
+
);
|
|
570
|
+
if (object.data) {
|
|
571
|
+
if (!locus.participants) {
|
|
572
|
+
locus.participants = [];
|
|
573
|
+
}
|
|
574
|
+
const participantObject = object.data;
|
|
575
|
+
participantObject.htMeta = object.htMeta;
|
|
576
|
+
locus.participants.push(participantObject);
|
|
577
|
+
this.hashTreeObjectId2ParticipantId.set(object.htMeta.elementId.id, participantObject.id);
|
|
578
|
+
} else {
|
|
579
|
+
const participantId = this.hashTreeObjectId2ParticipantId.get(object.htMeta.elementId.id);
|
|
580
|
+
|
|
581
|
+
if (!locus.jsSdkMeta) {
|
|
582
|
+
locus.jsSdkMeta = {removedParticipantIds: []};
|
|
583
|
+
}
|
|
584
|
+
locus.jsSdkMeta.removedParticipantIds.push(participantId);
|
|
585
|
+
this.hashTreeObjectId2ParticipantId.delete(object.htMeta.elementId.id);
|
|
586
|
+
}
|
|
587
|
+
break;
|
|
588
|
+
case ObjectType.self:
|
|
589
|
+
if (!object.data) {
|
|
590
|
+
// self without data is handled inside HashTreeParser and results in LocusInfoUpdateType.MEETING_ENDED, so we should never get here
|
|
591
|
+
LoggerProxy.logger.warn(
|
|
592
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> received SELF object without data, this is not expected!`
|
|
593
|
+
);
|
|
594
|
+
|
|
595
|
+
return locus;
|
|
596
|
+
}
|
|
597
|
+
LoggerProxy.logger.info(
|
|
598
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> SELF object updated`
|
|
599
|
+
);
|
|
600
|
+
locus.self = object.data;
|
|
601
|
+
break;
|
|
602
|
+
default:
|
|
603
|
+
LoggerProxy.logger.warn(
|
|
604
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> received unsupported object type ${type}`
|
|
605
|
+
);
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
return locus;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Sends a metric when we receive something from Locus that uses hash trees while we
|
|
614
|
+
* expect classic deltas or the other way around.
|
|
615
|
+
* @param {Meeting} meeting
|
|
616
|
+
* @param {string} message
|
|
617
|
+
* @returns {void}
|
|
618
|
+
*/
|
|
619
|
+
sendClassicVsHashTreeMismatchMetric(meeting: any, message: string) {
|
|
620
|
+
LoggerProxy.logger.warn(
|
|
621
|
+
`Locus-info:index#sendClassicVsHashTreeMismatchMetric --> classic vs hash tree mismatch! ${message}`
|
|
622
|
+
);
|
|
623
|
+
|
|
624
|
+
// we don't want to flood the metrics system
|
|
625
|
+
if (this.classicVsHashTreeMismatchMetricCounter < 5) {
|
|
626
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.LOCUS_CLASSIC_VS_HASH_TREE_MISMATCH, {
|
|
627
|
+
correlationId: meeting.correlationId,
|
|
628
|
+
message,
|
|
629
|
+
});
|
|
630
|
+
this.classicVsHashTreeMismatchMetricCounter += 1;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Handles a hash tree message received from Locus.
|
|
636
|
+
*
|
|
637
|
+
* @param {Meeting} meeting - The meeting object
|
|
638
|
+
* @param {eventType} eventType - The event type
|
|
639
|
+
* @param {HashTreeMessage} message incoming hash tree message
|
|
640
|
+
* @returns {void}
|
|
641
|
+
*/
|
|
642
|
+
private handleHashTreeMessage(meeting: any, eventType: LOCUSEVENT, message: HashTreeMessage) {
|
|
643
|
+
if (eventType !== LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
|
|
644
|
+
this.sendClassicVsHashTreeMismatchMetric(
|
|
645
|
+
meeting,
|
|
646
|
+
`got ${eventType}, expected ${LOCUSEVENT.HASH_TREE_DATA_UPDATED}`
|
|
647
|
+
);
|
|
648
|
+
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
this.hashTreeParser.handleMessage(message);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Callback registered with HashTreeParser to receive locus info updates.
|
|
657
|
+
* Updates our locus info based on the data parsed by the hash tree parser.
|
|
658
|
+
*
|
|
659
|
+
* @param {LocusInfoUpdateType} updateType - The type of update received.
|
|
660
|
+
* @param {Object} [data] - Additional data for the update, if applicable.
|
|
661
|
+
* @returns {void}
|
|
662
|
+
*/
|
|
663
|
+
private updateFromHashTree(
|
|
664
|
+
updateType: LocusInfoUpdateType,
|
|
665
|
+
data?: {updatedObjects: HashTreeObject[]}
|
|
666
|
+
) {
|
|
667
|
+
switch (updateType) {
|
|
668
|
+
case LocusInfoUpdateType.OBJECTS_UPDATED: {
|
|
669
|
+
// initialize our new locus
|
|
670
|
+
let locus: LocusDTO = {
|
|
671
|
+
participants: [],
|
|
672
|
+
jsSdkMeta: {removedParticipantIds: []},
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
// first go over all the updates and check what happens with the main locus object
|
|
676
|
+
let locusObjectStateAfterUpdates: LocusObjectStateAfterUpdates =
|
|
677
|
+
LocusObjectStateAfterUpdates.unchanged;
|
|
678
|
+
data.updatedObjects.forEach((object) => {
|
|
679
|
+
if (object.htMeta.elementId.type.toLowerCase() === ObjectType.locus) {
|
|
680
|
+
if (locusObjectStateAfterUpdates === LocusObjectStateAfterUpdates.updated) {
|
|
681
|
+
// this code doesn't supported it right now,
|
|
682
|
+
// cases for "updated" followed by "removed", or multiple "updated" would need more handling
|
|
683
|
+
// but these should never happen
|
|
684
|
+
LoggerProxy.logger.warn(
|
|
685
|
+
`Locus-info:index#updateFromHashTree --> received multiple LOCUS objects in one update, this is unexpected!`
|
|
686
|
+
);
|
|
687
|
+
Metrics.sendBehavioralMetric(
|
|
688
|
+
BEHAVIORAL_METRICS.LOCUS_HASH_TREE_UNSUPPORTED_OPERATION,
|
|
689
|
+
{
|
|
690
|
+
locusUrl: object.data?.url || this.url,
|
|
691
|
+
message: object.data
|
|
692
|
+
? 'multiple LOCUS object updates'
|
|
693
|
+
: 'LOCUS object update followed by removal',
|
|
694
|
+
}
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
if (object.data) {
|
|
698
|
+
locusObjectStateAfterUpdates = LocusObjectStateAfterUpdates.updated;
|
|
699
|
+
} else {
|
|
700
|
+
locusObjectStateAfterUpdates = LocusObjectStateAfterUpdates.removed;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
// if Locus object is unchanged or removed, we need to keep using the existing locus
|
|
706
|
+
// because the rest of the locusInfo code expects locus to always be present (with at least some of the fields)
|
|
707
|
+
// if it gets updated, we don't need to do anything and we start with an empty one
|
|
708
|
+
// so that when it gets updated, if the new one is missing some field, that field will
|
|
709
|
+
// be removed from our locusInfo
|
|
710
|
+
if (
|
|
711
|
+
locusObjectStateAfterUpdates === LocusObjectStateAfterUpdates.unchanged ||
|
|
712
|
+
locusObjectStateAfterUpdates === LocusObjectStateAfterUpdates.removed
|
|
713
|
+
) {
|
|
714
|
+
// copy over existing locus
|
|
715
|
+
LocusDtoTopLevelKeys.forEach((key) => {
|
|
716
|
+
if (key !== 'participants') {
|
|
717
|
+
locus[key] = cloneDeep(this[key]);
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
LoggerProxy.logger.info(
|
|
723
|
+
`Locus-info:index#updateFromHashTree --> LOCUS object is ${locusObjectStateAfterUpdates}, all updates: ${JSON.stringify(
|
|
724
|
+
data.updatedObjects.map((o) => ({
|
|
725
|
+
type: o.htMeta.elementId.type,
|
|
726
|
+
id: o.htMeta.elementId.id,
|
|
727
|
+
hasData: o.data !== undefined,
|
|
728
|
+
}))
|
|
729
|
+
)}`
|
|
730
|
+
);
|
|
731
|
+
// now apply all the updates from the hash tree onto the locus
|
|
732
|
+
data.updatedObjects.forEach((object) => {
|
|
733
|
+
locus = this.updateLocusFromHashTreeObject(object, locus);
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
// update our locus info with the new locus
|
|
737
|
+
this.onDeltaLocus(locus);
|
|
738
|
+
|
|
739
|
+
break;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
case LocusInfoUpdateType.MEETING_ENDED: {
|
|
743
|
+
LoggerProxy.logger.info(
|
|
744
|
+
`Locus-info:index#updateFromHashTree --> received signal that meeting ended, destroying meeting ${this.meetingId}`
|
|
745
|
+
);
|
|
746
|
+
const meeting = this.webex.meetings.meetingCollection.get(this.meetingId);
|
|
747
|
+
this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.SELF_REMOVED);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
379
750
|
}
|
|
380
751
|
|
|
381
752
|
/**
|
|
@@ -385,38 +756,52 @@ export default class LocusInfo extends EventsScope {
|
|
|
385
756
|
* @memberof LocusInfo
|
|
386
757
|
*/
|
|
387
758
|
parse(meeting: any, data: any) {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
759
|
+
if (this.hashTreeParser) {
|
|
760
|
+
this.handleHashTreeMessage(
|
|
761
|
+
meeting,
|
|
762
|
+
data.eventType,
|
|
763
|
+
data.stateElementsMessage as HashTreeMessage
|
|
764
|
+
);
|
|
765
|
+
} else {
|
|
766
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
767
|
+
const {eventType} = data;
|
|
768
|
+
const locus = this.getTheLocusToUpdate(data.locus);
|
|
769
|
+
LoggerProxy.logger.info(`Locus-info:index#parse --> received locus data: ${eventType}`);
|
|
770
|
+
|
|
771
|
+
locus.jsSdkMeta = {removedParticipantIds: []};
|
|
772
|
+
|
|
773
|
+
switch (eventType) {
|
|
774
|
+
case LOCUSEVENT.PARTICIPANT_JOIN:
|
|
775
|
+
case LOCUSEVENT.PARTICIPANT_LEFT:
|
|
776
|
+
case LOCUSEVENT.CONTROLS_UPDATED:
|
|
777
|
+
case LOCUSEVENT.PARTICIPANT_AUDIO_MUTED:
|
|
778
|
+
case LOCUSEVENT.PARTICIPANT_AUDIO_UNMUTED:
|
|
779
|
+
case LOCUSEVENT.PARTICIPANT_VIDEO_MUTED:
|
|
780
|
+
case LOCUSEVENT.PARTICIPANT_VIDEO_UNMUTED:
|
|
781
|
+
case LOCUSEVENT.SELF_CHANGED:
|
|
782
|
+
case LOCUSEVENT.PARTICIPANT_UPDATED:
|
|
783
|
+
case LOCUSEVENT.PARTICIPANT_CONTROLS_UPDATED:
|
|
784
|
+
case LOCUSEVENT.PARTICIPANT_ROLES_UPDATED:
|
|
785
|
+
case LOCUSEVENT.PARTICIPANT_DECLINED:
|
|
786
|
+
case LOCUSEVENT.FLOOR_GRANTED:
|
|
787
|
+
case LOCUSEVENT.FLOOR_RELEASED:
|
|
788
|
+
this.onFullLocus(locus, eventType);
|
|
789
|
+
break;
|
|
790
|
+
case LOCUSEVENT.DIFFERENCE:
|
|
791
|
+
this.handleLocusDelta(locus, meeting);
|
|
792
|
+
break;
|
|
793
|
+
case LOCUSEVENT.HASH_TREE_DATA_UPDATED:
|
|
794
|
+
this.sendClassicVsHashTreeMismatchMetric(
|
|
795
|
+
meeting,
|
|
796
|
+
`got ${eventType}, expected classic events`
|
|
797
|
+
);
|
|
798
|
+
break;
|
|
415
799
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
800
|
+
default:
|
|
801
|
+
// Why will there be a event with no eventType ????
|
|
802
|
+
// we may not need this, we can get full locus
|
|
803
|
+
this.handleLocusDelta(locus, meeting);
|
|
804
|
+
}
|
|
420
805
|
}
|
|
421
806
|
}
|
|
422
807
|
|
|
@@ -432,19 +817,45 @@ export default class LocusInfo extends EventsScope {
|
|
|
432
817
|
}
|
|
433
818
|
|
|
434
819
|
/**
|
|
435
|
-
*
|
|
820
|
+
* Function for handling full locus when it's using hash trees (so not the "classic" one).
|
|
821
|
+
*
|
|
436
822
|
* @param {object} locus locus object
|
|
437
|
-
* @param {string} eventType
|
|
438
|
-
* @
|
|
439
|
-
* @
|
|
823
|
+
* @param {string} eventType locus event
|
|
824
|
+
* @param {DataSet[]} dataSets
|
|
825
|
+
* @returns {void}
|
|
440
826
|
*/
|
|
441
|
-
|
|
442
|
-
if (!
|
|
443
|
-
LoggerProxy.logger.
|
|
444
|
-
|
|
827
|
+
private onFullLocusWithHashTrees(locus: any, eventType?: string, dataSets?: Array<DataSet>) {
|
|
828
|
+
if (!this.hashTreeParser) {
|
|
829
|
+
LoggerProxy.logger.info(`Locus-info:index#onFullLocus --> creating hash tree parser`);
|
|
830
|
+
LoggerProxy.logger.info(
|
|
831
|
+
'Locus-info:index#onFullLocus --> dataSets:',
|
|
832
|
+
dataSets,
|
|
833
|
+
' and locus:',
|
|
834
|
+
locus
|
|
835
|
+
);
|
|
836
|
+
this.hashTreeParser = this.createHashTreeParser({
|
|
837
|
+
initialLocus: {locus, dataSets},
|
|
838
|
+
});
|
|
839
|
+
this.onFullLocusCommon(locus, eventType);
|
|
840
|
+
} else {
|
|
841
|
+
// in this case the Locus we're getting is not necessarily the full one
|
|
842
|
+
// so treat it like if we just got it in any api response
|
|
843
|
+
|
|
844
|
+
LoggerProxy.logger.info(
|
|
845
|
+
'Locus-info:index#onFullLocus --> hash tree parser already exists, handling it like a normal API response'
|
|
445
846
|
);
|
|
847
|
+
this.handleLocusAPIResponse(undefined, {dataSets, locus});
|
|
446
848
|
}
|
|
849
|
+
}
|
|
447
850
|
|
|
851
|
+
/**
|
|
852
|
+
* Function for handling full locus when it's the "classic" one (not hash trees)
|
|
853
|
+
*
|
|
854
|
+
* @param {object} locus locus object
|
|
855
|
+
* @param {string} eventType locus event
|
|
856
|
+
* @returns {void}
|
|
857
|
+
*/
|
|
858
|
+
private onFullLocusClassic(locus: any, eventType?: string) {
|
|
448
859
|
if (!this.locusParser.isNewFullLocus(locus)) {
|
|
449
860
|
LoggerProxy.logger.info(
|
|
450
861
|
`Locus-info:index#onFullLocus --> ignoring old full locus DTO, eventType=${eventType}`
|
|
@@ -452,9 +863,47 @@ export default class LocusInfo extends EventsScope {
|
|
|
452
863
|
|
|
453
864
|
return;
|
|
454
865
|
}
|
|
866
|
+
this.onFullLocusCommon(locus, eventType);
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* updates the locus with full locus object
|
|
871
|
+
* @param {object} locus locus object
|
|
872
|
+
* @param {string} eventType locus event
|
|
873
|
+
* @param {DataSet[]} dataSets
|
|
874
|
+
* @returns {object} null
|
|
875
|
+
* @memberof LocusInfo
|
|
876
|
+
*/
|
|
877
|
+
onFullLocus(locus: any, eventType?: string, dataSets?: Array<DataSet>) {
|
|
878
|
+
if (!locus) {
|
|
879
|
+
LoggerProxy.logger.error(
|
|
880
|
+
'Locus-info:index#onFullLocus --> object passed as argument was invalid, continuing.'
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
if (dataSets) {
|
|
885
|
+
// this is the new hashmap Locus DTO format (only applicable to webinars for now)
|
|
886
|
+
this.onFullLocusWithHashTrees(locus, eventType, dataSets);
|
|
887
|
+
} else {
|
|
888
|
+
this.onFullLocusClassic(locus, eventType);
|
|
889
|
+
}
|
|
890
|
+
}
|
|
455
891
|
|
|
892
|
+
/**
|
|
893
|
+
* Common part of handling full locus, used by both classic and hash tree based locus handling
|
|
894
|
+
* @param {object} locus locus object
|
|
895
|
+
* @param {string} eventType locus event
|
|
896
|
+
* @returns {void}
|
|
897
|
+
*/
|
|
898
|
+
private onFullLocusCommon(locus: any, eventType?: string) {
|
|
456
899
|
this.scheduledMeeting = locus.meeting || null;
|
|
457
900
|
this.participants = locus.participants;
|
|
901
|
+
this.participants?.forEach((participant) => {
|
|
902
|
+
// participant.htMeta is set only for hash tree based locus
|
|
903
|
+
if (participant.htMeta?.elementId.id) {
|
|
904
|
+
this.hashTreeObjectId2ParticipantId.set(participant.htMeta.elementId.id, participant.id);
|
|
905
|
+
}
|
|
906
|
+
});
|
|
458
907
|
const isReplaceMembers = ControlsUtils.isNeedReplaceMembers(this.controls, locus.controls);
|
|
459
908
|
this.updateLocusInfo(locus);
|
|
460
909
|
this.updateParticipants(
|