@webex/plugin-meetings 3.12.0-next.9 → 3.12.0-next.90
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/AGENTS.md +9 -0
- package/dist/aiEnableRequest/index.js +15 -2
- package/dist/aiEnableRequest/index.js.map +1 -1
- package/dist/breakouts/breakout.js +8 -3
- package/dist/breakouts/breakout.js.map +1 -1
- package/dist/breakouts/index.js +26 -2
- package/dist/breakouts/index.js.map +1 -1
- package/dist/config.js +2 -2
- package/dist/config.js.map +1 -1
- package/dist/constants.js +35 -9
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.js +11 -1
- package/dist/controls-options-manager/constants.js.map +1 -1
- package/dist/controls-options-manager/index.js +67 -29
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/controls-options-manager/util.js +91 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/hashTree/constants.js +13 -1
- package/dist/hashTree/constants.js.map +1 -1
- package/dist/hashTree/hashTreeParser.js +880 -382
- package/dist/hashTree/hashTreeParser.js.map +1 -1
- package/dist/hashTree/utils.js +42 -0
- package/dist/hashTree/utils.js.map +1 -1
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -1
- package/dist/interceptors/dataChannelAuthToken.js +75 -15
- package/dist/interceptors/dataChannelAuthToken.js.map +1 -1
- package/dist/interceptors/locusRetry.js +23 -8
- package/dist/interceptors/locusRetry.js.map +1 -1
- package/dist/interpretation/index.js +10 -1
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/interpretation.types.js +7 -0
- package/dist/interpretation/interpretation.types.js.map +1 -0
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +4 -1
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +303 -88
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/infoUtils.js +36 -5
- package/dist/locus-info/infoUtils.js.map +1 -1
- package/dist/locus-info/types.js +19 -0
- package/dist/locus-info/types.js.map +1 -1
- package/dist/media/index.js +3 -1
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.js +1 -0
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +5 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +1233 -793
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +229 -82
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +10 -1
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +5 -2
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/util.js +35 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +2 -2
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +231 -118
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.js +6 -1
- package/dist/meetings/meetings.types.js.map +1 -1
- package/dist/meetings/request.js +39 -0
- package/dist/meetings/request.js.map +1 -1
- package/dist/meetings/util.js +79 -5
- package/dist/meetings/util.js.map +1 -1
- package/dist/member/index.js +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js.map +1 -1
- package/dist/member/util.js +30 -0
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +101 -43
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +8 -1
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +5 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/codec/constants.js +63 -0
- package/dist/multistream/codec/constants.js.map +1 -0
- package/dist/multistream/mediaRequestManager.js +62 -15
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/receiveSlot.js +9 -0
- package/dist/multistream/receiveSlot.js.map +1 -1
- package/dist/reachability/index.js +10 -13
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +2 -0
- package/dist/reachability/reachability.types.js.map +1 -1
- package/dist/reachability/util.js +45 -0
- package/dist/reachability/util.js.map +1 -1
- package/dist/reactions/reactions.type.js.map +1 -1
- package/dist/recording-controller/index.js +1 -3
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/types/config.d.ts +2 -2
- package/dist/types/constants.d.ts +12 -1
- package/dist/types/controls-options-manager/constants.d.ts +6 -1
- package/dist/types/controls-options-manager/index.d.ts +16 -0
- package/dist/types/hashTree/constants.d.ts +2 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +146 -17
- package/dist/types/hashTree/utils.d.ts +18 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/interceptors/locusRetry.d.ts +4 -4
- package/dist/types/interpretation/interpretation.types.d.ts +10 -0
- package/dist/types/locus-info/index.d.ts +50 -6
- package/dist/types/locus-info/infoUtils.d.ts +8 -0
- package/dist/types/locus-info/types.d.ts +21 -1
- package/dist/types/media/properties.d.ts +1 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +4 -0
- package/dist/types/meeting/index.d.ts +94 -7
- package/dist/types/meeting/locusMediaRequest.d.ts +12 -0
- package/dist/types/meeting/request.d.ts +1 -0
- package/dist/types/meeting/util.d.ts +9 -0
- package/dist/types/meetings/index.d.ts +30 -18
- package/dist/types/meetings/meetings.types.d.ts +15 -0
- package/dist/types/meetings/request.d.ts +14 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/types.d.ts +1 -0
- package/dist/types/member/util.d.ts +9 -0
- package/dist/types/members/index.d.ts +15 -2
- package/dist/types/members/util.d.ts +1 -5
- package/dist/types/metrics/constants.d.ts +4 -0
- package/dist/types/multistream/codec/constants.d.ts +7 -0
- package/dist/types/multistream/mediaRequestManager.d.ts +22 -5
- package/dist/types/reachability/index.d.ts +1 -1
- package/dist/types/reachability/reachability.types.d.ts +7 -0
- package/dist/types/reachability/util.d.ts +17 -0
- package/dist/types/reactions/reactions.type.d.ts +3 -0
- package/dist/webinar/index.js +305 -159
- package/dist/webinar/index.js.map +1 -1
- package/package.json +22 -22
- package/src/aiEnableRequest/index.ts +16 -0
- package/src/breakouts/breakout.ts +3 -1
- package/src/breakouts/index.ts +31 -0
- package/src/config.ts +2 -2
- package/src/constants.ts +20 -3
- package/src/controls-options-manager/constants.ts +14 -1
- package/src/controls-options-manager/index.ts +87 -28
- package/src/controls-options-manager/util.ts +81 -1
- package/src/hashTree/constants.ts +16 -0
- package/src/hashTree/hashTreeParser.ts +580 -196
- package/src/hashTree/utils.ts +36 -0
- package/src/index.ts +6 -0
- package/src/interceptors/dataChannelAuthToken.ts +88 -12
- package/src/interceptors/locusRetry.ts +25 -4
- package/src/interpretation/index.ts +27 -9
- package/src/interpretation/interpretation.types.ts +11 -0
- package/src/locus-info/controlsUtils.ts +3 -1
- package/src/locus-info/index.ts +304 -100
- package/src/locus-info/infoUtils.ts +41 -6
- package/src/locus-info/types.ts +25 -1
- package/src/media/index.ts +3 -0
- package/src/media/properties.ts +1 -0
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +494 -67
- package/src/meeting/locusMediaRequest.ts +106 -6
- package/src/meeting/muteState.ts +10 -1
- package/src/meeting/request.ts +11 -0
- package/src/meeting/util.ts +47 -5
- package/src/meeting-info/meeting-info-v2.ts +4 -2
- package/src/meetings/index.ts +133 -78
- package/src/meetings/meetings.types.ts +19 -0
- package/src/meetings/request.ts +43 -0
- package/src/meetings/util.ts +97 -1
- package/src/member/index.ts +10 -0
- package/src/member/types.ts +1 -0
- package/src/member/util.ts +29 -0
- package/src/members/index.ts +70 -7
- package/src/members/util.ts +12 -4
- package/src/metrics/constants.ts +4 -0
- package/src/multistream/codec/constants.ts +58 -0
- package/src/multistream/mediaRequestManager.ts +119 -28
- package/src/multistream/receiveSlot.ts +18 -0
- package/src/reachability/index.ts +19 -15
- package/src/reachability/reachability.types.ts +11 -0
- package/src/reachability/util.ts +36 -0
- package/src/reactions/reactions.type.ts +3 -0
- package/src/recording-controller/index.ts +1 -2
- package/src/webinar/index.ts +214 -36
- package/test/unit/spec/aiEnableRequest/index.ts +86 -0
- package/test/unit/spec/breakouts/breakout.ts +9 -3
- package/test/unit/spec/breakouts/index.ts +49 -0
- package/test/unit/spec/controls-options-manager/index.js +244 -29
- package/test/unit/spec/controls-options-manager/util.js +165 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +1838 -180
- package/test/unit/spec/hashTree/utils.ts +125 -1
- package/test/unit/spec/interceptors/dataChannelAuthToken.ts +196 -0
- package/test/unit/spec/interceptors/locusRetry.ts +205 -4
- package/test/unit/spec/interpretation/index.ts +26 -4
- package/test/unit/spec/locus-info/controlsUtils.js +172 -57
- package/test/unit/spec/locus-info/index.js +499 -81
- package/test/unit/spec/locus-info/infoUtils.js +184 -1
- package/test/unit/spec/media/index.ts +31 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
- package/test/unit/spec/meeting/index.js +1615 -42
- package/test/unit/spec/meeting/locusMediaRequest.ts +302 -4
- package/test/unit/spec/meeting/muteState.js +81 -0
- package/test/unit/spec/meeting/request.js +12 -0
- package/test/unit/spec/meeting/utils.js +157 -1
- package/test/unit/spec/meeting-info/meetinginfov2.js +19 -10
- package/test/unit/spec/meetings/index.js +363 -36
- package/test/unit/spec/meetings/request.js +141 -0
- package/test/unit/spec/meetings/utils.js +189 -0
- package/test/unit/spec/member/index.js +7 -0
- package/test/unit/spec/member/util.js +89 -0
- package/test/unit/spec/members/index.js +216 -0
- package/test/unit/spec/members/request.js +37 -1
- package/test/unit/spec/members/utils.js +63 -0
- package/test/unit/spec/multistream/mediaRequestManager.ts +501 -37
- package/test/unit/spec/reachability/index.ts +59 -46
- package/test/unit/spec/reachability/util.ts +31 -0
- package/test/unit/spec/recording-controller/index.js +9 -8
- package/test/unit/spec/webinar/index.ts +329 -28
package/src/locus-info/index.ts
CHANGED
|
@@ -34,6 +34,7 @@ import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
|
34
34
|
import HashTreeParser, {
|
|
35
35
|
DataSet,
|
|
36
36
|
HashTreeMessage,
|
|
37
|
+
LocusInfoUpdate,
|
|
37
38
|
LocusInfoUpdateType,
|
|
38
39
|
Metadata,
|
|
39
40
|
} from '../hashTree/hashTreeParser';
|
|
@@ -97,7 +98,7 @@ export type HashTreeParserEntry = {
|
|
|
97
98
|
* Gets the replacement information
|
|
98
99
|
*
|
|
99
100
|
* @param {any} self - "self" object from Locus DTO
|
|
100
|
-
* @param {string} deviceUrl - The URL of the
|
|
101
|
+
* @param {string} deviceUrl - The URL of the specified device
|
|
101
102
|
* @returns {any} The replace information if available, otherwise undefined
|
|
102
103
|
*/
|
|
103
104
|
function getReplaceInfoFromSelf(self: any, deviceUrl: string): ReplacesInfo | undefined {
|
|
@@ -137,14 +138,15 @@ function findLocusUrlInAnyHashTreeParser(
|
|
|
137
138
|
*
|
|
138
139
|
* @param {HashTreeMessage} message - The hash tree message to find the meeting for
|
|
139
140
|
* @param {MeetingCollection} meetingCollection - The collection of meetings to search
|
|
140
|
-
* @param {string} deviceUrl - The URL of the user's device
|
|
141
141
|
* @returns {any} The meeting if found, otherwise undefined
|
|
142
142
|
*/
|
|
143
143
|
export function findMeetingForHashTreeMessage(
|
|
144
|
-
message: HashTreeMessage,
|
|
145
|
-
meetingCollection: MeetingCollection
|
|
146
|
-
deviceUrl: string
|
|
144
|
+
message: HashTreeMessage | undefined,
|
|
145
|
+
meetingCollection: MeetingCollection
|
|
147
146
|
): any {
|
|
147
|
+
if (!message) {
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
148
150
|
let foundMeeting = findLocusUrlInAnyHashTreeParser(meetingCollection, message.locusUrl);
|
|
149
151
|
|
|
150
152
|
if (foundMeeting) {
|
|
@@ -154,7 +156,7 @@ export function findMeetingForHashTreeMessage(
|
|
|
154
156
|
// if we haven't found anything, it may mean that message has a new locusUrl
|
|
155
157
|
// check if it indicates that it replaces some existing current locusUrl (this is indicated in "self")
|
|
156
158
|
const self = message.locusStateElements?.find((el) => isSelf(el))?.data;
|
|
157
|
-
const replaces = getReplaceInfoFromSelf(self, deviceUrl);
|
|
159
|
+
const replaces = getReplaceInfoFromSelf(self, self?.deviceUrl);
|
|
158
160
|
|
|
159
161
|
if (replaces?.locusUrl) {
|
|
160
162
|
foundMeeting = findLocusUrlInAnyHashTreeParser(meetingCollection, replaces.locusUrl);
|
|
@@ -545,7 +547,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
545
547
|
dataSets: Array<DataSet>;
|
|
546
548
|
locus: any;
|
|
547
549
|
};
|
|
548
|
-
metadata: Metadata;
|
|
550
|
+
metadata: Metadata | null;
|
|
549
551
|
replacedAt?: string;
|
|
550
552
|
}): HashTreeParser {
|
|
551
553
|
const parser = new HashTreeParser({
|
|
@@ -553,7 +555,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
553
555
|
metadata,
|
|
554
556
|
webexRequest: this.webex.request.bind(this.webex),
|
|
555
557
|
locusInfoUpdateCallback: this.updateFromHashTree.bind(this, locusUrl),
|
|
556
|
-
debugId: `HT-${locusUrl.split('/')
|
|
558
|
+
debugId: `HT-${locusUrl.split('/')?.pop()?.substring(0, 4)}`,
|
|
557
559
|
excludedDataSets: this.webex.config.meetings.locus?.excludedDataSets,
|
|
558
560
|
});
|
|
559
561
|
|
|
@@ -580,6 +582,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
580
582
|
|
|
581
583
|
/**
|
|
582
584
|
* @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
|
|
585
|
+
* @param {Function} [onLocusSynced] - optional callback that will be called at the end of initial setup, when locus info is fully synced. It will be called with the full locus snapshot as an argument (which may be null if we haven't received any full locus DTOs during the initial setup, for example in case we receive only hash tree messages without full locus DTOs)
|
|
583
586
|
* @returns {undefined}
|
|
584
587
|
* @memberof LocusInfo
|
|
585
588
|
*/
|
|
@@ -599,8 +602,10 @@ export default class LocusInfo extends EventsScope {
|
|
|
599
602
|
| {
|
|
600
603
|
trigger: 'get-loci-response';
|
|
601
604
|
locus?: LocusDTO;
|
|
602
|
-
}
|
|
605
|
+
},
|
|
606
|
+
onLocusSynced?: (locus: LocusDTO) => void
|
|
603
607
|
) {
|
|
608
|
+
let initialFullLocus: LocusDTO | null = null;
|
|
604
609
|
switch (data.trigger) {
|
|
605
610
|
case 'locus-message':
|
|
606
611
|
if (data.hashTreeMessage) {
|
|
@@ -648,6 +653,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
648
653
|
case 'join-response':
|
|
649
654
|
this.updateLocusCache(data.locus);
|
|
650
655
|
this.onFullLocus('join response', data.locus, undefined, data.dataSets, data.metadata);
|
|
656
|
+
initialFullLocus = data.locus;
|
|
651
657
|
break;
|
|
652
658
|
case 'get-loci-response':
|
|
653
659
|
if (data.locus?.links?.resources?.visibleDataSets?.url) {
|
|
@@ -656,7 +662,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
656
662
|
);
|
|
657
663
|
// first create the HashTreeParser, but don't initialize it with any data yet
|
|
658
664
|
const hashTreeParser = this.createHashTreeParser({
|
|
659
|
-
locusUrl: data.locus.url,
|
|
665
|
+
locusUrl: data.locus.url as string,
|
|
660
666
|
initialLocus: {
|
|
661
667
|
locus: null,
|
|
662
668
|
dataSets: [], // empty, because we don't have them yet
|
|
@@ -670,52 +676,99 @@ export default class LocusInfo extends EventsScope {
|
|
|
670
676
|
// "classic" Locus case, no hash trees involved
|
|
671
677
|
this.updateLocusCache(data.locus);
|
|
672
678
|
this.onFullLocus('classic get-loci-response', data.locus, undefined);
|
|
679
|
+
initialFullLocus = data.locus || null;
|
|
673
680
|
}
|
|
674
681
|
}
|
|
682
|
+
|
|
683
|
+
if (onLocusSynced) {
|
|
684
|
+
try {
|
|
685
|
+
onLocusSynced(initialFullLocus || this.getCurrentLocusSnapshot());
|
|
686
|
+
} catch (error) {
|
|
687
|
+
LoggerProxy.logger.warn(
|
|
688
|
+
`Locus-info:index#initialSetup --> onLocusSynced callback failed: ${error}`
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
675
693
|
// Change it to true after it receives it first locus object
|
|
676
694
|
this.emitChange = true;
|
|
677
695
|
}
|
|
678
696
|
|
|
697
|
+
/**
|
|
698
|
+
* Builds a full locus DTO snapshot from current internal locus state.
|
|
699
|
+
*
|
|
700
|
+
* @returns {LocusDTO}
|
|
701
|
+
*/
|
|
702
|
+
private getCurrentLocusSnapshot(): LocusDTO {
|
|
703
|
+
const locus: Record<string, any> = {};
|
|
704
|
+
|
|
705
|
+
LocusDtoTopLevelKeys.forEach((key) => {
|
|
706
|
+
const value = (this as Record<string, any>)[key];
|
|
707
|
+
|
|
708
|
+
if (value !== undefined && value !== null) {
|
|
709
|
+
locus[key] = cloneDeep(value);
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
if (!Array.isArray(locus.participants)) {
|
|
714
|
+
locus.participants = [];
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
return locus as LocusDTO;
|
|
718
|
+
}
|
|
719
|
+
|
|
679
720
|
/**
|
|
680
721
|
* Handles HTTP response from Locus API call.
|
|
681
722
|
* @param {Meeting} meeting meeting object
|
|
682
723
|
* @param {LocusApiResponseBody} responseBody body of the http response from Locus API call
|
|
683
724
|
* @returns {void}
|
|
684
725
|
*/
|
|
685
|
-
handleLocusAPIResponse(meeting, responseBody: LocusApiResponseBody): void {
|
|
726
|
+
handleLocusAPIResponse(meeting: any, responseBody: LocusApiResponseBody): void {
|
|
686
727
|
const isWrapped = 'locus' in responseBody;
|
|
687
728
|
const locusUrl = isWrapped ? responseBody.locus?.url : responseBody.url;
|
|
688
729
|
const hashTreeParserEntry = locusUrl && this.hashTreeParsers.get(locusUrl);
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
730
|
+
const locus = isWrapped
|
|
731
|
+
? (responseBody as {locus: LocusDTO}).locus
|
|
732
|
+
: (responseBody as LocusDTO);
|
|
733
|
+
|
|
734
|
+
if (this.hashTreeParsers.size > 0) {
|
|
735
|
+
// We are in hash tree mode. Check if we need to create/reactivate a parser for this locusUrl.
|
|
736
|
+
if (!hashTreeParserEntry || hashTreeParserEntry.parser.state === 'stopped') {
|
|
737
|
+
if (!locusUrl) {
|
|
738
|
+
LoggerProxy.logger.warn(
|
|
739
|
+
'Locus-info:index#handleLocusAPIResponse --> API response has no locusUrl, cannot handle hash tree parser switch'
|
|
695
740
|
);
|
|
696
|
-
|
|
741
|
+
|
|
742
|
+
return;
|
|
697
743
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
744
|
+
|
|
745
|
+
this.handleHashTreeParserSwitchForAPIResponse(locusUrl, locus);
|
|
746
|
+
|
|
747
|
+
return;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// Active parser found - pass the API response to it
|
|
751
|
+
if (isWrapped) {
|
|
702
752
|
// update the data in our hash trees
|
|
703
753
|
hashTreeParserEntry.parser.handleLocusUpdate(responseBody);
|
|
704
754
|
} else {
|
|
705
|
-
// LocusDTO without wrapper - pass it through as if it had no dataSets
|
|
755
|
+
// LocusDTO without wrapper - pass it through as if it had no dataSets nor metadata
|
|
706
756
|
hashTreeParserEntry.parser.handleLocusUpdate({locus: responseBody});
|
|
707
757
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
this.sendClassicVsHashTreeMismatchMetric(
|
|
711
|
-
meeting,
|
|
712
|
-
`unexpected hash tree dataSets in API response`
|
|
713
|
-
);
|
|
714
|
-
}
|
|
715
|
-
// classic Locus delta
|
|
716
|
-
const locus = isWrapped ? responseBody.locus : responseBody;
|
|
717
|
-
this.handleLocusDelta(locus, meeting);
|
|
758
|
+
|
|
759
|
+
return;
|
|
718
760
|
}
|
|
761
|
+
|
|
762
|
+
// No hash tree parsers - classic Locus mode
|
|
763
|
+
if (isWrapped && responseBody.dataSets) {
|
|
764
|
+
this.sendClassicVsHashTreeMismatchMetric(
|
|
765
|
+
meeting,
|
|
766
|
+
`unexpected hash tree dataSets in API response`
|
|
767
|
+
);
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// classic Locus delta
|
|
771
|
+
this.handleLocusDelta(locus, meeting);
|
|
719
772
|
}
|
|
720
773
|
|
|
721
774
|
/**
|
|
@@ -877,14 +930,22 @@ export default class LocusInfo extends EventsScope {
|
|
|
877
930
|
if (!object.data) {
|
|
878
931
|
// self without data is handled inside HashTreeParser and results in LocusInfoUpdateType.MEETING_ENDED, so we should never get here
|
|
879
932
|
// all other types info, fullstate, etc - Locus should never send them without data
|
|
880
|
-
|
|
881
|
-
|
|
933
|
+
// but we end up with this method being called without the data for them when the main dataset is removed from visible datasets list
|
|
934
|
+
LoggerProxy.logger.info(
|
|
935
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> received ${type} object without data, version=${object.htMeta.elementId.version}`
|
|
882
936
|
);
|
|
883
937
|
} else {
|
|
884
938
|
LoggerProxy.logger.info(
|
|
885
939
|
`Locus-info:index#updateLocusFromHashTreeObject --> ${type} object updated to version ${object.htMeta.elementId.version}`
|
|
886
940
|
);
|
|
887
|
-
|
|
941
|
+
|
|
942
|
+
if (type === ObjectType.self) {
|
|
943
|
+
LoggerProxy.logger.info(
|
|
944
|
+
`Locus-info:index#updateLocusFromHashTreeObject --> self data: removed=${object.data.removed} state=${object.data.state} reason=${object.data.reason}`
|
|
945
|
+
);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
const locusDtoKey = ObjectTypeToLocusKeyMap[type] as keyof LocusDTO;
|
|
888
949
|
locus[locusDtoKey] = object.data;
|
|
889
950
|
|
|
890
951
|
/* Hash tree based webinar attendees don't receive a Participant object for themselves from Locus,
|
|
@@ -944,6 +1005,114 @@ export default class LocusInfo extends EventsScope {
|
|
|
944
1005
|
}
|
|
945
1006
|
}
|
|
946
1007
|
|
|
1008
|
+
/**
|
|
1009
|
+
* Helper that handles the common logic for reactivating a stopped HashTreeParser when
|
|
1010
|
+
* a newer "replaces" is detected. Used by both the message and API response parser switch methods.
|
|
1011
|
+
*
|
|
1012
|
+
* @param {string} callerName - name of the calling method, used in log messages
|
|
1013
|
+
* @param {string} locusUrl - the locus URL of the stopped parser
|
|
1014
|
+
* @param {HashTreeParserEntry} stoppedEntry - the stopped parser entry
|
|
1015
|
+
* @param {ReplacesInfo} replaces - replacement info extracted from self
|
|
1016
|
+
* @param {Function} resumeCallback - callback to invoke after reactivation to resume the parser
|
|
1017
|
+
* @returns {void}
|
|
1018
|
+
*/
|
|
1019
|
+
private resumeStoppedParser(
|
|
1020
|
+
callerName: string,
|
|
1021
|
+
locusUrl: string,
|
|
1022
|
+
stoppedEntry: HashTreeParserEntry,
|
|
1023
|
+
replaces: ReplacesInfo | undefined,
|
|
1024
|
+
resumeCallback: () => void
|
|
1025
|
+
): void {
|
|
1026
|
+
// this check is just for typescript, it should never happen, replaces should always be defined
|
|
1027
|
+
if (!replaces) {
|
|
1028
|
+
LoggerProxy.logger.info(
|
|
1029
|
+
`Locus-info:index#${callerName} --> received data for stopped HashTreeParser with locusUrl ${locusUrl}, but no replaces info provided, so not re-activating the parser`
|
|
1030
|
+
);
|
|
1031
|
+
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
if (replaces.replacedAt <= (stoppedEntry.replacedAt || '')) {
|
|
1036
|
+
LoggerProxy.logger.info(
|
|
1037
|
+
`Locus-info:index#${callerName} --> received data for stopped HashTreeParser with locusUrl ${locusUrl}, but replaces info provided is not newer, so not re-activating the parser`
|
|
1038
|
+
);
|
|
1039
|
+
|
|
1040
|
+
return;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
LoggerProxy.logger.info(
|
|
1044
|
+
`Locus-info:index#${callerName} --> reactivating HashTreeParser for locusUrl=${locusUrl}, which replaces ${replaces.locusUrl}`
|
|
1045
|
+
);
|
|
1046
|
+
|
|
1047
|
+
const replacedEntry = this.hashTreeParsers.get(replaces.locusUrl);
|
|
1048
|
+
|
|
1049
|
+
if (replacedEntry) {
|
|
1050
|
+
replacedEntry.replacedAt = replaces.replacedAt;
|
|
1051
|
+
replacedEntry.parser.stop();
|
|
1052
|
+
} else {
|
|
1053
|
+
LoggerProxy.logger.warn(
|
|
1054
|
+
`Locus-info:index#${callerName} --> the parser that is supposed to be replaced with the currently reactivated parser is not found, locusUrl=${replaces.locusUrl}`
|
|
1055
|
+
);
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
stoppedEntry.initializedFromHashTree = false;
|
|
1059
|
+
this.hashTreeObjectId2ParticipantId.clear();
|
|
1060
|
+
|
|
1061
|
+
resumeCallback();
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
/**
|
|
1065
|
+
* Handles an API response whose locusUrl doesn't match any active HashTreeParser
|
|
1066
|
+
* (either no entry exists, or the existing entry is stopped).
|
|
1067
|
+
* Creates a new parser or reactivates a stopped one using initializeFromGetLociResponse.
|
|
1068
|
+
*
|
|
1069
|
+
* @param {string} locusUrl - the locus URL from the API response
|
|
1070
|
+
* @param {LocusDTO} locus - the locus DTO from the API response
|
|
1071
|
+
* @returns {void}
|
|
1072
|
+
*/
|
|
1073
|
+
private handleHashTreeParserSwitchForAPIResponse(locusUrl: string, locus: LocusDTO): void {
|
|
1074
|
+
const entry = this.hashTreeParsers.get(locusUrl);
|
|
1075
|
+
|
|
1076
|
+
const replaces = getReplaceInfoFromSelf(
|
|
1077
|
+
locus.self,
|
|
1078
|
+
// @ts-ignore
|
|
1079
|
+
this.webex.internal.device.url
|
|
1080
|
+
);
|
|
1081
|
+
|
|
1082
|
+
if (!entry) {
|
|
1083
|
+
LoggerProxy.logger.info(
|
|
1084
|
+
`Locus-info:index#handleHashTreeParserSwitchForAPIResponse --> no parser for locusUrl ${locusUrl}, creating a new one`
|
|
1085
|
+
);
|
|
1086
|
+
|
|
1087
|
+
const parser = this.createHashTreeParser({
|
|
1088
|
+
locusUrl,
|
|
1089
|
+
initialLocus: {locus: null, dataSets: []},
|
|
1090
|
+
metadata: null,
|
|
1091
|
+
replacedAt: replaces?.replacedAt,
|
|
1092
|
+
});
|
|
1093
|
+
|
|
1094
|
+
parser.initializeFromGetLociResponse(locus);
|
|
1095
|
+
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
if (entry.parser.state !== 'stopped') {
|
|
1100
|
+
LoggerProxy.logger.warn(
|
|
1101
|
+
`Locus-info:index#handleHashTreeParserSwitchForAPIResponse --> unexpected parser state "${entry.parser.state}" for locusUrl ${locusUrl}`
|
|
1102
|
+
);
|
|
1103
|
+
|
|
1104
|
+
return;
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
this.resumeStoppedParser(
|
|
1108
|
+
'handleHashTreeParserSwitchForAPIResponse',
|
|
1109
|
+
locusUrl,
|
|
1110
|
+
entry,
|
|
1111
|
+
replaces,
|
|
1112
|
+
() => entry.parser.resumeFromApiResponse(locus)
|
|
1113
|
+
);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
947
1116
|
/**
|
|
948
1117
|
* Checks if the hash tree message should trigger a switch to a different HashTreeParser
|
|
949
1118
|
*
|
|
@@ -965,7 +1134,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
965
1134
|
// but it's buried inside the message, we need to find it and pass it to HashTreeParser constructor
|
|
966
1135
|
const metadata = message.locusStateElements?.find((el) => isMetadata(el));
|
|
967
1136
|
|
|
968
|
-
if (metadata
|
|
1137
|
+
if (metadata && metadata.data?.visibleDataSets?.length > 0) {
|
|
969
1138
|
LoggerProxy.logger.info(
|
|
970
1139
|
`Locus-info:index#handleHashTreeParserSwitch --> no hash tree parser found for locusUrl ${message.locusUrl}, creating a new one`
|
|
971
1140
|
);
|
|
@@ -992,36 +1161,12 @@ export default class LocusInfo extends EventsScope {
|
|
|
992
1161
|
if (entry.parser.state === 'stopped') {
|
|
993
1162
|
// the message matches a stopped parser, we need to check if maybe this is a new "replacement" and we need to re-activate the parser
|
|
994
1163
|
// this happens when you move from breakout A -> breakout B -> back to breakout A
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
if (replacedEntry) {
|
|
1003
|
-
replacedEntry.replacedAt = replaces.replacedAt;
|
|
1004
|
-
entry.initializedFromHashTree = false;
|
|
1005
|
-
this.hashTreeObjectId2ParticipantId.clear();
|
|
1006
|
-
|
|
1007
|
-
replacedEntry.parser.stop();
|
|
1008
|
-
entry.parser.resume(message);
|
|
1009
|
-
} else {
|
|
1010
|
-
LoggerProxy.logger.warn(
|
|
1011
|
-
`Locus-info:index#handleHashTreeParserSwitch --> the parser that is supposed to be replaced with the currently resumed parser is not found, locusUrl=${replaces.locusUrl}`
|
|
1012
|
-
);
|
|
1013
|
-
}
|
|
1014
|
-
} else {
|
|
1015
|
-
LoggerProxy.logger.info(
|
|
1016
|
-
`Locus-info:index#handleHashTreeParserSwitch --> received message for stopped HashTreeParser with locusUrl ${message.locusUrl}, but replaces info provided is not newer, so not re-activating the parser`
|
|
1017
|
-
);
|
|
1018
|
-
}
|
|
1019
|
-
|
|
1020
|
-
return true;
|
|
1021
|
-
}
|
|
1022
|
-
|
|
1023
|
-
LoggerProxy.logger.info(
|
|
1024
|
-
`Locus-info:index#handleHashTreeParserSwitch --> received message for stopped HashTreeParser with locusUrl ${message.locusUrl}, but no replaces info provided, so not re-activating the parser`
|
|
1164
|
+
this.resumeStoppedParser(
|
|
1165
|
+
'handleHashTreeParserSwitch',
|
|
1166
|
+
message.locusUrl,
|
|
1167
|
+
entry,
|
|
1168
|
+
replaces,
|
|
1169
|
+
() => entry.parser.resumeFromMessage(message)
|
|
1025
1170
|
);
|
|
1026
1171
|
|
|
1027
1172
|
return true;
|
|
@@ -1056,7 +1201,27 @@ export default class LocusInfo extends EventsScope {
|
|
|
1056
1201
|
|
|
1057
1202
|
const entry = this.hashTreeParsers.get(message.locusUrl);
|
|
1058
1203
|
|
|
1059
|
-
entry
|
|
1204
|
+
// the check is just for typescript, the case of no entry in hashTreeParsers is handled in handleHashTreeParserSwitch() above
|
|
1205
|
+
if (entry) {
|
|
1206
|
+
entry.parser.handleMessage(message);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
/**
|
|
1211
|
+
* Triggers a sync of all hash tree datasets for all hash tree parsers associated with this meeting.
|
|
1212
|
+
* The syncs are executed sequentially within each parser.
|
|
1213
|
+
*
|
|
1214
|
+
* @param {Object} [options={}] - Options for syncing
|
|
1215
|
+
* @param {boolean} [options.onlyLLM=false] - Whether to sync only LLM based data sets
|
|
1216
|
+
* @returns {Promise<void>}
|
|
1217
|
+
*/
|
|
1218
|
+
async syncAllHashTreeDatasets(options: {onlyLLM?: boolean} = {}): Promise<void> {
|
|
1219
|
+
for (const [, entry] of this.hashTreeParsers) {
|
|
1220
|
+
if (entry.parser) {
|
|
1221
|
+
// eslint-disable-next-line no-await-in-loop
|
|
1222
|
+
await entry.parser.syncAllDatasets(options);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1060
1225
|
}
|
|
1061
1226
|
|
|
1062
1227
|
/**
|
|
@@ -1064,16 +1229,11 @@ export default class LocusInfo extends EventsScope {
|
|
|
1064
1229
|
* Updates our locus info based on the data parsed by the hash tree parser.
|
|
1065
1230
|
*
|
|
1066
1231
|
* @param {string} locusUrl - the locus URL for which the update is received
|
|
1067
|
-
* @param {
|
|
1068
|
-
* @param {Object} [data] - Additional data for the update, if applicable.
|
|
1232
|
+
* @param {LocusInfoUpdate} update - Details about the update.
|
|
1069
1233
|
* @returns {void}
|
|
1070
1234
|
*/
|
|
1071
|
-
private updateFromHashTree(
|
|
1072
|
-
|
|
1073
|
-
updateType: LocusInfoUpdateType,
|
|
1074
|
-
data?: {updatedObjects: HashTreeObject[]}
|
|
1075
|
-
) {
|
|
1076
|
-
switch (updateType) {
|
|
1235
|
+
private updateFromHashTree(locusUrl: string, update: LocusInfoUpdate) {
|
|
1236
|
+
switch (update.updateType) {
|
|
1077
1237
|
case LocusInfoUpdateType.OBJECTS_UPDATED: {
|
|
1078
1238
|
// initialize our new locus
|
|
1079
1239
|
let locus: LocusDTO = {
|
|
@@ -1087,7 +1247,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1087
1247
|
// first go over all the updates and check what happens with the main locus object
|
|
1088
1248
|
let locusObjectStateAfterUpdates: LocusObjectStateAfterUpdates =
|
|
1089
1249
|
LocusObjectStateAfterUpdates.unchanged;
|
|
1090
|
-
|
|
1250
|
+
update.updatedObjects.forEach((object) => {
|
|
1091
1251
|
if (object.htMeta.elementId.type.toLowerCase() === ObjectType.locus) {
|
|
1092
1252
|
if (locusObjectStateAfterUpdates === LocusObjectStateAfterUpdates.updated) {
|
|
1093
1253
|
// this code doesn't supported it right now,
|
|
@@ -1116,6 +1276,14 @@ export default class LocusInfo extends EventsScope {
|
|
|
1116
1276
|
|
|
1117
1277
|
const hashTreeParserEntry = this.hashTreeParsers.get(locusUrl);
|
|
1118
1278
|
|
|
1279
|
+
if (!hashTreeParserEntry) {
|
|
1280
|
+
LoggerProxy.logger.warn(
|
|
1281
|
+
`Locus-info:index#updateFromHashTree --> no HashTreeParser found for locusUrl ${locusUrl} when trying to apply updates from hash tree`
|
|
1282
|
+
);
|
|
1283
|
+
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1119
1287
|
if (!hashTreeParserEntry.initializedFromHashTree) {
|
|
1120
1288
|
// this is the first time we're getting an update for this locusUrl,
|
|
1121
1289
|
// so it's probably a move to/from breakout. We need to start from a clean state,
|
|
@@ -1124,7 +1292,8 @@ export default class LocusInfo extends EventsScope {
|
|
|
1124
1292
|
`Locus-info:index#updateFromHashTree --> first INITIAL update for locusUrl ${locusUrl}, starting from empty state`
|
|
1125
1293
|
);
|
|
1126
1294
|
hashTreeParserEntry.initializedFromHashTree = true;
|
|
1127
|
-
|
|
1295
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1296
|
+
locus.jsSdkMeta!.forceReplaceMembers = true;
|
|
1128
1297
|
} else if (
|
|
1129
1298
|
// if Locus object is unchanged or removed, we need to keep using the existing locus
|
|
1130
1299
|
// because the rest of the locusInfo code expects locus to always be present (with at least some of the fields)
|
|
@@ -1137,7 +1306,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1137
1306
|
// copy over all of existing locus except participants
|
|
1138
1307
|
LocusDtoTopLevelKeys.forEach((key) => {
|
|
1139
1308
|
if (key !== 'participants') {
|
|
1140
|
-
locus[key] = cloneDeep(this[key]);
|
|
1309
|
+
(locus as Record<string, any>)[key] = cloneDeep((this as Record<string, any>)[key]);
|
|
1141
1310
|
}
|
|
1142
1311
|
});
|
|
1143
1312
|
} else {
|
|
@@ -1145,14 +1314,16 @@ export default class LocusInfo extends EventsScope {
|
|
|
1145
1314
|
// (except participants, which need to stay empty - that means "no participant changes")
|
|
1146
1315
|
Object.values(ObjectTypeToLocusKeyMap).forEach((locusDtoKey) => {
|
|
1147
1316
|
if (locusDtoKey !== 'participants') {
|
|
1148
|
-
locus[locusDtoKey] = cloneDeep(
|
|
1317
|
+
(locus as Record<string, any>)[locusDtoKey] = cloneDeep(
|
|
1318
|
+
(this as Record<string, any>)[locusDtoKey]
|
|
1319
|
+
);
|
|
1149
1320
|
}
|
|
1150
1321
|
});
|
|
1151
1322
|
}
|
|
1152
1323
|
|
|
1153
1324
|
LoggerProxy.logger.info(
|
|
1154
1325
|
`Locus-info:index#updateFromHashTree --> LOCUS object is ${locusObjectStateAfterUpdates}, all updates: ${JSON.stringify(
|
|
1155
|
-
|
|
1326
|
+
update.updatedObjects.map((o) => ({
|
|
1156
1327
|
type: o.htMeta.elementId.type,
|
|
1157
1328
|
id: o.htMeta.elementId.id,
|
|
1158
1329
|
hasData: !!o.data,
|
|
@@ -1160,7 +1331,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1160
1331
|
)}`
|
|
1161
1332
|
);
|
|
1162
1333
|
// now apply all the updates from the hash tree onto the locus
|
|
1163
|
-
|
|
1334
|
+
update.updatedObjects.forEach((object) => {
|
|
1164
1335
|
locus = this.updateLocusFromHashTreeObject(object, locus);
|
|
1165
1336
|
});
|
|
1166
1337
|
|
|
@@ -1179,6 +1350,21 @@ export default class LocusInfo extends EventsScope {
|
|
|
1179
1350
|
);
|
|
1180
1351
|
this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.SELF_REMOVED);
|
|
1181
1352
|
}
|
|
1353
|
+
break;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1356
|
+
case LocusInfoUpdateType.LOCUS_NOT_FOUND: {
|
|
1357
|
+
LoggerProxy.logger.info(
|
|
1358
|
+
`Locus-info:index#updateFromHashTree --> received LOCUS_NOT_FOUND for ${locusUrl}, triggering syncMeetings`
|
|
1359
|
+
);
|
|
1360
|
+
this.webex.meetings
|
|
1361
|
+
.syncMeetings({keepOnlyLocusMeetings: false, skipHashTreeSync: true})
|
|
1362
|
+
.catch((syncError) => {
|
|
1363
|
+
LoggerProxy.logger.error(
|
|
1364
|
+
`Locus-info:index#updateFromHashTree --> syncMeetings failed after LOCUS_NOT_FOUND: ${syncError}`
|
|
1365
|
+
);
|
|
1366
|
+
});
|
|
1367
|
+
break;
|
|
1182
1368
|
}
|
|
1183
1369
|
}
|
|
1184
1370
|
}
|
|
@@ -1191,11 +1377,17 @@ export default class LocusInfo extends EventsScope {
|
|
|
1191
1377
|
*/
|
|
1192
1378
|
parse(meeting: any, data: any) {
|
|
1193
1379
|
if (this.hashTreeParsers.size > 0) {
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
data.
|
|
1198
|
-
|
|
1380
|
+
if (data.eventType === LOCUSEVENT.SDK_LOCUS_FROM_SYNC_MEETINGS) {
|
|
1381
|
+
// sync meetings response follows the format of "not wrapped" locus API responses,
|
|
1382
|
+
// so has no dataSets nor Metadata
|
|
1383
|
+
this.handleLocusAPIResponse(meeting, {...data.locus});
|
|
1384
|
+
} else {
|
|
1385
|
+
this.handleHashTreeMessage(
|
|
1386
|
+
meeting,
|
|
1387
|
+
data.eventType,
|
|
1388
|
+
data.stateElementsMessage as HashTreeMessage
|
|
1389
|
+
);
|
|
1390
|
+
}
|
|
1199
1391
|
} else {
|
|
1200
1392
|
const {eventType} = data;
|
|
1201
1393
|
|
|
@@ -1260,16 +1452,16 @@ export default class LocusInfo extends EventsScope {
|
|
|
1260
1452
|
* @param {string} debugText string explaining the trigger for this call, added to logs for debugging purposes
|
|
1261
1453
|
* @param {object} locus locus object
|
|
1262
1454
|
* @param {object} metadata locus hash trees metadata
|
|
1263
|
-
* @param {string} eventType locus event
|
|
1264
1455
|
* @param {DataSet[]} dataSets
|
|
1456
|
+
* @param {string} eventType locus event
|
|
1265
1457
|
* @returns {void}
|
|
1266
1458
|
*/
|
|
1267
1459
|
private onFullLocusWithHashTrees(
|
|
1268
1460
|
debugText: string,
|
|
1269
1461
|
locus: any,
|
|
1270
1462
|
metadata: Metadata,
|
|
1271
|
-
|
|
1272
|
-
|
|
1463
|
+
dataSets: Array<DataSet>,
|
|
1464
|
+
eventType?: string
|
|
1273
1465
|
) {
|
|
1274
1466
|
if (!this.hashTreeParsers.has(locus.url)) {
|
|
1275
1467
|
LoggerProxy.logger.info(
|
|
@@ -1289,7 +1481,8 @@ export default class LocusInfo extends EventsScope {
|
|
|
1289
1481
|
metadata,
|
|
1290
1482
|
});
|
|
1291
1483
|
// we have a full locus to start with, so we consider Locus info to be "initialized"
|
|
1292
|
-
|
|
1484
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
1485
|
+
this.hashTreeParsers.get(locus.url)!.initializedFromHashTree = true;
|
|
1293
1486
|
this.onFullLocusCommon(locus, eventType);
|
|
1294
1487
|
} else {
|
|
1295
1488
|
// in this case the Locus we're getting is not necessarily the full one
|
|
@@ -1351,7 +1544,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1351
1544
|
);
|
|
1352
1545
|
}
|
|
1353
1546
|
// this is the new hashmap Locus DTO format (only applicable to webinars for now)
|
|
1354
|
-
this.onFullLocusWithHashTrees(debugText, locus, metadata,
|
|
1547
|
+
this.onFullLocusWithHashTrees(debugText, locus, metadata, dataSets, eventType);
|
|
1355
1548
|
} else {
|
|
1356
1549
|
this.onFullLocusClassic(debugText, locus, eventType);
|
|
1357
1550
|
}
|
|
@@ -1495,7 +1688,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1495
1688
|
* @memberof LocusInfo
|
|
1496
1689
|
*/
|
|
1497
1690
|
updateLocusInfo(locus) {
|
|
1498
|
-
if (
|
|
1691
|
+
if (MeetingsUtil.isSelfMovedOrBreakoutEnded(locus)) {
|
|
1499
1692
|
// When moved to a breakout session locus sends a message for the previous locus
|
|
1500
1693
|
// indicating that we have been moved. It isn't helpful to continue parsing this
|
|
1501
1694
|
// as it gets interpreted as if we have left the call
|
|
@@ -1648,14 +1841,9 @@ export default class LocusInfo extends EventsScope {
|
|
|
1648
1841
|
);
|
|
1649
1842
|
}
|
|
1650
1843
|
} else if (this.parsedLocus.fullState?.type === _MEETING_) {
|
|
1651
|
-
if (
|
|
1652
|
-
this.fullState &&
|
|
1653
|
-
(this.fullState.state === LOCUS.STATE.INACTIVE ||
|
|
1654
|
-
// @ts-ignore
|
|
1655
|
-
this.fullState.state === LOCUS.STATE.TERMINATING)
|
|
1656
|
-
) {
|
|
1844
|
+
if (this.fullState && MeetingsUtil.isWholeMeetingEnded(this.fullState)) {
|
|
1657
1845
|
LoggerProxy.logger.warn(
|
|
1658
|
-
'Locus-info:index#isMeetingActive --> Meeting is ending due to inactive
|
|
1846
|
+
'Locus-info:index#isMeetingActive --> Meeting is ending due to inactive'
|
|
1659
1847
|
);
|
|
1660
1848
|
|
|
1661
1849
|
// @ts-ignore
|
|
@@ -1918,6 +2106,8 @@ export default class LocusInfo extends EventsScope {
|
|
|
1918
2106
|
state,
|
|
1919
2107
|
modifiedBy: current.record.modifiedBy,
|
|
1920
2108
|
lastModified: current.record.lastModified,
|
|
2109
|
+
modifiedByServiceAppName: current.record.modifiedByServiceAppName,
|
|
2110
|
+
modifiedByServiceAppId: current.record.modifiedByServiceAppId,
|
|
1921
2111
|
}
|
|
1922
2112
|
);
|
|
1923
2113
|
}
|
|
@@ -2587,6 +2777,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
2587
2777
|
{
|
|
2588
2778
|
muted: parsedSelves.current.remoteMuted,
|
|
2589
2779
|
unmuteAllowed: parsedSelves.current.unmuteAllowed,
|
|
2780
|
+
modifiedBy: parsedSelves.current.modifiedBy ?? null,
|
|
2590
2781
|
}
|
|
2591
2782
|
);
|
|
2592
2783
|
}
|
|
@@ -2859,4 +3050,17 @@ export default class LocusInfo extends EventsScope {
|
|
|
2859
3050
|
clearMainSessionLocusCache() {
|
|
2860
3051
|
this.mainSessionLocusCache = null;
|
|
2861
3052
|
}
|
|
3053
|
+
|
|
3054
|
+
/**
|
|
3055
|
+
* Cleans up all hash tree parsers and clears internal maps.
|
|
3056
|
+
* @returns {void}
|
|
3057
|
+
* @memberof LocusInfo
|
|
3058
|
+
*/
|
|
3059
|
+
cleanUp() {
|
|
3060
|
+
this.hashTreeParsers.forEach((entry) => {
|
|
3061
|
+
entry.parser.cleanUp();
|
|
3062
|
+
});
|
|
3063
|
+
this.hashTreeParsers.clear();
|
|
3064
|
+
this.hashTreeObjectId2ParticipantId.clear();
|
|
3065
|
+
}
|
|
2862
3066
|
}
|