@webex/plugin-meetings 3.8.0-next.4 → 3.8.0-next.40
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/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/constants.js +14 -1
- package/dist/constants.js.map +1 -1
- package/dist/controls-options-manager/enums.js +2 -0
- package/dist/controls-options-manager/enums.js.map +1 -1
- package/dist/controls-options-manager/types.js.map +1 -1
- package/dist/controls-options-manager/util.js +52 -0
- package/dist/controls-options-manager/util.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/controlsUtils.js +28 -10
- package/dist/locus-info/controlsUtils.js.map +1 -1
- package/dist/locus-info/index.js +20 -1
- package/dist/locus-info/index.js.map +1 -1
- package/dist/media/index.js +3 -15
- package/dist/media/index.js.map +1 -1
- package/dist/meeting/in-meeting-actions.js +11 -1
- package/dist/meeting/in-meeting-actions.js.map +1 -1
- package/dist/meeting/index.js +443 -256
- package/dist/meeting/index.js.map +1 -1
- package/dist/meeting/locusMediaRequest.js +21 -22
- package/dist/meeting/locusMediaRequest.js.map +1 -1
- package/dist/meeting/muteState.js +0 -2
- package/dist/meeting/muteState.js.map +1 -1
- package/dist/meeting/request.js +30 -0
- package/dist/meeting/request.js.map +1 -1
- package/dist/meeting/request.type.js.map +1 -1
- package/dist/meeting/util.js +10 -2
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +359 -60
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +60 -1
- package/dist/meetings/index.js.map +1 -1
- package/dist/member/index.js +10 -0
- package/dist/member/index.js.map +1 -1
- package/dist/member/util.js +3 -0
- package/dist/member/util.js.map +1 -1
- package/dist/metrics/constants.js +9 -0
- package/dist/metrics/constants.js.map +1 -1
- package/dist/reachability/clusterReachability.js +52 -8
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/reachability/index.js +70 -45
- package/dist/reachability/index.js.map +1 -1
- package/dist/reachability/reachability.types.js +14 -0
- package/dist/reachability/reachability.types.js.map +1 -1
- package/dist/reachability/request.js +19 -3
- package/dist/reachability/request.js.map +1 -1
- package/dist/reconnection-manager/index.js +2 -2
- package/dist/reconnection-manager/index.js.map +1 -1
- package/dist/recording-controller/util.js +5 -5
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/roap/index.js.map +1 -1
- package/dist/roap/turnDiscovery.js +45 -27
- package/dist/roap/turnDiscovery.js.map +1 -1
- package/dist/roap/types.js +17 -0
- package/dist/roap/types.js.map +1 -0
- package/dist/types/config.d.ts +1 -0
- package/dist/types/constants.d.ts +10 -0
- package/dist/types/controls-options-manager/enums.d.ts +3 -1
- package/dist/types/controls-options-manager/types.d.ts +7 -1
- package/dist/types/locus-info/index.d.ts +1 -0
- package/dist/types/meeting/in-meeting-actions.d.ts +10 -0
- package/dist/types/meeting/index.d.ts +47 -1
- package/dist/types/meeting/muteState.d.ts +0 -1
- package/dist/types/meeting/request.d.ts +12 -1
- package/dist/types/meeting/request.type.d.ts +6 -0
- package/dist/types/meeting/util.d.ts +2 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +80 -0
- package/dist/types/meetings/index.d.ts +29 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/metrics/constants.d.ts +9 -0
- package/dist/types/reachability/clusterReachability.d.ts +13 -1
- package/dist/types/reachability/index.d.ts +2 -1
- package/dist/types/reachability/reachability.types.d.ts +5 -0
- package/dist/types/roap/index.d.ts +3 -2
- package/dist/types/roap/turnDiscovery.d.ts +5 -17
- package/dist/types/roap/types.d.ts +16 -0
- package/dist/webinar/index.js +1 -1
- package/package.json +22 -22
- package/src/config.ts +1 -0
- package/src/constants.ts +17 -0
- package/src/controls-options-manager/enums.ts +2 -0
- package/src/controls-options-manager/types.ts +11 -1
- package/src/controls-options-manager/util.ts +62 -0
- package/src/locus-info/controlsUtils.ts +44 -14
- package/src/locus-info/index.ts +23 -1
- package/src/media/index.ts +5 -21
- package/src/meeting/in-meeting-actions.ts +20 -0
- package/src/meeting/index.ts +263 -69
- package/src/meeting/locusMediaRequest.ts +27 -22
- package/src/meeting/muteState.ts +0 -2
- package/src/meeting/request.ts +36 -1
- package/src/meeting/request.type.ts +7 -0
- package/src/meeting/util.ts +9 -2
- package/src/meeting-info/meeting-info-v2.ts +247 -6
- package/src/meetings/index.ts +72 -1
- package/src/member/index.ts +11 -0
- package/src/member/util.ts +3 -0
- package/src/metrics/constants.ts +9 -0
- package/src/reachability/clusterReachability.ts +47 -1
- package/src/reachability/index.ts +15 -0
- package/src/reachability/reachability.types.ts +6 -0
- package/src/reachability/request.ts +7 -0
- package/src/reconnection-manager/index.ts +2 -2
- package/src/recording-controller/util.ts +17 -13
- package/src/roap/index.ts +3 -7
- package/src/roap/turnDiscovery.ts +34 -39
- package/src/roap/types.ts +23 -0
- package/test/unit/spec/controls-options-manager/util.js +120 -0
- package/test/unit/spec/locus-info/controlsUtils.js +103 -9
- package/test/unit/spec/locus-info/index.js +28 -0
- package/test/unit/spec/media/index.ts +6 -16
- package/test/unit/spec/meeting/in-meeting-actions.ts +13 -4
- package/test/unit/spec/meeting/index.js +490 -130
- package/test/unit/spec/meeting/locusMediaRequest.ts +95 -87
- package/test/unit/spec/meeting/muteState.js +0 -2
- package/test/unit/spec/meeting/request.js +32 -1
- package/test/unit/spec/meeting/utils.js +115 -18
- package/test/unit/spec/meeting-info/meetinginfov2.js +443 -114
- package/test/unit/spec/meetings/index.js +78 -1
- package/test/unit/spec/member/index.js +7 -0
- package/test/unit/spec/member/util.js +24 -0
- package/test/unit/spec/reachability/clusterReachability.ts +47 -1
- package/test/unit/spec/reachability/index.ts +12 -0
- package/test/unit/spec/reachability/request.js +47 -2
- package/test/unit/spec/reconnection-manager/index.js +4 -4
- package/test/unit/spec/roap/turnDiscovery.ts +110 -28
package/src/locus-info/index.ts
CHANGED
@@ -17,7 +17,9 @@ import {
|
|
17
17
|
MEETING_REMOVED_REASON,
|
18
18
|
CALL_REMOVED_REASON,
|
19
19
|
RECORDING_STATE,
|
20
|
+
BREAKOUTS,
|
20
21
|
} from '../constants';
|
22
|
+
|
21
23
|
import InfoUtils from './infoUtils';
|
22
24
|
import FullState from './fullState';
|
23
25
|
import SelfUtils from './selfUtils';
|
@@ -67,6 +69,7 @@ export default class LocusInfo extends EventsScope {
|
|
67
69
|
services: any;
|
68
70
|
resources: any;
|
69
71
|
mainSessionLocusCache: any;
|
72
|
+
self: any;
|
70
73
|
/**
|
71
74
|
* Constructor
|
72
75
|
* @param {function} updateMeeting callback to update the meeting object from an object
|
@@ -814,6 +817,8 @@ export default class LocusInfo extends EventsScope {
|
|
814
817
|
hasMeetingFullChanged,
|
815
818
|
hasPracticeSessionEnabledChanged,
|
816
819
|
hasStageViewChanged,
|
820
|
+
hasAnnotationControlChanged,
|
821
|
+
hasRemoteDesktopControlChanged,
|
817
822
|
},
|
818
823
|
current,
|
819
824
|
} = ControlsUtils.getControls(this.controls, controls);
|
@@ -1049,6 +1054,22 @@ export default class LocusInfo extends EventsScope {
|
|
1049
1054
|
);
|
1050
1055
|
}
|
1051
1056
|
|
1057
|
+
if (hasAnnotationControlChanged) {
|
1058
|
+
this.emitScoped(
|
1059
|
+
{file: 'locus-info', function: 'updateControls'},
|
1060
|
+
LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED,
|
1061
|
+
{state: current.annotationControl}
|
1062
|
+
);
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
if (hasRemoteDesktopControlChanged) {
|
1066
|
+
this.emitScoped(
|
1067
|
+
{file: 'locus-info', function: 'updateControls'},
|
1068
|
+
LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED,
|
1069
|
+
{state: current.rdcControl}
|
1070
|
+
);
|
1071
|
+
}
|
1072
|
+
|
1052
1073
|
this.controls = controls;
|
1053
1074
|
}
|
1054
1075
|
}
|
@@ -1706,7 +1727,8 @@ export default class LocusInfo extends EventsScope {
|
|
1706
1727
|
* @memberof LocusInfo
|
1707
1728
|
*/
|
1708
1729
|
getTheLocusToUpdate(newLocus: any) {
|
1709
|
-
const switchStatus = ControlsUtils.getSessionSwitchStatus(this
|
1730
|
+
const switchStatus = ControlsUtils.getSessionSwitchStatus(this, newLocus);
|
1731
|
+
|
1710
1732
|
if (switchStatus.isReturnToMain && this.mainSessionLocusCache) {
|
1711
1733
|
return cloneDeep(this.mainSessionLocusCache);
|
1712
1734
|
}
|
package/src/media/index.ts
CHANGED
@@ -21,6 +21,7 @@ import {MEDIA_TRACK_CONSTRAINT} from '../constants';
|
|
21
21
|
import Config from '../config';
|
22
22
|
import StaticConfig from '../common/config';
|
23
23
|
import BrowserDetection from '../common/browser-detection';
|
24
|
+
import {TurnServerInfo} from '../roap/types';
|
24
25
|
|
25
26
|
const {isBrowser} = BrowserDetection();
|
26
27
|
|
@@ -138,11 +139,7 @@ Media.createMediaConnection = (
|
|
138
139
|
remoteQualityLevel?: 'LOW' | 'MEDIUM' | 'HIGH';
|
139
140
|
enableRtx?: boolean;
|
140
141
|
enableExtmap?: boolean;
|
141
|
-
turnServerInfo?:
|
142
|
-
url: string;
|
143
|
-
username: string;
|
144
|
-
password: string;
|
145
|
-
};
|
142
|
+
turnServerInfo?: TurnServerInfo;
|
146
143
|
bundlePolicy?: BundlePolicy;
|
147
144
|
iceCandidatesTimeout?: number;
|
148
145
|
}
|
@@ -160,24 +157,11 @@ Media.createMediaConnection = (
|
|
160
157
|
|
161
158
|
const iceServers = [];
|
162
159
|
|
163
|
-
// we might not have any TURN server if TURN discovery failed or wasn't done or
|
164
|
-
|
165
|
-
if (turnServerInfo?.url) {
|
166
|
-
if (!isBrowser('firefox')) {
|
167
|
-
let bareTurnServer = turnServerInfo.url;
|
168
|
-
bareTurnServer = bareTurnServer.replace('turns:', 'turn:');
|
169
|
-
bareTurnServer = bareTurnServer.replace('443', '5004');
|
170
|
-
|
171
|
-
iceServers.push({
|
172
|
-
urls: bareTurnServer,
|
173
|
-
username: turnServerInfo.username || '',
|
174
|
-
credential: turnServerInfo.password || '',
|
175
|
-
});
|
176
|
-
}
|
177
|
-
|
160
|
+
// we might not have any TURN server if TURN discovery failed or wasn't done or we land on a video mesh node
|
161
|
+
if (turnServerInfo?.urls.length > 0) {
|
178
162
|
// TURN-TLS server
|
179
163
|
iceServers.push({
|
180
|
-
urls: turnServerInfo.
|
164
|
+
urls: turnServerInfo.urls,
|
181
165
|
username: turnServerInfo.username || '',
|
182
166
|
credential: turnServerInfo.password || '',
|
183
167
|
});
|
@@ -99,6 +99,11 @@ interface IInMeetingActions {
|
|
99
99
|
isPracticeSessionOff?: boolean;
|
100
100
|
canStartPracticeSession?: boolean;
|
101
101
|
canStopPracticeSession?: boolean;
|
102
|
+
requiresPostMeetingDataConsentPrompt?: boolean;
|
103
|
+
canEnableAnnotation?: boolean;
|
104
|
+
canDisableAnnotation?: boolean;
|
105
|
+
canEnableRemoteDesktopControl?: boolean;
|
106
|
+
canDisableRemoteDesktopControl?: boolean;
|
102
107
|
}
|
103
108
|
|
104
109
|
/**
|
@@ -285,6 +290,16 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
285
290
|
|
286
291
|
canStopPracticeSession = null;
|
287
292
|
|
293
|
+
requiresPostMeetingDataConsentPrompt = null;
|
294
|
+
|
295
|
+
canEnableAnnotation = null;
|
296
|
+
|
297
|
+
canDisableAnnotation = null;
|
298
|
+
|
299
|
+
canEnableRemoteDesktopControl = null;
|
300
|
+
|
301
|
+
canDisableRemoteDesktopControl = null;
|
302
|
+
|
288
303
|
/**
|
289
304
|
* Returns all meeting action options
|
290
305
|
* @returns {Object}
|
@@ -379,6 +394,11 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
379
394
|
isPracticeSessionOff: this.isPracticeSessionOff,
|
380
395
|
canStartPracticeSession: this.canStartPracticeSession,
|
381
396
|
canStopPracticeSession: this.canStopPracticeSession,
|
397
|
+
requiresPostMeetingDataConsentPrompt: this.requiresPostMeetingDataConsentPrompt,
|
398
|
+
canEnableAnnotation: this.canEnableAnnotation,
|
399
|
+
canDisableAnnotation: this.canDisableAnnotation,
|
400
|
+
canEnableRemoteDesktopControl: this.canEnableRemoteDesktopControl,
|
401
|
+
canDisableRemoteDesktopControl: this.canDisableRemoteDesktopControl,
|
382
402
|
});
|
383
403
|
|
384
404
|
/**
|
package/src/meeting/index.ts
CHANGED
@@ -60,11 +60,8 @@ import {
|
|
60
60
|
import LoggerProxy from '../common/logs/logger-proxy';
|
61
61
|
import EventsUtil from '../common/events/util';
|
62
62
|
import Trigger from '../common/events/trigger-proxy';
|
63
|
-
import Roap, {
|
64
|
-
|
65
|
-
type TurnServerInfo,
|
66
|
-
type TurnDiscoverySkipReason,
|
67
|
-
} from '../roap/index';
|
63
|
+
import Roap, {type TurnDiscoveryResult, type TurnDiscoverySkipReason} from '../roap/index';
|
64
|
+
import {type TurnServerInfo} from '../roap/types';
|
68
65
|
import Media, {type BundlePolicy} from '../media';
|
69
66
|
import MediaProperties from '../media/properties';
|
70
67
|
import MeetingStateMachine from './state';
|
@@ -241,6 +238,8 @@ export type CallStateForMetrics = {
|
|
241
238
|
sessionCorrelationId?: string;
|
242
239
|
joinTrigger?: string;
|
243
240
|
loginType?: string;
|
241
|
+
userNameInput?: string;
|
242
|
+
emailInput?: string;
|
244
243
|
};
|
245
244
|
|
246
245
|
export const MEDIA_UPDATE_TYPE = {
|
@@ -648,6 +647,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
648
647
|
allowMediaInLobby: boolean;
|
649
648
|
localShareInstanceId: string;
|
650
649
|
remoteShareInstanceId: string;
|
650
|
+
shareCAEventSentStatus: {
|
651
|
+
transmitStart: boolean;
|
652
|
+
transmitStop: boolean;
|
653
|
+
receiveStart: boolean;
|
654
|
+
receiveStop: boolean;
|
655
|
+
};
|
656
|
+
|
651
657
|
turnDiscoverySkippedReason: TurnDiscoverySkipReason;
|
652
658
|
turnServerUsed: boolean;
|
653
659
|
areVoiceaEventsSetup = false;
|
@@ -1420,6 +1426,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1420
1426
|
*/
|
1421
1427
|
this.remoteShareInstanceId = null;
|
1422
1428
|
|
1429
|
+
/**
|
1430
|
+
* Status used for ensuring we do not oversend metrics
|
1431
|
+
* @instance
|
1432
|
+
* @private
|
1433
|
+
* @memberof Meeting
|
1434
|
+
*/
|
1435
|
+
this.shareCAEventSentStatus = {
|
1436
|
+
transmitStart: false,
|
1437
|
+
transmitStop: false,
|
1438
|
+
receiveStart: false,
|
1439
|
+
receiveStop: false,
|
1440
|
+
};
|
1441
|
+
|
1423
1442
|
/**
|
1424
1443
|
* The class that helps to control recording functions: start, stop, pause, resume, etc
|
1425
1444
|
* @instance
|
@@ -1627,6 +1646,38 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1627
1646
|
this.callStateForMetrics.correlationId = correlationId;
|
1628
1647
|
}
|
1629
1648
|
|
1649
|
+
/**
|
1650
|
+
* Getter - Returns callStateForMetrics.userNameInput
|
1651
|
+
* @returns {string}
|
1652
|
+
*/
|
1653
|
+
get userNameInput() {
|
1654
|
+
return this.callStateForMetrics?.userNameInput;
|
1655
|
+
}
|
1656
|
+
|
1657
|
+
/**
|
1658
|
+
* Setter - sets callStateForMetrics.userNameInput
|
1659
|
+
* @param {string} userNameInput
|
1660
|
+
*/
|
1661
|
+
set userNameInput(userNameInput: string) {
|
1662
|
+
this.callStateForMetrics.userNameInput = userNameInput;
|
1663
|
+
}
|
1664
|
+
|
1665
|
+
/**
|
1666
|
+
* Getter - Returns callStateForMetrics.emailInput
|
1667
|
+
* @returns {string}
|
1668
|
+
*/
|
1669
|
+
get emailInput() {
|
1670
|
+
return this.callStateForMetrics?.emailInput;
|
1671
|
+
}
|
1672
|
+
|
1673
|
+
/**
|
1674
|
+
* Setter - sets callStateForMetrics.emailInput
|
1675
|
+
* @param {string} emailInput
|
1676
|
+
*/
|
1677
|
+
set emailInput(emailInput: string) {
|
1678
|
+
this.callStateForMetrics.emailInput = emailInput;
|
1679
|
+
}
|
1680
|
+
|
1630
1681
|
/**
|
1631
1682
|
* Getter - Returns callStateForMetrics.sessionCorrelationId
|
1632
1683
|
* @returns {string}
|
@@ -1652,6 +1703,33 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
1652
1703
|
return this.#isoLocalClientMeetingJoinTime;
|
1653
1704
|
}
|
1654
1705
|
|
1706
|
+
/**
|
1707
|
+
* Setter - sets isoLocalClientMeetingJoinTime
|
1708
|
+
* This will be set once on meeting join, and not updated again
|
1709
|
+
* this will always produce an ISO string
|
1710
|
+
* If the iso string is invalid, it will fallback to the current system time
|
1711
|
+
* @param {string | undefined} time
|
1712
|
+
*/
|
1713
|
+
set isoLocalClientMeetingJoinTime(time: string | undefined) {
|
1714
|
+
const fallback = new Date().toISOString();
|
1715
|
+
if (!time) {
|
1716
|
+
this.#isoLocalClientMeetingJoinTime = fallback;
|
1717
|
+
} else {
|
1718
|
+
const date = new Date(time);
|
1719
|
+
|
1720
|
+
// Check if the date is valid
|
1721
|
+
if (Number.isNaN(date.getTime())) {
|
1722
|
+
LoggerProxy.logger.info(
|
1723
|
+
// @ts-ignore
|
1724
|
+
`Meeting:index#isoLocalClientMeetingJoinTime --> Invalid date provided: ${time}. Falling back to system clock.`
|
1725
|
+
);
|
1726
|
+
this.#isoLocalClientMeetingJoinTime = fallback;
|
1727
|
+
} else {
|
1728
|
+
this.#isoLocalClientMeetingJoinTime = date.toISOString();
|
1729
|
+
}
|
1730
|
+
}
|
1731
|
+
}
|
1732
|
+
|
1655
1733
|
/**
|
1656
1734
|
* Set meeting info and trigger `MEETING_INFO_AVAILABLE` event
|
1657
1735
|
* @param {any} info
|
@@ -2793,6 +2871,24 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2793
2871
|
{state}
|
2794
2872
|
);
|
2795
2873
|
});
|
2874
|
+
|
2875
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ANNOTATION_CHANGED, ({state}) => {
|
2876
|
+
Trigger.trigger(
|
2877
|
+
this,
|
2878
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
2879
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_ANNOTATION_UPDATED,
|
2880
|
+
{state}
|
2881
|
+
);
|
2882
|
+
});
|
2883
|
+
|
2884
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_REMOTE_DESKTOP_CONTROL_CHANGED, ({state}) => {
|
2885
|
+
Trigger.trigger(
|
2886
|
+
this,
|
2887
|
+
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
2888
|
+
EVENT_TRIGGERS.MEETING_CONTROLS_REMOTE_DESKTOP_CONTROL_UPDATED,
|
2889
|
+
{state}
|
2890
|
+
);
|
2891
|
+
});
|
2796
2892
|
}
|
2797
2893
|
|
2798
2894
|
/**
|
@@ -2965,6 +3061,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
2965
3061
|
case SHARE_STATUS.REMOTE_SHARE_ACTIVE: {
|
2966
3062
|
const sendStartedSharingRemote = () => {
|
2967
3063
|
this.remoteShareInstanceId = contentShare.shareInstanceId;
|
3064
|
+
this.shareCAEventSentStatus.receiveStart = false;
|
3065
|
+
this.shareCAEventSentStatus.receiveStop = false;
|
2968
3066
|
|
2969
3067
|
Trigger.trigger(
|
2970
3068
|
this,
|
@@ -3018,6 +3116,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3018
3116
|
},
|
3019
3117
|
options: {meetingId: this.id},
|
3020
3118
|
});
|
3119
|
+
|
3021
3120
|
break;
|
3022
3121
|
|
3023
3122
|
case SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE:
|
@@ -3058,6 +3157,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3058
3157
|
// if we got here, then some remote participant has stolen
|
3059
3158
|
// the presentation from another remote participant
|
3060
3159
|
this.remoteShareInstanceId = contentShare.shareInstanceId;
|
3160
|
+
this.shareCAEventSentStatus.receiveStart = false;
|
3161
|
+
this.shareCAEventSentStatus.receiveStop = false;
|
3061
3162
|
|
3062
3163
|
Trigger.trigger(
|
3063
3164
|
this,
|
@@ -3741,7 +3842,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3741
3842
|
return Promise.reject(error);
|
3742
3843
|
}
|
3743
3844
|
|
3744
|
-
return this.brbState.enable(enabled, this.sendSlotManager)
|
3845
|
+
return this.brbState.enable(enabled, this.sendSlotManager).then(() => {
|
3846
|
+
if (this.audio && enabled) {
|
3847
|
+
// locus mutes the participant with brb enabled request,
|
3848
|
+
// so we need to explicitly update remote mute for correct logic flow
|
3849
|
+
this.audio.handleServerRemoteMuteUpdate(this, enabled);
|
3850
|
+
}
|
3851
|
+
});
|
3745
3852
|
}
|
3746
3853
|
|
3747
3854
|
/**
|
@@ -3933,7 +4040,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3933
4040
|
canAdmitParticipant: MeetingUtil.canAdmitParticipant(this.userDisplayHints),
|
3934
4041
|
canLock: MeetingUtil.canUserLock(this.userDisplayHints),
|
3935
4042
|
canUnlock: MeetingUtil.canUserUnlock(this.userDisplayHints),
|
3936
|
-
canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
|
4043
|
+
canShareWhiteBoard: MeetingUtil.canShareWhiteBoard(
|
4044
|
+
this.userDisplayHints,
|
4045
|
+
this.selfUserPolicies
|
4046
|
+
),
|
3937
4047
|
canSetDisallowUnmute: ControlsOptionsUtil.canSetDisallowUnmute(this.userDisplayHints),
|
3938
4048
|
canUnsetDisallowUnmute: ControlsOptionsUtil.canUnsetDisallowUnmute(this.userDisplayHints),
|
3939
4049
|
canSetMuteOnEntry: ControlsOptionsUtil.canSetMuteOnEntry(this.userDisplayHints),
|
@@ -3982,6 +4092,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
3982
4092
|
this.inMeetingActions.canSendReactions,
|
3983
4093
|
this.userDisplayHints
|
3984
4094
|
),
|
4095
|
+
requiresPostMeetingDataConsentPrompt: MeetingUtil.requiresPostMeetingDataConsentPrompt(
|
4096
|
+
this.userDisplayHints
|
4097
|
+
),
|
3985
4098
|
canManageBreakout: MeetingUtil.canManageBreakout(this.userDisplayHints),
|
3986
4099
|
canStartBreakout: MeetingUtil.canStartBreakout(this.userDisplayHints),
|
3987
4100
|
canBroadcastMessageToBreakout: MeetingUtil.canBroadcastMessageToBreakout(
|
@@ -4177,6 +4290,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
4177
4290
|
requiredPolicies: [SELF_POLICY.SUPPORT_ANNOTATION],
|
4178
4291
|
policies: this.selfUserPolicies,
|
4179
4292
|
}),
|
4293
|
+
canEnableAnnotation: ControlsOptionsUtil.hasHints({
|
4294
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_ANNOTATION_MEETING_OPTION],
|
4295
|
+
displayHints: this.userDisplayHints,
|
4296
|
+
}),
|
4297
|
+
canDisableAnnotation: ControlsOptionsUtil.hasHints({
|
4298
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_ANNOTATION_MEETING_OPTION],
|
4299
|
+
displayHints: this.userDisplayHints,
|
4300
|
+
}),
|
4301
|
+
canEnableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
|
4302
|
+
requiredHints: [DISPLAY_HINTS.ENABLE_RDC_MEETING_OPTION],
|
4303
|
+
displayHints: this.userDisplayHints,
|
4304
|
+
}),
|
4305
|
+
canDisableRemoteDesktopControl: ControlsOptionsUtil.hasHints({
|
4306
|
+
requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
|
4307
|
+
displayHints: this.userDisplayHints,
|
4308
|
+
}),
|
4180
4309
|
}) || changed;
|
4181
4310
|
}
|
4182
4311
|
if (changed) {
|
@@ -5684,8 +5813,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
5684
5813
|
// @ts-ignore
|
5685
5814
|
this.webex.internal.device.meetingStarted();
|
5686
5815
|
|
5687
|
-
this.#isoLocalClientMeetingJoinTime = new Date().toISOString();
|
5688
|
-
|
5689
5816
|
LoggerProxy.logger.log('Meeting:index#join --> Success');
|
5690
5817
|
|
5691
5818
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
|
@@ -6146,10 +6273,18 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6146
6273
|
},
|
6147
6274
|
options: {meetingId: this.id, rawError: error},
|
6148
6275
|
});
|
6149
|
-
} else if (
|
6150
|
-
error
|
6151
|
-
|
6152
|
-
|
6276
|
+
} else if (error instanceof Errors.SdpOfferHandlingError) {
|
6277
|
+
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
|
6278
|
+
|
6279
|
+
// @ts-ignore
|
6280
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6281
|
+
name: 'client.media-engine.remote-sdp-received',
|
6282
|
+
payload: {
|
6283
|
+
canProceed: false,
|
6284
|
+
},
|
6285
|
+
options: {meetingId: this.id, rawError: error},
|
6286
|
+
});
|
6287
|
+
} else if (error instanceof Errors.SdpAnswerHandlingError) {
|
6153
6288
|
sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.correlationId);
|
6154
6289
|
|
6155
6290
|
// @ts-ignore
|
@@ -6160,6 +6295,13 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6160
6295
|
},
|
6161
6296
|
options: {meetingId: this.id, rawError: error},
|
6162
6297
|
});
|
6298
|
+
|
6299
|
+
if (this.deferSDPAnswer) {
|
6300
|
+
clearTimeout(this.sdpResponseTimer);
|
6301
|
+
this.sdpResponseTimer = undefined;
|
6302
|
+
|
6303
|
+
this.deferSDPAnswer.reject();
|
6304
|
+
}
|
6163
6305
|
} else if (error instanceof Errors.SdpError) {
|
6164
6306
|
// this covers also the case of Errors.IceGatheringError which extends Errors.SdpError
|
6165
6307
|
sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.correlationId);
|
@@ -6694,30 +6836,42 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6694
6836
|
EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
|
6695
6837
|
data
|
6696
6838
|
);
|
6697
|
-
|
6698
|
-
|
6699
|
-
|
6700
|
-
|
6701
|
-
|
6702
|
-
|
6703
|
-
|
6704
|
-
|
6705
|
-
|
6706
|
-
|
6707
|
-
|
6839
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStart) {
|
6840
|
+
// @ts-ignore
|
6841
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6842
|
+
name: 'client.media.tx.start',
|
6843
|
+
payload: {
|
6844
|
+
mediaType: data.mediaType,
|
6845
|
+
shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
|
6846
|
+
},
|
6847
|
+
options: {
|
6848
|
+
meetingId: this.id,
|
6849
|
+
},
|
6850
|
+
});
|
6851
|
+
|
6852
|
+
if (data.mediaType === 'share') {
|
6853
|
+
this.shareCAEventSentStatus.transmitStart = true;
|
6854
|
+
}
|
6855
|
+
}
|
6708
6856
|
});
|
6709
6857
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.LOCAL_MEDIA_STOPPED, (data) => {
|
6710
|
-
|
6711
|
-
|
6712
|
-
|
6713
|
-
|
6714
|
-
|
6715
|
-
|
6716
|
-
|
6717
|
-
|
6718
|
-
|
6719
|
-
|
6720
|
-
|
6858
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.transmitStop) {
|
6859
|
+
// @ts-ignore
|
6860
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6861
|
+
name: 'client.media.tx.stop',
|
6862
|
+
payload: {
|
6863
|
+
mediaType: data.mediaType,
|
6864
|
+
shareInstanceId: data.mediaType === 'share' ? this.localShareInstanceId : undefined,
|
6865
|
+
},
|
6866
|
+
options: {
|
6867
|
+
meetingId: this.id,
|
6868
|
+
},
|
6869
|
+
});
|
6870
|
+
|
6871
|
+
if (data.mediaType === 'share') {
|
6872
|
+
this.shareCAEventSentStatus.transmitStop = true;
|
6873
|
+
}
|
6874
|
+
}
|
6721
6875
|
});
|
6722
6876
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STARTED, (data) => {
|
6723
6877
|
Trigger.trigger(
|
@@ -6729,57 +6883,65 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6729
6883
|
EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
|
6730
6884
|
data
|
6731
6885
|
);
|
6732
|
-
|
6733
|
-
this.webex.internal.newMetrics.submitClientEvent({
|
6734
|
-
name: 'client.media.rx.start',
|
6735
|
-
payload: {
|
6736
|
-
mediaType: data.mediaType,
|
6737
|
-
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6738
|
-
},
|
6739
|
-
options: {
|
6740
|
-
meetingId: this.id,
|
6741
|
-
},
|
6742
|
-
});
|
6743
|
-
|
6744
|
-
if (data.mediaType === 'share') {
|
6886
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStart) {
|
6745
6887
|
// @ts-ignore
|
6746
6888
|
this.webex.internal.newMetrics.submitClientEvent({
|
6747
|
-
name: 'client.media.
|
6889
|
+
name: 'client.media.rx.start',
|
6748
6890
|
payload: {
|
6749
|
-
mediaType:
|
6750
|
-
shareInstanceId: this.remoteShareInstanceId,
|
6891
|
+
mediaType: data.mediaType,
|
6892
|
+
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6751
6893
|
},
|
6752
6894
|
options: {
|
6753
6895
|
meetingId: this.id,
|
6754
6896
|
},
|
6755
6897
|
});
|
6898
|
+
|
6899
|
+
if (data.mediaType === 'share') {
|
6900
|
+
// @ts-ignore
|
6901
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6902
|
+
name: 'client.media.render.start',
|
6903
|
+
payload: {
|
6904
|
+
mediaType: 'share',
|
6905
|
+
shareInstanceId: this.remoteShareInstanceId,
|
6906
|
+
},
|
6907
|
+
options: {
|
6908
|
+
meetingId: this.id,
|
6909
|
+
},
|
6910
|
+
});
|
6911
|
+
|
6912
|
+
this.shareCAEventSentStatus.receiveStart = true;
|
6913
|
+
}
|
6756
6914
|
}
|
6757
6915
|
});
|
6758
6916
|
this.statsAnalyzer.on(StatsAnalyzerEventNames.REMOTE_MEDIA_STOPPED, (data) => {
|
6759
|
-
|
6760
|
-
this.webex.internal.newMetrics.submitClientEvent({
|
6761
|
-
name: 'client.media.rx.stop',
|
6762
|
-
payload: {
|
6763
|
-
mediaType: data.mediaType,
|
6764
|
-
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6765
|
-
},
|
6766
|
-
options: {
|
6767
|
-
meetingId: this.id,
|
6768
|
-
},
|
6769
|
-
});
|
6770
|
-
|
6771
|
-
if (data.mediaType === 'share') {
|
6917
|
+
if (data.mediaType !== 'share' || !this.shareCAEventSentStatus.receiveStop) {
|
6772
6918
|
// @ts-ignore
|
6773
6919
|
this.webex.internal.newMetrics.submitClientEvent({
|
6774
|
-
name: 'client.media.
|
6920
|
+
name: 'client.media.rx.stop',
|
6775
6921
|
payload: {
|
6776
|
-
mediaType:
|
6777
|
-
shareInstanceId: this.remoteShareInstanceId,
|
6922
|
+
mediaType: data.mediaType,
|
6923
|
+
shareInstanceId: data.mediaType === 'share' ? this.remoteShareInstanceId : undefined,
|
6778
6924
|
},
|
6779
6925
|
options: {
|
6780
6926
|
meetingId: this.id,
|
6781
6927
|
},
|
6782
6928
|
});
|
6929
|
+
|
6930
|
+
if (data.mediaType === 'share') {
|
6931
|
+
// @ts-ignore
|
6932
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
6933
|
+
name: 'client.media.render.stop',
|
6934
|
+
payload: {
|
6935
|
+
mediaType: 'share',
|
6936
|
+
shareInstanceId: this.remoteShareInstanceId,
|
6937
|
+
},
|
6938
|
+
options: {
|
6939
|
+
meetingId: this.id,
|
6940
|
+
},
|
6941
|
+
});
|
6942
|
+
|
6943
|
+
this.shareCAEventSentStatus.receiveStop = true;
|
6944
|
+
}
|
6783
6945
|
}
|
6784
6946
|
});
|
6785
6947
|
};
|
@@ -6796,7 +6958,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6796
6958
|
* @param {AddMediaOptions} [options] Options for enabling/disabling audio/video
|
6797
6959
|
* @returns {RoapMediaConnection | MultistreamRoapMediaConnection}
|
6798
6960
|
*/
|
6799
|
-
private async createMediaConnection(
|
6961
|
+
private async createMediaConnection(
|
6962
|
+
turnServerInfo?: TurnServerInfo,
|
6963
|
+
bundlePolicy?: BundlePolicy
|
6964
|
+
) {
|
6800
6965
|
this.rtcMetrics = this.isMultistream
|
6801
6966
|
? // @ts-ignore
|
6802
6967
|
new RtcMetrics(this.webex, {meetingId: this.id}, this.correlationId)
|
@@ -6997,6 +7162,12 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
6997
7162
|
networkQualityMonitor: this.networkQualityMonitor,
|
6998
7163
|
isMultistream: this.isMultistream,
|
6999
7164
|
});
|
7165
|
+
this.shareCAEventSentStatus = {
|
7166
|
+
transmitStart: false,
|
7167
|
+
transmitStop: false,
|
7168
|
+
receiveStart: false,
|
7169
|
+
receiveStop: false,
|
7170
|
+
};
|
7000
7171
|
this.setupStatsAnalyzerEventHandlers();
|
7001
7172
|
this.networkQualityMonitor.on(
|
7002
7173
|
NetworkQualityEventNames.NETWORK_QUALITY,
|
@@ -8681,6 +8852,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8681
8852
|
LoggerProxy.logger.log(
|
8682
8853
|
`Meeting:index#handleShareVideoStreamMuteStateChange --> Share video stream mute state changed to muted ${muted}`
|
8683
8854
|
);
|
8855
|
+
|
8856
|
+
const shareVideoStreamSettings = this.mediaProperties?.shareVideoStream?.getSettings();
|
8857
|
+
|
8684
8858
|
Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_VIDEO_MUTE_STATE_CHANGE, {
|
8685
8859
|
correlationId: this.correlationId,
|
8686
8860
|
muted,
|
@@ -8689,8 +8863,9 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
8689
8863
|
// SDK to TypeScript 5, which may affect other packages, use bracket notation for now, since
|
8690
8864
|
// all we're doing here is adding metrics.
|
8691
8865
|
// eslint-disable-next-line dot-notation
|
8692
|
-
displaySurface:
|
8866
|
+
displaySurface: shareVideoStreamSettings?.['displaySurface'],
|
8693
8867
|
isMultistream: this.isMultistream,
|
8868
|
+
frameRate: shareVideoStreamSettings?.frameRate,
|
8694
8869
|
});
|
8695
8870
|
};
|
8696
8871
|
|
@@ -9017,6 +9192,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9017
9192
|
});
|
9018
9193
|
}
|
9019
9194
|
|
9195
|
+
/**
|
9196
|
+
* Method to set post meeting data consent.
|
9197
|
+
*
|
9198
|
+
* @param {boolean} accept - whether consent accepted or declined
|
9199
|
+
* @returns {Promise}
|
9200
|
+
* @public
|
9201
|
+
* @memberof Meeting
|
9202
|
+
*/
|
9203
|
+
public setPostMeetingDataConsent(accept: boolean) {
|
9204
|
+
return this.meetingRequest.setPostMeetingDataConsent({
|
9205
|
+
postMeetingDataConsent: accept,
|
9206
|
+
locusUrl: this.locusUrl,
|
9207
|
+
deviceUrl: this.deviceUrl,
|
9208
|
+
selfId: this.members.selfId,
|
9209
|
+
});
|
9210
|
+
}
|
9211
|
+
|
9020
9212
|
/**
|
9021
9213
|
* Throws if we don't have a media connection created
|
9022
9214
|
*
|
@@ -9257,6 +9449,8 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
9257
9449
|
|
9258
9450
|
if (floorRequestNeeded) {
|
9259
9451
|
this.localShareInstanceId = uuid.v4();
|
9452
|
+
this.shareCAEventSentStatus.transmitStart = false;
|
9453
|
+
this.shareCAEventSentStatus.transmitStop = false;
|
9260
9454
|
|
9261
9455
|
// @ts-ignore
|
9262
9456
|
this.webex.internal.newMetrics.submitClientEvent({
|