@webex/plugin-meetings 3.9.0-webinar5k.1 → 3.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.js +16 -0
- package/dist/constants.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +40 -328
- package/dist/locus-info/index.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +6 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +196 -160
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/muteState.js +5 -2
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/type.js +7 -0
- package/dist/meeting/type.js.map +1 -0
- package/dist/meeting/util.js +79 -10
- package/dist/meeting/util.js.map +1 -1
- package/dist/meetings/index.js +37 -39
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/types.js.map +1 -1
- package/dist/members/collection.js +0 -13
- package/dist/members/collection.js.map +1 -1
- package/dist/members/index.js +21 -40
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -1
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +34 -5
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +42 -2
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/types/constants.d.ts +16 -0
- package/dist/types/locus-info/index.d.ts +3 -102
- package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
- package/dist/types/meeting/index.d.ts +23 -28
- package/dist/types/meeting/type.d.ts +9 -0
- package/dist/types/meeting/util.d.ts +6 -3
- package/dist/types/member/types.d.ts +0 -1
- package/dist/types/members/collection.d.ts +0 -6
- package/dist/types/members/index.d.ts +7 -16
- package/dist/types/members/util.d.ts +2 -1
- package/dist/types/multistream/remoteMedia.d.ts +20 -1
- package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -24
- package/src/constants.ts +16 -2
- package/src/locus-info/index.ts +39 -409
- package/src/meeting/in-meeting-actions.ts +13 -0
- package/src/meeting/index.ts +92 -63
- package/src/meeting/muteState.ts +6 -2
- package/src/meeting/type.ts +9 -0
- package/src/meeting/util.ts +93 -19
- package/src/meetings/index.ts +6 -19
- package/src/member/types.ts +0 -1
- package/src/members/collection.ts +0 -11
- package/src/members/index.ts +10 -33
- package/src/members/util.ts +2 -1
- package/src/multistream/mediaRequestManager.ts +7 -7
- package/src/multistream/remoteMedia.ts +34 -4
- package/src/multistream/remoteMediaGroup.ts +37 -2
- package/test/unit/spec/locus-info/index.js +8 -365
- package/test/unit/spec/meeting/in-meeting-actions.ts +6 -0
- package/test/unit/spec/meeting/index.js +254 -38
- package/test/unit/spec/meeting/utils.js +122 -1
- package/test/unit/spec/meetings/index.js +2 -0
- package/test/unit/spec/members/index.js +37 -1
- package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
- package/test/unit/spec/multistream/remoteMedia.ts +66 -2
- package/dist/hashTree/constants.js +0 -23
- package/dist/hashTree/constants.js.map +0 -1
- package/dist/hashTree/hashTree.js +0 -516
- package/dist/hashTree/hashTree.js.map +0 -1
- package/dist/hashTree/hashTreeParser.js +0 -521
- package/dist/hashTree/hashTreeParser.js.map +0 -1
- package/dist/types/hashTree/constants.d.ts +0 -8
- package/dist/types/hashTree/hashTree.d.ts +0 -128
- package/dist/types/hashTree/hashTreeParser.d.ts +0 -152
- package/src/hashTree/constants.ts +0 -12
- package/src/hashTree/hashTree.ts +0 -460
- package/src/hashTree/hashTreeParser.ts +0 -556
- package/test/unit/spec/hashTree/hashTree.ts +0 -394
- package/test/unit/spec/hashTree/hashTreeParser.ts +0 -156
package/src/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
|
69
|
+
import LocusInfo 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';
|
@@ -166,7 +166,7 @@ import MultistreamNotSupportedError from '../common/errors/multistream-not-suppo
|
|
166
166
|
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
167
167
|
import {ReachabilityMetrics} from '../reachability/reachability.types';
|
168
168
|
import {SetStageOptions, SetStageVideoLayout, UnsetStageVideoLayout} from './request.type';
|
169
|
-
import {
|
169
|
+
import {Invitee} from './type';
|
170
170
|
|
171
171
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
172
172
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
@@ -251,6 +251,7 @@ export type CallStateForMetrics = {
|
|
251
251
|
loginType?: string;
|
252
252
|
userNameInput?: string;
|
253
253
|
emailInput?: string;
|
254
|
+
pstnCorrelationId?: string;
|
254
255
|
};
|
255
256
|
|
256
257
|
export const MEDIA_UPDATE_TYPE = {
|
@@ -744,10 +745,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
744
745
|
/**
|
745
746
|
* @param {Object} attrs
|
746
747
|
* @param {Object} options
|
748
|
+
* @param {Function} callback - if provided, it will be called with the newly created meeting object as soon as the meeting.id is set
|
747
749
|
* @constructor
|
748
750
|
* @memberof Meeting
|
749
751
|
*/
|
750
|
-
constructor(attrs: any, options: object) {
|
752
|
+
constructor(attrs: any, options: object, callback: (meeting: Meeting) => void) {
|
751
753
|
super({}, options);
|
752
754
|
/**
|
753
755
|
* @instance
|
@@ -773,6 +775,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
773
775
|
* @memberof Meeting
|
774
776
|
*/
|
775
777
|
this.id = uuid.v4();
|
778
|
+
|
779
|
+
if (callback) {
|
780
|
+
callback(this);
|
781
|
+
}
|
782
|
+
|
776
783
|
/**
|
777
784
|
* Call state used for metrics
|
778
785
|
* @instance
|
@@ -1677,6 +1684,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1677
1684
|
this.callStateForMetrics.correlationId = correlationId;
|
1678
1685
|
}
|
1679
1686
|
|
1687
|
+
/**
|
1688
|
+
* Getter - Returns callStateForMetrics.pstnCorrelationId
|
1689
|
+
* @returns {string | undefined}
|
1690
|
+
*/
|
1691
|
+
get pstnCorrelationId(): string | undefined {
|
1692
|
+
return this.callStateForMetrics.pstnCorrelationId;
|
1693
|
+
}
|
1694
|
+
|
1695
|
+
/**
|
1696
|
+
* Setter - sets callStateForMetrics.pstnCorrelationId
|
1697
|
+
* @param {string | undefined} correlationId
|
1698
|
+
*/
|
1699
|
+
set pstnCorrelationId(correlationId: string | undefined) {
|
1700
|
+
this.callStateForMetrics.pstnCorrelationId = correlationId;
|
1701
|
+
}
|
1702
|
+
|
1680
1703
|
/**
|
1681
1704
|
* Getter - Returns callStateForMetrics.userNameInput
|
1682
1705
|
* @returns {string}
|
@@ -3059,12 +3082,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3059
3082
|
// There is no concept of local/remote share for whiteboard
|
3060
3083
|
// It does not matter who requested to share the whiteboard, everyone gets the same view
|
3061
3084
|
else if (whiteboardShare.disposition === FLOOR_ACTION.GRANTED) {
|
3062
|
-
|
3063
|
-
|
3064
|
-
|
3065
|
-
|
3066
|
-
|
3067
|
-
|
3085
|
+
if (this.locusInfo?.info?.isWebinar && this.webinar?.selfIsAttendee) {
|
3086
|
+
// WHITEBOARD - sharing whiteboard
|
3087
|
+
// Webinar attendee should receive whiteboard as remote share
|
3088
|
+
newShareStatus = SHARE_STATUS.REMOTE_SHARE_ACTIVE;
|
3089
|
+
} else if (this.guest) {
|
3090
|
+
// If user is a guest to a meeting, they should receive whiteboard as remote share
|
3091
|
+
newShareStatus = SHARE_STATUS.REMOTE_SHARE_ACTIVE;
|
3092
|
+
} else {
|
3093
|
+
newShareStatus = SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
3094
|
+
}
|
3068
3095
|
}
|
3069
3096
|
// or if content share is either released or null and whiteboard share is either released or null, no one is sharing
|
3070
3097
|
else if (
|
@@ -3830,49 +3857,43 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3830
3857
|
|
3831
3858
|
/**
|
3832
3859
|
* Invite a guest to the call that isn't normally part of this call
|
3833
|
-
* @param {
|
3860
|
+
* @param {Invitee} invitee
|
3834
3861
|
* @param {String} invitee.emailAddress
|
3835
3862
|
* @param {String} invitee.email
|
3836
3863
|
* @param {String} invitee.phoneNumber
|
3837
3864
|
* @param {Boolean} [alertIfActive]
|
3865
|
+
* @param {Boolean} [invitee.skipEmailValidation]
|
3866
|
+
* @param {Boolean} [invitee.isInternalNumber]
|
3838
3867
|
* @returns {Promise} see #members.addMember
|
3839
3868
|
* @public
|
3840
3869
|
* @memberof Meeting
|
3841
3870
|
*/
|
3842
|
-
public invite(
|
3843
|
-
invitee: {
|
3844
|
-
emailAddress: string;
|
3845
|
-
email: string;
|
3846
|
-
phoneNumber: string;
|
3847
|
-
roles: Array<string>;
|
3848
|
-
},
|
3849
|
-
alertIfActive = true
|
3850
|
-
) {
|
3871
|
+
public invite(invitee: Invitee, alertIfActive = true) {
|
3851
3872
|
return this.members.addMember(invitee, alertIfActive);
|
3852
3873
|
}
|
3853
3874
|
|
3854
3875
|
/**
|
3855
3876
|
* Cancel an outgoing phone call invitation made during a meeting
|
3856
|
-
* @param {
|
3877
|
+
* @param {Invitee} invitee
|
3857
3878
|
* @param {String} invitee.phoneNumber
|
3858
3879
|
* @returns {Promise} see #members.cancelPhoneInvite
|
3859
3880
|
* @public
|
3860
3881
|
* @memberof Meeting
|
3861
3882
|
*/
|
3862
|
-
public cancelPhoneInvite(invitee:
|
3883
|
+
public cancelPhoneInvite(invitee: Invitee) {
|
3863
3884
|
return this.members.cancelPhoneInvite(invitee);
|
3864
3885
|
}
|
3865
3886
|
|
3866
3887
|
/**
|
3867
3888
|
* Cancel an SIP/phone call invitation made during a meeting
|
3868
|
-
* @param {
|
3889
|
+
* @param {Invitee} invitee
|
3869
3890
|
* @param {String} invitee.memberId
|
3870
3891
|
* @param {Boolean} [invitee.isInternalNumber] - When cancel phone invitation, if the number is internal
|
3871
3892
|
* @returns {Promise} see #members.cancelInviteByMemberId
|
3872
3893
|
* @public
|
3873
3894
|
* @memberof Meeting
|
3874
3895
|
*/
|
3875
|
-
public cancelInviteByMemberId(invitee:
|
3896
|
+
public cancelInviteByMemberId(invitee: Invitee) {
|
3876
3897
|
return this.members.cancelInviteByMemberId(invitee);
|
3877
3898
|
}
|
3878
3899
|
|
@@ -4171,6 +4192,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4171
4192
|
isClosedCaptionActive: MeetingUtil.isClosedCaptionActive(this.userDisplayHints),
|
4172
4193
|
canStartManualCaption: MeetingUtil.canStartManualCaption(this.userDisplayHints),
|
4173
4194
|
canStopManualCaption: MeetingUtil.canStopManualCaption(this.userDisplayHints),
|
4195
|
+
isLocalRecordingStarted: MeetingUtil.isLocalRecordingStarted(this.userDisplayHints),
|
4196
|
+
isLocalRecordingStopped: MeetingUtil.isLocalRecordingStopped(this.userDisplayHints),
|
4197
|
+
isLocalRecordingPaused: MeetingUtil.isLocalRecordingPaused(this.userDisplayHints),
|
4174
4198
|
isManualCaptionActive: MeetingUtil.isManualCaptionActive(this.userDisplayHints),
|
4175
4199
|
isSaveTranscriptsEnabled: MeetingUtil.isSaveTranscriptsEnabled(this.userDisplayHints),
|
4176
4200
|
isWebexAssistantActive: MeetingUtil.isWebexAssistantActive(this.userDisplayHints),
|
@@ -4479,13 +4503,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4479
4503
|
setLocus(
|
4480
4504
|
locus:
|
4481
4505
|
| {
|
4482
|
-
locus: LocusDTO;
|
4483
4506
|
mediaConnections: Array<any>;
|
4484
4507
|
locusUrl: string;
|
4485
4508
|
locusId: string;
|
4486
4509
|
mediaId: string;
|
4487
4510
|
host: object;
|
4488
|
-
dataSets: DataSet[];
|
4489
4511
|
}
|
4490
4512
|
| any
|
4491
4513
|
) {
|
@@ -4499,7 +4521,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4499
4521
|
this.selfId = locus.selfId;
|
4500
4522
|
this.mediaId = locus.mediaId;
|
4501
4523
|
this.hostId = mtgLocus.host ? mtgLocus.host.id : this.hostId;
|
4502
|
-
this.locusInfo.initialSetup(mtgLocus
|
4524
|
+
this.locusInfo.initialSetup(mtgLocus);
|
4503
4525
|
}
|
4504
4526
|
|
4505
4527
|
/**
|
@@ -5612,21 +5634,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
5612
5634
|
}
|
5613
5635
|
}
|
5614
5636
|
|
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
|
-
|
5630
5637
|
/**
|
5631
5638
|
* Callback called when a relay event is received from meeting LLM Connection
|
5632
5639
|
* @param {RelayEvent} e Event object coming from LLM Connection
|
@@ -5945,15 +5952,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
5945
5952
|
this.meetingFiniteStateMachine.fail(error);
|
5946
5953
|
LoggerProxy.logger.error('Meeting:index#join --> Failed', error);
|
5947
5954
|
|
5948
|
-
// @ts-ignore
|
5949
|
-
this.webex.internal.newMetrics.submitClientEvent({
|
5950
|
-
name: 'client.locus.join.response',
|
5951
|
-
payload: {
|
5952
|
-
identifiers: {meetingLookupUrl: this.meetingInfo?.meetingLookupUrl},
|
5953
|
-
},
|
5954
|
-
options: {meetingId: this.id, rawError: error},
|
5955
|
-
});
|
5956
|
-
|
5957
5955
|
// TODO: change this to error codes and pre defined dictionary
|
5958
5956
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_FAILURE, {
|
5959
5957
|
correlation_id: this.correlationId,
|
@@ -6047,8 +6045,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6047
6045
|
);
|
6048
6046
|
// @ts-ignore - Fix type
|
6049
6047
|
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);
|
6052
6048
|
}
|
6053
6049
|
|
6054
6050
|
if (!isJoined) {
|
@@ -6063,10 +6059,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6063
6059
|
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
6064
6060
|
// @ts-ignore - Fix type
|
6065
6061
|
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);
|
6070
6062
|
LoggerProxy.logger.info(
|
6071
6063
|
'Meeting:index#updateLLMConnection --> enabled to receive relay events!'
|
6072
6064
|
);
|
@@ -6109,8 +6101,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6109
6101
|
*/
|
6110
6102
|
private dialInPstn() {
|
6111
6103
|
if (this.isPhoneProvisioned(this.dialInDeviceStatus)) return Promise.resolve(); // prevent multiple dial in devices from being provisioned
|
6104
|
+
this.pstnCorrelationId = uuid.v4();
|
6112
6105
|
|
6113
|
-
const {
|
6106
|
+
const {pstnCorrelationId, locusUrl} = this;
|
6114
6107
|
|
6115
6108
|
if (!this.dialInUrl) this.dialInUrl = `dialin:///${uuid.v4()}`;
|
6116
6109
|
|
@@ -6118,7 +6111,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6118
6111
|
this.meetingRequest
|
6119
6112
|
// @ts-ignore
|
6120
6113
|
.dialIn({
|
6121
|
-
correlationId,
|
6114
|
+
correlationId: pstnCorrelationId,
|
6122
6115
|
dialInUrl: this.dialInUrl,
|
6123
6116
|
locusUrl,
|
6124
6117
|
clientUrl: this.deviceUrl,
|
@@ -6127,12 +6120,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6127
6120
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
|
6128
6121
|
correlation_id: this.correlationId,
|
6129
6122
|
dial_in_url: this.dialInUrl,
|
6123
|
+
dial_in_correlation_id: pstnCorrelationId,
|
6130
6124
|
locus_id: locusUrl.split('/').pop(),
|
6131
6125
|
client_url: this.deviceUrl,
|
6132
6126
|
reason: error.error?.message,
|
6133
6127
|
stack: error.stack,
|
6134
6128
|
});
|
6135
6129
|
|
6130
|
+
if (this.pstnCorrelationId === pstnCorrelationId) {
|
6131
|
+
this.pstnCorrelationId = undefined;
|
6132
|
+
}
|
6133
|
+
|
6136
6134
|
return Promise.reject(error);
|
6137
6135
|
})
|
6138
6136
|
);
|
@@ -6147,8 +6145,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6147
6145
|
*/
|
6148
6146
|
private dialOutPstn(phoneNumber: string) {
|
6149
6147
|
if (this.isPhoneProvisioned(this.dialOutDeviceStatus)) return Promise.resolve(); // prevent multiple dial out devices from being provisioned
|
6148
|
+
this.pstnCorrelationId = uuid.v4();
|
6150
6149
|
|
6151
|
-
const {
|
6150
|
+
const {locusUrl, pstnCorrelationId} = this;
|
6152
6151
|
|
6153
6152
|
if (!this.dialOutUrl) this.dialOutUrl = `dialout:///${uuid.v4()}`;
|
6154
6153
|
|
@@ -6156,7 +6155,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6156
6155
|
this.meetingRequest
|
6157
6156
|
// @ts-ignore
|
6158
6157
|
.dialOut({
|
6159
|
-
correlationId,
|
6158
|
+
correlationId: pstnCorrelationId,
|
6160
6159
|
dialOutUrl: this.dialOutUrl,
|
6161
6160
|
phoneNumber,
|
6162
6161
|
locusUrl,
|
@@ -6166,12 +6165,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6166
6165
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
|
6167
6166
|
correlation_id: this.correlationId,
|
6168
6167
|
dial_out_url: this.dialOutUrl,
|
6168
|
+
dial_out_correlation_id: pstnCorrelationId,
|
6169
6169
|
locus_id: locusUrl.split('/').pop(),
|
6170
6170
|
client_url: this.deviceUrl,
|
6171
6171
|
reason: error.error?.message,
|
6172
6172
|
stack: error.stack,
|
6173
6173
|
});
|
6174
6174
|
|
6175
|
+
if (this.pstnCorrelationId === pstnCorrelationId) {
|
6176
|
+
this.pstnCorrelationId = undefined;
|
6177
|
+
}
|
6178
|
+
|
6175
6179
|
return Promise.reject(error);
|
6176
6180
|
})
|
6177
6181
|
);
|
@@ -6185,6 +6189,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6185
6189
|
* @returns {Promise}
|
6186
6190
|
*/
|
6187
6191
|
public disconnectPhoneAudio() {
|
6192
|
+
const correlationToClear = this.pstnCorrelationId;
|
6193
|
+
|
6188
6194
|
return Promise.all([
|
6189
6195
|
this.isPhoneProvisioned(this.dialInDeviceStatus)
|
6190
6196
|
? MeetingUtil.disconnectPhoneAudio(this, this.dialInUrl)
|
@@ -6192,7 +6198,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6192
6198
|
this.isPhoneProvisioned(this.dialOutDeviceStatus)
|
6193
6199
|
? MeetingUtil.disconnectPhoneAudio(this, this.dialOutUrl)
|
6194
6200
|
: Promise.resolve(),
|
6195
|
-
])
|
6201
|
+
]).then(() => {
|
6202
|
+
if (this.pstnCorrelationId === correlationToClear) {
|
6203
|
+
this.pstnCorrelationId = undefined;
|
6204
|
+
}
|
6205
|
+
});
|
6196
6206
|
}
|
6197
6207
|
|
6198
6208
|
/**
|
@@ -8414,6 +8424,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8414
8424
|
}
|
8415
8425
|
|
8416
8426
|
if (whiteboard) {
|
8427
|
+
// @ts-ignore
|
8428
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
8429
|
+
key: 'internal.client.share.initiated',
|
8430
|
+
});
|
8417
8431
|
// @ts-ignore
|
8418
8432
|
this.webex.internal.newMetrics.submitClientEvent({
|
8419
8433
|
name: 'client.share.initiated',
|
@@ -8473,11 +8487,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8473
8487
|
const whiteboard = this.locusInfo.mediaShares.find((element) => element.name === 'whiteboard');
|
8474
8488
|
|
8475
8489
|
if (whiteboard) {
|
8490
|
+
// @ts-ignore
|
8491
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
8492
|
+
key: 'internal.client.share.stopped',
|
8493
|
+
});
|
8476
8494
|
// @ts-ignore
|
8477
8495
|
this.webex.internal.newMetrics.submitClientEvent({
|
8478
8496
|
name: 'client.share.stopped',
|
8479
8497
|
payload: {
|
8480
8498
|
mediaType: 'whiteboard',
|
8499
|
+
// @ts-ignore
|
8500
|
+
shareDuration: this.webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration(),
|
8481
8501
|
},
|
8482
8502
|
options: {
|
8483
8503
|
meetingId: this.id,
|
@@ -8635,12 +8655,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8635
8655
|
}
|
8636
8656
|
this.screenShareFloorState = ScreenShareFloorStatus.RELEASED;
|
8637
8657
|
if (content) {
|
8658
|
+
// @ts-ignore
|
8659
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
8660
|
+
key: 'internal.client.share.stopped',
|
8661
|
+
});
|
8638
8662
|
// @ts-ignore
|
8639
8663
|
this.webex.internal.newMetrics.submitClientEvent({
|
8640
8664
|
name: 'client.share.stopped',
|
8641
8665
|
payload: {
|
8642
8666
|
mediaType: 'share',
|
8643
8667
|
shareInstanceId: this.localShareInstanceId,
|
8668
|
+
// @ts-ignore
|
8669
|
+
shareDuration: this.webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration(),
|
8644
8670
|
},
|
8645
8671
|
options: {meetingId: this.id},
|
8646
8672
|
});
|
@@ -9238,8 +9264,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9238
9264
|
|
9239
9265
|
// @ts-ignore - fix types
|
9240
9266
|
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);
|
9243
9267
|
};
|
9244
9268
|
|
9245
9269
|
/**
|
@@ -9619,6 +9643,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9619
9643
|
this.shareCAEventSentStatus.transmitStart = false;
|
9620
9644
|
this.shareCAEventSentStatus.transmitStop = false;
|
9621
9645
|
|
9646
|
+
// @ts-ignore
|
9647
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
9648
|
+
key: 'internal.client.share.initiated',
|
9649
|
+
});
|
9650
|
+
|
9622
9651
|
// @ts-ignore
|
9623
9652
|
this.webex.internal.newMetrics.submitClientEvent({
|
9624
9653
|
name: 'client.share.initiated',
|
package/src/meeting/muteState.ts
CHANGED
@@ -291,14 +291,18 @@ export class MuteState {
|
|
291
291
|
);
|
292
292
|
|
293
293
|
return MeetingUtil.remoteUpdateAudioVideo(meeting, audioMuted, videoMuted)
|
294
|
-
.then((
|
294
|
+
.then((locus) => {
|
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
|
-
|
301
|
+
if (locus) {
|
302
|
+
meeting.locusInfo.handleLocusDelta(locus, meeting);
|
303
|
+
}
|
304
|
+
|
305
|
+
return locus;
|
302
306
|
})
|
303
307
|
.catch((remoteUpdateError) => {
|
304
308
|
LoggerProxy.logger.warn(
|
package/src/meeting/util.ts
CHANGED
@@ -31,7 +31,6 @@ 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;
|
35
34
|
parsed.mediaConnections = response.body.mediaConnections;
|
36
35
|
parsed.locusUrl = parsed.locus.url;
|
37
36
|
parsed.locusId = parsed.locus.url.split('/').pop();
|
@@ -60,16 +59,18 @@ const MeetingUtil = {
|
|
60
59
|
);
|
61
60
|
}
|
62
61
|
|
63
|
-
return meeting.locusMediaRequest
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
62
|
+
return meeting.locusMediaRequest
|
63
|
+
.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
|
+
})
|
73
|
+
.then((response) => response?.body?.locus);
|
73
74
|
},
|
74
75
|
|
75
76
|
hasOwner: (info) => info && info.owner,
|
@@ -196,6 +197,17 @@ const MeetingUtil = {
|
|
196
197
|
});
|
197
198
|
|
198
199
|
return parsed;
|
200
|
+
})
|
201
|
+
.catch((err) => {
|
202
|
+
webex.internal.newMetrics.submitClientEvent({
|
203
|
+
name: 'client.locus.join.response',
|
204
|
+
payload: {
|
205
|
+
identifiers: {meetingLookupUrl: meeting.meetingInfo?.meetingLookupUrl},
|
206
|
+
},
|
207
|
+
options: {meetingId: meeting.id, rawError: err},
|
208
|
+
});
|
209
|
+
|
210
|
+
throw err;
|
199
211
|
});
|
200
212
|
},
|
201
213
|
|
@@ -207,6 +219,10 @@ const MeetingUtil = {
|
|
207
219
|
meeting.simultaneousInterpretation.cleanUp();
|
208
220
|
meeting.locusMediaRequest = undefined;
|
209
221
|
|
222
|
+
meeting.webex?.internal?.newMetrics?.callDiagnosticMetrics?.clearEventLimitsForCorrelationId(
|
223
|
+
meeting.correlationId
|
224
|
+
);
|
225
|
+
|
210
226
|
// make sure we send last metrics before we close the peerconnection
|
211
227
|
const stopStatsAnalyzer = meeting.statsAnalyzer
|
212
228
|
? meeting.statsAnalyzer.stopAnalyzer()
|
@@ -327,10 +343,57 @@ const MeetingUtil = {
|
|
327
343
|
meeting.resourceId = meeting.resourceId || options.resourceId;
|
328
344
|
|
329
345
|
if (meeting.requiredCaptcha) {
|
330
|
-
|
346
|
+
const errorToThrow = new CaptchaError();
|
347
|
+
|
348
|
+
// @ts-ignore
|
349
|
+
webex.internal.newMetrics.submitClientEvent({
|
350
|
+
name: 'client.meetinginfo.response',
|
351
|
+
options: {
|
352
|
+
meetingId: meeting.id,
|
353
|
+
},
|
354
|
+
payload: {
|
355
|
+
errors: [
|
356
|
+
{
|
357
|
+
fatal: false,
|
358
|
+
category: 'expected',
|
359
|
+
name: 'other',
|
360
|
+
shownToUser: false,
|
361
|
+
errorCode: errorToThrow.code,
|
362
|
+
errorDescription: errorToThrow.name,
|
363
|
+
rawErrorMessage: errorToThrow.sdkMessage,
|
364
|
+
},
|
365
|
+
],
|
366
|
+
},
|
367
|
+
});
|
368
|
+
|
369
|
+
return Promise.reject(errorToThrow);
|
331
370
|
}
|
371
|
+
|
332
372
|
if (meeting.passwordStatus === PASSWORD_STATUS.REQUIRED) {
|
333
|
-
|
373
|
+
const errorToThrow = new PasswordError();
|
374
|
+
|
375
|
+
// @ts-ignore
|
376
|
+
webex.internal.newMetrics.submitClientEvent({
|
377
|
+
name: 'client.meetinginfo.response',
|
378
|
+
options: {
|
379
|
+
meetingId: meeting.id,
|
380
|
+
},
|
381
|
+
payload: {
|
382
|
+
errors: [
|
383
|
+
{
|
384
|
+
fatal: false,
|
385
|
+
category: 'expected',
|
386
|
+
name: 'other',
|
387
|
+
shownToUser: false,
|
388
|
+
errorCode: errorToThrow.code,
|
389
|
+
errorDescription: errorToThrow.name,
|
390
|
+
rawErrorMessage: errorToThrow.sdkMessage,
|
391
|
+
},
|
392
|
+
],
|
393
|
+
},
|
394
|
+
});
|
395
|
+
|
396
|
+
return Promise.reject(errorToThrow);
|
334
397
|
}
|
335
398
|
|
336
399
|
if (options.pin) {
|
@@ -541,6 +604,15 @@ const MeetingUtil = {
|
|
541
604
|
canStartManualCaption: (displayHints) =>
|
542
605
|
displayHints.includes(DISPLAY_HINTS.MANUAL_CAPTION_START),
|
543
606
|
|
607
|
+
isLocalRecordingStarted: (displayHints) =>
|
608
|
+
displayHints.includes(DISPLAY_HINTS.LOCAL_RECORDING_STATUS_STARTED),
|
609
|
+
|
610
|
+
isLocalRecordingStopped: (displayHints) =>
|
611
|
+
displayHints.includes(DISPLAY_HINTS.LOCAL_RECORDING_STATUS_STOPPED),
|
612
|
+
|
613
|
+
isLocalRecordingPaused: (displayHints) =>
|
614
|
+
displayHints.includes(DISPLAY_HINTS.LOCAL_RECORDING_STATUS_PAUSED),
|
615
|
+
|
544
616
|
canStopManualCaption: (displayHints) => displayHints.includes(DISPLAY_HINTS.MANUAL_CAPTION_STOP),
|
545
617
|
|
546
618
|
isManualCaptionActive: (displayHints) =>
|
@@ -601,20 +673,22 @@ const MeetingUtil = {
|
|
601
673
|
},
|
602
674
|
|
603
675
|
/**
|
604
|
-
* Updates the locus info for the meeting with the locus
|
605
|
-
*
|
676
|
+
* Updates the locus info for the meeting with the delta locus
|
677
|
+
* returned from requests that include the sequence information
|
606
678
|
* Returns the original response object
|
607
679
|
* @param {Object} meeting The meeting object
|
608
680
|
* @param {Object} response The response of the http request
|
609
681
|
* @returns {Object}
|
610
682
|
*/
|
611
|
-
|
683
|
+
updateLocusWithDelta: (meeting, response) => {
|
612
684
|
if (!meeting) {
|
613
685
|
return response;
|
614
686
|
}
|
615
687
|
|
616
|
-
|
617
|
-
|
688
|
+
const locus = response?.body?.locus;
|
689
|
+
|
690
|
+
if (locus) {
|
691
|
+
meeting.locusInfo.handleLocusDelta(locus, meeting);
|
618
692
|
}
|
619
693
|
|
620
694
|
return response;
|
@@ -661,7 +735,7 @@ const MeetingUtil = {
|
|
661
735
|
|
662
736
|
return meeting
|
663
737
|
.request(options)
|
664
|
-
.then((response) => MeetingUtil.
|
738
|
+
.then((response) => MeetingUtil.updateLocusWithDelta(meeting, response));
|
665
739
|
};
|
666
740
|
|
667
741
|
return locusDeltaRequest;
|
package/src/meetings/index.ts
CHANGED
@@ -66,7 +66,6 @@ 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';
|
70
69
|
|
71
70
|
let mediaLogger;
|
72
71
|
|
@@ -408,13 +407,6 @@ export default class Meetings extends WebexPlugin {
|
|
408
407
|
* @memberof Meetings
|
409
408
|
*/
|
410
409
|
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
|
-
|
418
410
|
// getting meeting by correlationId. This will happen for the new event
|
419
411
|
// Either the locus
|
420
412
|
// TODO : Add check for the callBack Address
|
@@ -453,10 +445,7 @@ export default class Meetings extends WebexPlugin {
|
|
453
445
|
* @private
|
454
446
|
* @memberof Meetings
|
455
447
|
*/
|
456
|
-
private handleLocusEvent(
|
457
|
-
data: {locusUrl: string; locus: any; dataSets?: DataSet[]},
|
458
|
-
useRandomDelayForInfo = false
|
459
|
-
) {
|
448
|
+
private handleLocusEvent(data: {locusUrl: string; locus: any}, useRandomDelayForInfo = false) {
|
460
449
|
let meeting = this.getCorrespondingMeetingByLocus(data);
|
461
450
|
|
462
451
|
// Special case when locus has got replaced, This only happend once if a replace locus exists
|
@@ -535,7 +524,7 @@ export default class Meetings extends WebexPlugin {
|
|
535
524
|
meeting = newMeeting;
|
536
525
|
|
537
526
|
// It's a new meeting so initialize the locus data
|
538
|
-
meeting.locusInfo.initialSetup(data.locus
|
527
|
+
meeting.locusInfo.initialSetup(data.locus);
|
539
528
|
this.checkHandleBreakoutLocus(data.locus);
|
540
529
|
})
|
541
530
|
.catch((e) => {
|
@@ -1571,11 +1560,12 @@ export default class Meetings extends WebexPlugin {
|
|
1571
1560
|
{
|
1572
1561
|
// @ts-ignore
|
1573
1562
|
parent: this.webex,
|
1563
|
+
},
|
1564
|
+
(newMeeting) => {
|
1565
|
+
this.meetingCollection.set(newMeeting);
|
1574
1566
|
}
|
1575
1567
|
);
|
1576
1568
|
|
1577
|
-
this.meetingCollection.set(meeting);
|
1578
|
-
|
1579
1569
|
try {
|
1580
1570
|
// if no participant has joined the scheduled meeting (meaning meeting is not active) and we get a locusEvent,
|
1581
1571
|
// it means the meeting will start in 5-6 min. In that case, we want to fetchMeetingInfo
|
@@ -1835,10 +1825,7 @@ export default class Meetings extends WebexPlugin {
|
|
1835
1825
|
}
|
1836
1826
|
|
1837
1827
|
const associateBreakoutLocus = this.breakoutLocusForHandleLater[existIndex];
|
1838
|
-
this.handleLocusEvent({
|
1839
|
-
locus: associateBreakoutLocus,
|
1840
|
-
locusUrl: associateBreakoutLocus.url,
|
1841
|
-
});
|
1828
|
+
this.handleLocusEvent({locus: associateBreakoutLocus, locusUrl: associateBreakoutLocus.url});
|
1842
1829
|
this.breakoutLocusForHandleLater.splice(existIndex, 1);
|
1843
1830
|
}
|
1844
1831
|
|