@webex/plugin-meetings 3.9.0-webinar5k.1 → 3.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/index.js +1 -1
- package/dist/constants.js +24 -0
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/index.js +22 -5
- package/dist/controls-options-manager/index.js.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/interceptors/index.js +7 -0
- package/dist/interceptors/index.js.map +1 -1
- package/dist/interceptors/locusRouteToken.js +116 -0
- package/dist/interceptors/locusRouteToken.js.map +1 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +11 -2
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +76 -322
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/parser.js +4 -1
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/media/properties.js +53 -5
- package/dist/media/properties.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +14 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +467 -277
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/request.js +177 -14
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/type.js +7 -0
- package/dist/meeting/type.js.map +1 -0
- package/dist/meeting/util.js +100 -3
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +29 -21
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +20 -16
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js +9 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +10 -0
- package/dist/member/util.js.map +1 -1
- package/dist/members/index.js +10 -7
- package/dist/members/index.js.map +1 -1
- package/dist/members/util.js +7 -2
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +2 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/mediaRequestManager.js +1 -1
- package/dist/multistream/mediaRequestManager.js.map +1 -1
- package/dist/multistream/remoteMedia.js +34 -5
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/remoteMediaGroup.js +42 -2
- package/dist/multistream/remoteMediaGroup.js.map +1 -1
- package/dist/reachability/index.js +3 -3
- package/dist/reachability/index.js.map +1 -1
- package/dist/types/constants.d.ts +23 -0
- package/dist/types/controls-options-manager/index.d.ts +9 -1
- package/dist/types/interceptors/index.d.ts +2 -1
- package/dist/types/interceptors/locusRouteToken.d.ts +38 -0
- package/dist/types/locus-info/index.d.ts +9 -54
- package/dist/types/media/properties.d.ts +21 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +14 -0
- package/dist/types/meeting/index.d.ts +64 -29
- package/dist/types/meeting/request.d.ts +42 -0
- package/dist/types/meeting/type.d.ts +9 -0
- package/dist/types/meeting/util.d.ts +13 -0
- package/dist/types/meeting-info/meeting-info-v2.d.ts +6 -3
- package/dist/types/meetings/index.d.ts +3 -1
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/util.d.ts +5 -0
- package/dist/types/members/index.d.ts +12 -11
- package/dist/types/members/util.d.ts +8 -4
- package/dist/types/metrics/constants.d.ts +1 -0
- package/dist/types/multistream/remoteMedia.d.ts +20 -1
- package/dist/types/multistream/remoteMediaGroup.d.ts +11 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +25 -27
- package/src/constants.ts +26 -2
- package/src/controls-options-manager/index.ts +26 -5
- package/src/index.ts +2 -1
- package/src/interceptors/index.ts +2 -1
- package/src/interceptors/locusRouteToken.ts +80 -0
- package/src/locus-info/controlsUtils.ts +18 -0
- package/src/locus-info/index.ts +69 -357
- package/src/locus-info/parser.ts +5 -1
- package/src/media/properties.ts +43 -0
- package/src/meeting/in-meeting-actions.ts +29 -0
- package/src/meeting/index.ts +296 -87
- package/src/meeting/request.ts +141 -0
- package/src/meeting/type.ts +9 -0
- package/src/meeting/util.ts +107 -3
- package/src/meeting-info/meeting-info-v2.ts +24 -5
- package/src/meetings/index.ts +15 -22
- package/src/member/index.ts +10 -0
- package/src/member/util.ts +14 -0
- package/src/members/index.ts +20 -10
- package/src/members/util.ts +20 -3
- package/src/metrics/constants.ts +1 -0
- package/src/multistream/mediaRequestManager.ts +7 -7
- package/src/multistream/remoteMedia.ts +34 -4
- package/src/multistream/remoteMediaGroup.ts +37 -2
- package/src/reachability/index.ts +3 -3
- package/test/unit/spec/common/browser-detection.js +0 -24
- package/test/unit/spec/controls-options-manager/index.js +47 -0
- package/test/unit/spec/fixture/locus.js +1 -0
- package/test/unit/spec/interceptors/locusRouteToken.ts +87 -0
- package/test/unit/spec/locus-info/index.js +80 -361
- package/test/unit/spec/locus-info/parser.js +3 -2
- package/test/unit/spec/media/properties.ts +137 -0
- package/test/unit/spec/meeting/in-meeting-actions.ts +14 -0
- package/test/unit/spec/meeting/index.js +637 -53
- package/test/unit/spec/meeting/muteState.js +32 -6
- package/test/unit/spec/meeting/request.js +21 -0
- package/test/unit/spec/meeting/utils.js +171 -18
- package/test/unit/spec/meeting-info/meetinginfov2.js +8 -3
- package/test/unit/spec/meetings/index.js +12 -5
- package/test/unit/spec/member/util.js +24 -0
- package/test/unit/spec/members/collection.js +120 -0
- package/test/unit/spec/members/index.js +107 -2
- package/test/unit/spec/members/request.js +55 -0
- package/test/unit/spec/members/utils.js +116 -14
- package/test/unit/spec/multistream/mediaRequestManager.ts +19 -6
- package/test/unit/spec/multistream/remoteMedia.ts +66 -2
- package/test/unit/spec/reachability/index.ts +158 -3
- package/test/unit/spec/roap/turnDiscovery.ts +3 -3
- package/dist/hashTree/constants.js +0 -23
- package/dist/hashTree/constants.js.map +0 -1
- package/dist/hashTree/hashTree.js +0 -516
- package/dist/hashTree/hashTree.js.map +0 -1
- package/dist/hashTree/hashTreeParser.js +0 -521
- package/dist/hashTree/hashTreeParser.js.map +0 -1
- package/dist/types/hashTree/constants.d.ts +0 -8
- package/dist/types/hashTree/hashTree.d.ts +0 -128
- package/dist/types/hashTree/hashTreeParser.d.ts +0 -152
- package/src/hashTree/constants.ts +0 -12
- package/src/hashTree/hashTree.ts +0 -460
- package/src/hashTree/hashTreeParser.ts +0 -556
- package/test/unit/spec/hashTree/hashTree.ts +0 -394
- package/test/unit/spec/hashTree/hashTreeParser.ts +0 -156
package/src/meeting/index.ts
CHANGED
|
@@ -28,6 +28,8 @@ import {
|
|
|
28
28
|
StatsAnalyzerEventNames,
|
|
29
29
|
NetworkQualityEventNames,
|
|
30
30
|
NetworkQualityMonitor,
|
|
31
|
+
StatsMonitor,
|
|
32
|
+
StatsMonitorEventNames,
|
|
31
33
|
} from '@webex/internal-media-core';
|
|
32
34
|
|
|
33
35
|
import {
|
|
@@ -66,7 +68,7 @@ import Media, {type BundlePolicy} from '../media';
|
|
|
66
68
|
import MediaProperties from '../media/properties';
|
|
67
69
|
import MeetingStateMachine from './state';
|
|
68
70
|
import {createMuteState} from './muteState';
|
|
69
|
-
import LocusInfo
|
|
71
|
+
import LocusInfo from '../locus-info';
|
|
70
72
|
import Metrics from '../metrics';
|
|
71
73
|
import ReconnectionManager from '../reconnection-manager';
|
|
72
74
|
import ReconnectionNotStartedError from '../common/errors/reconnection-not-started';
|
|
@@ -166,7 +168,7 @@ import MultistreamNotSupportedError from '../common/errors/multistream-not-suppo
|
|
|
166
168
|
import JoinForbiddenError from '../common/errors/join-forbidden-error';
|
|
167
169
|
import {ReachabilityMetrics} from '../reachability/reachability.types';
|
|
168
170
|
import {SetStageOptions, SetStageVideoLayout, UnsetStageVideoLayout} from './request.type';
|
|
169
|
-
import {
|
|
171
|
+
import {Invitee} from './type';
|
|
170
172
|
|
|
171
173
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
|
172
174
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
|
@@ -251,6 +253,7 @@ export type CallStateForMetrics = {
|
|
|
251
253
|
loginType?: string;
|
|
252
254
|
userNameInput?: string;
|
|
253
255
|
emailInput?: string;
|
|
256
|
+
pstnCorrelationId?: string;
|
|
254
257
|
};
|
|
255
258
|
|
|
256
259
|
export const MEDIA_UPDATE_TYPE = {
|
|
@@ -268,6 +271,7 @@ export enum ScreenShareFloorStatus {
|
|
|
268
271
|
type FetchMeetingInfoParams = {
|
|
269
272
|
password?: string;
|
|
270
273
|
registrationId?: string;
|
|
274
|
+
classificationId?: string;
|
|
271
275
|
captchaCode?: string;
|
|
272
276
|
extraParams?: Record<string, any>;
|
|
273
277
|
sendCAevents?: boolean;
|
|
@@ -632,6 +636,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
632
636
|
shareStatus: string;
|
|
633
637
|
screenShareFloorState: ScreenShareFloorStatus;
|
|
634
638
|
statsAnalyzer: StatsAnalyzer;
|
|
639
|
+
statsMonitor: StatsMonitor;
|
|
635
640
|
transcription: Transcription;
|
|
636
641
|
updateMediaConnections: (mediaConnections: any[]) => void;
|
|
637
642
|
userDisplayHints: any;
|
|
@@ -744,10 +749,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
744
749
|
/**
|
|
745
750
|
* @param {Object} attrs
|
|
746
751
|
* @param {Object} options
|
|
752
|
+
* @param {Function} callback - if provided, it will be called with the newly created meeting object as soon as the meeting.id is set
|
|
747
753
|
* @constructor
|
|
748
754
|
* @memberof Meeting
|
|
749
755
|
*/
|
|
750
|
-
constructor(attrs: any, options: object) {
|
|
756
|
+
constructor(attrs: any, options: object, callback: (meeting: Meeting) => void) {
|
|
751
757
|
super({}, options);
|
|
752
758
|
/**
|
|
753
759
|
* @instance
|
|
@@ -773,6 +779,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
773
779
|
* @memberof Meeting
|
|
774
780
|
*/
|
|
775
781
|
this.id = uuid.v4();
|
|
782
|
+
|
|
783
|
+
if (callback) {
|
|
784
|
+
callback(this);
|
|
785
|
+
}
|
|
786
|
+
|
|
776
787
|
/**
|
|
777
788
|
* Call state used for metrics
|
|
778
789
|
* @instance
|
|
@@ -1279,6 +1290,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1279
1290
|
* @memberof Meeting
|
|
1280
1291
|
*/
|
|
1281
1292
|
this.networkQualityMonitor = null;
|
|
1293
|
+
/**
|
|
1294
|
+
* @instance
|
|
1295
|
+
* @type {StatsMonitor}
|
|
1296
|
+
* @private
|
|
1297
|
+
* @memberof Meeting
|
|
1298
|
+
*/
|
|
1299
|
+
this.statsMonitor = null;
|
|
1282
1300
|
/**
|
|
1283
1301
|
* Indicates network status of the webrtc media connection
|
|
1284
1302
|
* @instance
|
|
@@ -1677,6 +1695,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1677
1695
|
this.callStateForMetrics.correlationId = correlationId;
|
|
1678
1696
|
}
|
|
1679
1697
|
|
|
1698
|
+
/**
|
|
1699
|
+
* Getter - Returns callStateForMetrics.pstnCorrelationId
|
|
1700
|
+
* @returns {string | undefined}
|
|
1701
|
+
*/
|
|
1702
|
+
get pstnCorrelationId(): string | undefined {
|
|
1703
|
+
return this.callStateForMetrics.pstnCorrelationId;
|
|
1704
|
+
}
|
|
1705
|
+
|
|
1706
|
+
/**
|
|
1707
|
+
* Setter - sets callStateForMetrics.pstnCorrelationId
|
|
1708
|
+
* @param {string | undefined} correlationId
|
|
1709
|
+
*/
|
|
1710
|
+
set pstnCorrelationId(correlationId: string | undefined) {
|
|
1711
|
+
this.callStateForMetrics.pstnCorrelationId = correlationId;
|
|
1712
|
+
}
|
|
1713
|
+
|
|
1680
1714
|
/**
|
|
1681
1715
|
* Getter - Returns callStateForMetrics.userNameInput
|
|
1682
1716
|
* @returns {string}
|
|
@@ -1879,6 +1913,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1879
1913
|
extraParams = {},
|
|
1880
1914
|
sendCAevents = false,
|
|
1881
1915
|
registrationId = null,
|
|
1916
|
+
classificationId = null,
|
|
1882
1917
|
}): Promise<void> {
|
|
1883
1918
|
try {
|
|
1884
1919
|
const captchaInfo = captchaCode
|
|
@@ -1895,7 +1930,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1895
1930
|
this.locusId,
|
|
1896
1931
|
extraParams,
|
|
1897
1932
|
{meetingId: this.id, sendCAevents},
|
|
1898
|
-
registrationId
|
|
1933
|
+
registrationId,
|
|
1934
|
+
null,
|
|
1935
|
+
classificationId
|
|
1899
1936
|
);
|
|
1900
1937
|
|
|
1901
1938
|
this.parseMeetingInfo(info?.body, this.destination, info?.errors);
|
|
@@ -2939,6 +2976,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2939
2976
|
);
|
|
2940
2977
|
});
|
|
2941
2978
|
|
|
2979
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_AUTO_END_MEETING_WARNING_CHANGED, ({state}) => {
|
|
2980
|
+
Trigger.trigger(
|
|
2981
|
+
this,
|
|
2982
|
+
{
|
|
2983
|
+
file: 'meeting/index',
|
|
2984
|
+
function: 'setupLocusControlsListener',
|
|
2985
|
+
},
|
|
2986
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_AUTO_END_MEETING_WARNING_UPDATED,
|
|
2987
|
+
{state}
|
|
2988
|
+
);
|
|
2989
|
+
});
|
|
2990
|
+
|
|
2942
2991
|
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED, ({state}) => {
|
|
2943
2992
|
Trigger.trigger(
|
|
2944
2993
|
this,
|
|
@@ -3059,12 +3108,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3059
3108
|
// There is no concept of local/remote share for whiteboard
|
|
3060
3109
|
// It does not matter who requested to share the whiteboard, everyone gets the same view
|
|
3061
3110
|
else if (whiteboardShare.disposition === FLOOR_ACTION.GRANTED) {
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3111
|
+
if (this.locusInfo?.info?.isWebinar && this.webinar?.selfIsAttendee) {
|
|
3112
|
+
// WHITEBOARD - sharing whiteboard
|
|
3113
|
+
// Webinar attendee should receive whiteboard as remote share
|
|
3114
|
+
newShareStatus = SHARE_STATUS.REMOTE_SHARE_ACTIVE;
|
|
3115
|
+
} else if (this.guest) {
|
|
3116
|
+
// If user is a guest to a meeting, they should receive whiteboard as remote share
|
|
3117
|
+
newShareStatus = SHARE_STATUS.REMOTE_SHARE_ACTIVE;
|
|
3118
|
+
} else {
|
|
3119
|
+
newShareStatus = SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
3120
|
+
}
|
|
3068
3121
|
}
|
|
3069
3122
|
// or if content share is either released or null and whiteboard share is either released or null, no one is sharing
|
|
3070
3123
|
else if (
|
|
@@ -3122,6 +3175,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3122
3175
|
},
|
|
3123
3176
|
EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD
|
|
3124
3177
|
);
|
|
3178
|
+
// @ts-ignore
|
|
3179
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
|
3180
|
+
key: 'internal.client.share.stopped',
|
|
3181
|
+
});
|
|
3182
|
+
// @ts-ignore
|
|
3183
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
3184
|
+
name: 'client.share.stopped',
|
|
3185
|
+
payload: {
|
|
3186
|
+
mediaType: 'whiteboard',
|
|
3187
|
+
shareDuration:
|
|
3188
|
+
// @ts-ignore
|
|
3189
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration(),
|
|
3190
|
+
},
|
|
3191
|
+
options: {
|
|
3192
|
+
meetingId: this.id,
|
|
3193
|
+
},
|
|
3194
|
+
});
|
|
3125
3195
|
break;
|
|
3126
3196
|
|
|
3127
3197
|
case SHARE_STATUS.NO_SHARE:
|
|
@@ -3140,6 +3210,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3140
3210
|
this.shareCAEventSentStatus.receiveStart = false;
|
|
3141
3211
|
this.shareCAEventSentStatus.receiveStop = false;
|
|
3142
3212
|
|
|
3213
|
+
let finalBeneficiaryId = contentShare.beneficiaryId;
|
|
3214
|
+
// In case of attendee in webinar, the whiteboard is shared by other participants
|
|
3215
|
+
if (this.locusInfo?.info?.isWebinar && this.webinar?.selfIsAttendee) {
|
|
3216
|
+
if (!finalBeneficiaryId && whiteboardShare.beneficiaryId) {
|
|
3217
|
+
finalBeneficiaryId = whiteboardShare.beneficiaryId;
|
|
3218
|
+
}
|
|
3219
|
+
}
|
|
3220
|
+
|
|
3143
3221
|
Trigger.trigger(
|
|
3144
3222
|
this,
|
|
3145
3223
|
{
|
|
@@ -3148,7 +3226,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3148
3226
|
},
|
|
3149
3227
|
EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
|
|
3150
3228
|
{
|
|
3151
|
-
memberId:
|
|
3229
|
+
memberId: finalBeneficiaryId,
|
|
3152
3230
|
url: contentShare.url,
|
|
3153
3231
|
shareInstanceId: this.remoteShareInstanceId,
|
|
3154
3232
|
annotationInfo: contentShare.annotation,
|
|
@@ -3290,27 +3368,31 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3290
3368
|
* @memberof Meeting
|
|
3291
3369
|
*/
|
|
3292
3370
|
private setUpLocusUrlListener() {
|
|
3293
|
-
this.locusInfo.on(
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3371
|
+
this.locusInfo.on(
|
|
3372
|
+
EVENTS.LOCUS_INFO_UPDATE_URL,
|
|
3373
|
+
(payload: {url: string; isMainLocus?: boolean}) => {
|
|
3374
|
+
const {url, isMainLocus} = payload;
|
|
3375
|
+
this.members.locusUrlUpdate(url);
|
|
3376
|
+
this.breakouts.locusUrlUpdate(url);
|
|
3377
|
+
this.simultaneousInterpretation.locusUrlUpdate(url);
|
|
3378
|
+
this.annotation.locusUrlUpdate(url);
|
|
3379
|
+
this.locusUrl = url;
|
|
3380
|
+
this.locusId = this.locusUrl?.split('/').pop();
|
|
3381
|
+
this.recordingController.setLocusUrl(this.locusUrl);
|
|
3382
|
+
this.controlsOptionsManager.setLocusUrl(this.locusUrl, !!isMainLocus);
|
|
3383
|
+
this.webinar.locusUrlUpdate(url);
|
|
3303
3384
|
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3385
|
+
Trigger.trigger(
|
|
3386
|
+
this,
|
|
3387
|
+
{
|
|
3388
|
+
file: 'meeting/index',
|
|
3389
|
+
function: 'setUpLocusSelfListener',
|
|
3390
|
+
},
|
|
3391
|
+
EVENT_TRIGGERS.MEETING_LOCUS_URL_UPDATE,
|
|
3392
|
+
{locusUrl: url}
|
|
3393
|
+
);
|
|
3394
|
+
}
|
|
3395
|
+
);
|
|
3314
3396
|
}
|
|
3315
3397
|
|
|
3316
3398
|
/**
|
|
@@ -3830,49 +3912,43 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3830
3912
|
|
|
3831
3913
|
/**
|
|
3832
3914
|
* Invite a guest to the call that isn't normally part of this call
|
|
3833
|
-
* @param {
|
|
3915
|
+
* @param {Invitee} invitee
|
|
3834
3916
|
* @param {String} invitee.emailAddress
|
|
3835
3917
|
* @param {String} invitee.email
|
|
3836
3918
|
* @param {String} invitee.phoneNumber
|
|
3837
3919
|
* @param {Boolean} [alertIfActive]
|
|
3920
|
+
* @param {Boolean} [invitee.skipEmailValidation]
|
|
3921
|
+
* @param {Boolean} [invitee.isInternalNumber]
|
|
3838
3922
|
* @returns {Promise} see #members.addMember
|
|
3839
3923
|
* @public
|
|
3840
3924
|
* @memberof Meeting
|
|
3841
3925
|
*/
|
|
3842
|
-
public invite(
|
|
3843
|
-
invitee: {
|
|
3844
|
-
emailAddress: string;
|
|
3845
|
-
email: string;
|
|
3846
|
-
phoneNumber: string;
|
|
3847
|
-
roles: Array<string>;
|
|
3848
|
-
},
|
|
3849
|
-
alertIfActive = true
|
|
3850
|
-
) {
|
|
3926
|
+
public invite(invitee: Invitee, alertIfActive = true) {
|
|
3851
3927
|
return this.members.addMember(invitee, alertIfActive);
|
|
3852
3928
|
}
|
|
3853
3929
|
|
|
3854
3930
|
/**
|
|
3855
3931
|
* Cancel an outgoing phone call invitation made during a meeting
|
|
3856
|
-
* @param {
|
|
3932
|
+
* @param {Invitee} invitee
|
|
3857
3933
|
* @param {String} invitee.phoneNumber
|
|
3858
3934
|
* @returns {Promise} see #members.cancelPhoneInvite
|
|
3859
3935
|
* @public
|
|
3860
3936
|
* @memberof Meeting
|
|
3861
3937
|
*/
|
|
3862
|
-
public cancelPhoneInvite(invitee:
|
|
3938
|
+
public cancelPhoneInvite(invitee: Invitee) {
|
|
3863
3939
|
return this.members.cancelPhoneInvite(invitee);
|
|
3864
3940
|
}
|
|
3865
3941
|
|
|
3866
3942
|
/**
|
|
3867
3943
|
* Cancel an SIP/phone call invitation made during a meeting
|
|
3868
|
-
* @param {
|
|
3944
|
+
* @param {Invitee} invitee
|
|
3869
3945
|
* @param {String} invitee.memberId
|
|
3870
3946
|
* @param {Boolean} [invitee.isInternalNumber] - When cancel phone invitation, if the number is internal
|
|
3871
3947
|
* @returns {Promise} see #members.cancelInviteByMemberId
|
|
3872
3948
|
* @public
|
|
3873
3949
|
* @memberof Meeting
|
|
3874
3950
|
*/
|
|
3875
|
-
public cancelInviteByMemberId(invitee:
|
|
3951
|
+
public cancelInviteByMemberId(invitee: Invitee) {
|
|
3876
3952
|
return this.members.cancelInviteByMemberId(invitee);
|
|
3877
3953
|
}
|
|
3878
3954
|
|
|
@@ -4159,6 +4235,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4159
4235
|
this.userDisplayHints,
|
|
4160
4236
|
this.selfUserPolicies
|
|
4161
4237
|
),
|
|
4238
|
+
showAutoEndMeetingWarning: MeetingUtil.showAutoEndMeetingWarning(this.userDisplayHints),
|
|
4162
4239
|
canRaiseHand: MeetingUtil.canUserRaiseHand(this.userDisplayHints),
|
|
4163
4240
|
canLowerAllHands: MeetingUtil.canUserLowerAllHands(this.userDisplayHints),
|
|
4164
4241
|
canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(this.userDisplayHints),
|
|
@@ -4171,8 +4248,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4171
4248
|
isClosedCaptionActive: MeetingUtil.isClosedCaptionActive(this.userDisplayHints),
|
|
4172
4249
|
canStartManualCaption: MeetingUtil.canStartManualCaption(this.userDisplayHints),
|
|
4173
4250
|
canStopManualCaption: MeetingUtil.canStopManualCaption(this.userDisplayHints),
|
|
4251
|
+
isLocalRecordingStarted: MeetingUtil.isLocalRecordingStarted(this.userDisplayHints),
|
|
4252
|
+
isLocalRecordingStopped: MeetingUtil.isLocalRecordingStopped(this.userDisplayHints),
|
|
4253
|
+
isLocalRecordingPaused: MeetingUtil.isLocalRecordingPaused(this.userDisplayHints),
|
|
4254
|
+
isLocalStreamingStarted: MeetingUtil.isLocalStreamingStarted(this.userDisplayHints),
|
|
4255
|
+
isLocalStreamingStopped: MeetingUtil.isLocalStreamingStopped(this.userDisplayHints),
|
|
4174
4256
|
isManualCaptionActive: MeetingUtil.isManualCaptionActive(this.userDisplayHints),
|
|
4175
4257
|
isSaveTranscriptsEnabled: MeetingUtil.isSaveTranscriptsEnabled(this.userDisplayHints),
|
|
4258
|
+
isSpokenLanguageAutoDetectionEnabled: MeetingUtil.isSpokenLanguageAutoDetectionEnabled(
|
|
4259
|
+
this.userDisplayHints
|
|
4260
|
+
),
|
|
4176
4261
|
isWebexAssistantActive: MeetingUtil.isWebexAssistantActive(this.userDisplayHints),
|
|
4177
4262
|
canViewCaptionPanel: MeetingUtil.canViewCaptionPanel(this.userDisplayHints),
|
|
4178
4263
|
isRealTimeTranslationEnabled: MeetingUtil.isRealTimeTranslationEnabled(
|
|
@@ -4479,13 +4564,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4479
4564
|
setLocus(
|
|
4480
4565
|
locus:
|
|
4481
4566
|
| {
|
|
4482
|
-
locus: LocusDTO;
|
|
4483
4567
|
mediaConnections: Array<any>;
|
|
4484
4568
|
locusUrl: string;
|
|
4485
4569
|
locusId: string;
|
|
4486
4570
|
mediaId: string;
|
|
4487
4571
|
host: object;
|
|
4488
|
-
dataSets: DataSet[];
|
|
4489
4572
|
}
|
|
4490
4573
|
| any
|
|
4491
4574
|
) {
|
|
@@ -4499,7 +4582,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4499
4582
|
this.selfId = locus.selfId;
|
|
4500
4583
|
this.mediaId = locus.mediaId;
|
|
4501
4584
|
this.hostId = mtgLocus.host ? mtgLocus.host.id : this.hostId;
|
|
4502
|
-
this.locusInfo.initialSetup(mtgLocus
|
|
4585
|
+
this.locusInfo.initialSetup(mtgLocus);
|
|
4503
4586
|
}
|
|
4504
4587
|
|
|
4505
4588
|
/**
|
|
@@ -5612,21 +5695,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5612
5695
|
}
|
|
5613
5696
|
}
|
|
5614
5697
|
|
|
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
5698
|
/**
|
|
5631
5699
|
* Callback called when a relay event is received from meeting LLM Connection
|
|
5632
5700
|
* @param {RelayEvent} e Event object coming from LLM Connection
|
|
@@ -5945,15 +6013,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5945
6013
|
this.meetingFiniteStateMachine.fail(error);
|
|
5946
6014
|
LoggerProxy.logger.error('Meeting:index#join --> Failed', error);
|
|
5947
6015
|
|
|
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
6016
|
// TODO: change this to error codes and pre defined dictionary
|
|
5958
6017
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_FAILURE, {
|
|
5959
6018
|
correlation_id: this.correlationId,
|
|
@@ -6047,8 +6106,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6047
6106
|
);
|
|
6048
6107
|
// @ts-ignore - Fix type
|
|
6049
6108
|
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
6109
|
}
|
|
6053
6110
|
|
|
6054
6111
|
if (!isJoined) {
|
|
@@ -6063,10 +6120,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6063
6120
|
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
|
6064
6121
|
// @ts-ignore - Fix type
|
|
6065
6122
|
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
6123
|
LoggerProxy.logger.info(
|
|
6071
6124
|
'Meeting:index#updateLLMConnection --> enabled to receive relay events!'
|
|
6072
6125
|
);
|
|
@@ -6109,8 +6162,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6109
6162
|
*/
|
|
6110
6163
|
private dialInPstn() {
|
|
6111
6164
|
if (this.isPhoneProvisioned(this.dialInDeviceStatus)) return Promise.resolve(); // prevent multiple dial in devices from being provisioned
|
|
6165
|
+
this.pstnCorrelationId = uuid.v4();
|
|
6112
6166
|
|
|
6113
|
-
const {
|
|
6167
|
+
const {pstnCorrelationId, locusUrl} = this;
|
|
6114
6168
|
|
|
6115
6169
|
if (!this.dialInUrl) this.dialInUrl = `dialin:///${uuid.v4()}`;
|
|
6116
6170
|
|
|
@@ -6118,7 +6172,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6118
6172
|
this.meetingRequest
|
|
6119
6173
|
// @ts-ignore
|
|
6120
6174
|
.dialIn({
|
|
6121
|
-
correlationId,
|
|
6175
|
+
correlationId: pstnCorrelationId,
|
|
6122
6176
|
dialInUrl: this.dialInUrl,
|
|
6123
6177
|
locusUrl,
|
|
6124
6178
|
clientUrl: this.deviceUrl,
|
|
@@ -6127,12 +6181,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6127
6181
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
|
|
6128
6182
|
correlation_id: this.correlationId,
|
|
6129
6183
|
dial_in_url: this.dialInUrl,
|
|
6184
|
+
dial_in_correlation_id: pstnCorrelationId,
|
|
6130
6185
|
locus_id: locusUrl.split('/').pop(),
|
|
6131
6186
|
client_url: this.deviceUrl,
|
|
6132
6187
|
reason: error.error?.message,
|
|
6133
6188
|
stack: error.stack,
|
|
6134
6189
|
});
|
|
6135
6190
|
|
|
6191
|
+
if (this.pstnCorrelationId === pstnCorrelationId) {
|
|
6192
|
+
this.pstnCorrelationId = undefined;
|
|
6193
|
+
}
|
|
6194
|
+
|
|
6136
6195
|
return Promise.reject(error);
|
|
6137
6196
|
})
|
|
6138
6197
|
);
|
|
@@ -6147,8 +6206,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6147
6206
|
*/
|
|
6148
6207
|
private dialOutPstn(phoneNumber: string) {
|
|
6149
6208
|
if (this.isPhoneProvisioned(this.dialOutDeviceStatus)) return Promise.resolve(); // prevent multiple dial out devices from being provisioned
|
|
6209
|
+
this.pstnCorrelationId = uuid.v4();
|
|
6150
6210
|
|
|
6151
|
-
const {
|
|
6211
|
+
const {locusUrl, pstnCorrelationId} = this;
|
|
6152
6212
|
|
|
6153
6213
|
if (!this.dialOutUrl) this.dialOutUrl = `dialout:///${uuid.v4()}`;
|
|
6154
6214
|
|
|
@@ -6156,7 +6216,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6156
6216
|
this.meetingRequest
|
|
6157
6217
|
// @ts-ignore
|
|
6158
6218
|
.dialOut({
|
|
6159
|
-
correlationId,
|
|
6219
|
+
correlationId: pstnCorrelationId,
|
|
6160
6220
|
dialOutUrl: this.dialOutUrl,
|
|
6161
6221
|
phoneNumber,
|
|
6162
6222
|
locusUrl,
|
|
@@ -6166,12 +6226,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6166
6226
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
|
|
6167
6227
|
correlation_id: this.correlationId,
|
|
6168
6228
|
dial_out_url: this.dialOutUrl,
|
|
6229
|
+
dial_out_correlation_id: pstnCorrelationId,
|
|
6169
6230
|
locus_id: locusUrl.split('/').pop(),
|
|
6170
6231
|
client_url: this.deviceUrl,
|
|
6171
6232
|
reason: error.error?.message,
|
|
6172
6233
|
stack: error.stack,
|
|
6173
6234
|
});
|
|
6174
6235
|
|
|
6236
|
+
if (this.pstnCorrelationId === pstnCorrelationId) {
|
|
6237
|
+
this.pstnCorrelationId = undefined;
|
|
6238
|
+
}
|
|
6239
|
+
|
|
6175
6240
|
return Promise.reject(error);
|
|
6176
6241
|
})
|
|
6177
6242
|
);
|
|
@@ -6185,6 +6250,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6185
6250
|
* @returns {Promise}
|
|
6186
6251
|
*/
|
|
6187
6252
|
public disconnectPhoneAudio() {
|
|
6253
|
+
const correlationToClear = this.pstnCorrelationId;
|
|
6254
|
+
|
|
6188
6255
|
return Promise.all([
|
|
6189
6256
|
this.isPhoneProvisioned(this.dialInDeviceStatus)
|
|
6190
6257
|
? MeetingUtil.disconnectPhoneAudio(this, this.dialInUrl)
|
|
@@ -6192,7 +6259,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6192
6259
|
this.isPhoneProvisioned(this.dialOutDeviceStatus)
|
|
6193
6260
|
? MeetingUtil.disconnectPhoneAudio(this, this.dialOutUrl)
|
|
6194
6261
|
: Promise.resolve(),
|
|
6195
|
-
])
|
|
6262
|
+
]).then(() => {
|
|
6263
|
+
if (this.pstnCorrelationId === correlationToClear) {
|
|
6264
|
+
this.pstnCorrelationId = undefined;
|
|
6265
|
+
}
|
|
6266
|
+
});
|
|
6196
6267
|
}
|
|
6197
6268
|
|
|
6198
6269
|
/**
|
|
@@ -6769,6 +6840,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6769
6840
|
// @ts-ignore
|
|
6770
6841
|
this.webex.internal.newMetrics.submitClientEvent({
|
|
6771
6842
|
name: 'client.ice.start',
|
|
6843
|
+
payload: {
|
|
6844
|
+
// @ts-ignore
|
|
6845
|
+
labels: MeetingUtil.getCaEventLabelsForIpVersion(this.webex),
|
|
6846
|
+
},
|
|
6772
6847
|
options: {
|
|
6773
6848
|
meetingId: this.id,
|
|
6774
6849
|
},
|
|
@@ -6938,10 +7013,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6938
7013
|
}
|
|
6939
7014
|
}
|
|
6940
7015
|
|
|
6941
|
-
// Count members that are in the meeting.
|
|
7016
|
+
// Count members that are in the meeting or in the lobby.
|
|
6942
7017
|
const {members} = this.getMembers().membersCollection;
|
|
6943
7018
|
event.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
|
|
6944
|
-
(member: Member) => member.isInMeeting
|
|
7019
|
+
(member: Member) => member.isInMeeting || member.isInLobby
|
|
6945
7020
|
).length;
|
|
6946
7021
|
|
|
6947
7022
|
// @ts-ignore
|
|
@@ -7300,10 +7375,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7300
7375
|
if (this.config.stats.enableStatsAnalyzer) {
|
|
7301
7376
|
// @ts-ignore - config coming from registerPlugin
|
|
7302
7377
|
this.networkQualityMonitor = new NetworkQualityMonitor(this.config.stats);
|
|
7378
|
+
this.statsMonitor = new StatsMonitor();
|
|
7303
7379
|
this.statsAnalyzer = new StatsAnalyzer({
|
|
7304
7380
|
// @ts-ignore - config coming from registerPlugin
|
|
7305
7381
|
config: this.config.stats,
|
|
7306
7382
|
networkQualityMonitor: this.networkQualityMonitor,
|
|
7383
|
+
statsMonitor: this.statsMonitor,
|
|
7307
7384
|
isMultistream: this.isMultistream,
|
|
7308
7385
|
});
|
|
7309
7386
|
this.shareCAEventSentStatus = {
|
|
@@ -7317,6 +7394,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7317
7394
|
NetworkQualityEventNames.NETWORK_QUALITY,
|
|
7318
7395
|
this.sendNetworkQualityEvent.bind(this)
|
|
7319
7396
|
);
|
|
7397
|
+
|
|
7398
|
+
this.statsMonitor.on(StatsMonitorEventNames.INBOUND_AUDIO_ISSUE, (data) => {
|
|
7399
|
+
// Before forwarding any inbound audio issues to the app, make sure that we have at least one other
|
|
7400
|
+
// participant in the meeting with unmuted audio.
|
|
7401
|
+
// We don't check this.mediaProperties.mediaDirection here, because that's already handled in statsAnalyzer,
|
|
7402
|
+
// so we won't get this event if we are not setup to receive any audio
|
|
7403
|
+
const atLeastOneUnmutedOtherMember = Object.values(
|
|
7404
|
+
this.members.membersCollection.getAll()
|
|
7405
|
+
).find((member) => {
|
|
7406
|
+
return !member.isSelf && !member.isPairedWithSelf && !member.isAudioMuted;
|
|
7407
|
+
});
|
|
7408
|
+
|
|
7409
|
+
if (atLeastOneUnmutedOtherMember) {
|
|
7410
|
+
this.mediaProperties.sendMediaIssueMetric(
|
|
7411
|
+
'inbound_audio',
|
|
7412
|
+
data.issueSubType,
|
|
7413
|
+
this.correlationId
|
|
7414
|
+
);
|
|
7415
|
+
|
|
7416
|
+
Trigger.trigger(
|
|
7417
|
+
this,
|
|
7418
|
+
{file: 'meeting/index', function: 'createStatsAnalyzer'},
|
|
7419
|
+
EVENT_TRIGGERS.MEDIA_INBOUND_AUDIO_ISSUE_DETECTED,
|
|
7420
|
+
data
|
|
7421
|
+
);
|
|
7422
|
+
}
|
|
7423
|
+
});
|
|
7320
7424
|
}
|
|
7321
7425
|
}
|
|
7322
7426
|
|
|
@@ -7615,6 +7719,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7615
7719
|
}
|
|
7616
7720
|
|
|
7617
7721
|
this.statsAnalyzer = null;
|
|
7722
|
+
this.networkQualityMonitor?.removeAllListeners();
|
|
7723
|
+
this.networkQualityMonitor = null;
|
|
7724
|
+
this.statsMonitor?.removeAllListeners();
|
|
7725
|
+
this.statsMonitor = null;
|
|
7618
7726
|
|
|
7619
7727
|
// when media fails, we want to upload a webrtc dump to see whats going on
|
|
7620
7728
|
// this function is async, but returns once the stats have been gathered
|
|
@@ -7638,6 +7746,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7638
7746
|
await this.statsAnalyzer.stopAnalyzer();
|
|
7639
7747
|
}
|
|
7640
7748
|
this.statsAnalyzer = null;
|
|
7749
|
+
this.networkQualityMonitor?.removeAllListeners();
|
|
7750
|
+
this.networkQualityMonitor = null;
|
|
7751
|
+
this.statsMonitor?.removeAllListeners();
|
|
7752
|
+
this.statsMonitor = null;
|
|
7641
7753
|
|
|
7642
7754
|
this.isMultistream = false;
|
|
7643
7755
|
|
|
@@ -7809,6 +7921,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7809
7921
|
|
|
7810
7922
|
this.allowMediaInLobby = options?.allowMediaInLobby;
|
|
7811
7923
|
|
|
7924
|
+
// @ts-ignore
|
|
7925
|
+
const ipver = MeetingUtil.getIpVersion(this.webex); // used just for metrics
|
|
7926
|
+
|
|
7812
7927
|
// If the user is unjoined or guest waiting in lobby dont allow the user to addMedia
|
|
7813
7928
|
// @ts-ignore - isUserUnadmitted coming from SelfUtil
|
|
7814
7929
|
if (this.isUserUnadmitted && !this.wirelessShare && !this.allowMediaInLobby) {
|
|
@@ -7907,6 +8022,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7907
8022
|
locus_id: this.locusUrl.split('/').pop(),
|
|
7908
8023
|
connectionType,
|
|
7909
8024
|
ipVersion,
|
|
8025
|
+
ipver,
|
|
7910
8026
|
selectedCandidatePairChanges,
|
|
7911
8027
|
numTransports,
|
|
7912
8028
|
isMultistream: this.isMultistream,
|
|
@@ -7975,6 +8091,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7975
8091
|
...reachabilityMetrics,
|
|
7976
8092
|
...iceCandidateErrors,
|
|
7977
8093
|
iceCandidatesCount: this.iceCandidatesCount,
|
|
8094
|
+
ipver,
|
|
7978
8095
|
});
|
|
7979
8096
|
|
|
7980
8097
|
await this.cleanUpOnAddMediaFailure();
|
|
@@ -8414,6 +8531,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
8414
8531
|
}
|
|
8415
8532
|
|
|
8416
8533
|
if (whiteboard) {
|
|
8534
|
+
// @ts-ignore
|
|
8535
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
|
8536
|
+
key: 'internal.client.share.initiated',
|
|
8537
|
+
});
|
|
8417
8538
|
// @ts-ignore
|
|
8418
8539
|
this.webex.internal.newMetrics.submitClientEvent({
|
|
8419
8540
|
name: 'client.share.initiated',
|
|
@@ -8473,11 +8594,17 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
8473
8594
|
const whiteboard = this.locusInfo.mediaShares.find((element) => element.name === 'whiteboard');
|
|
8474
8595
|
|
|
8475
8596
|
if (whiteboard) {
|
|
8597
|
+
// @ts-ignore
|
|
8598
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
|
8599
|
+
key: 'internal.client.share.stopped',
|
|
8600
|
+
});
|
|
8476
8601
|
// @ts-ignore
|
|
8477
8602
|
this.webex.internal.newMetrics.submitClientEvent({
|
|
8478
8603
|
name: 'client.share.stopped',
|
|
8479
8604
|
payload: {
|
|
8480
8605
|
mediaType: 'whiteboard',
|
|
8606
|
+
// @ts-ignore
|
|
8607
|
+
shareDuration: this.webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration(),
|
|
8481
8608
|
},
|
|
8482
8609
|
options: {
|
|
8483
8610
|
meetingId: this.id,
|
|
@@ -8635,12 +8762,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
8635
8762
|
}
|
|
8636
8763
|
this.screenShareFloorState = ScreenShareFloorStatus.RELEASED;
|
|
8637
8764
|
if (content) {
|
|
8765
|
+
// @ts-ignore
|
|
8766
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
|
8767
|
+
key: 'internal.client.share.stopped',
|
|
8768
|
+
});
|
|
8638
8769
|
// @ts-ignore
|
|
8639
8770
|
this.webex.internal.newMetrics.submitClientEvent({
|
|
8640
8771
|
name: 'client.share.stopped',
|
|
8641
8772
|
payload: {
|
|
8642
8773
|
mediaType: 'share',
|
|
8643
8774
|
shareInstanceId: this.localShareInstanceId,
|
|
8775
|
+
// @ts-ignore
|
|
8776
|
+
shareDuration: this.webex.internal.newMetrics.callDiagnosticLatencies.getShareDuration(),
|
|
8644
8777
|
},
|
|
8645
8778
|
options: {meetingId: this.id},
|
|
8646
8779
|
});
|
|
@@ -9238,8 +9371,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
9238
9371
|
|
|
9239
9372
|
// @ts-ignore - fix types
|
|
9240
9373
|
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
9374
|
};
|
|
9244
9375
|
|
|
9245
9376
|
/**
|
|
@@ -9337,6 +9468,36 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
9337
9468
|
return Promise.reject(new Error('Error sending reaction, service url not found.'));
|
|
9338
9469
|
}
|
|
9339
9470
|
|
|
9471
|
+
/**
|
|
9472
|
+
* Extend the current meeting duration.
|
|
9473
|
+
*
|
|
9474
|
+
* @param {number} extensionMinutes - how many minutes to extend
|
|
9475
|
+
* @returns {Promise}
|
|
9476
|
+
* @public
|
|
9477
|
+
* @memberof Meeting
|
|
9478
|
+
*/
|
|
9479
|
+
public extendMeeting({
|
|
9480
|
+
meetingPolicyUrl,
|
|
9481
|
+
meetingInstanceId,
|
|
9482
|
+
participantId,
|
|
9483
|
+
extensionMinutes = 30,
|
|
9484
|
+
}) {
|
|
9485
|
+
if (!meetingInstanceId || !participantId) {
|
|
9486
|
+
return Promise.reject(new Error('Missing meetingInstanceId or participantId'));
|
|
9487
|
+
}
|
|
9488
|
+
|
|
9489
|
+
if (!meetingPolicyUrl) {
|
|
9490
|
+
return Promise.reject(new Error('Missing meetingPolicyUrl'));
|
|
9491
|
+
}
|
|
9492
|
+
|
|
9493
|
+
return this.meetingRequest.extendMeeting({
|
|
9494
|
+
meetingInstanceId,
|
|
9495
|
+
participantId,
|
|
9496
|
+
extensionMinutes,
|
|
9497
|
+
meetingPolicyUrl,
|
|
9498
|
+
});
|
|
9499
|
+
}
|
|
9500
|
+
|
|
9340
9501
|
/**
|
|
9341
9502
|
* Method to enable or disable reactions inside the meeting.
|
|
9342
9503
|
*
|
|
@@ -9619,6 +9780,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
9619
9780
|
this.shareCAEventSentStatus.transmitStart = false;
|
|
9620
9781
|
this.shareCAEventSentStatus.transmitStop = false;
|
|
9621
9782
|
|
|
9783
|
+
// @ts-ignore
|
|
9784
|
+
this.webex.internal.newMetrics.callDiagnosticLatencies.saveTimestamp({
|
|
9785
|
+
key: 'internal.client.share.initiated',
|
|
9786
|
+
});
|
|
9787
|
+
|
|
9622
9788
|
// @ts-ignore
|
|
9623
9789
|
this.webex.internal.newMetrics.submitClientEvent({
|
|
9624
9790
|
name: 'client.share.initiated',
|
|
@@ -9861,4 +10027,47 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
9861
10027
|
|
|
9862
10028
|
return this.meetingRequest.synchronizeStage(this.locusUrl, videoLayout);
|
|
9863
10029
|
}
|
|
10030
|
+
|
|
10031
|
+
/**
|
|
10032
|
+
* Notifies the host with the given meeting UUID and display names.
|
|
10033
|
+
*
|
|
10034
|
+
* @param {string} meetingUuid - The UUID of the meeting.
|
|
10035
|
+
* @param {string[]} displayName - An array of display names to notify the host with.
|
|
10036
|
+
* @returns {Promise<any>} The result of the notifyHost request.
|
|
10037
|
+
*/
|
|
10038
|
+
notifyHost(meetingUuid: string, displayName: string[]) {
|
|
10039
|
+
return this.meetingRequest.notifyHost(
|
|
10040
|
+
this.meetingInfo.siteFullUrl,
|
|
10041
|
+
this.locusId,
|
|
10042
|
+
meetingUuid,
|
|
10043
|
+
displayName
|
|
10044
|
+
);
|
|
10045
|
+
}
|
|
10046
|
+
|
|
10047
|
+
/**
|
|
10048
|
+
* Call out a SIP participant to a meeting
|
|
10049
|
+
* @param {string} address - The SIP address or phone number
|
|
10050
|
+
* @param {string} displayName - The display name for the participant
|
|
10051
|
+
* @param {string} [correlationId] - Optional correlation ID
|
|
10052
|
+
* @returns {Promise} Promise that resolves when the call-out is initiated
|
|
10053
|
+
*/
|
|
10054
|
+
sipCallOut(address: string, displayName: string) {
|
|
10055
|
+
return this.meetingRequest.sipCallOut(
|
|
10056
|
+
this.meetingInfo.meetingId,
|
|
10057
|
+
this.meetingInfo.meetingId,
|
|
10058
|
+
address,
|
|
10059
|
+
displayName
|
|
10060
|
+
);
|
|
10061
|
+
}
|
|
10062
|
+
|
|
10063
|
+
/**
|
|
10064
|
+
* Cancel an ongoing SIP call-out
|
|
10065
|
+
* @param {string} participantId - The participant ID to cancel
|
|
10066
|
+
* @returns {Promise} Promise that resolves when the call-out is cancelled
|
|
10067
|
+
* @public
|
|
10068
|
+
* @memberof Meetings
|
|
10069
|
+
*/
|
|
10070
|
+
cancelSipCallOut(participantId: string) {
|
|
10071
|
+
return this.meetingRequest.cancelSipCallOut(participantId);
|
|
10072
|
+
}
|
|
9864
10073
|
}
|