@webex/plugin-meetings 3.7.0-next.3 → 3.7.0-next.30
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/common/errors/{webinar-registration-error.js → join-webinar-error.js} +12 -12
- package/dist/common/errors/join-webinar-error.js.map +1 -0
- package/dist/config.js +1 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.js +31 -6
- package/dist/constants.js.map +1 -1
- package/dist/index.js +8 -15
- package/dist/index.js.map +1 -1
- package/dist/interpretation/index.js +1 -1
- package/dist/interpretation/siLanguage.js +1 -1
- package/dist/locus-info/index.js +13 -2
- package/dist/locus-info/index.js.map +1 -1
- package/dist/locus-info/selfUtils.js +30 -17
- package/dist/locus-info/selfUtils.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 +810 -779
- package/dist/meeting/index.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 +3 -8
- package/dist/meeting/util.js.map +1 -1
- package/dist/meeting-info/meeting-info-v2.js +29 -17
- package/dist/meeting-info/meeting-info-v2.js.map +1 -1
- package/dist/meetings/index.js +6 -3
- 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/types.js.map +1 -1
- package/dist/member/util.js +39 -28
- package/dist/member/util.js.map +1 -1
- package/dist/members/util.js +4 -2
- package/dist/members/util.js.map +1 -1
- package/dist/metrics/constants.js +1 -1
- package/dist/metrics/constants.js.map +1 -1
- package/dist/multistream/remoteMedia.js +30 -15
- package/dist/multistream/remoteMedia.js.map +1 -1
- package/dist/multistream/sendSlotManager.js +24 -0
- package/dist/multistream/sendSlotManager.js.map +1 -1
- package/dist/reachability/clusterReachability.js +12 -11
- package/dist/reachability/clusterReachability.js.map +1 -1
- package/dist/recording-controller/enums.js +8 -4
- package/dist/recording-controller/enums.js.map +1 -1
- package/dist/recording-controller/index.js +18 -9
- package/dist/recording-controller/index.js.map +1 -1
- package/dist/recording-controller/util.js +13 -9
- package/dist/recording-controller/util.js.map +1 -1
- package/dist/types/common/errors/{webinar-registration-error.d.ts → join-webinar-error.d.ts} +2 -2
- package/dist/types/constants.d.ts +23 -1
- package/dist/types/index.d.ts +3 -3
- package/dist/types/locus-info/index.d.ts +2 -1
- package/dist/types/meeting/in-meeting-actions.d.ts +10 -0
- package/dist/types/meeting/index.d.ts +9 -10
- 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 +1 -1
- package/dist/types/meeting-info/meeting-info-v2.d.ts +4 -4
- package/dist/types/meetings/index.d.ts +3 -0
- package/dist/types/member/index.d.ts +1 -0
- package/dist/types/member/types.d.ts +7 -0
- package/dist/types/members/util.d.ts +2 -0
- package/dist/types/metrics/constants.d.ts +1 -1
- package/dist/types/multistream/sendSlotManager.d.ts +8 -1
- package/dist/types/recording-controller/enums.d.ts +5 -2
- package/dist/types/recording-controller/index.d.ts +1 -0
- package/dist/types/recording-controller/util.d.ts +2 -1
- package/dist/webinar/index.js +390 -7
- package/dist/webinar/index.js.map +1 -1
- package/package.json +23 -22
- package/src/common/errors/join-webinar-error.ts +24 -0
- package/src/config.ts +1 -1
- package/src/constants.ts +28 -3
- package/src/index.ts +2 -3
- package/src/locus-info/index.ts +17 -2
- package/src/locus-info/selfUtils.ts +19 -6
- package/src/meeting/in-meeting-actions.ts +21 -0
- package/src/meeting/index.ts +147 -54
- package/src/meeting/request.ts +26 -1
- package/src/meeting/request.type.ts +7 -0
- package/src/meeting/util.ts +3 -9
- package/src/meeting-info/meeting-info-v2.ts +23 -11
- package/src/meetings/index.ts +8 -2
- package/src/member/index.ts +9 -0
- package/src/member/types.ts +8 -0
- package/src/member/util.ts +34 -24
- package/src/members/util.ts +1 -0
- package/src/metrics/constants.ts +1 -1
- package/src/multistream/remoteMedia.ts +28 -15
- package/src/multistream/sendSlotManager.ts +31 -0
- package/src/reachability/clusterReachability.ts +4 -1
- package/src/recording-controller/enums.ts +5 -2
- package/src/recording-controller/index.ts +17 -4
- package/src/recording-controller/util.ts +20 -5
- package/src/webinar/index.ts +235 -9
- package/test/unit/spec/locus-info/index.js +222 -0
- package/test/unit/spec/locus-info/selfConstant.js +7 -0
- package/test/unit/spec/locus-info/selfUtils.js +91 -1
- package/test/unit/spec/meeting/in-meeting-actions.ts +13 -1
- package/test/unit/spec/meeting/index.js +318 -81
- package/test/unit/spec/meeting/utils.js +11 -19
- package/test/unit/spec/meeting-info/meetinginfov2.js +9 -4
- package/test/unit/spec/meetings/index.js +9 -5
- package/test/unit/spec/member/util.js +52 -11
- package/test/unit/spec/members/utils.js +95 -0
- package/test/unit/spec/multistream/remoteMedia.ts +11 -7
- package/test/unit/spec/reachability/clusterReachability.ts +7 -0
- package/test/unit/spec/recording-controller/index.js +61 -5
- package/test/unit/spec/recording-controller/util.js +39 -3
- package/test/unit/spec/webinar/index.ts +504 -0
- package/dist/common/errors/webinar-registration-error.js.map +0 -1
- package/src/common/errors/webinar-registration-error.ts +0 -27
package/src/constants.ts
CHANGED
|
@@ -198,6 +198,8 @@ export const RETRY_TIMEOUT = 3000;
|
|
|
198
198
|
|
|
199
199
|
export const ICE_AND_DTLS_CONNECTION_TIMEOUT = 20000;
|
|
200
200
|
export const ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT = 35000;
|
|
201
|
+
export const WEBINAR_ERROR_WEBCAST = [403026];
|
|
202
|
+
export const WEBINAR_ERROR_REGISTRATIONID = [403037, 403137];
|
|
201
203
|
|
|
202
204
|
// ******************** REGEX **********************
|
|
203
205
|
// Please alphabetize
|
|
@@ -303,6 +305,7 @@ export const EVENT_TRIGGERS = {
|
|
|
303
305
|
MEETING_SELF_CANNOT_VIEW_PARTICIPANT_LIST: 'meeting:self:cannotViewParticipantList',
|
|
304
306
|
MEETING_SELF_IS_SHARING_BLOCKED: 'meeting:self:isSharingBlocked',
|
|
305
307
|
MEETING_SELF_ROLES_CHANGED: 'meeting:self:rolesChanged',
|
|
308
|
+
MEETING_SELF_BRB_UPDATE: 'meeting:self:brbUpdate',
|
|
306
309
|
MEETING_CONTROLS_LAYOUT_UPDATE: 'meeting:layout:update',
|
|
307
310
|
MEETING_ENTRY_EXIT_TONE_UPDATE: 'meeting:entryExitTone:update',
|
|
308
311
|
MEETING_BREAKOUTS_UPDATE: 'meeting:breakouts:update',
|
|
@@ -325,6 +328,7 @@ export const EVENT_TRIGGERS = {
|
|
|
325
328
|
MEETING_RECONNECTION_FAILURE: 'meeting:reconnectionFailure',
|
|
326
329
|
MEETING_UNLOCKED: 'meeting:unlocked',
|
|
327
330
|
MEETING_LOCKED: 'meeting:locked',
|
|
331
|
+
MEETING_RESOURCE_LINKS_UPDATE: 'meeting:resourceLinks:update',
|
|
328
332
|
MEETING_INFO_AVAILABLE: 'meeting:meetingInfoAvailable',
|
|
329
333
|
MEETING_INFO_UPDATED: 'meeting:meetingInfoUpdated',
|
|
330
334
|
MEETING_LOG_UPLOAD_SUCCESS: 'meeting:logUpload:success',
|
|
@@ -383,6 +387,13 @@ export const EVENT_TYPES = {
|
|
|
383
387
|
ERROR: 'error',
|
|
384
388
|
};
|
|
385
389
|
|
|
390
|
+
export const HEADERS = {
|
|
391
|
+
CONTENT_TYPE: 'Content-Type',
|
|
392
|
+
CONTENT_TYPE_VALUE: {
|
|
393
|
+
APPLICATION_JSON: 'application/json',
|
|
394
|
+
},
|
|
395
|
+
};
|
|
396
|
+
|
|
386
397
|
// Handles the reason when meeting gets destroyed
|
|
387
398
|
// host removed you from the meeting
|
|
388
399
|
// You are the host and you left the meeting
|
|
@@ -529,9 +540,9 @@ export const ERROR_DICTIONARY = {
|
|
|
529
540
|
'Reconnection was not started, because there is one already in progress or reconnections are disabled in config.',
|
|
530
541
|
CODE: 15,
|
|
531
542
|
},
|
|
532
|
-
|
|
533
|
-
NAME: '
|
|
534
|
-
MESSAGE: 'An error occurred while the webinar
|
|
543
|
+
JoinWebinarError: {
|
|
544
|
+
NAME: 'JoinWebinarError',
|
|
545
|
+
MESSAGE: 'An error occurred while the join webinar.',
|
|
535
546
|
CODE: 16,
|
|
536
547
|
},
|
|
537
548
|
};
|
|
@@ -709,6 +720,7 @@ export const LOCUSINFO = {
|
|
|
709
720
|
SELF_IS_SHARING_BLOCKED_CHANGE: 'SELF_IS_SHARING_BLOCKED_CHANGE',
|
|
710
721
|
SELF_MEETING_BREAKOUTS_CHANGED: 'SELF_MEETING_BREAKOUTS_CHANGED',
|
|
711
722
|
SELF_MEETING_INTERPRETATION_CHANGED: 'SELF_MEETING_INTERPRETATION_CHANGED',
|
|
723
|
+
SELF_MEETING_BRB_CHANGED: 'SELF_MEETING_BRB_CHANGED',
|
|
712
724
|
MEDIA_INACTIVITY: 'MEDIA_INACTIVITY',
|
|
713
725
|
LINKS_SERVICES: 'LINKS_SERVICES',
|
|
714
726
|
LINKS_RESOURCES: 'LINKS_RESOURCES',
|
|
@@ -904,6 +916,10 @@ export const DISPLAY_HINTS = {
|
|
|
904
916
|
RECORDING_CONTROL_PAUSE: 'RECORDING_CONTROL_PAUSE',
|
|
905
917
|
RECORDING_CONTROL_STOP: 'RECORDING_CONTROL_STOP',
|
|
906
918
|
RECORDING_CONTROL_RESUME: 'RECORDING_CONTROL_RESUME',
|
|
919
|
+
PREMISE_RECORDING_CONTROL_START: 'PREMISE_RECORDING_CONTROL_START',
|
|
920
|
+
PREMISE_RECORDING_CONTROL_PAUSE: 'PREMISE_RECORDING_CONTROL_PAUSE',
|
|
921
|
+
PREMISE_RECORDING_CONTROL_STOP: 'PREMISE_RECORDING_CONTROL_STOP',
|
|
922
|
+
PREMISE_RECORDING_CONTROL_RESUME: 'PREMISE_RECORDING_CONTROL_RESUME',
|
|
907
923
|
LOCK_CONTROL_UNLOCK: 'LOCK_CONTROL_UNLOCK',
|
|
908
924
|
LOCK_CONTROL_LOCK: 'LOCK_CONTROL_LOCK',
|
|
909
925
|
LOCK_STATUS_LOCKED: 'LOCK_STATUS_LOCKED',
|
|
@@ -950,6 +966,7 @@ export const DISPLAY_HINTS = {
|
|
|
950
966
|
DISABLE_ASK_FOR_HELP: 'DISABLE_ASK_FOR_HELP',
|
|
951
967
|
DISABLE_BREAKOUT_PREASSIGNMENTS: 'DISABLE_BREAKOUT_PREASSIGNMENTS',
|
|
952
968
|
DISABLE_LOBBY_TO_BREAKOUT: 'DISABLE_LOBBY_TO_BREAKOUT',
|
|
969
|
+
DISABLE_BREAKOUT_START: 'DISABLE_BREAKOUT_START',
|
|
953
970
|
|
|
954
971
|
// participants list
|
|
955
972
|
DISABLE_VIEW_THE_PARTICIPANT_LIST: 'DISABLE_VIEW_THE_PARTICIPANT_LIST',
|
|
@@ -988,6 +1005,12 @@ export const DISPLAY_HINTS = {
|
|
|
988
1005
|
STAGE_VIEW_INACTIVE: 'STAGE_VIEW_INACTIVE',
|
|
989
1006
|
ENABLE_STAGE_VIEW: 'ENABLE_STAGE_VIEW',
|
|
990
1007
|
DISABLE_STAGE_VIEW: 'DISABLE_STAGE_VIEW',
|
|
1008
|
+
|
|
1009
|
+
// Practice Session
|
|
1010
|
+
PRACTICE_SESSION_ON: 'PRACTICE_SESSION_ON',
|
|
1011
|
+
PRACTICE_SESSION_OFF: 'PRACTICE_SESSION_OFF',
|
|
1012
|
+
SHOW_PRACTICE_SESSION_START: 'SHOW_PRACTICE_SESSION_START',
|
|
1013
|
+
SHOW_PRACTICE_SESSION_STOP: 'SHOW_PRACTICE_SESSION_STOP',
|
|
991
1014
|
};
|
|
992
1015
|
|
|
993
1016
|
export const INTERSTITIAL_DISPLAY_HINTS = [DISPLAY_HINTS.VOIP_IS_ENABLED];
|
|
@@ -1300,6 +1323,8 @@ export const MEETING_INFO_FAILURE_REASON = {
|
|
|
1300
1323
|
WRONG_CAPTCHA: 'WRONG_CAPTCHA', // wbxappapi requires a captcha code or a wrong captcha code was provided
|
|
1301
1324
|
POLICY: 'POLICY', // meeting info request violates some meeting policy
|
|
1302
1325
|
WEBINAR_REGISTRATION: 'WEBINAR_REGISTRATION', // webinar need registration
|
|
1326
|
+
NEED_JOIN_WITH_WEBCAST: 'NEED_JOIN_WITH_WEBCAST', // webinar need using webcast join
|
|
1327
|
+
WEBINAR_NEED_REGISTRATIONID: 'WEBINAR_NEED_REGISTRATIONID', // webinar need registrationID
|
|
1303
1328
|
OTHER: 'OTHER', // any other error (network, etc)
|
|
1304
1329
|
};
|
|
1305
1330
|
|
package/src/index.ts
CHANGED
|
@@ -8,7 +8,7 @@ import CaptchaError from './common/errors/captcha-error';
|
|
|
8
8
|
import IntentToJoinError from './common/errors/intent-to-join';
|
|
9
9
|
import PasswordError from './common/errors/password-error';
|
|
10
10
|
import PermissionError from './common/errors/permission';
|
|
11
|
-
import
|
|
11
|
+
import JoinWebinarError from './common/errors/join-webinar-error';
|
|
12
12
|
import {
|
|
13
13
|
ReclaimHostEmptyWrongKeyError,
|
|
14
14
|
ReclaimHostIsHostAlreadyError,
|
|
@@ -27,7 +27,6 @@ registerPlugin('meetings', Meetings, {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
export {
|
|
30
|
-
getDevices,
|
|
31
30
|
LocalStream,
|
|
32
31
|
LocalDisplayStream,
|
|
33
32
|
LocalSystemAudioStream,
|
|
@@ -69,7 +68,7 @@ export {
|
|
|
69
68
|
ReclaimHostEmptyWrongKeyError,
|
|
70
69
|
Meeting,
|
|
71
70
|
MeetingInfoUtil,
|
|
72
|
-
|
|
71
|
+
JoinWebinarError,
|
|
73
72
|
};
|
|
74
73
|
|
|
75
74
|
export {RemoteMedia} from './multistream/remoteMedia';
|
package/src/locus-info/index.ts
CHANGED
|
@@ -1283,12 +1283,13 @@ export default class LocusInfo extends EventsScope {
|
|
|
1283
1283
|
/**
|
|
1284
1284
|
* handles when the locus.mediaShares is updated
|
|
1285
1285
|
* @param {Object} mediaShares the locus.mediaShares property
|
|
1286
|
+
* @param {boolean} forceUpdate force to update the mediaShares
|
|
1286
1287
|
* @returns {undefined}
|
|
1287
1288
|
* @memberof LocusInfo
|
|
1288
1289
|
* emits internal event locus_info_update_media_shares
|
|
1289
1290
|
*/
|
|
1290
|
-
updateMediaShares(mediaShares: object) {
|
|
1291
|
-
if (mediaShares && !isEqual(this.mediaShares, mediaShares)) {
|
|
1291
|
+
updateMediaShares(mediaShares: object, forceUpdate = false) {
|
|
1292
|
+
if (mediaShares && (!isEqual(this.mediaShares, mediaShares) || forceUpdate)) {
|
|
1292
1293
|
const parsedMediaShares = MediaSharesUtils.getMediaShares(this.mediaShares, mediaShares);
|
|
1293
1294
|
|
|
1294
1295
|
this.updateMeeting(parsedMediaShares.current);
|
|
@@ -1303,6 +1304,7 @@ export default class LocusInfo extends EventsScope {
|
|
|
1303
1304
|
{
|
|
1304
1305
|
current: parsedMediaShares.current,
|
|
1305
1306
|
previous: parsedMediaShares.previous,
|
|
1307
|
+
forceUpdate,
|
|
1306
1308
|
}
|
|
1307
1309
|
);
|
|
1308
1310
|
}
|
|
@@ -1393,6 +1395,19 @@ export default class LocusInfo extends EventsScope {
|
|
|
1393
1395
|
);
|
|
1394
1396
|
}
|
|
1395
1397
|
|
|
1398
|
+
if (parsedSelves.updates.brbChanged) {
|
|
1399
|
+
this.emitScoped(
|
|
1400
|
+
{
|
|
1401
|
+
file: 'locus-info',
|
|
1402
|
+
function: 'updateSelf',
|
|
1403
|
+
},
|
|
1404
|
+
LOCUSINFO.EVENTS.SELF_MEETING_BRB_CHANGED,
|
|
1405
|
+
{
|
|
1406
|
+
brb: parsedSelves.current.brb,
|
|
1407
|
+
}
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1396
1411
|
if (parsedSelves.updates.interpretationChanged) {
|
|
1397
1412
|
this.emitScoped(
|
|
1398
1413
|
{
|
|
@@ -66,6 +66,7 @@ SelfUtils.parse = (self: any, deviceId: string) => {
|
|
|
66
66
|
breakoutSessions: SelfUtils.getBreakoutSessions(self),
|
|
67
67
|
breakout: SelfUtils.getBreakout(self),
|
|
68
68
|
interpretation: SelfUtils.getInterpretation(self),
|
|
69
|
+
brb: SelfUtils.getBrb(self),
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
|
|
@@ -75,6 +76,7 @@ SelfUtils.parse = (self: any, deviceId: string) => {
|
|
|
75
76
|
SelfUtils.getBreakoutSessions = (self) => self?.controls?.breakout?.sessions;
|
|
76
77
|
SelfUtils.getBreakout = (self) => self?.controls?.breakout;
|
|
77
78
|
SelfUtils.getInterpretation = (self) => self?.controls?.interpretation;
|
|
79
|
+
SelfUtils.getBrb = (self) => self?.controls?.brb;
|
|
78
80
|
|
|
79
81
|
SelfUtils.getLayout = (self) =>
|
|
80
82
|
Array.isArray(self?.controls?.layouts) ? self.controls.layouts[0].type : undefined;
|
|
@@ -97,7 +99,7 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
|
|
|
97
99
|
const current = newSelf && SelfUtils.parse(newSelf, deviceId);
|
|
98
100
|
const updates: any = {};
|
|
99
101
|
|
|
100
|
-
updates.isUserUnadmitted = SelfUtils.isUserUnadmitted(current);
|
|
102
|
+
updates.isUserUnadmitted = SelfUtils.isUserUnadmitted(previous, current);
|
|
101
103
|
updates.isUserAdmitted = SelfUtils.isUserAdmitted(previous, current);
|
|
102
104
|
updates.isVideoMutedByOthersChanged = SelfUtils.videoMutedByOthersChanged(previous, current);
|
|
103
105
|
updates.isMutedByOthersChanged = SelfUtils.mutedByOthersChanged(previous, current);
|
|
@@ -128,6 +130,7 @@ SelfUtils.getSelves = (oldSelf, newSelf, deviceId) => {
|
|
|
128
130
|
updates.isSharingBlockedChanged = previous?.isSharingBlocked !== current.isSharingBlocked;
|
|
129
131
|
updates.breakoutsChanged = SelfUtils.breakoutsChanged(previous, current);
|
|
130
132
|
updates.interpretationChanged = SelfUtils.interpretationChanged(previous, current);
|
|
133
|
+
updates.brbChanged = SelfUtils.brbChanged(previous, current);
|
|
131
134
|
|
|
132
135
|
return {
|
|
133
136
|
previous,
|
|
@@ -159,6 +162,9 @@ SelfUtils.breakoutsChanged = (previous, current) =>
|
|
|
159
162
|
SelfUtils.interpretationChanged = (previous, current) =>
|
|
160
163
|
!isEqual(previous?.interpretation, current?.interpretation) && !!current?.interpretation;
|
|
161
164
|
|
|
165
|
+
SelfUtils.brbChanged = (previous, current) =>
|
|
166
|
+
!isEqual(previous?.brb, current?.brb) && current?.brb !== undefined;
|
|
167
|
+
|
|
162
168
|
SelfUtils.isMediaInactive = (previous, current) => {
|
|
163
169
|
if (
|
|
164
170
|
previous &&
|
|
@@ -324,16 +330,23 @@ SelfUtils.isLocusUserAdmitted = (check: any) =>
|
|
|
324
330
|
check && check.joinedWith?.intent?.type !== _WAIT_ && check.state === _JOINED_;
|
|
325
331
|
|
|
326
332
|
/**
|
|
327
|
-
* @param {Object}
|
|
333
|
+
* @param {Object} oldSelf
|
|
334
|
+
* @param {Object} changedSelf
|
|
328
335
|
* @returns {Boolean}
|
|
329
336
|
* @throws {Error} when self is undefined
|
|
330
337
|
*/
|
|
331
|
-
SelfUtils.isUserUnadmitted = (
|
|
332
|
-
if (!
|
|
333
|
-
throw new ParameterError(
|
|
338
|
+
SelfUtils.isUserUnadmitted = (oldSelf: object, changedSelf: object) => {
|
|
339
|
+
if (!changedSelf) {
|
|
340
|
+
throw new ParameterError(
|
|
341
|
+
'changedSelf must be defined to determine if self is unadmitted as guest.'
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
if (SelfUtils.isLocusUserUnadmitted(oldSelf)) {
|
|
346
|
+
return false;
|
|
334
347
|
}
|
|
335
348
|
|
|
336
|
-
return SelfUtils.isLocusUserUnadmitted(
|
|
349
|
+
return SelfUtils.isLocusUserUnadmitted(changedSelf);
|
|
337
350
|
};
|
|
338
351
|
|
|
339
352
|
SelfUtils.moderatorChanged = (oldSelf, changedSelf) => {
|
|
@@ -26,6 +26,7 @@ interface IInMeetingActions {
|
|
|
26
26
|
canStartRecording?: boolean;
|
|
27
27
|
canPauseRecording?: boolean;
|
|
28
28
|
canResumeRecording?: boolean;
|
|
29
|
+
isPremiseRecordingEnabled?: boolean;
|
|
29
30
|
canStopRecording?: boolean;
|
|
30
31
|
canRaiseHand?: boolean;
|
|
31
32
|
canLowerAllHands?: boolean;
|
|
@@ -93,6 +94,10 @@ interface IInMeetingActions {
|
|
|
93
94
|
canShowStageView?: boolean;
|
|
94
95
|
canEnableStageView?: boolean;
|
|
95
96
|
canDisableStageView?: boolean;
|
|
97
|
+
isPracticeSessionOn?: boolean;
|
|
98
|
+
isPracticeSessionOff?: boolean;
|
|
99
|
+
canStartPracticeSession?: boolean;
|
|
100
|
+
canStopPracticeSession?: boolean;
|
|
96
101
|
}
|
|
97
102
|
|
|
98
103
|
/**
|
|
@@ -117,6 +122,8 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
117
122
|
|
|
118
123
|
canResumeRecording = null;
|
|
119
124
|
|
|
125
|
+
isPremiseRecordingEnabled = null;
|
|
126
|
+
|
|
120
127
|
canStopRecording = null;
|
|
121
128
|
|
|
122
129
|
canSetMuteOnEntry = null;
|
|
@@ -266,6 +273,15 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
266
273
|
canEnableStageView = null;
|
|
267
274
|
|
|
268
275
|
canDisableStageView = null;
|
|
276
|
+
|
|
277
|
+
isPracticeSessionOn = null;
|
|
278
|
+
|
|
279
|
+
isPracticeSessionOff = null;
|
|
280
|
+
|
|
281
|
+
canStartPracticeSession = null;
|
|
282
|
+
|
|
283
|
+
canStopPracticeSession = null;
|
|
284
|
+
|
|
269
285
|
/**
|
|
270
286
|
* Returns all meeting action options
|
|
271
287
|
* @returns {Object}
|
|
@@ -288,6 +304,7 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
288
304
|
canPauseRecording: this.canPauseRecording,
|
|
289
305
|
canResumeRecording: this.canResumeRecording,
|
|
290
306
|
canStopRecording: this.canStopRecording,
|
|
307
|
+
isPremiseRecordingEnabled: this.isPremiseRecordingEnabled,
|
|
291
308
|
canRaiseHand: this.canRaiseHand,
|
|
292
309
|
canLowerAllHands: this.canLowerAllHands,
|
|
293
310
|
canLowerSomeoneElsesHand: this.canLowerSomeoneElsesHand,
|
|
@@ -354,6 +371,10 @@ export default class InMeetingActions implements IInMeetingActions {
|
|
|
354
371
|
canShowStageView: this.canShowStageView,
|
|
355
372
|
canEnableStageView: this.canEnableStageView,
|
|
356
373
|
canDisableStageView: this.canDisableStageView,
|
|
374
|
+
isPracticeSessionOn: this.isPracticeSessionOn,
|
|
375
|
+
isPracticeSessionOff: this.isPracticeSessionOff,
|
|
376
|
+
canStartPracticeSession: this.canStartPracticeSession,
|
|
377
|
+
canStopPracticeSession: this.canStopPracticeSession,
|
|
357
378
|
});
|
|
358
379
|
|
|
359
380
|
/**
|
package/src/meeting/index.ts
CHANGED
|
@@ -31,7 +31,6 @@ import {
|
|
|
31
31
|
} from '@webex/internal-media-core';
|
|
32
32
|
|
|
33
33
|
import {
|
|
34
|
-
getDevices,
|
|
35
34
|
LocalStream,
|
|
36
35
|
LocalCameraStream,
|
|
37
36
|
LocalDisplayStream,
|
|
@@ -122,6 +121,8 @@ import {
|
|
|
122
121
|
MEETING_PERMISSION_TOKEN_REFRESH_REASON,
|
|
123
122
|
ROAP_OFFER_ANSWER_EXCHANGE_TIMEOUT,
|
|
124
123
|
NAMED_MEDIA_GROUP_TYPE_AUDIO,
|
|
124
|
+
WEBINAR_ERROR_WEBCAST,
|
|
125
|
+
WEBINAR_ERROR_REGISTRATIONID,
|
|
125
126
|
} from '../constants';
|
|
126
127
|
import BEHAVIORAL_METRICS from '../metrics/constants';
|
|
127
128
|
import ParameterError from '../common/errors/parameter';
|
|
@@ -129,7 +130,7 @@ import {
|
|
|
129
130
|
MeetingInfoV2PasswordError,
|
|
130
131
|
MeetingInfoV2CaptchaError,
|
|
131
132
|
MeetingInfoV2PolicyError,
|
|
132
|
-
|
|
133
|
+
MeetingInfoV2JoinWebinarError,
|
|
133
134
|
} from '../meeting-info/meeting-info-v2';
|
|
134
135
|
import {CSI, ReceiveSlotManager} from '../multistream/receiveSlotManager';
|
|
135
136
|
import SendSlotManager from '../multistream/sendSlotManager';
|
|
@@ -158,7 +159,8 @@ import ControlsOptionsManager from '../controls-options-manager';
|
|
|
158
159
|
import PermissionError from '../common/errors/permission';
|
|
159
160
|
import {LocusMediaRequest} from './locusMediaRequest';
|
|
160
161
|
import {ConnectionStateHandler, ConnectionStateEvent} from './connectionStateHandler';
|
|
161
|
-
import
|
|
162
|
+
import JoinWebinarError from '../common/errors/join-webinar-error';
|
|
163
|
+
import Member from '../member';
|
|
162
164
|
|
|
163
165
|
// default callback so we don't call an undefined function, but in practice it should never be used
|
|
164
166
|
const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
|
|
@@ -848,7 +850,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
848
850
|
* @memberof Meeting
|
|
849
851
|
*/
|
|
850
852
|
// @ts-ignore
|
|
851
|
-
this.webinar = new Webinar({}, {parent: this.webex});
|
|
853
|
+
this.webinar = new Webinar({meetingId: this.id}, {parent: this.webex});
|
|
852
854
|
/**
|
|
853
855
|
* helper class for managing receive slots (for multistream media connections)
|
|
854
856
|
*/
|
|
@@ -1767,15 +1769,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
1767
1769
|
this.meetingInfo = err.meetingInfo;
|
|
1768
1770
|
}
|
|
1769
1771
|
throw new PermissionError();
|
|
1770
|
-
} else if (err instanceof
|
|
1772
|
+
} else if (err instanceof MeetingInfoV2JoinWebinarError) {
|
|
1771
1773
|
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_REGISTRATION;
|
|
1774
|
+
if (WEBINAR_ERROR_WEBCAST.includes(err.wbxAppApiCode)) {
|
|
1775
|
+
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.NEED_JOIN_WITH_WEBCAST;
|
|
1776
|
+
} else if (WEBINAR_ERROR_REGISTRATIONID.includes(err.wbxAppApiCode)) {
|
|
1777
|
+
this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.WEBINAR_NEED_REGISTRATIONID;
|
|
1778
|
+
}
|
|
1772
1779
|
this.meetingInfoFailureCode = err.wbxAppApiCode;
|
|
1773
1780
|
|
|
1774
1781
|
if (err.meetingInfo) {
|
|
1775
1782
|
this.meetingInfo = err.meetingInfo;
|
|
1776
1783
|
}
|
|
1777
1784
|
|
|
1778
|
-
throw new
|
|
1785
|
+
throw new JoinWebinarError();
|
|
1779
1786
|
} else if (err instanceof MeetingInfoV2PasswordError) {
|
|
1780
1787
|
LoggerProxy.logger.info(
|
|
1781
1788
|
// @ts-ignore
|
|
@@ -2660,6 +2667,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2660
2667
|
});
|
|
2661
2668
|
|
|
2662
2669
|
this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_PRACTICE_SESSION_STATUS_UPDATED, ({state}) => {
|
|
2670
|
+
this.webinar.updatePracticeSessionStatus(state);
|
|
2663
2671
|
Trigger.trigger(
|
|
2664
2672
|
this,
|
|
2665
2673
|
{file: 'meeting/index', function: 'setupLocusControlsListener'},
|
|
@@ -2733,6 +2741,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2733
2741
|
this.triggerAnnotationInfoEvent(contentShare, previousContentShare);
|
|
2734
2742
|
|
|
2735
2743
|
if (
|
|
2744
|
+
!payload.forceUpdate &&
|
|
2736
2745
|
contentShare.beneficiaryId === previousContentShare?.beneficiaryId &&
|
|
2737
2746
|
contentShare.disposition === previousContentShare?.disposition &&
|
|
2738
2747
|
contentShare.deviceUrlSharing === previousContentShare.deviceUrlSharing &&
|
|
@@ -2779,7 +2788,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2779
2788
|
// It does not matter who requested to share the whiteboard, everyone gets the same view
|
|
2780
2789
|
else if (whiteboardShare.disposition === FLOOR_ACTION.GRANTED) {
|
|
2781
2790
|
// WHITEBOARD - sharing whiteboard
|
|
2782
|
-
|
|
2791
|
+
// Webinar attendee should receive whiteboard as remote share
|
|
2792
|
+
newShareStatus =
|
|
2793
|
+
this.locusInfo?.info?.isWebinar && this.webinar?.selfIsAttendee
|
|
2794
|
+
? SHARE_STATUS.REMOTE_SHARE_ACTIVE
|
|
2795
|
+
: SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE;
|
|
2783
2796
|
}
|
|
2784
2797
|
// or if content share is either released or null and whiteboard share is either released or null, no one is sharing
|
|
2785
2798
|
else if (
|
|
@@ -2794,6 +2807,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
2794
2807
|
LoggerProxy.logger.info(
|
|
2795
2808
|
`Meeting:index#setUpLocusInfoMediaInactiveListener --> this.shareStatus=${this.shareStatus} newShareStatus=${newShareStatus}`
|
|
2796
2809
|
);
|
|
2810
|
+
|
|
2797
2811
|
if (newShareStatus !== this.shareStatus) {
|
|
2798
2812
|
const oldShareStatus = this.shareStatus;
|
|
2799
2813
|
|
|
@@ -3051,7 +3065,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3051
3065
|
*/
|
|
3052
3066
|
private setUpLocusResourcesListener() {
|
|
3053
3067
|
this.locusInfo.on(LOCUSINFO.EVENTS.LINKS_RESOURCES, (payload) => {
|
|
3054
|
-
|
|
3068
|
+
if (payload) {
|
|
3069
|
+
this.webinar.updateWebcastUrl(payload);
|
|
3070
|
+
Trigger.trigger(
|
|
3071
|
+
this,
|
|
3072
|
+
{
|
|
3073
|
+
file: 'meeting/index',
|
|
3074
|
+
function: 'setUpLocusInfoMeetingInfoListener',
|
|
3075
|
+
},
|
|
3076
|
+
EVENT_TRIGGERS.MEETING_RESOURCE_LINKS_UPDATE,
|
|
3077
|
+
{
|
|
3078
|
+
payload,
|
|
3079
|
+
}
|
|
3080
|
+
);
|
|
3081
|
+
}
|
|
3055
3082
|
});
|
|
3056
3083
|
}
|
|
3057
3084
|
|
|
@@ -3361,6 +3388,20 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3361
3388
|
}
|
|
3362
3389
|
});
|
|
3363
3390
|
|
|
3391
|
+
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_MEETING_BRB_CHANGED, (payload) => {
|
|
3392
|
+
Trigger.trigger(
|
|
3393
|
+
this,
|
|
3394
|
+
{
|
|
3395
|
+
file: 'meeting/index',
|
|
3396
|
+
function: 'setUpLocusInfoSelfListener',
|
|
3397
|
+
},
|
|
3398
|
+
EVENT_TRIGGERS.MEETING_SELF_BRB_UPDATE,
|
|
3399
|
+
{
|
|
3400
|
+
payload,
|
|
3401
|
+
}
|
|
3402
|
+
);
|
|
3403
|
+
});
|
|
3404
|
+
|
|
3364
3405
|
this.locusInfo.on(LOCUSINFO.EVENTS.SELF_ROLES_CHANGED, (payload) => {
|
|
3365
3406
|
const isModeratorOrCohost =
|
|
3366
3407
|
payload.newRoles?.includes(SELF_ROLES.MODERATOR) ||
|
|
@@ -3370,6 +3411,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3370
3411
|
payload.newRoles?.includes(SELF_ROLES.MODERATOR)
|
|
3371
3412
|
);
|
|
3372
3413
|
this.webinar.updateRoleChanged(payload);
|
|
3414
|
+
|
|
3373
3415
|
Trigger.trigger(
|
|
3374
3416
|
this,
|
|
3375
3417
|
{
|
|
@@ -3516,6 +3558,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3516
3558
|
emailAddress: string;
|
|
3517
3559
|
email: string;
|
|
3518
3560
|
phoneNumber: string;
|
|
3561
|
+
roles: Array<string>;
|
|
3519
3562
|
},
|
|
3520
3563
|
alertIfActive = true
|
|
3521
3564
|
) {
|
|
@@ -3563,6 +3606,50 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3563
3606
|
return this.members.admitMembers(memberIds, locusUrls);
|
|
3564
3607
|
}
|
|
3565
3608
|
|
|
3609
|
+
/**
|
|
3610
|
+
* Manages be right back status updates for the current participant.
|
|
3611
|
+
*
|
|
3612
|
+
* @param {boolean} enabled - Indicates whether the user enabled brb or not.
|
|
3613
|
+
* @returns {Promise<void>} resolves when the brb status is updated or does nothing if not in a multistream meeting.
|
|
3614
|
+
* @throws {Error} - Throws an error if the request fails.
|
|
3615
|
+
*/
|
|
3616
|
+
public async beRightBack(enabled: boolean): Promise<void> {
|
|
3617
|
+
if (!this.isMultistream) {
|
|
3618
|
+
const errorMessage = 'Meeting:index#beRightBack --> Not a multistream meeting';
|
|
3619
|
+
const error = new Error(errorMessage);
|
|
3620
|
+
|
|
3621
|
+
LoggerProxy.logger.error(error);
|
|
3622
|
+
|
|
3623
|
+
return Promise.reject(error);
|
|
3624
|
+
}
|
|
3625
|
+
|
|
3626
|
+
if (!this.mediaProperties.webrtcMediaConnection) {
|
|
3627
|
+
const errorMessage = 'Meeting:index#beRightBack --> WebRTC media connection is not defined';
|
|
3628
|
+
const error = new Error(errorMessage);
|
|
3629
|
+
|
|
3630
|
+
LoggerProxy.logger.error(error);
|
|
3631
|
+
|
|
3632
|
+
return Promise.reject(error);
|
|
3633
|
+
}
|
|
3634
|
+
|
|
3635
|
+
// this logic should be applied only to multistream meetings
|
|
3636
|
+
return this.meetingRequest
|
|
3637
|
+
.setBrb({
|
|
3638
|
+
enabled,
|
|
3639
|
+
locusUrl: this.locusUrl,
|
|
3640
|
+
deviceUrl: this.deviceUrl,
|
|
3641
|
+
selfId: this.selfId,
|
|
3642
|
+
})
|
|
3643
|
+
.then(() => {
|
|
3644
|
+
this.sendSlotManager.setSourceStateOverride(MediaType.VideoMain, enabled ? 'away' : null);
|
|
3645
|
+
})
|
|
3646
|
+
.catch((error) => {
|
|
3647
|
+
LoggerProxy.logger.error('Meeting:index#beRightBack --> Error ', error);
|
|
3648
|
+
|
|
3649
|
+
return Promise.reject(error);
|
|
3650
|
+
});
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3566
3653
|
/**
|
|
3567
3654
|
* Remove the member from the meeting, boot them
|
|
3568
3655
|
* @param {String} memberId
|
|
@@ -3772,6 +3859,10 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3772
3859
|
this.userDisplayHints,
|
|
3773
3860
|
this.selfUserPolicies
|
|
3774
3861
|
),
|
|
3862
|
+
isPremiseRecordingEnabled: RecordingUtil.isPremiseRecordingEnabled(
|
|
3863
|
+
this.userDisplayHints,
|
|
3864
|
+
this.selfUserPolicies
|
|
3865
|
+
),
|
|
3775
3866
|
canRaiseHand: MeetingUtil.canUserRaiseHand(this.userDisplayHints),
|
|
3776
3867
|
canLowerAllHands: MeetingUtil.canUserLowerAllHands(this.userDisplayHints),
|
|
3777
3868
|
canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(this.userDisplayHints),
|
|
@@ -3915,6 +4006,22 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
3915
4006
|
requiredHints: [DISPLAY_HINTS.DISABLE_STAGE_VIEW],
|
|
3916
4007
|
displayHints: this.userDisplayHints,
|
|
3917
4008
|
}),
|
|
4009
|
+
isPracticeSessionOn: ControlsOptionsUtil.hasHints({
|
|
4010
|
+
requiredHints: [DISPLAY_HINTS.PRACTICE_SESSION_ON],
|
|
4011
|
+
displayHints: this.userDisplayHints,
|
|
4012
|
+
}),
|
|
4013
|
+
isPracticeSessionOff: ControlsOptionsUtil.hasHints({
|
|
4014
|
+
requiredHints: [DISPLAY_HINTS.PRACTICE_SESSION_OFF],
|
|
4015
|
+
displayHints: this.userDisplayHints,
|
|
4016
|
+
}),
|
|
4017
|
+
canStartPracticeSession: ControlsOptionsUtil.hasHints({
|
|
4018
|
+
requiredHints: [DISPLAY_HINTS.SHOW_PRACTICE_SESSION_START],
|
|
4019
|
+
displayHints: this.userDisplayHints,
|
|
4020
|
+
}),
|
|
4021
|
+
canStopPracticeSession: ControlsOptionsUtil.hasHints({
|
|
4022
|
+
requiredHints: [DISPLAY_HINTS.SHOW_PRACTICE_SESSION_STOP],
|
|
4023
|
+
displayHints: this.userDisplayHints,
|
|
4024
|
+
}),
|
|
3918
4025
|
canShareFile:
|
|
3919
4026
|
(ControlsOptionsUtil.hasHints({
|
|
3920
4027
|
requiredHints: [DISPLAY_HINTS.SHARE_FILE],
|
|
@@ -4077,10 +4184,11 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
4077
4184
|
*/
|
|
4078
4185
|
private setLogUploadTimer() {
|
|
4079
4186
|
// start with short timeouts and increase them later on so in case users have very long multi-hour meetings we don't get too fragmented logs
|
|
4080
|
-
const LOG_UPLOAD_INTERVALS = [0.1,
|
|
4187
|
+
const LOG_UPLOAD_INTERVALS = [0.1, 15, 30, 60]; // in minutes
|
|
4081
4188
|
|
|
4082
4189
|
const delay =
|
|
4083
4190
|
1000 *
|
|
4191
|
+
60 *
|
|
4084
4192
|
// @ts-ignore - config coming from registerPlugin
|
|
4085
4193
|
this.config.logUploadIntervalMultiplicationFactor *
|
|
4086
4194
|
LOG_UPLOAD_INTERVALS[this.logUploadIntervalIndex];
|
|
@@ -5351,16 +5459,19 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5351
5459
|
this.meetingFiniteStateMachine.reset();
|
|
5352
5460
|
}
|
|
5353
5461
|
|
|
5354
|
-
//
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5462
|
+
// send client.call.initiated unless told not to
|
|
5463
|
+
if (options.sendCallInitiated !== false) {
|
|
5464
|
+
// @ts-ignore
|
|
5465
|
+
this.webex.internal.newMetrics.submitClientEvent({
|
|
5466
|
+
name: 'client.call.initiated',
|
|
5467
|
+
payload: {
|
|
5468
|
+
trigger: this.callStateForMetrics.joinTrigger || 'user-interaction',
|
|
5469
|
+
isRoapCallEnabled: true,
|
|
5470
|
+
pstnAudioType: options?.pstnAudioType,
|
|
5471
|
+
},
|
|
5472
|
+
options: {meetingId: this.id},
|
|
5473
|
+
});
|
|
5474
|
+
}
|
|
5364
5475
|
|
|
5365
5476
|
LoggerProxy.logger.log('Meeting:index#join --> Joining a meeting');
|
|
5366
5477
|
|
|
@@ -5548,17 +5659,23 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5548
5659
|
*/
|
|
5549
5660
|
async updateLLMConnection() {
|
|
5550
5661
|
// @ts-ignore - Fix type
|
|
5551
|
-
const {url, info: {datachannelUrl} = {}} = this.locusInfo;
|
|
5662
|
+
const {url, info: {datachannelUrl, practiceSessionDatachannelUrl} = {}} = this.locusInfo;
|
|
5552
5663
|
|
|
5553
5664
|
const isJoined = this.isJoined();
|
|
5554
5665
|
|
|
5666
|
+
// webinar panelist should use new data channel in practice session
|
|
5667
|
+
const dataChannelUrl =
|
|
5668
|
+
this.webinar.isJoinPracticeSessionDataChannel() && practiceSessionDatachannelUrl
|
|
5669
|
+
? practiceSessionDatachannelUrl
|
|
5670
|
+
: datachannelUrl;
|
|
5671
|
+
|
|
5555
5672
|
// @ts-ignore - Fix type
|
|
5556
5673
|
if (this.webex.internal.llm.isConnected()) {
|
|
5557
5674
|
if (
|
|
5558
5675
|
// @ts-ignore - Fix type
|
|
5559
5676
|
url === this.webex.internal.llm.getLocusUrl() &&
|
|
5560
5677
|
// @ts-ignore - Fix type
|
|
5561
|
-
|
|
5678
|
+
dataChannelUrl === this.webex.internal.llm.getDatachannelUrl() &&
|
|
5562
5679
|
isJoined
|
|
5563
5680
|
) {
|
|
5564
5681
|
return undefined;
|
|
@@ -5575,7 +5692,7 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
5575
5692
|
|
|
5576
5693
|
// @ts-ignore - Fix type
|
|
5577
5694
|
return this.webex.internal.llm
|
|
5578
|
-
.registerAndConnect(url,
|
|
5695
|
+
.registerAndConnect(url, dataChannelUrl)
|
|
5579
5696
|
.then((registerAndConnectResult) => {
|
|
5580
5697
|
// @ts-ignore - Fix type
|
|
5581
5698
|
this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
|
|
@@ -6414,6 +6531,14 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6414
6531
|
this.webex.meetings.geoHintInfo?.clientAddress ||
|
|
6415
6532
|
options.data.intervalMetadata.peerReflexiveIP ||
|
|
6416
6533
|
MQA_STATS.DEFAULT_IP;
|
|
6534
|
+
|
|
6535
|
+
const {members} = this.getMembers().membersCollection;
|
|
6536
|
+
|
|
6537
|
+
// Count members that are in the meeting
|
|
6538
|
+
options.data.intervalMetadata.meetingUserCount = Object.values(members).filter(
|
|
6539
|
+
(member: Member) => member.isInMeeting
|
|
6540
|
+
).length;
|
|
6541
|
+
|
|
6417
6542
|
// @ts-ignore
|
|
6418
6543
|
this.webex.internal.newMetrics.submitMQE({
|
|
6419
6544
|
name: 'client.mediaquality.event',
|
|
@@ -6745,32 +6870,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
6745
6870
|
}
|
|
6746
6871
|
}
|
|
6747
6872
|
|
|
6748
|
-
/**
|
|
6749
|
-
* Handles device logging
|
|
6750
|
-
*
|
|
6751
|
-
* @private
|
|
6752
|
-
* @static
|
|
6753
|
-
* @param {boolean} isAudioEnabled
|
|
6754
|
-
* @param {boolean} isVideoEnabled
|
|
6755
|
-
* @returns {Promise<void>}
|
|
6756
|
-
*/
|
|
6757
|
-
|
|
6758
|
-
private static async handleDeviceLogging(isAudioEnabled, isVideoEnabled): Promise<void> {
|
|
6759
|
-
try {
|
|
6760
|
-
let devices = [];
|
|
6761
|
-
if (isVideoEnabled && isAudioEnabled) {
|
|
6762
|
-
devices = await getDevices();
|
|
6763
|
-
} else if (isVideoEnabled) {
|
|
6764
|
-
devices = await getDevices(Media.DeviceKind.VIDEO_INPUT);
|
|
6765
|
-
} else if (isAudioEnabled) {
|
|
6766
|
-
devices = await getDevices(Media.DeviceKind.AUDIO_INPUT);
|
|
6767
|
-
}
|
|
6768
|
-
MeetingUtil.handleDeviceLogging(devices);
|
|
6769
|
-
} catch {
|
|
6770
|
-
// getDevices may fail if we don't have browser permissions, that's ok, we still can have a media connection
|
|
6771
|
-
}
|
|
6772
|
-
}
|
|
6773
|
-
|
|
6774
6873
|
/**
|
|
6775
6874
|
* Returns a promise. This promise is created once the local sdp offer has been successfully created and is resolved
|
|
6776
6875
|
* once the remote sdp answer has been received.
|
|
@@ -7273,12 +7372,6 @@ export default class Meeting extends StatelessWebexPlugin {
|
|
|
7273
7372
|
turnServerInfo
|
|
7274
7373
|
);
|
|
7275
7374
|
|
|
7276
|
-
if (audioEnabled || videoEnabled) {
|
|
7277
|
-
await Meeting.handleDeviceLogging(audioEnabled, videoEnabled);
|
|
7278
|
-
} else {
|
|
7279
|
-
LoggerProxy.logger.info(`${LOG_HEADER} device logging not required`);
|
|
7280
|
-
}
|
|
7281
|
-
|
|
7282
7375
|
if (this.mediaProperties.hasLocalShareStream()) {
|
|
7283
7376
|
await this.enqueueScreenShareFloorRequest();
|
|
7284
7377
|
}
|