@webex/plugin-meetings 2.60.0-next.1 → 2.60.0-next.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/annotation/annotation.types.d.ts +42 -0
- package/dist/annotation/constants.d.ts +31 -0
- package/dist/annotation/index.d.ts +117 -0
- package/dist/breakouts/breakout.d.ts +8 -0
- package/dist/breakouts/breakout.js +1 -1
- package/dist/breakouts/collection.d.ts +5 -0
- package/dist/breakouts/edit-lock-error.d.ts +15 -0
- package/dist/breakouts/events.d.ts +8 -0
- package/dist/breakouts/index.d.ts +5 -0
- package/dist/breakouts/index.js +1 -1
- package/dist/breakouts/request.d.ts +22 -0
- package/dist/breakouts/utils.d.ts +15 -0
- package/dist/common/browser-detection.d.ts +9 -0
- package/dist/common/collection.d.ts +48 -0
- package/dist/common/config.d.ts +2 -0
- package/dist/common/errors/captcha-error.d.ts +15 -0
- package/dist/common/errors/intent-to-join.d.ts +16 -0
- package/dist/common/errors/join-meeting.d.ts +17 -0
- package/dist/common/errors/media.d.ts +15 -0
- package/dist/common/errors/no-meeting-info.d.ts +14 -0
- package/dist/common/errors/parameter.d.ts +15 -0
- package/dist/common/errors/password-error.d.ts +15 -0
- package/dist/common/errors/permission.d.ts +14 -0
- package/dist/common/errors/reclaim-host-role-errors.d.ts +60 -0
- package/dist/common/errors/reconnection-in-progress.d.ts +9 -0
- package/dist/common/errors/reconnection.d.ts +15 -0
- package/dist/common/errors/stats.d.ts +15 -0
- package/dist/common/errors/webex-errors.d.ts +93 -0
- package/dist/common/errors/webex-meetings-error.d.ts +20 -0
- package/dist/common/events/events-scope.d.ts +17 -0
- package/dist/common/events/events.d.ts +12 -0
- package/dist/common/events/trigger-proxy.d.ts +2 -0
- package/dist/common/events/util.d.ts +2 -0
- package/dist/common/logs/logger-config.d.ts +2 -0
- package/dist/common/logs/logger-proxy.d.ts +2 -0
- package/dist/common/logs/request.d.ts +36 -0
- package/dist/common/queue.d.ts +34 -0
- package/dist/config.d.ts +71 -0
- package/dist/constants.d.ts +1072 -0
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/constants.d.ts +4 -0
- package/dist/controls-options-manager/enums.d.ts +15 -0
- package/dist/controls-options-manager/enums.js +2 -1
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/index.d.ts +136 -0
- package/dist/controls-options-manager/types.d.ts +43 -0
- package/dist/controls-options-manager/util.d.ts +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/interpretation/collection.d.ts +5 -0
- package/dist/interpretation/index.d.ts +5 -0
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.d.ts +5 -0
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.d.ts +2 -0
- package/dist/locus-info/embeddedAppsUtils.d.ts +2 -0
- package/dist/locus-info/fullState.d.ts +2 -0
- package/dist/locus-info/hostUtils.d.ts +2 -0
- package/dist/locus-info/index.d.ts +322 -0
- package/dist/locus-info/infoUtils.d.ts +2 -0
- package/dist/locus-info/mediaSharesUtils.d.ts +2 -0
- package/dist/locus-info/parser.d.ts +272 -0
- package/dist/locus-info/parser.js +5 -5
- package/dist/locus-info/parser.js.map +1 -1
- package/dist/locus-info/selfUtils.d.ts +2 -0
- package/dist/media/index.d.ts +34 -0
- package/dist/media/index.js +6 -5
- package/dist/media/index.js.map +1 -1
- package/dist/media/properties.d.ts +93 -0
- package/dist/media/util.d.ts +2 -0
- package/dist/mediaQualityMetrics/config.d.ts +237 -0
- package/dist/mediaQualityMetrics/config.js +1 -202
- package/dist/mediaQualityMetrics/config.js.map +1 -1
- package/dist/meeting/in-meeting-actions.d.ts +167 -0
- package/dist/meeting/in-meeting-actions.js +4 -0
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.d.ts +1719 -0
- package/dist/meeting/index.js +288 -155
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.d.ts +74 -0
- package/dist/meeting/muteState.d.ts +184 -0
- package/dist/meeting/request.d.ts +290 -0
- package/dist/meeting/request.type.d.ts +11 -0
- package/dist/meeting/state.d.ts +9 -0
- package/dist/meeting/util.d.ts +103 -0
- package/dist/meeting-info/collection.d.ts +20 -0
- package/dist/meeting-info/index.d.ts +69 -0
- package/dist/meeting-info/meeting-info-v2.d.ts +123 -0
- package/dist/meeting-info/meeting-info-v2.js +3 -0
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meeting-info/request.d.ts +22 -0
- package/dist/meeting-info/util.d.ts +2 -0
- package/dist/meeting-info/utilv2.d.ts +2 -0
- package/dist/meeting-info/utilv2.js +14 -29
- package/dist/meeting-info/utilv2.js.map +1 -1
- package/dist/meetings/collection.d.ts +40 -0
- package/dist/meetings/collection.js +17 -0
- package/dist/meetings/collection.js.map +1 -1
- package/dist/meetings/index.d.ts +378 -0
- package/dist/meetings/index.js +30 -9
- package/dist/meetings/index.js.map +1 -1
- package/dist/meetings/meetings.types.d.ts +4 -0
- package/dist/meetings/request.d.ts +27 -0
- package/dist/meetings/util.d.ts +18 -0
- package/dist/member/index.d.ts +160 -0
- package/dist/member/member.types.d.ts +11 -0
- package/dist/member/types.d.ts +32 -0
- package/dist/member/util.d.ts +2 -0
- package/dist/members/collection.d.ts +29 -0
- package/dist/members/index.d.ts +353 -0
- package/dist/members/request.d.ts +114 -0
- package/dist/members/types.d.ts +25 -0
- package/dist/members/util.d.ts +215 -0
- package/dist/metrics/constants.d.ts +68 -0
- package/dist/metrics/constants.js +3 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/metrics/index.d.ts +45 -0
- package/dist/multistream/mediaRequestManager.d.ts +118 -0
- package/dist/multistream/receiveSlot.d.ts +68 -0
- package/dist/multistream/receiveSlotManager.d.ts +56 -0
- package/dist/multistream/remoteMedia.d.ts +72 -0
- package/dist/multistream/remoteMediaGroup.d.ts +47 -0
- package/dist/multistream/remoteMediaManager.d.ts +285 -0
- package/dist/multistream/sendSlotManager.d.ts +61 -0
- package/dist/networkQualityMonitor/index.d.ts +70 -0
- package/dist/personal-meeting-room/index.d.ts +47 -0
- package/dist/personal-meeting-room/request.d.ts +14 -0
- package/dist/personal-meeting-room/util.d.ts +2 -0
- package/dist/reachability/index.d.ts +194 -0
- package/dist/reachability/request.d.ts +39 -0
- package/dist/reactions/constants.d.ts +3 -0
- package/dist/reactions/reactions.d.ts +4 -0
- package/dist/reactions/reactions.type.d.ts +52 -0
- package/dist/reconnection-manager/index.d.ts +136 -0
- package/dist/reconnection-manager/index.js +27 -28
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/enums.d.ts +7 -0
- package/dist/recording-controller/index.d.ts +207 -0
- package/dist/recording-controller/util.d.ts +14 -0
- package/dist/roap/index.d.ts +78 -0
- package/dist/roap/request.d.ts +41 -0
- package/dist/roap/turnDiscovery.d.ts +92 -0
- package/dist/rtcMetrics/constants.d.ts +4 -0
- package/dist/rtcMetrics/index.d.ts +54 -0
- package/dist/rtcMetrics/index.js +25 -0
- package/dist/rtcMetrics/index.js.map +1 -1
- package/dist/statsAnalyzer/global.d.ts +36 -0
- package/dist/statsAnalyzer/index.d.ts +191 -0
- package/dist/statsAnalyzer/index.js +53 -146
- package/dist/statsAnalyzer/index.js.map +1 -1
- package/dist/statsAnalyzer/mqaUtil.d.ts +24 -0
- package/dist/statsAnalyzer/mqaUtil.js +11 -12
- package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
- package/dist/transcription/index.d.ts +64 -0
- package/dist/webinar/collection.d.ts +16 -0
- package/dist/webinar/index.d.ts +5 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +26 -27
- package/src/constants.ts +10 -4
- package/src/controls-options-manager/enums.ts +2 -0
- package/src/locus-info/parser.ts +6 -6
- package/src/media/index.ts +5 -5
- package/src/mediaQualityMetrics/config.ts +0 -135
- package/src/meeting/in-meeting-actions.ts +8 -0
- package/src/meeting/index.ts +263 -125
- package/src/meeting-info/meeting-info-v2.ts +4 -0
- package/src/meeting-info/utilv2.ts +6 -19
- package/src/meetings/collection.ts +13 -0
- package/src/meetings/index.ts +28 -10
- package/src/metrics/constants.ts +3 -0
- package/src/reconnection-manager/index.ts +63 -68
- package/src/rtcMetrics/index.ts +24 -0
- package/src/statsAnalyzer/index.ts +68 -216
- package/src/statsAnalyzer/mqaUtil.ts +17 -22
- package/test/unit/spec/media/index.ts +20 -4
- package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
- package/test/unit/spec/meeting/index.js +1376 -189
- package/test/unit/spec/meeting/muteState.js +2 -1
- package/test/unit/spec/meeting-info/meetinginfov2.js +28 -0
- package/test/unit/spec/meetings/collection.js +12 -0
- package/test/unit/spec/meetings/index.js +382 -118
- package/test/unit/spec/member/util.js +0 -31
- package/test/unit/spec/reconnection-manager/index.js +42 -12
- package/test/unit/spec/rtcMetrics/index.ts +20 -0
- package/test/unit/spec/stats-analyzer/index.js +12 -2
package/src/meeting/index.ts
CHANGED
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
ClientEvent,
|
|
10
10
|
ClientEventLeaveReason,
|
|
11
11
|
CallDiagnosticUtils,
|
|
12
|
-
CALL_DIAGNOSTIC_CONFIG,
|
|
13
12
|
} from '@webex/internal-plugin-metrics';
|
|
14
13
|
import {
|
|
15
14
|
ConnectionState,
|
|
@@ -105,6 +104,7 @@ import {
|
|
|
105
104
|
MEETING_PERMISSION_TOKEN_REFRESH_THRESHOLD_IN_SEC,
|
|
106
105
|
MEETING_PERMISSION_TOKEN_REFRESH_REASON,
|
|
107
106
|
ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT,
|
|
107
|
+
RECONNECTION,
|
|
108
108
|
} from '../constants';
|
|
109
109
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
110
110
|
import ParameterError from '../common/errors/parameter';
|
|
@@ -178,6 +178,12 @@ export type AddMediaOptions = {
|
|
|
178
178
|
allowMediaInLobby?: boolean; // allows adding media when in the lobby
|
|
179
179
|
};
|
|
180
180
|
|
|
181
|
+
export type CallStateForMetrics = {
|
|
182
|
+
correlationId?: string;
|
|
183
|
+
joinTrigger?: string;
|
|
184
|
+
loginType?: string;
|
|
185
|
+
};
|
|
186
|
+
|
|
181
187
|
export const MEDIA_UPDATE_TYPE = {
|
|
182
188
|
TRANSCODED_MEDIA_CONNECTION: 'TRANSCODED_MEDIA_CONNECTION',
|
|
183
189
|
SHARE_FLOOR_REQUEST: 'SHARE_FLOOR_REQUEST',
|
|
@@ -470,7 +476,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
470
476
|
annotation: any;
|
|
471
477
|
webinar: any;
|
|
472
478
|
conversationUrl: string;
|
|
473
|
-
|
|
479
|
+
callStateForMetrics: CallStateForMetrics;
|
|
474
480
|
destination: string;
|
|
475
481
|
destinationType: string;
|
|
476
482
|
deviceUrl: string;
|
|
@@ -528,7 +534,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
528
534
|
meetingInfoFailureCode?: number;
|
|
529
535
|
meetingInfoExtraParams?: Record<string, any>;
|
|
530
536
|
networkQualityMonitor: NetworkQualityMonitor;
|
|
531
|
-
networkStatus
|
|
537
|
+
networkStatus?: NETWORK_STATUS;
|
|
532
538
|
passwordStatus: string;
|
|
533
539
|
queuedMediaUpdates: any[];
|
|
534
540
|
recording: any;
|
|
@@ -538,6 +544,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
538
544
|
requiredCaptcha: any;
|
|
539
545
|
receiveSlotManager: ReceiveSlotManager;
|
|
540
546
|
selfUserPolicies: any;
|
|
547
|
+
enforceVBGImagesURL: string;
|
|
541
548
|
shareStatus: string;
|
|
542
549
|
screenShareFloorState: ScreenShareFloorStatus;
|
|
543
550
|
statsAnalyzer: StatsAnalyzer;
|
|
@@ -560,6 +567,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
560
567
|
meetingState: any;
|
|
561
568
|
permissionToken: string;
|
|
562
569
|
permissionTokenPayload: any;
|
|
570
|
+
permissionTokenReceivedLocalTime: number;
|
|
563
571
|
resourceId: any;
|
|
564
572
|
resourceUrl: string;
|
|
565
573
|
selfId: string;
|
|
@@ -577,6 +585,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
577
585
|
private sendSlotManager: SendSlotManager = new SendSlotManager(LoggerProxy);
|
|
578
586
|
private deferSDPAnswer?: Defer; // used for waiting for a response
|
|
579
587
|
private sdpResponseTimer?: ReturnType<typeof setTimeout>;
|
|
588
|
+
private hasMediaConnectionConnectedAtLeastOnce: boolean;
|
|
580
589
|
|
|
581
590
|
/**
|
|
582
591
|
* @param {Object} attrs
|
|
@@ -611,20 +620,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
611
620
|
*/
|
|
612
621
|
this.id = uuid.v4();
|
|
613
622
|
/**
|
|
614
|
-
*
|
|
623
|
+
* Call state used for metrics
|
|
615
624
|
* @instance
|
|
616
|
-
* @type {
|
|
625
|
+
* @type {CallStateForMetrics}
|
|
617
626
|
* @readonly
|
|
618
627
|
* @public
|
|
619
628
|
* @memberof Meeting
|
|
620
629
|
*/
|
|
621
|
-
|
|
630
|
+
this.callStateForMetrics = attrs.callStateForMetrics || {};
|
|
631
|
+
const correlationId = attrs.correlationId || attrs.callStateForMetrics?.correlationId;
|
|
632
|
+
if (correlationId) {
|
|
622
633
|
LoggerProxy.logger.log(
|
|
623
|
-
`Meetings:index#constructor --> Initializing the meeting object with correlation id from app ${
|
|
634
|
+
`Meetings:index#constructor --> Initializing the meeting object with correlation id from app ${correlationId}`
|
|
624
635
|
);
|
|
625
|
-
this.correlationId =
|
|
636
|
+
this.callStateForMetrics.correlationId = correlationId;
|
|
626
637
|
} else {
|
|
627
|
-
this.correlationId = this.id;
|
|
638
|
+
this.callStateForMetrics.correlationId = this.id;
|
|
628
639
|
}
|
|
629
640
|
/**
|
|
630
641
|
* @instance
|
|
@@ -1096,13 +1107,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1096
1107
|
*/
|
|
1097
1108
|
this.networkQualityMonitor = null;
|
|
1098
1109
|
/**
|
|
1110
|
+
* Indicates network status of the webrtc media connection
|
|
1099
1111
|
* @instance
|
|
1100
1112
|
* @type {String}
|
|
1101
1113
|
* @readonly
|
|
1102
1114
|
* @public
|
|
1103
1115
|
* @memberof Meeting
|
|
1104
1116
|
*/
|
|
1105
|
-
this.networkStatus =
|
|
1117
|
+
this.networkStatus = undefined;
|
|
1106
1118
|
/**
|
|
1107
1119
|
* Passing only info as we send basic info for meeting added event
|
|
1108
1120
|
* @instance
|
|
@@ -1318,6 +1330,15 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1318
1330
|
* @memberof Meeting
|
|
1319
1331
|
*/
|
|
1320
1332
|
this.retriedWithTurnServer = false;
|
|
1333
|
+
|
|
1334
|
+
/**
|
|
1335
|
+
* Whether or not the media connection has ever successfully connected.
|
|
1336
|
+
* @instance
|
|
1337
|
+
* @type {boolean}
|
|
1338
|
+
* @private
|
|
1339
|
+
* @memberof Meeting
|
|
1340
|
+
*/
|
|
1341
|
+
this.hasMediaConnectionConnectedAtLeastOnce = false;
|
|
1321
1342
|
}
|
|
1322
1343
|
|
|
1323
1344
|
/**
|
|
@@ -1350,6 +1371,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1350
1371
|
return this.type === 'CALL';
|
|
1351
1372
|
}
|
|
1352
1373
|
|
|
1374
|
+
/**
|
|
1375
|
+
* Getter - Returns callStateForMetrics.correlationId
|
|
1376
|
+
* @returns {string}
|
|
1377
|
+
*/
|
|
1378
|
+
get correlationId() {
|
|
1379
|
+
return this.callStateForMetrics.correlationId;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* Setter - sets callStateForMetrics.correlationId
|
|
1384
|
+
* @param {string} correlationId
|
|
1385
|
+
*/
|
|
1386
|
+
set correlationId(correlationId: string) {
|
|
1387
|
+
this.callStateForMetrics.correlationId = correlationId;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1353
1390
|
/**
|
|
1354
1391
|
* Internal method for fetching meeting info
|
|
1355
1392
|
*
|
|
@@ -1491,15 +1528,21 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1491
1528
|
: this.destination;
|
|
1492
1529
|
const destinationType = isStartingSpaceInstantV2Meeting ? _MEETING_LINK_ : this.destinationType;
|
|
1493
1530
|
|
|
1494
|
-
const
|
|
1531
|
+
const permissionTokenExpiryInfo = this.getPermissionTokenExpiryInfo();
|
|
1532
|
+
|
|
1533
|
+
const timeLeft = permissionTokenExpiryInfo?.timeLeft;
|
|
1534
|
+
const expiryTime = permissionTokenExpiryInfo?.expiryTime;
|
|
1535
|
+
const currentTime = permissionTokenExpiryInfo?.currentTime;
|
|
1495
1536
|
|
|
1496
1537
|
LoggerProxy.logger.info(
|
|
1497
|
-
`Meeting:index#refreshPermissionToken --> refreshing permission token, destinationType=${destinationType}, timeLeft=${timeLeft}, reason=${reason}`
|
|
1538
|
+
`Meeting:index#refreshPermissionToken --> refreshing permission token, destinationType=${destinationType}, timeLeft=${timeLeft}, permissionTokenExpiry=${expiryTime}, currentTimestamp=${currentTime},reason=${reason}`
|
|
1498
1539
|
);
|
|
1499
1540
|
|
|
1500
1541
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.PERMISSION_TOKEN_REFRESH, {
|
|
1501
1542
|
correlationId: this.correlationId,
|
|
1502
1543
|
timeLeft,
|
|
1544
|
+
expiryTime,
|
|
1545
|
+
currentTime,
|
|
1503
1546
|
reason,
|
|
1504
1547
|
destinationType,
|
|
1505
1548
|
});
|
|
@@ -1928,12 +1971,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1928
1971
|
|
|
1929
1972
|
/**
|
|
1930
1973
|
* sets the network status on meeting object
|
|
1931
|
-
* @param {
|
|
1974
|
+
* @param {NETWORK_STATUS} networkStatus
|
|
1932
1975
|
* @private
|
|
1933
1976
|
* @returns {undefined}
|
|
1934
1977
|
* @memberof Meeting
|
|
1935
1978
|
*/
|
|
1936
|
-
private setNetworkStatus(networkStatus
|
|
1979
|
+
private setNetworkStatus(networkStatus?: NETWORK_STATUS) {
|
|
1937
1980
|
if (networkStatus === NETWORK_STATUS.DISCONNECTED) {
|
|
1938
1981
|
Trigger.trigger(
|
|
1939
1982
|
this,
|
|
@@ -3275,6 +3318,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3275
3318
|
}) &&
|
|
3276
3319
|
this.meetingInfo?.video?.supportHDV) ||
|
|
3277
3320
|
!this.arePolicyRestrictionsSupported(),
|
|
3321
|
+
enforceVirtualBackground:
|
|
3322
|
+
ControlsOptionsUtil.hasPolicies({
|
|
3323
|
+
requiredPolicies: [SELF_POLICY.ENFORCE_VIRTUAL_BACKGROUND],
|
|
3324
|
+
policies: this.selfUserPolicies,
|
|
3325
|
+
}) && this.arePolicyRestrictionsSupported(),
|
|
3278
3326
|
supportHQV:
|
|
3279
3327
|
(ControlsOptionsUtil.hasPolicies({
|
|
3280
3328
|
requiredPolicies: [SELF_POLICY.SUPPORT_HQV],
|
|
@@ -3428,6 +3476,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3428
3476
|
requiredPolicies: [SELF_POLICY.SUPPORT_FILE_TRANSFER],
|
|
3429
3477
|
policies: this.selfUserPolicies,
|
|
3430
3478
|
}),
|
|
3479
|
+
canChat: ControlsOptionsUtil.hasPolicies({
|
|
3480
|
+
requiredPolicies: [SELF_POLICY.SUPPORT_CHAT],
|
|
3481
|
+
policies: this.selfUserPolicies,
|
|
3482
|
+
}),
|
|
3431
3483
|
canShareApplication:
|
|
3432
3484
|
(ControlsOptionsUtil.hasHints({
|
|
3433
3485
|
requiredHints: [DISPLAY_HINTS.SHARE_APPLICATION],
|
|
@@ -3487,6 +3539,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3487
3539
|
*/
|
|
3488
3540
|
setSelfUserPolicies() {
|
|
3489
3541
|
this.selfUserPolicies = this.permissionTokenPayload?.permission?.userPolicies;
|
|
3542
|
+
this.enforceVBGImagesURL = this.permissionTokenPayload?.permission?.enforceVBGImagesURL;
|
|
3490
3543
|
}
|
|
3491
3544
|
|
|
3492
3545
|
/**
|
|
@@ -3497,6 +3550,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3497
3550
|
*/
|
|
3498
3551
|
public setPermissionTokenPayload(permissionToken: string) {
|
|
3499
3552
|
this.permissionTokenPayload = decode(permissionToken);
|
|
3553
|
+
this.permissionTokenReceivedLocalTime = new Date().getTime();
|
|
3500
3554
|
}
|
|
3501
3555
|
|
|
3502
3556
|
/**
|
|
@@ -3590,8 +3644,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3590
3644
|
* @memberof Meeting
|
|
3591
3645
|
*/
|
|
3592
3646
|
closeRemoteStreams() {
|
|
3593
|
-
const {remoteAudioStream, remoteVideoStream, remoteShareStream
|
|
3594
|
-
this.mediaProperties;
|
|
3647
|
+
const {remoteAudioStream, remoteVideoStream, remoteShareStream} = this.mediaProperties;
|
|
3595
3648
|
|
|
3596
3649
|
/**
|
|
3597
3650
|
* Triggers an event to the developer
|
|
@@ -3632,7 +3685,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3632
3685
|
stopStream(remoteAudioStream, EVENT_TYPES.REMOTE_AUDIO),
|
|
3633
3686
|
stopStream(remoteVideoStream, EVENT_TYPES.REMOTE_VIDEO),
|
|
3634
3687
|
stopStream(remoteShareStream, EVENT_TYPES.REMOTE_SHARE),
|
|
3635
|
-
stopStream(shareAudioStream, EVENT_TYPES.REMOTE_SHARE_AUDIO),
|
|
3636
3688
|
]);
|
|
3637
3689
|
}
|
|
3638
3690
|
|
|
@@ -3703,11 +3755,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3703
3755
|
private async setLocalShareVideoStream(localDisplayStream?: LocalDisplayStream) {
|
|
3704
3756
|
const oldStream = this.mediaProperties.shareVideoStream;
|
|
3705
3757
|
|
|
3758
|
+
oldStream?.off(StreamEventNames.MuteStateChange, this.handleShareVideoStreamMuteStateChange);
|
|
3706
3759
|
oldStream?.off(StreamEventNames.Ended, this.handleShareVideoStreamEnded);
|
|
3707
3760
|
oldStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
3708
3761
|
|
|
3709
3762
|
this.mediaProperties.setLocalShareVideoStream(localDisplayStream);
|
|
3710
3763
|
|
|
3764
|
+
localDisplayStream?.on(
|
|
3765
|
+
StreamEventNames.MuteStateChange,
|
|
3766
|
+
this.handleShareVideoStreamMuteStateChange
|
|
3767
|
+
);
|
|
3711
3768
|
localDisplayStream?.on(StreamEventNames.Ended, this.handleShareVideoStreamEnded);
|
|
3712
3769
|
localDisplayStream?.on(
|
|
3713
3770
|
LocalStreamEventNames.OutputTrackChange,
|
|
@@ -3763,7 +3820,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3763
3820
|
functionName: string;
|
|
3764
3821
|
isPublished: boolean;
|
|
3765
3822
|
mediaType: MediaType;
|
|
3766
|
-
stream:
|
|
3823
|
+
stream: LocalStream;
|
|
3767
3824
|
}) {
|
|
3768
3825
|
const {functionName, isPublished, mediaType, stream} = options;
|
|
3769
3826
|
Trigger.trigger(
|
|
@@ -3797,12 +3854,16 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3797
3854
|
videoStream?.off(StreamEventNames.MuteStateChange, this.localVideoStreamMuteStateHandler);
|
|
3798
3855
|
videoStream?.off(LocalStreamEventNames.OutputTrackChange, this.localOutputTrackChangeHandler);
|
|
3799
3856
|
|
|
3800
|
-
shareAudioStream?.off(StreamEventNames.
|
|
3857
|
+
shareAudioStream?.off(StreamEventNames.Ended, this.handleShareAudioStreamEnded);
|
|
3801
3858
|
shareAudioStream?.off(
|
|
3802
3859
|
LocalStreamEventNames.OutputTrackChange,
|
|
3803
3860
|
this.localOutputTrackChangeHandler
|
|
3804
3861
|
);
|
|
3805
|
-
shareVideoStream?.off(
|
|
3862
|
+
shareVideoStream?.off(
|
|
3863
|
+
StreamEventNames.MuteStateChange,
|
|
3864
|
+
this.handleShareVideoStreamMuteStateChange
|
|
3865
|
+
);
|
|
3866
|
+
shareVideoStream?.off(StreamEventNames.Ended, this.handleShareVideoStreamEnded);
|
|
3806
3867
|
shareVideoStream?.off(
|
|
3807
3868
|
LocalStreamEventNames.OutputTrackChange,
|
|
3808
3869
|
this.localOutputTrackChangeHandler
|
|
@@ -3916,6 +3977,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3916
3977
|
this.receiveSlotManager.reset();
|
|
3917
3978
|
this.mediaProperties.webrtcMediaConnection.close();
|
|
3918
3979
|
this.sendSlotManager.reset();
|
|
3980
|
+
this.setNetworkStatus(undefined);
|
|
3919
3981
|
}
|
|
3920
3982
|
|
|
3921
3983
|
this.audio = null;
|
|
@@ -3943,14 +4005,25 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3943
4005
|
}
|
|
3944
4006
|
|
|
3945
4007
|
/**
|
|
3946
|
-
* Convenience method to set the correlation id for the
|
|
3947
|
-
* @param {String} id correlation id to set on the
|
|
4008
|
+
* Convenience method to set the correlation id for the callStateForMetrics
|
|
4009
|
+
* @param {String} id correlation id to set on the callStateForMetrics
|
|
3948
4010
|
* @returns {undefined}
|
|
3949
4011
|
* @public
|
|
3950
4012
|
* @memberof Meeting
|
|
3951
4013
|
*/
|
|
3952
4014
|
public setCorrelationId(id: string) {
|
|
3953
|
-
this.correlationId = id;
|
|
4015
|
+
this.callStateForMetrics.correlationId = id;
|
|
4016
|
+
}
|
|
4017
|
+
|
|
4018
|
+
/**
|
|
4019
|
+
* Update the callStateForMetrics
|
|
4020
|
+
* @param {CallStateForMetrics} callStateForMetrics updated values for callStateForMetrics
|
|
4021
|
+
* @returns {undefined}
|
|
4022
|
+
* @public
|
|
4023
|
+
* @memberof Meeting
|
|
4024
|
+
*/
|
|
4025
|
+
public updateCallStateForMetrics(callStateForMetrics: CallStateForMetrics) {
|
|
4026
|
+
this.callStateForMetrics = {...this.callStateForMetrics, ...callStateForMetrics};
|
|
3954
4027
|
}
|
|
3955
4028
|
|
|
3956
4029
|
/**
|
|
@@ -4268,6 +4341,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4268
4341
|
|
|
4269
4342
|
return this.reconnectionManager
|
|
4270
4343
|
.reconnect(options)
|
|
4344
|
+
.then(() => this.waitForRemoteSDPAnswer())
|
|
4345
|
+
.then(() => this.waitForMediaConnectionConnected())
|
|
4271
4346
|
.then(() => {
|
|
4272
4347
|
Trigger.trigger(
|
|
4273
4348
|
this,
|
|
@@ -4278,6 +4353,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4278
4353
|
EVENT_TRIGGERS.MEETING_RECONNECTION_SUCCESS
|
|
4279
4354
|
);
|
|
4280
4355
|
LoggerProxy.logger.log('Meeting:index#reconnect --> Meeting reconnect success');
|
|
4356
|
+
|
|
4357
|
+
// @ts-ignore
|
|
4358
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
4359
|
+
name: 'client.media.recovered',
|
|
4360
|
+
payload: {
|
|
4361
|
+
recoveredBy: 'new',
|
|
4362
|
+
},
|
|
4363
|
+
options: {
|
|
4364
|
+
meetingId: this.id,
|
|
4365
|
+
},
|
|
4366
|
+
});
|
|
4367
|
+
this.reconnectionManager.setStatus(RECONNECTION.STATE.COMPLETE);
|
|
4281
4368
|
})
|
|
4282
4369
|
.catch((error) => {
|
|
4283
4370
|
Trigger.trigger(
|
|
@@ -4587,7 +4674,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4587
4674
|
// @ts-ignore
|
|
4588
4675
|
this.webex.internal.newMetrics.submitClientEvent({
|
|
4589
4676
|
name: 'client.call.initiated',
|
|
4590
|
-
payload: {
|
|
4677
|
+
payload: {
|
|
4678
|
+
trigger: this.callStateForMetrics.joinTrigger || 'user-interaction',
|
|
4679
|
+
isRoapCallEnabled: true,
|
|
4680
|
+
pstnAudioType: options?.pstnAudioType,
|
|
4681
|
+
},
|
|
4591
4682
|
options: {meetingId: this.id},
|
|
4592
4683
|
});
|
|
4593
4684
|
|
|
@@ -4753,7 +4844,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4753
4844
|
.then((join) => {
|
|
4754
4845
|
if (isBrowser) {
|
|
4755
4846
|
// @ts-ignore - config coming from registerPlugin
|
|
4756
|
-
if (this.config.receiveTranscription ||
|
|
4847
|
+
if (this.config.receiveTranscription || options.receiveTranscription) {
|
|
4757
4848
|
if (this.isTranscriptionSupported()) {
|
|
4758
4849
|
LoggerProxy.logger.info(
|
|
4759
4850
|
'Meeting:index#join --> Attempting to enabled to receive transcription!'
|
|
@@ -5398,40 +5489,25 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5398
5489
|
|
|
5399
5490
|
this.mediaProperties.webrtcMediaConnection.on(Event.CONNECTION_STATE_CHANGED, (event) => {
|
|
5400
5491
|
const connectionFailed = () => {
|
|
5401
|
-
// we know the media connection failed and browser will not attempt to recover it any more
|
|
5402
|
-
// so reset the timer as it's not needed anymore, we want to reconnect immediately
|
|
5403
|
-
this.reconnectionManager.resetReconnectionTimer();
|
|
5404
|
-
|
|
5405
|
-
this.reconnect({networkDisconnect: true});
|
|
5406
|
-
// @ts-ignore
|
|
5407
|
-
this.webex.internal.newMetrics.submitClientEvent({
|
|
5408
|
-
name: 'client.ice.end',
|
|
5409
|
-
payload: {
|
|
5410
|
-
canProceed: false,
|
|
5411
|
-
icePhase: 'IN_MEETING',
|
|
5412
|
-
errors: [
|
|
5413
|
-
// @ts-ignore
|
|
5414
|
-
this.webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode(
|
|
5415
|
-
{
|
|
5416
|
-
clientErrorCode: CALL_DIAGNOSTIC_CONFIG.ICE_FAILURE_CLIENT_CODE,
|
|
5417
|
-
}
|
|
5418
|
-
),
|
|
5419
|
-
],
|
|
5420
|
-
},
|
|
5421
|
-
options: {
|
|
5422
|
-
meetingId: this.id,
|
|
5423
|
-
},
|
|
5424
|
-
});
|
|
5425
|
-
|
|
5426
|
-
this.uploadLogs({
|
|
5427
|
-
file: 'peer-connection-manager/index',
|
|
5428
|
-
function: 'connectionFailed',
|
|
5429
|
-
});
|
|
5430
|
-
|
|
5431
5492
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.CONNECTION_FAILURE, {
|
|
5432
5493
|
correlation_id: this.correlationId,
|
|
5433
5494
|
locus_id: this.locusId,
|
|
5495
|
+
networkStatus: this.networkStatus,
|
|
5496
|
+
hasMediaConnectionConnectedAtLeastOnce: this.hasMediaConnectionConnectedAtLeastOnce,
|
|
5434
5497
|
});
|
|
5498
|
+
|
|
5499
|
+
if (this.hasMediaConnectionConnectedAtLeastOnce) {
|
|
5500
|
+
// we know the media connection failed and browser will not attempt to recover it any more
|
|
5501
|
+
// so reset the timer as it's not needed anymore, we want to reconnect immediately
|
|
5502
|
+
this.reconnectionManager.resetReconnectionTimer();
|
|
5503
|
+
|
|
5504
|
+
this.reconnect({networkDisconnect: true});
|
|
5505
|
+
|
|
5506
|
+
this.uploadLogs({
|
|
5507
|
+
file: 'peer-connection-manager/index',
|
|
5508
|
+
function: 'connectionFailed',
|
|
5509
|
+
});
|
|
5510
|
+
}
|
|
5435
5511
|
};
|
|
5436
5512
|
|
|
5437
5513
|
LoggerProxy.logger.info(
|
|
@@ -5443,22 +5519,32 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5443
5519
|
|
|
5444
5520
|
switch (event.state) {
|
|
5445
5521
|
case ConnectionState.Connecting:
|
|
5446
|
-
|
|
5447
|
-
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
|
|
5451
|
-
|
|
5452
|
-
|
|
5522
|
+
if (!this.hasMediaConnectionConnectedAtLeastOnce) {
|
|
5523
|
+
// Only send CA event for join flow if we haven't successfully connected media yet
|
|
5524
|
+
// @ts-ignore
|
|
5525
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
5526
|
+
name: 'client.ice.start',
|
|
5527
|
+
options: {
|
|
5528
|
+
meetingId: this.id,
|
|
5529
|
+
},
|
|
5530
|
+
});
|
|
5531
|
+
}
|
|
5453
5532
|
break;
|
|
5454
5533
|
case ConnectionState.Connected:
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5534
|
+
if (!this.hasMediaConnectionConnectedAtLeastOnce) {
|
|
5535
|
+
// Only send CA event for join flow if we haven't successfully connected media yet
|
|
5536
|
+
// @ts-ignore
|
|
5537
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
5538
|
+
name: 'client.ice.end',
|
|
5539
|
+
payload: {
|
|
5540
|
+
canProceed: true,
|
|
5541
|
+
icePhase: 'JOIN_MEETING_FINAL',
|
|
5542
|
+
},
|
|
5543
|
+
options: {
|
|
5544
|
+
meetingId: this.id,
|
|
5545
|
+
},
|
|
5546
|
+
});
|
|
5547
|
+
}
|
|
5462
5548
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.CONNECTION_SUCCESS, {
|
|
5463
5549
|
correlation_id: this.correlationId,
|
|
5464
5550
|
locus_id: this.locusId,
|
|
@@ -5467,6 +5553,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5467
5553
|
this.setNetworkStatus(NETWORK_STATUS.CONNECTED);
|
|
5468
5554
|
this.reconnectionManager.iceReconnected();
|
|
5469
5555
|
this.statsAnalyzer.startAnalyzer(this.mediaProperties.webrtcMediaConnection);
|
|
5556
|
+
this.hasMediaConnectionConnectedAtLeastOnce = true;
|
|
5470
5557
|
break;
|
|
5471
5558
|
case ConnectionState.Disconnected:
|
|
5472
5559
|
this.setNetworkStatus(NETWORK_STATUS.DISCONNECTED);
|
|
@@ -5771,36 +5858,42 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5771
5858
|
try {
|
|
5772
5859
|
await this.mediaProperties.waitForMediaConnectionConnected();
|
|
5773
5860
|
} catch (error) {
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
|
|
5779
|
-
|
|
5780
|
-
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5797
|
-
|
|
5798
|
-
|
|
5799
|
-
|
|
5800
|
-
|
|
5801
|
-
|
|
5802
|
-
|
|
5803
|
-
|
|
5861
|
+
if (!this.hasMediaConnectionConnectedAtLeastOnce) {
|
|
5862
|
+
// Only send CA event for join flow if we haven't successfully connected media yet
|
|
5863
|
+
// @ts-ignore
|
|
5864
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
5865
|
+
name: 'client.ice.end',
|
|
5866
|
+
payload: {
|
|
5867
|
+
canProceed: !this.turnServerUsed, // If we haven't done turn tls retry yet we will proceed with join attempt
|
|
5868
|
+
icePhase: this.turnServerUsed ? 'JOIN_MEETING_FINAL' : 'JOIN_MEETING_RETRY',
|
|
5869
|
+
errors: [
|
|
5870
|
+
// @ts-ignore
|
|
5871
|
+
this.webex.internal.newMetrics.callDiagnosticMetrics.getErrorPayloadForClientErrorCode(
|
|
5872
|
+
{
|
|
5873
|
+
clientErrorCode: CallDiagnosticUtils.generateClientErrorCodeForIceFailure({
|
|
5874
|
+
signalingState:
|
|
5875
|
+
this.mediaProperties.webrtcMediaConnection?.multistreamConnection?.pc?.pc
|
|
5876
|
+
?.signalingState ||
|
|
5877
|
+
this.mediaProperties.webrtcMediaConnection?.mediaConnection?.pc
|
|
5878
|
+
?.signalingState ||
|
|
5879
|
+
'unknown',
|
|
5880
|
+
iceConnectionState:
|
|
5881
|
+
this.mediaProperties.webrtcMediaConnection?.multistreamConnection?.pc?.pc
|
|
5882
|
+
?.iceConnectionState ||
|
|
5883
|
+
this.mediaProperties.webrtcMediaConnection?.mediaConnection?.pc
|
|
5884
|
+
?.iceConnectionState ||
|
|
5885
|
+
'unknown',
|
|
5886
|
+
turnServerUsed: this.turnServerUsed,
|
|
5887
|
+
}),
|
|
5888
|
+
}
|
|
5889
|
+
),
|
|
5890
|
+
],
|
|
5891
|
+
},
|
|
5892
|
+
options: {
|
|
5893
|
+
meetingId: this.id,
|
|
5894
|
+
},
|
|
5895
|
+
});
|
|
5896
|
+
}
|
|
5804
5897
|
throw new Error(
|
|
5805
5898
|
`Timed out waiting for media connection to be connected, correlationId=${this.correlationId}`
|
|
5806
5899
|
);
|
|
@@ -5924,9 +6017,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5924
6017
|
bundlePolicy?: BundlePolicy
|
|
5925
6018
|
): Promise<void> {
|
|
5926
6019
|
this.retriedWithTurnServer = true;
|
|
6020
|
+
const LOG_HEADER = 'Meeting:index#addMedia():retryWithForcedTurnDiscovery -->';
|
|
5927
6021
|
|
|
5928
6022
|
await this.cleanUpBeforeRetryWithTurnServer();
|
|
5929
6023
|
|
|
6024
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_RETRY, {
|
|
6025
|
+
correlation_id: this.correlationId,
|
|
6026
|
+
state: this.state,
|
|
6027
|
+
meetingState: this.meetingState,
|
|
6028
|
+
reason: 'forcingTurnTls',
|
|
6029
|
+
});
|
|
6030
|
+
|
|
6031
|
+
if (this.state === MEETING_STATE.STATES.LEFT) {
|
|
6032
|
+
LoggerProxy.logger.info(
|
|
6033
|
+
`${LOG_HEADER} meeting state was LEFT after first attempt to establish media connection. Attempting to rejoin. `
|
|
6034
|
+
);
|
|
6035
|
+
await this.join({rejoin: true});
|
|
6036
|
+
}
|
|
6037
|
+
|
|
5930
6038
|
await this.retryEstablishMediaConnectionWithForcedTurnDiscovery(
|
|
5931
6039
|
remoteMediaManagerConfig,
|
|
5932
6040
|
bundlePolicy
|
|
@@ -6130,10 +6238,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6130
6238
|
*/
|
|
6131
6239
|
async addMedia(options: AddMediaOptions = {}): Promise<void> {
|
|
6132
6240
|
this.retriedWithTurnServer = false;
|
|
6241
|
+
this.hasMediaConnectionConnectedAtLeastOnce = false;
|
|
6133
6242
|
const LOG_HEADER = 'Meeting:index#addMedia -->';
|
|
6134
6243
|
LoggerProxy.logger.info(`${LOG_HEADER} called with: ${JSON.stringify(options)}`);
|
|
6135
6244
|
|
|
6136
|
-
if (this.meetingState !== FULL_STATE.ACTIVE) {
|
|
6245
|
+
if (options.allowMediaInLobby !== true && this.meetingState !== FULL_STATE.ACTIVE) {
|
|
6137
6246
|
throw new MeetingNotActiveError();
|
|
6138
6247
|
}
|
|
6139
6248
|
|
|
@@ -6807,17 +6916,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6807
6916
|
.catch((error) => {
|
|
6808
6917
|
LoggerProxy.logger.error('Meeting:index#stopWhiteboardShare --> Error ', error);
|
|
6809
6918
|
|
|
6810
|
-
Metrics.sendBehavioralMetric(
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
stack: error.stack,
|
|
6818
|
-
board: {channelUrl},
|
|
6819
|
-
}
|
|
6820
|
-
);
|
|
6919
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_STOP_WHITEBOARD_SHARE_FAILURE, {
|
|
6920
|
+
correlation_id: this.correlationId,
|
|
6921
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
6922
|
+
reason: error.message,
|
|
6923
|
+
stack: error.stack,
|
|
6924
|
+
board: {channelUrl},
|
|
6925
|
+
});
|
|
6821
6926
|
|
|
6822
6927
|
return Promise.reject(error);
|
|
6823
6928
|
})
|
|
@@ -6872,6 +6977,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6872
6977
|
.then(() => {
|
|
6873
6978
|
this.screenShareFloorState = ScreenShareFloorStatus.GRANTED;
|
|
6874
6979
|
|
|
6980
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_SUCCESS, {
|
|
6981
|
+
correlation_id: this.correlationId,
|
|
6982
|
+
locus_id: this.locusUrl.split('/').pop(),
|
|
6983
|
+
});
|
|
6984
|
+
|
|
6875
6985
|
return Promise.resolve();
|
|
6876
6986
|
})
|
|
6877
6987
|
.catch((error) => {
|
|
@@ -7293,6 +7403,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7293
7403
|
}
|
|
7294
7404
|
};
|
|
7295
7405
|
|
|
7406
|
+
/**
|
|
7407
|
+
* Functionality for when a share video is muted or unmuted.
|
|
7408
|
+
* @private
|
|
7409
|
+
* @memberof Meeting
|
|
7410
|
+
* @param {boolean} muted
|
|
7411
|
+
* @returns {undefined}
|
|
7412
|
+
*/
|
|
7413
|
+
private handleShareVideoStreamMuteStateChange = (muted: boolean) => {
|
|
7414
|
+
LoggerProxy.logger.log(
|
|
7415
|
+
`Meeting:index#handleShareVideoStreamMuteStateChange --> Share video stream mute state changed to muted ${muted}`
|
|
7416
|
+
);
|
|
7417
|
+
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE, {
|
|
7418
|
+
correlationId: this.correlationId,
|
|
7419
|
+
muted,
|
|
7420
|
+
});
|
|
7421
|
+
};
|
|
7422
|
+
|
|
7296
7423
|
/**
|
|
7297
7424
|
* Functionality for when a share video is ended.
|
|
7298
7425
|
* @private
|
|
@@ -7659,10 +7786,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7659
7786
|
.update({
|
|
7660
7787
|
// TODO: RoapMediaConnection is not ready to use stream classes yet, so we pass the raw MediaStreamTrack for now
|
|
7661
7788
|
localTracks: {
|
|
7662
|
-
audio: this.mediaProperties.audioStream?.
|
|
7663
|
-
video: this.mediaProperties.videoStream?.
|
|
7664
|
-
screenShareVideo:
|
|
7665
|
-
|
|
7789
|
+
audio: this.mediaProperties.audioStream?.outputStream?.getTracks()[0] || null,
|
|
7790
|
+
video: this.mediaProperties.videoStream?.outputStream?.getTracks()[0] || null,
|
|
7791
|
+
screenShareVideo:
|
|
7792
|
+
this.mediaProperties.shareVideoStream?.outputStream?.getTracks()[0] || null,
|
|
7793
|
+
screenShareAudio:
|
|
7794
|
+
this.mediaProperties.shareAudioStream?.outputStream?.getTracks()[0] || null,
|
|
7666
7795
|
},
|
|
7667
7796
|
direction: {
|
|
7668
7797
|
audio: Media.getDirection(
|
|
@@ -7851,25 +7980,34 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7851
7980
|
}
|
|
7852
7981
|
|
|
7853
7982
|
/**
|
|
7854
|
-
* Gets
|
|
7983
|
+
* Gets permission token expiry information including timeLeft, expiryTime, currentTime
|
|
7855
7984
|
* (from the time the function has been fired)
|
|
7856
7985
|
*
|
|
7857
|
-
* @returns {
|
|
7986
|
+
* @returns {object} permissionTokenExpiryInfo
|
|
7987
|
+
* @returns {number} permissionTokenExpiryInfo.timeLeft The time left for token to expire
|
|
7988
|
+
* @returns {number} permissionTokenExpiryInfo.expiryTime The expiry time of permission token from the server
|
|
7989
|
+
* @returns {number} permissionTokenExpiryInfo.currentTime The current time of the local machine
|
|
7858
7990
|
*/
|
|
7859
|
-
public
|
|
7991
|
+
public getPermissionTokenExpiryInfo() {
|
|
7860
7992
|
if (!this.permissionTokenPayload) {
|
|
7861
7993
|
return undefined;
|
|
7862
7994
|
}
|
|
7863
7995
|
|
|
7864
|
-
const
|
|
7996
|
+
const permissionTokenExpiryFromServer = Number(this.permissionTokenPayload.exp);
|
|
7997
|
+
const permissionTokenIssuedTimeFromServer = Number(this.permissionTokenPayload.iat);
|
|
7998
|
+
|
|
7999
|
+
const shiftInTime = this.permissionTokenReceivedLocalTime - permissionTokenIssuedTimeFromServer;
|
|
7865
8000
|
|
|
7866
8001
|
// using new Date instead of Date.now() to allow for accurate unit testing
|
|
7867
8002
|
// https://github.com/sinonjs/fake-timers/issues/321
|
|
7868
|
-
const
|
|
8003
|
+
const currentTime = new Date().getTime();
|
|
8004
|
+
|
|
8005
|
+
// adjusted time is calculated in case your machine time is wrong
|
|
8006
|
+
const adjustedCurrentTime = currentTime - shiftInTime;
|
|
8007
|
+
|
|
8008
|
+
const timeLeft = (permissionTokenExpiryFromServer - adjustedCurrentTime) / 1000;
|
|
7869
8009
|
|
|
7870
|
-
|
|
7871
|
-
// (permissionTokenExp is a epoch timestamp, not a time to live duration)
|
|
7872
|
-
return (permissionTokenExpValue - now) / 1000;
|
|
8010
|
+
return {timeLeft, expiryTime: permissionTokenExpiryFromServer, currentTime};
|
|
7873
8011
|
}
|
|
7874
8012
|
|
|
7875
8013
|
/**
|
|
@@ -7881,9 +8019,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7881
8019
|
* @returns {Promise<void>}
|
|
7882
8020
|
*/
|
|
7883
8021
|
public checkAndRefreshPermissionToken(threshold: number, reason: string): Promise<void> {
|
|
7884
|
-
const
|
|
8022
|
+
const timeLeft = this.getPermissionTokenExpiryInfo()?.timeLeft;
|
|
7885
8023
|
|
|
7886
|
-
if (
|
|
8024
|
+
if (timeLeft !== undefined && timeLeft <= threshold) {
|
|
7887
8025
|
return this.refreshPermissionToken(reason);
|
|
7888
8026
|
}
|
|
7889
8027
|
|