@webex/plugin-meetings 3.8.1-web-workers-keepalive.1 → 3.9.0-webinar5k.1
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 +8 -2
- package/dist/constants.js.map +1 -1
- package/dist/hashTree/constants.js +23 -0
- package/dist/hashTree/constants.js.map +1 -0
- package/dist/hashTree/hashTree.js +516 -0
- package/dist/hashTree/hashTree.js.map +1 -0
- package/dist/hashTree/hashTreeParser.js +521 -0
- package/dist/hashTree/hashTreeParser.js.map +1 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +301 -59
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/brbState.js +14 -12
- package/dist/meeting/brbState.js.map +1 -1
- package/dist/meeting/index.js +110 -12
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +2 -5
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +19 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +8 -11
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +6 -2
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js.map +1 -1
- package/dist/member/types.js.map +1 -1
- package/dist/members/collection.js +13 -0
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +44 -23
- package/dist/members/index.js.map +1 -1
- package/dist/members/request.js +3 -3
- package/dist/members/request.js.map +1 -1
- package/dist/members/util.js +18 -6
- package/dist/members/util.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +32 -2
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/types/constants.d.ts +6 -0
- package/dist/types/hashTree/constants.d.ts +8 -0
- package/dist/types/hashTree/hashTree.d.ts +128 -0
- package/dist/types/hashTree/hashTreeParser.d.ts +152 -0
- package/dist/types/locus-info/index.d.ts +93 -3
- package/dist/types/meeting/brbState.d.ts +0 -1
- package/dist/types/meeting/index.d.ts +29 -3
- package/dist/types/meeting/request.d.ts +9 -1
- package/dist/types/meeting/request.type.d.ts +74 -0
- package/dist/types/meeting/util.d.ts +3 -3
- package/dist/types/member/types.d.ts +1 -0
- package/dist/types/members/collection.d.ts +6 -0
- package/dist/types/members/index.d.ts +15 -3
- package/dist/types/members/request.d.ts +1 -1
- package/dist/types/members/util.d.ts +5 -2
- package/dist/types/multistream/sendSlotManager.d.ts +16 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +24 -23
- package/src/constants.ts +7 -0
- package/src/hashTree/constants.ts +12 -0
- package/src/hashTree/hashTree.ts +460 -0
- package/src/hashTree/hashTreeParser.ts +556 -0
- package/src/locus-info/index.ts +393 -58
- package/src/meeting/brbState.ts +9 -7
- package/src/meeting/index.ts +104 -6
- package/src/meeting/muteState.ts +2 -6
- package/src/meeting/request.ts +16 -0
- package/src/meeting/request.type.ts +64 -0
- package/src/meeting/util.ts +17 -20
- package/src/meetings/index.ts +17 -3
- package/src/member/index.ts +1 -0
- package/src/member/types.ts +1 -0
- package/src/members/collection.ts +11 -0
- package/src/members/index.ts +33 -7
- package/src/members/request.ts +2 -2
- package/src/members/util.ts +14 -3
- package/src/multistream/sendSlotManager.ts +34 -2
- package/test/unit/spec/hashTree/hashTree.ts +394 -0
- package/test/unit/spec/hashTree/hashTreeParser.ts +156 -0
- package/test/unit/spec/locus-info/index.js +506 -55
- package/test/unit/spec/meeting/brbState.ts +9 -9
- package/test/unit/spec/meeting/index.js +475 -42
- package/test/unit/spec/meeting/request.js +71 -0
- package/test/unit/spec/members/index.js +33 -10
- package/test/unit/spec/members/request.js +2 -2
- package/test/unit/spec/members/utils.js +27 -7
- package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
- package/test/unit/spec/reachability/index.ts +3 -1
package/src/meeting/index.ts
CHANGED
@@ -66,7 +66,7 @@ import Media, {type BundlePolicy} from '../media';
|
|
66
66
|
import MediaProperties from '../media/properties';
|
67
67
|
import MeetingStateMachine from './state';
|
68
68
|
import {createMuteState} from './muteState';
|
69
|
-
import LocusInfo from '../locus-info';
|
69
|
+
import LocusInfo, {LocusDTO, LocusLLMEvent} from '../locus-info';
|
70
70
|
import Metrics from '../metrics';
|
71
71
|
import ReconnectionManager from '../reconnection-manager';
|
72
72
|
import ReconnectionNotStartedError from '../common/errors/reconnection-not-started';
|
@@ -121,6 +121,7 @@ import {
|
|
121
121
|
WEBINAR_ERROR_REGISTRATION_ID,
|
122
122
|
JOIN_BEFORE_HOST,
|
123
123
|
REGISTRATION_ID_STATUS,
|
124
|
+
STAGE_MANAGER_TYPE,
|
124
125
|
} from '../constants';
|
125
126
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
126
127
|
import ParameterError from '../common/errors/parameter';
|
@@ -164,6 +165,8 @@ import {BrbState, createBrbState} from './brbState';
|
|
164
165
|
import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
|
165
166
|
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
166
167
|
import {ReachabilityMetrics} from '../reachability/reachability.types';
|
168
|
+
import {SetStageOptions, SetStageVideoLayout, UnsetStageVideoLayout} from './request.type';
|
169
|
+
import {DataSet} from '../hashTree/hashTreeParser';
|
167
170
|
|
168
171
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
169
172
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
@@ -3861,15 +3864,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3861
3864
|
}
|
3862
3865
|
|
3863
3866
|
/**
|
3864
|
-
* Cancel an SIP call invitation made during a meeting
|
3867
|
+
* Cancel an SIP/phone call invitation made during a meeting
|
3865
3868
|
* @param {Object} invitee
|
3866
3869
|
* @param {String} invitee.memberId
|
3867
|
-
* @
|
3870
|
+
* @param {Boolean} [invitee.isInternalNumber] - When cancel phone invitation, if the number is internal
|
3871
|
+
* @returns {Promise} see #members.cancelInviteByMemberId
|
3868
3872
|
* @public
|
3869
3873
|
* @memberof Meeting
|
3870
3874
|
*/
|
3871
|
-
public
|
3872
|
-
return this.members.
|
3875
|
+
public cancelInviteByMemberId(invitee: {memberId: string; isInternalNumber?: boolean}) {
|
3876
|
+
return this.members.cancelInviteByMemberId(invitee);
|
3873
3877
|
}
|
3874
3878
|
|
3875
3879
|
/**
|
@@ -4475,11 +4479,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4475
4479
|
setLocus(
|
4476
4480
|
locus:
|
4477
4481
|
| {
|
4482
|
+
locus: LocusDTO;
|
4478
4483
|
mediaConnections: Array<any>;
|
4479
4484
|
locusUrl: string;
|
4480
4485
|
locusId: string;
|
4481
4486
|
mediaId: string;
|
4482
4487
|
host: object;
|
4488
|
+
dataSets: DataSet[];
|
4483
4489
|
}
|
4484
4490
|
| any
|
4485
4491
|
) {
|
@@ -4493,7 +4499,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4493
4499
|
this.selfId = locus.selfId;
|
4494
4500
|
this.mediaId = locus.mediaId;
|
4495
4501
|
this.hostId = mtgLocus.host ? mtgLocus.host.id : this.hostId;
|
4496
|
-
this.locusInfo.initialSetup(mtgLocus);
|
4502
|
+
this.locusInfo.initialSetup(mtgLocus, locus.dataSets);
|
4497
4503
|
}
|
4498
4504
|
|
4499
4505
|
/**
|
@@ -5606,6 +5612,21 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
5606
5612
|
}
|
5607
5613
|
}
|
5608
5614
|
|
5615
|
+
/** Handles Locus LLM events
|
5616
|
+
*
|
5617
|
+
* @param {LocusLLMEvent} event - The Locus LLM event to process
|
5618
|
+
* @returns {void}
|
5619
|
+
*/
|
5620
|
+
private processLocusLLMEvent = (event: LocusLLMEvent): void => {
|
5621
|
+
if (event.data.eventType === 'locus.state_message') {
|
5622
|
+
this.locusInfo.parse(this, event.data);
|
5623
|
+
} else {
|
5624
|
+
LoggerProxy.logger.warn(
|
5625
|
+
`Meeting:index#processLocusLLMEvent --> Unknown event type: ${event.data.eventType}`
|
5626
|
+
);
|
5627
|
+
}
|
5628
|
+
};
|
5629
|
+
|
5609
5630
|
/**
|
5610
5631
|
* Callback called when a relay event is received from meeting LLM Connection
|
5611
5632
|
* @param {RelayEvent} e Event object coming from LLM Connection
|
@@ -6026,6 +6047,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6026
6047
|
);
|
6027
6048
|
// @ts-ignore - Fix type
|
6028
6049
|
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
6050
|
+
// @ts-ignore - Fix type
|
6051
|
+
this.webex.internal.llm.off('event:locus.state_message', this.processLocusLLMEvent);
|
6029
6052
|
}
|
6030
6053
|
|
6031
6054
|
if (!isJoined) {
|
@@ -6040,6 +6063,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6040
6063
|
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
6041
6064
|
// @ts-ignore - Fix type
|
6042
6065
|
this.webex.internal.llm.on('event:relay.event', this.processRelayEvent);
|
6066
|
+
// @ts-ignore - Fix type
|
6067
|
+
this.webex.internal.llm.off('event:locus.state_message', this.processLocusLLMEvent);
|
6068
|
+
// @ts-ignore - Fix type
|
6069
|
+
this.webex.internal.llm.on('event:locus.state_message', this.processLocusLLMEvent);
|
6043
6070
|
LoggerProxy.logger.info(
|
6044
6071
|
'Meeting:index#updateLLMConnection --> enabled to receive relay events!'
|
6045
6072
|
);
|
@@ -9211,6 +9238,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9211
9238
|
|
9212
9239
|
// @ts-ignore - fix types
|
9213
9240
|
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
9241
|
+
// @ts-ignore - Fix type
|
9242
|
+
this.webex.internal.llm.off('event:locus.state_message', this.processLocusLLMEvent);
|
9214
9243
|
};
|
9215
9244
|
|
9216
9245
|
/**
|
@@ -9763,4 +9792,73 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9763
9792
|
selected_subnet: selectedSubnetFirstOctet ? `${selectedSubnetFirstOctet}.X.X.X` : null,
|
9764
9793
|
};
|
9765
9794
|
}
|
9795
|
+
|
9796
|
+
/**
|
9797
|
+
* Set the stage for the meeting
|
9798
|
+
*
|
9799
|
+
* @param {SetStageOptions} options Options to use when setting the stage
|
9800
|
+
* @returns {Promise} The locus request
|
9801
|
+
*/
|
9802
|
+
setStage({
|
9803
|
+
activeSpeakerProportion = 0.5,
|
9804
|
+
customBackground,
|
9805
|
+
customLogo,
|
9806
|
+
customNameLabel,
|
9807
|
+
importantParticipants,
|
9808
|
+
lockAttendeeViewOnStage = false,
|
9809
|
+
showActiveSpeaker = false,
|
9810
|
+
}: SetStageOptions = {}) {
|
9811
|
+
const videoLayout: SetStageVideoLayout = {
|
9812
|
+
overrideDefault: true,
|
9813
|
+
lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
|
9814
|
+
stageParameters: {
|
9815
|
+
activeSpeakerProportion,
|
9816
|
+
showActiveSpeaker: {show: showActiveSpeaker, order: 0},
|
9817
|
+
stageManagerType: 0,
|
9818
|
+
},
|
9819
|
+
};
|
9820
|
+
|
9821
|
+
if (importantParticipants?.length) {
|
9822
|
+
videoLayout.stageParameters.importantParticipants = importantParticipants.map(
|
9823
|
+
(importantParticipant, index) => ({...importantParticipant, order: index + 1})
|
9824
|
+
);
|
9825
|
+
}
|
9826
|
+
|
9827
|
+
if (customLogo) {
|
9828
|
+
if (!videoLayout.customLayouts) {
|
9829
|
+
videoLayout.customLayouts = {};
|
9830
|
+
}
|
9831
|
+
videoLayout.customLayouts.logo = customLogo;
|
9832
|
+
// eslint-disable-next-line no-bitwise
|
9833
|
+
videoLayout.stageParameters.stageManagerType |= STAGE_MANAGER_TYPE.LOGO;
|
9834
|
+
}
|
9835
|
+
|
9836
|
+
if (customBackground) {
|
9837
|
+
if (!videoLayout.customLayouts) {
|
9838
|
+
videoLayout.customLayouts = {};
|
9839
|
+
}
|
9840
|
+
videoLayout.customLayouts.background = customBackground;
|
9841
|
+
// eslint-disable-next-line no-bitwise
|
9842
|
+
videoLayout.stageParameters.stageManagerType |= STAGE_MANAGER_TYPE.BACKGROUND;
|
9843
|
+
}
|
9844
|
+
|
9845
|
+
if (customNameLabel) {
|
9846
|
+
videoLayout.nameLabelStyle = customNameLabel;
|
9847
|
+
// eslint-disable-next-line no-bitwise
|
9848
|
+
videoLayout.stageParameters.stageManagerType |= STAGE_MANAGER_TYPE.NAME_LABEL;
|
9849
|
+
}
|
9850
|
+
|
9851
|
+
return this.meetingRequest.synchronizeStage(this.locusUrl, videoLayout);
|
9852
|
+
}
|
9853
|
+
|
9854
|
+
/**
|
9855
|
+
* Unset the stage for the meeting
|
9856
|
+
*
|
9857
|
+
* @returns {Promise} The locus request
|
9858
|
+
*/
|
9859
|
+
unsetStage() {
|
9860
|
+
const videoLayout: UnsetStageVideoLayout = {overrideDefault: false};
|
9861
|
+
|
9862
|
+
return this.meetingRequest.synchronizeStage(this.locusUrl, videoLayout);
|
9863
|
+
}
|
9766
9864
|
}
|
package/src/meeting/muteState.ts
CHANGED
@@ -291,18 +291,14 @@ export class MuteState {
|
|
291
291
|
);
|
292
292
|
|
293
293
|
return MeetingUtil.remoteUpdateAudioVideo(meeting, audioMuted, videoMuted)
|
294
|
-
.then((
|
294
|
+
.then((response) => {
|
295
295
|
LoggerProxy.logger.info(
|
296
296
|
`Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: local mute (audio=${audioMuted}, video=${videoMuted}) applied to server`
|
297
297
|
);
|
298
298
|
|
299
299
|
this.state.server.localMute = this.type === AUDIO ? audioMuted : videoMuted;
|
300
300
|
|
301
|
-
|
302
|
-
meeting.locusInfo.handleLocusDelta(locus, meeting);
|
303
|
-
}
|
304
|
-
|
305
|
-
return locus;
|
301
|
+
return MeetingUtil.updateLocusFromApiResponse(meeting, response);
|
306
302
|
})
|
307
303
|
.catch((remoteUpdateError) => {
|
308
304
|
LoggerProxy.logger.warn(
|
package/src/meeting/request.ts
CHANGED
@@ -32,6 +32,7 @@ import {
|
|
32
32
|
BrbOptions,
|
33
33
|
ToggleReactionsOptions,
|
34
34
|
PostMeetingDataConsentOptions,
|
35
|
+
SynchronizeVideoLayout,
|
35
36
|
} from './request.type';
|
36
37
|
import MeetingUtil from './util';
|
37
38
|
import {AnnotationInfo} from '../annotation/annotation.types';
|
@@ -969,4 +970,19 @@ export default class MeetingRequest extends StatelessWebexPlugin {
|
|
969
970
|
},
|
970
971
|
});
|
971
972
|
}
|
973
|
+
|
974
|
+
/**
|
975
|
+
* Synchronize the stage for a meeting
|
976
|
+
*
|
977
|
+
* @param {LocusUrl} locusUrl The locus URL
|
978
|
+
* @param {SetStageVideoLayout} videoLayout The video layout to synchronize
|
979
|
+
* @returns {Promise} The locus request
|
980
|
+
*/
|
981
|
+
synchronizeStage(locusUrl: string, videoLayout: SynchronizeVideoLayout) {
|
982
|
+
return this.locusDeltaRequest({
|
983
|
+
method: HTTP_VERBS.PATCH,
|
984
|
+
uri: `${locusUrl}/${CONTROLS}`,
|
985
|
+
body: {videoLayout},
|
986
|
+
});
|
987
|
+
}
|
972
988
|
}
|
@@ -25,3 +25,67 @@ export type PostMeetingDataConsentOptions = {
|
|
25
25
|
deviceUrl: string;
|
26
26
|
selfId: string;
|
27
27
|
};
|
28
|
+
|
29
|
+
export type StageCustomLogoPositions =
|
30
|
+
| 'LowerLeft'
|
31
|
+
| 'LowerMiddle'
|
32
|
+
| 'LowerRight'
|
33
|
+
| 'UpperLeft'
|
34
|
+
| 'UpperMiddle'
|
35
|
+
| 'UpperRight';
|
36
|
+
|
37
|
+
export type StageNameLabelType = 'Primary' | 'PrimaryInverted' | 'Secondary' | 'SecondaryInverted';
|
38
|
+
|
39
|
+
export type StageCustomBackground = {
|
40
|
+
url: string;
|
41
|
+
[others: string]: unknown;
|
42
|
+
};
|
43
|
+
|
44
|
+
export type StageCustomLogo = {
|
45
|
+
url: string;
|
46
|
+
position: StageCustomLogoPositions;
|
47
|
+
[others: string]: unknown;
|
48
|
+
};
|
49
|
+
|
50
|
+
export type StageCustomNameLabel = {
|
51
|
+
accentColor: string;
|
52
|
+
background: {color: string};
|
53
|
+
border: {color: string};
|
54
|
+
content: {displayName: {color: string}; subtitle: {color: string}};
|
55
|
+
decoration: {color: string};
|
56
|
+
fadeOut?: {delay: number};
|
57
|
+
type: StageNameLabelType;
|
58
|
+
[others: string]: unknown;
|
59
|
+
};
|
60
|
+
|
61
|
+
export type SetStageOptions = {
|
62
|
+
activeSpeakerProportion?: number;
|
63
|
+
customBackground?: StageCustomBackground;
|
64
|
+
customLogo?: StageCustomLogo;
|
65
|
+
customNameLabel?: StageCustomNameLabel;
|
66
|
+
importantParticipants?: {mainCsi: number; participantId: string}[];
|
67
|
+
lockAttendeeViewOnStage?: boolean;
|
68
|
+
showActiveSpeaker?: boolean;
|
69
|
+
};
|
70
|
+
|
71
|
+
export type SetStageVideoLayout = {
|
72
|
+
overrideDefault: true;
|
73
|
+
lockAttendeeViewOnStageOnly: boolean;
|
74
|
+
stageParameters: {
|
75
|
+
importantParticipants?: {participantId: string; mainCsi: number; order: number}[];
|
76
|
+
showActiveSpeaker: {show: boolean; order: number};
|
77
|
+
activeSpeakerProportion: number;
|
78
|
+
stageManagerType: number;
|
79
|
+
};
|
80
|
+
customLayouts?: {
|
81
|
+
background?: StageCustomBackground;
|
82
|
+
logo?: StageCustomLogo;
|
83
|
+
};
|
84
|
+
nameLabelStyle?: StageCustomNameLabel;
|
85
|
+
};
|
86
|
+
|
87
|
+
export type UnsetStageVideoLayout = {
|
88
|
+
overrideDefault: false;
|
89
|
+
};
|
90
|
+
|
91
|
+
export type SynchronizeVideoLayout = SetStageVideoLayout | UnsetStageVideoLayout;
|
package/src/meeting/util.ts
CHANGED
@@ -31,6 +31,7 @@ const MeetingUtil = {
|
|
31
31
|
|
32
32
|
// First todo: add check for existance
|
33
33
|
parsed.locus = response.body.locus;
|
34
|
+
parsed.dataSets = response.body.dataSets;
|
34
35
|
parsed.mediaConnections = response.body.mediaConnections;
|
35
36
|
parsed.locusUrl = parsed.locus.url;
|
36
37
|
parsed.locusId = parsed.locus.url.split('/').pop();
|
@@ -59,18 +60,16 @@ const MeetingUtil = {
|
|
59
60
|
);
|
60
61
|
}
|
61
62
|
|
62
|
-
return meeting.locusMediaRequest
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
})
|
73
|
-
.then((response) => response?.body?.locus);
|
63
|
+
return meeting.locusMediaRequest.send({
|
64
|
+
type: 'LocalMute',
|
65
|
+
selfUrl: meeting.selfUrl,
|
66
|
+
mediaId: meeting.mediaId,
|
67
|
+
sequence: meeting.locusInfo.sequence,
|
68
|
+
muteOptions: {
|
69
|
+
audioMuted,
|
70
|
+
videoMuted,
|
71
|
+
},
|
72
|
+
});
|
74
73
|
},
|
75
74
|
|
76
75
|
hasOwner: (info) => info && info.owner,
|
@@ -602,22 +601,20 @@ const MeetingUtil = {
|
|
602
601
|
},
|
603
602
|
|
604
603
|
/**
|
605
|
-
* Updates the locus info for the meeting with the
|
606
|
-
* returned from requests
|
604
|
+
* Updates the locus info for the meeting with the locus
|
605
|
+
* information returned from API requests made to Locus
|
607
606
|
* Returns the original response object
|
608
607
|
* @param {Object} meeting The meeting object
|
609
608
|
* @param {Object} response The response of the http request
|
610
609
|
* @returns {Object}
|
611
610
|
*/
|
612
|
-
|
611
|
+
updateLocusFromApiResponse: (meeting, response) => {
|
613
612
|
if (!meeting) {
|
614
613
|
return response;
|
615
614
|
}
|
616
615
|
|
617
|
-
|
618
|
-
|
619
|
-
if (locus) {
|
620
|
-
meeting.locusInfo.handleLocusDelta(locus, meeting);
|
616
|
+
if (response?.body?.locus) {
|
617
|
+
meeting.locusInfo.handleLocusAPIResponse(meeting, response.body);
|
621
618
|
}
|
622
619
|
|
623
620
|
return response;
|
@@ -664,7 +661,7 @@ const MeetingUtil = {
|
|
664
661
|
|
665
662
|
return meeting
|
666
663
|
.request(options)
|
667
|
-
.then((response) => MeetingUtil.
|
664
|
+
.then((response) => MeetingUtil.updateLocusFromApiResponse(meeting, response));
|
668
665
|
};
|
669
666
|
|
670
667
|
return locusDeltaRequest;
|
package/src/meetings/index.ts
CHANGED
@@ -66,6 +66,7 @@ import JoinWebinarError from '../common/errors/join-webinar-error';
|
|
66
66
|
import {SpaceIDDeprecatedError} from '../common/errors/webex-errors';
|
67
67
|
import NoMeetingInfoError from '../common/errors/no-meeting-info';
|
68
68
|
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
69
|
+
import {DataSet} from '../hashTree/hashTreeParser';
|
69
70
|
|
70
71
|
let mediaLogger;
|
71
72
|
|
@@ -407,6 +408,13 @@ export default class Meetings extends WebexPlugin {
|
|
407
408
|
* @memberof Meetings
|
408
409
|
*/
|
409
410
|
getCorrespondingMeetingByLocus(data) {
|
411
|
+
if (data.eventType === 'locus.state_message' && data.stateElementsMessage?.locusUrl) {
|
412
|
+
return this.meetingCollection.getByKey(
|
413
|
+
MEETING_KEY.LOCUS_URL,
|
414
|
+
data.stateElementsMessage.locusUrl
|
415
|
+
);
|
416
|
+
}
|
417
|
+
|
410
418
|
// getting meeting by correlationId. This will happen for the new event
|
411
419
|
// Either the locus
|
412
420
|
// TODO : Add check for the callBack Address
|
@@ -445,7 +453,10 @@ export default class Meetings extends WebexPlugin {
|
|
445
453
|
* @private
|
446
454
|
* @memberof Meetings
|
447
455
|
*/
|
448
|
-
private handleLocusEvent(
|
456
|
+
private handleLocusEvent(
|
457
|
+
data: {locusUrl: string; locus: any; dataSets?: DataSet[]},
|
458
|
+
useRandomDelayForInfo = false
|
459
|
+
) {
|
449
460
|
let meeting = this.getCorrespondingMeetingByLocus(data);
|
450
461
|
|
451
462
|
// Special case when locus has got replaced, This only happend once if a replace locus exists
|
@@ -524,7 +535,7 @@ export default class Meetings extends WebexPlugin {
|
|
524
535
|
meeting = newMeeting;
|
525
536
|
|
526
537
|
// It's a new meeting so initialize the locus data
|
527
|
-
meeting.locusInfo.initialSetup(data.locus);
|
538
|
+
meeting.locusInfo.initialSetup(data.locus, data.dataSets);
|
528
539
|
this.checkHandleBreakoutLocus(data.locus);
|
529
540
|
})
|
530
541
|
.catch((e) => {
|
@@ -1824,7 +1835,10 @@ export default class Meetings extends WebexPlugin {
|
|
1824
1835
|
}
|
1825
1836
|
|
1826
1837
|
const associateBreakoutLocus = this.breakoutLocusForHandleLater[existIndex];
|
1827
|
-
this.handleLocusEvent({
|
1838
|
+
this.handleLocusEvent({
|
1839
|
+
locus: associateBreakoutLocus,
|
1840
|
+
locusUrl: associateBreakoutLocus.url,
|
1841
|
+
});
|
1828
1842
|
this.breakoutLocusForHandleLater.splice(existIndex, 1);
|
1829
1843
|
}
|
1830
1844
|
|
package/src/member/index.ts
CHANGED
package/src/member/types.ts
CHANGED
@@ -39,6 +39,17 @@ export default class MembersCollection {
|
|
39
39
|
return this.members;
|
40
40
|
}
|
41
41
|
|
42
|
+
/**
|
43
|
+
* Removes a member from the collection
|
44
|
+
* @param {String} id
|
45
|
+
* @returns {void}
|
46
|
+
*/
|
47
|
+
remove(id: string) {
|
48
|
+
if (this.members[id]) {
|
49
|
+
delete this.members[id];
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
42
53
|
/**
|
43
54
|
* @returns {void}
|
44
55
|
* reset members
|
package/src/members/index.ts
CHANGED
@@ -73,7 +73,11 @@ import {ServerRoleShape} from './types';
|
|
73
73
|
* @memberof Members
|
74
74
|
*/
|
75
75
|
|
76
|
-
type UpdatedMembers = {
|
76
|
+
type UpdatedMembers = {
|
77
|
+
added: Array<Member>;
|
78
|
+
updated: Array<Member>;
|
79
|
+
removedIds?: Array<string>; // removed member ids
|
80
|
+
};
|
77
81
|
/**
|
78
82
|
* @class Members
|
79
83
|
*/
|
@@ -388,7 +392,11 @@ export default class Members extends StatelessWebexPlugin {
|
|
388
392
|
* @private
|
389
393
|
* @memberof Members
|
390
394
|
*/
|
391
|
-
locusParticipantsUpdate(payload: {
|
395
|
+
locusParticipantsUpdate(payload: {
|
396
|
+
participants: object;
|
397
|
+
isReplace?: boolean;
|
398
|
+
removedParticipantIds?: Array<string>;
|
399
|
+
}) {
|
392
400
|
if (payload) {
|
393
401
|
if (payload.isReplace) {
|
394
402
|
this.clearMembers();
|
@@ -546,10 +554,22 @@ export default class Members extends StatelessWebexPlugin {
|
|
546
554
|
private handleMembersUpdate(membersUpdate: UpdatedMembers) {
|
547
555
|
this.constructMembers(membersUpdate.updated, true);
|
548
556
|
this.constructMembers(membersUpdate.added, false);
|
557
|
+
this.removeMembers(membersUpdate.removedIds);
|
549
558
|
|
550
559
|
return this.membersCollection.getAll();
|
551
560
|
}
|
552
561
|
|
562
|
+
/**
|
563
|
+
* removes members from the collection
|
564
|
+
* @param {Array<string>} removedMembers removed members ids
|
565
|
+
* @returns {void}
|
566
|
+
*/
|
567
|
+
private removeMembers(removedMembers: Array<string>) {
|
568
|
+
removedMembers.forEach((memberId) => {
|
569
|
+
this.membersCollection.remove(memberId);
|
570
|
+
});
|
571
|
+
}
|
572
|
+
|
553
573
|
/**
|
554
574
|
* set members to the member collection from each updated/added lists as passed in
|
555
575
|
* @param {Array} list
|
@@ -599,6 +619,10 @@ export default class Members extends StatelessWebexPlugin {
|
|
599
619
|
}
|
600
620
|
const memberUpdate = this.update(payload.participants);
|
601
621
|
|
622
|
+
// this code depends on memberIds being the same as participantIds
|
623
|
+
// if MemberUtil.extractId() ever changes, this will need to be updated
|
624
|
+
memberUpdate.removedIds = payload.removedParticipantIds || [];
|
625
|
+
|
602
626
|
return memberUpdate;
|
603
627
|
}
|
604
628
|
|
@@ -846,12 +870,14 @@ export default class Members extends StatelessWebexPlugin {
|
|
846
870
|
}
|
847
871
|
|
848
872
|
/**
|
849
|
-
* Cancels an SIP call to the associated meeting
|
850
|
-
* @param {
|
873
|
+
* Cancels an SIP/phone call to the associated meeting
|
874
|
+
* @param {Object} invitee
|
875
|
+
* @param {String} invitee.memberId - The memberId of the invitee
|
876
|
+
* @param {Boolean} [invitee.isInternalNumber] - When cancel phone invitation, if the number is internal
|
851
877
|
* @returns {Promise}
|
852
878
|
* @memberof Members
|
853
879
|
*/
|
854
|
-
|
880
|
+
cancelInviteByMemberId(invitee: {memberId: string; isInternalNumber?: boolean}) {
|
855
881
|
if (!this.locusUrl) {
|
856
882
|
return Promise.reject(
|
857
883
|
new ParameterError('The associated locus url for this meeting object must be defined.')
|
@@ -862,9 +888,9 @@ export default class Members extends StatelessWebexPlugin {
|
|
862
888
|
new ParameterError('The invitee must be defined with a memberId property.')
|
863
889
|
);
|
864
890
|
}
|
865
|
-
const options = MembersUtil.
|
891
|
+
const options = MembersUtil.cancelInviteByMemberIdOptions(invitee, this.locusUrl);
|
866
892
|
|
867
|
-
return this.membersRequest.
|
893
|
+
return this.membersRequest.cancelInviteByMemberId(options);
|
868
894
|
}
|
869
895
|
|
870
896
|
/**
|
package/src/members/request.ts
CHANGED
@@ -285,14 +285,14 @@ export default class MembersRequest extends StatelessWebexPlugin {
|
|
285
285
|
* @throws {Error} if the options are not valid and complete, must have invitee with memberId AND locusUrl
|
286
286
|
* @memberof MembersRequest
|
287
287
|
*/
|
288
|
-
|
288
|
+
cancelInviteByMemberId(options: any) {
|
289
289
|
if (!options?.invitee?.memberId || !options?.locusUrl) {
|
290
290
|
throw new ParameterError(
|
291
291
|
'invitee must be passed and the associated locus url for this meeting object must be defined.'
|
292
292
|
);
|
293
293
|
}
|
294
294
|
|
295
|
-
const requestParams = MembersUtil.
|
295
|
+
const requestParams = MembersUtil.generateCancelInviteByMemberIdRequestParams(options);
|
296
296
|
|
297
297
|
return this.locusDeltaRequest(requestParams);
|
298
298
|
}
|
package/src/members/util.ts
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import uuid from 'uuid';
|
2
|
+
import {has} from 'lodash';
|
2
3
|
import {
|
3
4
|
HTTP_VERBS,
|
4
5
|
CONTROLS,
|
@@ -47,6 +48,9 @@ const MembersUtil = {
|
|
47
48
|
address:
|
48
49
|
options.invitee.emailAddress || options.invitee.email || options.invitee.phoneNumber,
|
49
50
|
...(options.invitee.roles ? {roles: options.invitee.roles} : {}),
|
51
|
+
...(has(options.invitee, 'isInternalNumber')
|
52
|
+
? {isInternalNumber: options.invitee.isInternalNumber}
|
53
|
+
: {}),
|
50
54
|
},
|
51
55
|
],
|
52
56
|
alertIfActive: options.alertIfActive,
|
@@ -107,6 +111,10 @@ const MembersUtil = {
|
|
107
111
|
}
|
108
112
|
|
109
113
|
if (invitee.phoneNumber) {
|
114
|
+
if (invitee.isInternalNumber) {
|
115
|
+
return !DIALER_REGEX.INTERNAL_NUMBER.test(invitee.phoneNumber);
|
116
|
+
}
|
117
|
+
|
110
118
|
return !DIALER_REGEX.E164_FORMAT.test(invitee.phoneNumber);
|
111
119
|
}
|
112
120
|
|
@@ -371,17 +379,20 @@ const MembersUtil = {
|
|
371
379
|
return requestParams;
|
372
380
|
},
|
373
381
|
|
374
|
-
|
382
|
+
cancelInviteByMemberIdOptions: (invitee, locusUrl) => ({
|
375
383
|
invitee,
|
376
384
|
locusUrl,
|
377
385
|
}),
|
378
386
|
|
379
|
-
|
387
|
+
generateCancelInviteByMemberIdRequestParams: (options) => {
|
388
|
+
const {memberId, isInternalNumber} = options.invitee;
|
389
|
+
const hasIsInternalNumberProp = has(options.invitee, 'isInternalNumber');
|
380
390
|
const body = {
|
381
391
|
actionType: _REMOVE_,
|
382
392
|
invitees: [
|
383
393
|
{
|
384
|
-
address:
|
394
|
+
address: memberId,
|
395
|
+
...(hasIsInternalNumberProp ? {isInternalNumber} : {}),
|
385
396
|
},
|
386
397
|
],
|
387
398
|
};
|