@webex/plugin-meetings 3.0.0-beta.25 → 3.0.0-beta.27

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.
Files changed (46) hide show
  1. package/dist/breakouts/breakout.js +1 -1
  2. package/dist/breakouts/index.js +92 -2
  3. package/dist/breakouts/index.js.map +1 -1
  4. package/dist/constants.js +5 -1
  5. package/dist/constants.js.map +1 -1
  6. package/dist/controls-options-manager/constants.js +14 -0
  7. package/dist/controls-options-manager/constants.js.map +1 -0
  8. package/dist/controls-options-manager/enums.js +15 -0
  9. package/dist/controls-options-manager/enums.js.map +1 -0
  10. package/dist/controls-options-manager/index.js +203 -0
  11. package/dist/controls-options-manager/index.js.map +1 -0
  12. package/dist/controls-options-manager/util.js +28 -0
  13. package/dist/controls-options-manager/util.js.map +1 -0
  14. package/dist/meeting/in-meeting-actions.js +8 -0
  15. package/dist/meeting/in-meeting-actions.js.map +1 -1
  16. package/dist/meeting/index.js +61 -13
  17. package/dist/meeting/index.js.map +1 -1
  18. package/dist/meetings/util.js +17 -0
  19. package/dist/meetings/util.js.map +1 -1
  20. package/dist/types/constants.d.ts +4 -0
  21. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  22. package/dist/types/controls-options-manager/enums.d.ts +5 -0
  23. package/dist/types/controls-options-manager/index.d.ts +120 -0
  24. package/dist/types/controls-options-manager/util.d.ts +7 -0
  25. package/dist/types/meeting/in-meeting-actions.d.ts +8 -0
  26. package/dist/types/meeting/index.d.ts +18 -0
  27. package/package.json +18 -18
  28. package/src/breakouts/index.ts +73 -1
  29. package/src/constants.ts +4 -0
  30. package/src/controls-options-manager/constants.ts +5 -0
  31. package/src/controls-options-manager/enums.ts +6 -0
  32. package/src/controls-options-manager/index.ts +183 -0
  33. package/src/controls-options-manager/util.ts +20 -0
  34. package/src/meeting/in-meeting-actions.ts +16 -0
  35. package/src/meeting/index.ts +50 -0
  36. package/src/meetings/util.ts +24 -0
  37. package/test/integration/spec/converged-space-meetings.js +176 -0
  38. package/test/unit/spec/breakouts/index.ts +76 -0
  39. package/test/unit/spec/controls-options-manager/index.js +124 -0
  40. package/test/unit/spec/controls-options-manager/util.js +66 -0
  41. package/test/unit/spec/meeting/in-meeting-actions.ts +8 -0
  42. package/test/unit/spec/meeting/index.js +15 -0
  43. package/test/utils/constants.js +9 -0
  44. package/test/utils/testUtils.js +13 -6
  45. package/test/utils/webex-config.js +4 -0
  46. package/test/utils/webex-test-users.js +6 -3
@@ -62,11 +62,28 @@ MeetingsUtil.handleRoapMercury = function (envelope, meetingCollection) {
62
62
  errorType: errorType,
63
63
  errorCause: errorCause
64
64
  };
65
+ var mediaServer = MeetingsUtil.getMediaServer(roapMessage.sdp);
65
66
  meeting.mediaProperties.webrtcMediaConnection.roapMessageReceived(roapMessage);
67
+ if (mediaServer) {
68
+ meeting.mediaProperties.webrtcMediaConnection.mediaServer = mediaServer;
69
+ }
66
70
  }
67
71
  }
68
72
  }
69
73
  };
74
+ MeetingsUtil.getMediaServer = function (sdp) {
75
+ var mediaServer;
76
+
77
+ // Attempt to collect the media server from the roap message.
78
+ try {
79
+ mediaServer = sdp.split('\r\n').find(function (line) {
80
+ return line.startsWith('o=');
81
+ }).split(' ').shift().replace('o=', '');
82
+ } catch (_unused) {
83
+ mediaServer = undefined;
84
+ }
85
+ return mediaServer;
86
+ };
70
87
  MeetingsUtil.checkForCorrelationId = function (deviceUrl, locus) {
71
88
  var devices = [];
72
89
  if (locus) {
@@ -1 +1 @@
1
- {"version":3,"names":["MeetingsUtil","getMeetingAddedType","type","_LOCUS_ID_","_INCOMING_","_CREATED_","handleRoapMercury","envelope","meetingCollection","data","eventType","LOCUSEVENT","MESSAGE_ROAP","meeting","getByKey","CORRELATION_ID","correlationId","message","seq","messageType","tieBreaker","errorType","errorCause","ROAP","ROAP_TYPES","TURN_DISCOVERY_RESPONSE","roap","turnDiscovery","handleTurnDiscoveryResponse","roapMessage","sdp","sdps","length","undefined","mediaProperties","webrtcMediaConnection","roapMessageReceived","checkForCorrelationId","deviceUrl","locus","devices","self","foundDevice","find","device","url","parseDefaultSiteFromMeetingPreferences","userPreferences","result","sites","defaultSite","site","default","siteUrl","hasH264Codec","hasCodec","pc","window","RTCPeerConnection","createOffer","offerToReceiveVideo","offer","match","close","LoggerProxy","logger","warn","checkH264Support","options","firstChecked","disableNotifications","delay","maxDuration","shouldTrigger","shouldStopChecking","Trigger","trigger","file","function","EVENT_TRIGGERS","MEDIA_CODEC_LOADED","log","error","MEDIA_CODEC_MISSING","setTimeout","timestamp","call"],"sources":["util.ts"],"sourcesContent":["/* globals window */\n\nimport {\n _LOCUS_ID_,\n _INCOMING_,\n _CREATED_,\n LOCUSEVENT,\n CORRELATION_ID,\n EVENT_TRIGGERS,\n ROAP,\n} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport Trigger from '../common/events/trigger-proxy';\n\n/**\n * Meetings Media Codec Missing Event\n * Emitted when H.264 codec is not\n * found in the browser.\n * @event media:codec:missing\n * @instance\n * @memberof MeetingsUtil\n */\n\n/**\n * Meetings Media Codec Loaded Event\n * Emitted when H.264 codec has been\n * loaded in the browser.\n * @event media:codec:loaded\n * @instance\n * @memberof MeetingsUtil\n */\n\nconst MeetingsUtil: any = {};\n\nMeetingsUtil.getMeetingAddedType = (type) => (type === _LOCUS_ID_ ? _INCOMING_ : _CREATED_);\n\nMeetingsUtil.handleRoapMercury = (envelope, meetingCollection) => {\n const {data} = envelope;\n const {eventType} = data;\n\n if (eventType === LOCUSEVENT.MESSAGE_ROAP) {\n const meeting = meetingCollection.getByKey(CORRELATION_ID, data.correlationId);\n\n if (meeting) {\n const {seq, messageType, tieBreaker, errorType, errorCause} = data.message;\n\n if (messageType === ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {\n // turn discovery is not part of normal roap protocol and so we are not handling it\n // through the usual roap state machine\n meeting.roap.turnDiscovery.handleTurnDiscoveryResponse(data.message);\n } else {\n const roapMessage = {\n seq,\n messageType,\n sdp: data.message.sdps?.length > 0 ? data.message.sdps[0] : undefined,\n tieBreaker,\n errorType,\n errorCause,\n };\n\n meeting.mediaProperties.webrtcMediaConnection.roapMessageReceived(roapMessage);\n }\n }\n }\n};\n\nMeetingsUtil.checkForCorrelationId = (deviceUrl, locus) => {\n let devices = [];\n\n if (locus) {\n if (locus && locus.self && locus.self.devices) {\n devices = locus.self.devices;\n }\n\n const foundDevice = devices.find((device) => device.url === deviceUrl);\n\n if (foundDevice && foundDevice.correlationId) {\n return foundDevice.correlationId;\n }\n }\n\n return false;\n};\n\nMeetingsUtil.parseDefaultSiteFromMeetingPreferences = (userPreferences) => {\n let result = '';\n\n if (userPreferences && userPreferences.sites) {\n const defaultSite = userPreferences.sites.find((site) => site.default);\n\n if (defaultSite) {\n result = defaultSite.siteUrl;\n }\n }\n\n return result;\n};\n\n/**\n * Will check to see if the H.264 media codec is supported.\n * @async\n * @private\n * @returns {Promise<boolean>}\n */\nMeetingsUtil.hasH264Codec = async () => {\n let hasCodec = false;\n\n try {\n const pc = new window.RTCPeerConnection();\n const offer = await pc.createOffer({offerToReceiveVideo: true});\n\n if (offer.sdp.match(/^a=rtpmap:\\d+\\s+H264\\/\\d+/m)) {\n hasCodec = true;\n }\n pc.close();\n } catch (error) {\n LoggerProxy.logger.warn(\n 'Meetings:util#hasH264Codec --> Error creating peerConnection for H.264 test.'\n );\n }\n\n return hasCodec;\n};\n\n/**\n * Notifies the user whether or not the H.264\n * codec is present. Will continuously check\n * until max duration.\n * @async\n * @private\n * @param {object} options\n * @param {Number} options.firstChecked Timestamp in milliseconds\n * @param {boolean} options.disableNotifications Default is false. Boolean to enable/disable notification and events\n * @returns {undefined}\n */\nMeetingsUtil.checkH264Support = async function checkH264Support(options: {\n firstChecked: number;\n disableNotifications: boolean;\n}) {\n const {hasH264Codec} = MeetingsUtil;\n const {firstChecked, disableNotifications} = options || {};\n const delay = 5e3; // ms\n const maxDuration = 3e5; // ms\n const shouldTrigger = firstChecked === undefined;\n const shouldStopChecking = firstChecked && Date.now() - firstChecked >= maxDuration;\n\n // Disable notifications and start H.264 download only\n if (disableNotifications) {\n hasH264Codec();\n\n return;\n }\n\n // Codec loaded trigger event notification\n if (await hasH264Codec()) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_LOADED\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec loaded successfully.');\n\n return;\n }\n\n // Stop checking if past the timelimit\n if (shouldStopChecking) {\n LoggerProxy.logger.error(\n 'Meetings:util#checkH264Support --> Timed out waiting for H264 codec to load.'\n );\n\n return;\n }\n\n // Trigger only once\n if (shouldTrigger) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_MISSING\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec is missing.');\n }\n\n // Keep checking in intervals to see if codec loaded\n window.setTimeout(() => {\n const timestamp = firstChecked || Date.now();\n\n MeetingsUtil.checkH264Support.call(this, {firstChecked: timestamp});\n }, delay);\n};\n\nexport default MeetingsUtil;\n"],"mappings":"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"}
1
+ {"version":3,"names":["MeetingsUtil","getMeetingAddedType","type","_LOCUS_ID_","_INCOMING_","_CREATED_","handleRoapMercury","envelope","meetingCollection","data","eventType","LOCUSEVENT","MESSAGE_ROAP","meeting","getByKey","CORRELATION_ID","correlationId","message","seq","messageType","tieBreaker","errorType","errorCause","ROAP","ROAP_TYPES","TURN_DISCOVERY_RESPONSE","roap","turnDiscovery","handleTurnDiscoveryResponse","roapMessage","sdp","sdps","length","undefined","mediaServer","getMediaServer","mediaProperties","webrtcMediaConnection","roapMessageReceived","split","find","line","startsWith","shift","replace","checkForCorrelationId","deviceUrl","locus","devices","self","foundDevice","device","url","parseDefaultSiteFromMeetingPreferences","userPreferences","result","sites","defaultSite","site","default","siteUrl","hasH264Codec","hasCodec","pc","window","RTCPeerConnection","createOffer","offerToReceiveVideo","offer","match","close","LoggerProxy","logger","warn","checkH264Support","options","firstChecked","disableNotifications","delay","maxDuration","shouldTrigger","shouldStopChecking","Trigger","trigger","file","function","EVENT_TRIGGERS","MEDIA_CODEC_LOADED","log","error","MEDIA_CODEC_MISSING","setTimeout","timestamp","call"],"sources":["util.ts"],"sourcesContent":["/* globals window */\n\nimport {\n _LOCUS_ID_,\n _INCOMING_,\n _CREATED_,\n LOCUSEVENT,\n CORRELATION_ID,\n EVENT_TRIGGERS,\n ROAP,\n} from '../constants';\nimport LoggerProxy from '../common/logs/logger-proxy';\nimport Trigger from '../common/events/trigger-proxy';\n\n/**\n * Meetings Media Codec Missing Event\n * Emitted when H.264 codec is not\n * found in the browser.\n * @event media:codec:missing\n * @instance\n * @memberof MeetingsUtil\n */\n\n/**\n * Meetings Media Codec Loaded Event\n * Emitted when H.264 codec has been\n * loaded in the browser.\n * @event media:codec:loaded\n * @instance\n * @memberof MeetingsUtil\n */\n\nconst MeetingsUtil: any = {};\n\nMeetingsUtil.getMeetingAddedType = (type) => (type === _LOCUS_ID_ ? _INCOMING_ : _CREATED_);\n\nMeetingsUtil.handleRoapMercury = (envelope, meetingCollection) => {\n const {data} = envelope;\n const {eventType} = data;\n\n if (eventType === LOCUSEVENT.MESSAGE_ROAP) {\n const meeting = meetingCollection.getByKey(CORRELATION_ID, data.correlationId);\n\n if (meeting) {\n const {seq, messageType, tieBreaker, errorType, errorCause} = data.message;\n\n if (messageType === ROAP.ROAP_TYPES.TURN_DISCOVERY_RESPONSE) {\n // turn discovery is not part of normal roap protocol and so we are not handling it\n // through the usual roap state machine\n meeting.roap.turnDiscovery.handleTurnDiscoveryResponse(data.message);\n } else {\n const roapMessage = {\n seq,\n messageType,\n sdp: data.message.sdps?.length > 0 ? data.message.sdps[0] : undefined,\n tieBreaker,\n errorType,\n errorCause,\n };\n\n const mediaServer = MeetingsUtil.getMediaServer(roapMessage.sdp);\n\n meeting.mediaProperties.webrtcMediaConnection.roapMessageReceived(roapMessage);\n\n if (mediaServer) {\n meeting.mediaProperties.webrtcMediaConnection.mediaServer = mediaServer;\n }\n }\n }\n }\n};\n\nMeetingsUtil.getMediaServer = (sdp) => {\n let mediaServer;\n\n // Attempt to collect the media server from the roap message.\n try {\n mediaServer = sdp\n .split('\\r\\n')\n .find((line) => line.startsWith('o='))\n .split(' ')\n .shift()\n .replace('o=', '');\n } catch {\n mediaServer = undefined;\n }\n\n return mediaServer;\n};\n\nMeetingsUtil.checkForCorrelationId = (deviceUrl, locus) => {\n let devices = [];\n\n if (locus) {\n if (locus && locus.self && locus.self.devices) {\n devices = locus.self.devices;\n }\n\n const foundDevice = devices.find((device) => device.url === deviceUrl);\n\n if (foundDevice && foundDevice.correlationId) {\n return foundDevice.correlationId;\n }\n }\n\n return false;\n};\n\nMeetingsUtil.parseDefaultSiteFromMeetingPreferences = (userPreferences) => {\n let result = '';\n\n if (userPreferences && userPreferences.sites) {\n const defaultSite = userPreferences.sites.find((site) => site.default);\n\n if (defaultSite) {\n result = defaultSite.siteUrl;\n }\n }\n\n return result;\n};\n\n/**\n * Will check to see if the H.264 media codec is supported.\n * @async\n * @private\n * @returns {Promise<boolean>}\n */\nMeetingsUtil.hasH264Codec = async () => {\n let hasCodec = false;\n\n try {\n const pc = new window.RTCPeerConnection();\n const offer = await pc.createOffer({offerToReceiveVideo: true});\n\n if (offer.sdp.match(/^a=rtpmap:\\d+\\s+H264\\/\\d+/m)) {\n hasCodec = true;\n }\n pc.close();\n } catch (error) {\n LoggerProxy.logger.warn(\n 'Meetings:util#hasH264Codec --> Error creating peerConnection for H.264 test.'\n );\n }\n\n return hasCodec;\n};\n\n/**\n * Notifies the user whether or not the H.264\n * codec is present. Will continuously check\n * until max duration.\n * @async\n * @private\n * @param {object} options\n * @param {Number} options.firstChecked Timestamp in milliseconds\n * @param {boolean} options.disableNotifications Default is false. Boolean to enable/disable notification and events\n * @returns {undefined}\n */\nMeetingsUtil.checkH264Support = async function checkH264Support(options: {\n firstChecked: number;\n disableNotifications: boolean;\n}) {\n const {hasH264Codec} = MeetingsUtil;\n const {firstChecked, disableNotifications} = options || {};\n const delay = 5e3; // ms\n const maxDuration = 3e5; // ms\n const shouldTrigger = firstChecked === undefined;\n const shouldStopChecking = firstChecked && Date.now() - firstChecked >= maxDuration;\n\n // Disable notifications and start H.264 download only\n if (disableNotifications) {\n hasH264Codec();\n\n return;\n }\n\n // Codec loaded trigger event notification\n if (await hasH264Codec()) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_LOADED\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec loaded successfully.');\n\n return;\n }\n\n // Stop checking if past the timelimit\n if (shouldStopChecking) {\n LoggerProxy.logger.error(\n 'Meetings:util#checkH264Support --> Timed out waiting for H264 codec to load.'\n );\n\n return;\n }\n\n // Trigger only once\n if (shouldTrigger) {\n Trigger.trigger(\n this,\n {\n file: 'meetings/util',\n function: 'checkH264Support',\n },\n EVENT_TRIGGERS.MEDIA_CODEC_MISSING\n );\n LoggerProxy.logger.log('Meetings:util#checkH264Support --> H264 codec is missing.');\n }\n\n // Keep checking in intervals to see if codec loaded\n window.setTimeout(() => {\n const timestamp = firstChecked || Date.now();\n\n MeetingsUtil.checkH264Support.call(this, {firstChecked: timestamp});\n }, delay);\n};\n\nexport default MeetingsUtil;\n"],"mappings":"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"}
@@ -595,6 +595,10 @@ export declare const DISPLAY_HINTS: {
595
595
  DISABLE_REACTIONS: string;
596
596
  REACTIONS_ACTIVE: string;
597
597
  REACTIONS_INACTIVE: string;
598
+ ENABLE_MUTE_ON_ENTRY: string;
599
+ DISABLE_MUTE_ON_ENTRY: string;
600
+ ENABLE_HARD_MUTE: string;
601
+ DISABLE_HARD_MUTE: string;
598
602
  };
599
603
  export declare const SELF_ROLES: {
600
604
  COHOST: string;
@@ -0,0 +1,4 @@
1
+ declare const ENABLED = "enabled";
2
+ declare const CAN_SET = "canSet";
3
+ declare const CAN_UNSET = "canUnset";
4
+ export { ENABLED, CAN_SET, CAN_UNSET };
@@ -0,0 +1,5 @@
1
+ declare enum Setting {
2
+ disallowUnmute = "DisallowUnmute",
3
+ muteOnEntry = "MuteOnEntry"
4
+ }
5
+ export default Setting;
@@ -0,0 +1,120 @@
1
+ import MeetingRequest from '../meeting/request';
2
+ /**
3
+ * docs
4
+ * https://sqbu-github.cisco.com/pages/WebExSquared/locus/guides/mute.html
5
+ * https://confluence-eng-gpk2.cisco.com/conf/display/LOCUS/Hard+Mute+and+Audio+Privacy#HardMuteandAudioPrivacy-SelfMuteonEntry
6
+ * https://confluence-eng-gpk2.cisco.com/conf/pages/viewpage.action?spaceKey=UC&title=WEBEX-124454%3A+UCF%3A+Hard+mute+support+for+Teams+joining+Webex+meeting
7
+ * https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-180867
8
+ * https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-393351
9
+ */
10
+ /**
11
+ * @description ControlsOptionsManager is responsible for handling the behavior of participant controls when somebody joins a meeting
12
+ * @export
13
+ * @private
14
+ * @class Recording
15
+ */
16
+ export default class ControlsOptionsManager {
17
+ /**
18
+ * @instance
19
+ * @type {MeetingRequest}
20
+ * @private
21
+ * @memberof ControlsOptionsManager
22
+ */
23
+ private request;
24
+ /**
25
+ * @instance
26
+ * @type {Array}
27
+ * @private
28
+ * @memberof ControlsOptionsManager
29
+ */
30
+ private displayHints;
31
+ /**
32
+ * @instance
33
+ * @type {string}
34
+ * @private
35
+ * @memberof ControlsOptionsManager
36
+ */
37
+ private locusUrl;
38
+ /**
39
+ * @param {MeetingRequest} request
40
+ * @param {Object} options
41
+ * @constructor
42
+ * @memberof ControlsOptionsManager
43
+ */
44
+ constructor(request: MeetingRequest, options?: {
45
+ locusUrl: string;
46
+ displayHints?: Array<string>;
47
+ });
48
+ /**
49
+ * @param {MeetingRequest} request
50
+ * @returns {void}
51
+ * @private
52
+ * @memberof ControlsOptionsManager
53
+ */
54
+ private initialize;
55
+ /**
56
+ * @param {Object} options
57
+ * @returns {void}
58
+ * @public
59
+ * @memberof ControlsOptionsManager
60
+ */
61
+ set(options?: {
62
+ locusUrl: string;
63
+ displayHints?: Array<string>;
64
+ }): void;
65
+ /**
66
+ * @param {string} url
67
+ * @returns {void}
68
+ * @public
69
+ * @memberof ControlsOptionsManager
70
+ */
71
+ setLocusUrl(url: string): void;
72
+ /**
73
+ * @param {Array} hints
74
+ * @returns {void}
75
+ * @public
76
+ * @memberof ControlsOptionsManager
77
+ */
78
+ setDisplayHints(hints: Array<string>): void;
79
+ /**
80
+ * @returns {string}
81
+ * @public
82
+ * @memberof ControlsOptionsManager
83
+ */
84
+ getLocusUrl(): string;
85
+ /**
86
+ * @returns {Array}
87
+ * @public
88
+ * @memberof ControlsOptionsManager
89
+ */
90
+ getDisplayHints(): string[];
91
+ /**
92
+ * @param {Object} options
93
+ * @returns {void}
94
+ * @private
95
+ * @memberof ControlsOptionsManager
96
+ */
97
+ private extract;
98
+ /**
99
+ * @param {Setting} setting
100
+ * @param {boolean} enabled
101
+ * @private
102
+ * @memberof ControlsOptionsManager
103
+ * @returns {Promise}
104
+ */
105
+ private setControls;
106
+ /**
107
+ * @public
108
+ * @param {boolean} enabled
109
+ * @memberof ControlsOptionsManager
110
+ * @returns {Promise}
111
+ */
112
+ setMuteOnEntry(enabled: boolean): Promise<any>;
113
+ /**
114
+ * @public
115
+ * @param {boolean} enabled
116
+ * @memberof ControlsOptionsManager
117
+ * @returns {Promise}
118
+ */
119
+ setDisallowUnmute(enabled: boolean): Promise<any>;
120
+ }
@@ -0,0 +1,7 @@
1
+ declare const _default: {
2
+ canSetMuteOnEntry: (displayHints: string[]) => boolean;
3
+ canSetDisallowUnmute: (displayHints: string[]) => boolean;
4
+ canUnsetMuteOnEntry: (displayHints: string[]) => boolean;
5
+ canUnsetDisallowUnmute: (displayHints: string[]) => boolean;
6
+ };
7
+ export default _default;
@@ -10,6 +10,10 @@ interface IInMeetingActions {
10
10
  canAdmitParticipant?: boolean;
11
11
  canLock?: boolean;
12
12
  canUnlock?: boolean;
13
+ canSetMuteOnEntry?: boolean;
14
+ canUnsetMuteOnEntry?: boolean;
15
+ canSetDisallowUnmute?: boolean;
16
+ canUnsetDisallowUnmute?: boolean;
13
17
  canAssignHost?: boolean;
14
18
  canStartRecording?: boolean;
15
19
  canPauseRecording?: boolean;
@@ -45,6 +49,10 @@ export default class InMeetingActions implements IInMeetingActions {
45
49
  canPauseRecording: any;
46
50
  canResumeRecording: any;
47
51
  canStopRecording: any;
52
+ canSetMuteOnEntry: any;
53
+ canUnsetMuteOnEntry: any;
54
+ canSetDisallowUnmute: any;
55
+ canUnsetDisallowUnmute: any;
48
56
  canRaiseHand: any;
49
57
  canLowerAllHands: any;
50
58
  canLowerSomeoneElsesHand: any;
@@ -14,6 +14,7 @@ import { RemoteMediaManager } from '../multistream/remoteMediaManager';
14
14
  import { ReactionServerType, SkinToneType } from '../reactions/reactions.type';
15
15
  import InMeetingActions from './in-meeting-actions';
16
16
  import RecordingController from '../recording-controller';
17
+ import ControlsOptionsManager from '../controls-options-manager';
17
18
  export declare const MEDIA_UPDATE_TYPE: {
18
19
  ALL: string;
19
20
  AUDIO: string;
@@ -345,6 +346,7 @@ export default class Meeting extends StatelessWebexPlugin {
345
346
  recording: any;
346
347
  remoteMediaManager: RemoteMediaManager | null;
347
348
  recordingController: RecordingController;
349
+ controlsOptionsManager: ControlsOptionsManager;
348
350
  requiredCaptcha: any;
349
351
  receiveSlotManager: ReceiveSlotManager;
350
352
  shareStatus: string;
@@ -1378,6 +1380,22 @@ export default class Meeting extends StatelessWebexPlugin {
1378
1380
  * @memberof Meeting
1379
1381
  */
1380
1382
  startRecording(): Promise<any>;
1383
+ /**
1384
+ * set the mute on entry flag for participants if you're the host
1385
+ * @returns {Promise}
1386
+ * @param {boolean} enabled
1387
+ * @public
1388
+ * @memberof Meeting
1389
+ */
1390
+ setMuteOnEntry(enabled: boolean): Promise<any>;
1391
+ /**
1392
+ * set the disallow unmute flag for participants if you're the host
1393
+ * @returns {Promise}
1394
+ * @param {boolean} enabled
1395
+ * @public
1396
+ * @memberof Meeting
1397
+ */
1398
+ setDisallowUnmute(enabled: boolean): Promise<any>;
1381
1399
  /**
1382
1400
  * End the recording of this meeting
1383
1401
  * @returns {Promise}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webex/plugin-meetings",
3
- "version": "3.0.0-beta.25",
3
+ "version": "3.0.0-beta.27",
4
4
  "description": "",
5
5
  "license": "Cisco EULA (https://www.cisco.com/c/en/us/products/end-user-license-agreement.html)",
6
6
  "contributors": [
@@ -32,12 +32,12 @@
32
32
  "build": "yarn run -T tsc --declaration true --declarationDir ./dist/types"
33
33
  },
34
34
  "devDependencies": {
35
- "@webex/plugin-meetings": "3.0.0-beta.25",
36
- "@webex/test-helper-chai": "3.0.0-beta.25",
37
- "@webex/test-helper-mocha": "3.0.0-beta.25",
38
- "@webex/test-helper-mock-webex": "3.0.0-beta.25",
39
- "@webex/test-helper-retry": "3.0.0-beta.25",
40
- "@webex/test-helper-test-users": "3.0.0-beta.25",
35
+ "@webex/plugin-meetings": "3.0.0-beta.27",
36
+ "@webex/test-helper-chai": "3.0.0-beta.27",
37
+ "@webex/test-helper-mocha": "3.0.0-beta.27",
38
+ "@webex/test-helper-mock-webex": "3.0.0-beta.27",
39
+ "@webex/test-helper-retry": "3.0.0-beta.27",
40
+ "@webex/test-helper-test-users": "3.0.0-beta.27",
41
41
  "chai": "^4.3.4",
42
42
  "chai-as-promised": "^7.1.1",
43
43
  "jsdom-global": "3.0.2",
@@ -45,18 +45,18 @@
45
45
  "typed-emitter": "^2.1.0"
46
46
  },
47
47
  "dependencies": {
48
- "@webex/common": "3.0.0-beta.25",
48
+ "@webex/common": "3.0.0-beta.27",
49
49
  "@webex/internal-media-core": "1.33.2",
50
- "@webex/internal-plugin-conversation": "3.0.0-beta.25",
51
- "@webex/internal-plugin-device": "3.0.0-beta.25",
52
- "@webex/internal-plugin-llm": "3.0.0-beta.25",
53
- "@webex/internal-plugin-mercury": "3.0.0-beta.25",
54
- "@webex/internal-plugin-metrics": "3.0.0-beta.25",
55
- "@webex/internal-plugin-support": "3.0.0-beta.25",
56
- "@webex/internal-plugin-user": "3.0.0-beta.25",
57
- "@webex/plugin-people": "3.0.0-beta.25",
58
- "@webex/plugin-rooms": "3.0.0-beta.25",
59
- "@webex/webex-core": "3.0.0-beta.25",
50
+ "@webex/internal-plugin-conversation": "3.0.0-beta.27",
51
+ "@webex/internal-plugin-device": "3.0.0-beta.27",
52
+ "@webex/internal-plugin-llm": "3.0.0-beta.27",
53
+ "@webex/internal-plugin-mercury": "3.0.0-beta.27",
54
+ "@webex/internal-plugin-metrics": "3.0.0-beta.27",
55
+ "@webex/internal-plugin-support": "3.0.0-beta.27",
56
+ "@webex/internal-plugin-user": "3.0.0-beta.27",
57
+ "@webex/plugin-people": "3.0.0-beta.27",
58
+ "@webex/plugin-rooms": "3.0.0-beta.27",
59
+ "@webex/webex-core": "3.0.0-beta.27",
60
60
  "ampersand-collection": "^2.0.2",
61
61
  "bowser": "^2.11.0",
62
62
  "btoa": "^1.2.1",
@@ -5,7 +5,7 @@ import {WebexPlugin} from '@webex/webex-core';
5
5
  import {debounce, forEach} from 'lodash';
6
6
  import LoggerProxy from '../common/logs/logger-proxy';
7
7
 
8
- import {BREAKOUTS, MEETINGS} from '../constants';
8
+ import {BREAKOUTS, MEETINGS, HTTP_VERBS} from '../constants';
9
9
 
10
10
  import Breakout from './breakout';
11
11
  import BreakoutCollection from './collection';
@@ -32,6 +32,7 @@ const Breakouts = WebexPlugin.extend({
32
32
  status: 'string', // only present when in a breakout session
33
33
  url: 'string', // appears from the moment you enable breakouts
34
34
  locusUrl: 'string', // the current locus url
35
+ breakoutServiceUrl: 'string', // the current breakout resouce url
35
36
  },
36
37
 
37
38
  children: {
@@ -89,6 +90,15 @@ const Breakouts = WebexPlugin.extend({
89
90
  this.set('locusUrl', locusUrl);
90
91
  },
91
92
 
93
+ /**
94
+ * Update the current breakout resouce url
95
+ * @param {string} breakoutServiceUrl
96
+ * @returns {void}
97
+ */
98
+ breakoutServiceUrlUpdate(breakoutServiceUrl) {
99
+ this.set('breakoutServiceUrl', `${breakoutServiceUrl}/breakout/`);
100
+ },
101
+
92
102
  /**
93
103
  * The initial roster lists need to be queried because you don't
94
104
  * get a breakout.roster event when you join the meeting
@@ -184,6 +194,8 @@ const Breakouts = WebexPlugin.extend({
184
194
  [BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT]: false,
185
195
  [BREAKOUTS.SESSION_STATES.REQUESTED]: false,
186
196
  });
197
+
198
+ this.set('enableBreakoutSession', params.enableBreakoutSession);
187
199
  },
188
200
 
189
201
  /**
@@ -220,6 +232,66 @@ const Breakouts = WebexPlugin.extend({
220
232
 
221
233
  this.breakouts.set(Object.values(breakouts));
222
234
  },
235
+
236
+ /**
237
+ * Make enable breakout resource
238
+ * @returns {Promise}
239
+ */
240
+ enableBreakouts() {
241
+ if (this.breakoutServiceUrl) {
242
+ // @ts-ignore
243
+ return this.webex
244
+ .request({
245
+ method: HTTP_VERBS.POST,
246
+ uri: this.breakoutServiceUrl,
247
+ body: {
248
+ locusUrl: this.locusUrl,
249
+ },
250
+ })
251
+ .catch((err) => {
252
+ LoggerProxy.logger.error(
253
+ `Meeting:request#touchBreakout --> Error provisioning error ${err}`
254
+ );
255
+ throw err;
256
+ });
257
+ }
258
+
259
+ return Promise.reject(new Error(`enableBreakouts: the breakoutServiceUrl is empty`));
260
+ },
261
+
262
+ /**
263
+ * Make the meeting enbale or disable breakout session
264
+ * @param {boolean} enable
265
+ * @returns {Promise}
266
+ */
267
+ async toggleBreakout(enable) {
268
+ if (this.enableBreakoutSession === undefined) {
269
+ const info = await this.enableBreakouts();
270
+ if (!enable) {
271
+ // if enable is false, updateBreakout set the param then set enableBreakoutSession as false
272
+ this.updateBreakout(info.body);
273
+ await this.doToggleBreakout(enable);
274
+ }
275
+ } else {
276
+ await this.doToggleBreakout(enable);
277
+ }
278
+ },
279
+
280
+ /**
281
+ * do toggle meeting breakout session enable or disable
282
+ * @param {boolean} enable
283
+ * @returns {Promise}
284
+ */
285
+ doToggleBreakout(enable) {
286
+ // @ts-ignore
287
+ return this.webex.request({
288
+ method: HTTP_VERBS.PUT,
289
+ uri: this.url,
290
+ body: {
291
+ enableBreakoutSession: enable,
292
+ },
293
+ });
294
+ },
223
295
  });
224
296
 
225
297
  export default Breakouts;
package/src/constants.ts CHANGED
@@ -761,6 +761,10 @@ export const DISPLAY_HINTS = {
761
761
  DISABLE_REACTIONS: 'DISABLE_REACTIONS',
762
762
  REACTIONS_ACTIVE: 'REACTIONS_ACTIVE',
763
763
  REACTIONS_INACTIVE: 'REACTIONS_INACTIVE',
764
+ ENABLE_MUTE_ON_ENTRY: 'ENABLE_MUTE_ON_ENTRY',
765
+ DISABLE_MUTE_ON_ENTRY: 'DISABLE_MUTE_ON_ENTRY',
766
+ ENABLE_HARD_MUTE: 'ENABLE_HARD_MUTE',
767
+ DISABLE_HARD_MUTE: 'DISABLE_HARD_MUTE',
764
768
  };
765
769
 
766
770
  export const SELF_ROLES = {
@@ -0,0 +1,5 @@
1
+ const ENABLED = 'enabled';
2
+ const CAN_SET = 'canSet';
3
+ const CAN_UNSET = 'canUnset';
4
+
5
+ export {ENABLED, CAN_SET, CAN_UNSET};
@@ -0,0 +1,6 @@
1
+ enum Setting {
2
+ disallowUnmute = 'DisallowUnmute',
3
+ muteOnEntry = 'MuteOnEntry',
4
+ }
5
+
6
+ export default Setting;
@@ -0,0 +1,183 @@
1
+ import {camelCase} from 'lodash';
2
+ import PermissionError from '../common/errors/permission';
3
+ import {CONTROLS, HTTP_VERBS} from '../constants';
4
+ import MeetingRequest from '../meeting/request';
5
+ import LoggerProxy from '../common/logs/logger-proxy';
6
+ import Setting from './enums';
7
+ import Util from './util';
8
+ import {CAN_SET, CAN_UNSET, ENABLED} from './constants';
9
+
10
+ /**
11
+ * docs
12
+ * https://sqbu-github.cisco.com/pages/WebExSquared/locus/guides/mute.html
13
+ * https://confluence-eng-gpk2.cisco.com/conf/display/LOCUS/Hard+Mute+and+Audio+Privacy#HardMuteandAudioPrivacy-SelfMuteonEntry
14
+ * https://confluence-eng-gpk2.cisco.com/conf/pages/viewpage.action?spaceKey=UC&title=WEBEX-124454%3A+UCF%3A+Hard+mute+support+for+Teams+joining+Webex+meeting
15
+ * https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-180867
16
+ * https://jira-eng-gpk2.cisco.com/jira/browse/SPARK-393351
17
+ */
18
+
19
+ /**
20
+ * @description ControlsOptionsManager is responsible for handling the behavior of participant controls when somebody joins a meeting
21
+ * @export
22
+ * @private
23
+ * @class Recording
24
+ */
25
+ export default class ControlsOptionsManager {
26
+ /**
27
+ * @instance
28
+ * @type {MeetingRequest}
29
+ * @private
30
+ * @memberof ControlsOptionsManager
31
+ */
32
+ private request: MeetingRequest;
33
+
34
+ /**
35
+ * @instance
36
+ * @type {Array}
37
+ * @private
38
+ * @memberof ControlsOptionsManager
39
+ */
40
+ private displayHints: Array<string> = [];
41
+
42
+ /**
43
+ * @instance
44
+ * @type {string}
45
+ * @private
46
+ * @memberof ControlsOptionsManager
47
+ */
48
+ private locusUrl: string;
49
+
50
+ /**
51
+ * @param {MeetingRequest} request
52
+ * @param {Object} options
53
+ * @constructor
54
+ * @memberof ControlsOptionsManager
55
+ */
56
+ constructor(
57
+ request: MeetingRequest,
58
+ options?: {
59
+ locusUrl: string;
60
+ displayHints?: Array<string>;
61
+ }
62
+ ) {
63
+ this.initialize(request);
64
+ this.set(options);
65
+ }
66
+
67
+ /**
68
+ * @param {MeetingRequest} request
69
+ * @returns {void}
70
+ * @private
71
+ * @memberof ControlsOptionsManager
72
+ */
73
+ private initialize(request: MeetingRequest) {
74
+ this.request = request;
75
+ }
76
+
77
+ /**
78
+ * @param {Object} options
79
+ * @returns {void}
80
+ * @public
81
+ * @memberof ControlsOptionsManager
82
+ */
83
+ public set(options?: {locusUrl: string; displayHints?: Array<string>}) {
84
+ this.extract(options);
85
+ }
86
+
87
+ /**
88
+ * @param {string} url
89
+ * @returns {void}
90
+ * @public
91
+ * @memberof ControlsOptionsManager
92
+ */
93
+ public setLocusUrl(url: string) {
94
+ this.locusUrl = url;
95
+ }
96
+
97
+ /**
98
+ * @param {Array} hints
99
+ * @returns {void}
100
+ * @public
101
+ * @memberof ControlsOptionsManager
102
+ */
103
+ public setDisplayHints(hints: Array<string>) {
104
+ this.displayHints = hints;
105
+ }
106
+
107
+ /**
108
+ * @returns {string}
109
+ * @public
110
+ * @memberof ControlsOptionsManager
111
+ */
112
+ public getLocusUrl() {
113
+ return this.locusUrl;
114
+ }
115
+
116
+ /**
117
+ * @returns {Array}
118
+ * @public
119
+ * @memberof ControlsOptionsManager
120
+ */
121
+ public getDisplayHints() {
122
+ return this.displayHints;
123
+ }
124
+
125
+ /**
126
+ * @param {Object} options
127
+ * @returns {void}
128
+ * @private
129
+ * @memberof ControlsOptionsManager
130
+ */
131
+ private extract(options?: {locusUrl: string; displayHints?: Array<string>}) {
132
+ this.setDisplayHints(options?.displayHints);
133
+ this.setLocusUrl(options?.locusUrl);
134
+ }
135
+
136
+ /**
137
+ * @param {Setting} setting
138
+ * @param {boolean} enabled
139
+ * @private
140
+ * @memberof ControlsOptionsManager
141
+ * @returns {Promise}
142
+ */
143
+ private setControls(setting: Setting, enabled: boolean): Promise<any> {
144
+ LoggerProxy.logger.log(`ControlsOptionsManager:index#setControls --> ${setting} [${enabled}]`);
145
+
146
+ if (Util?.[`${enabled ? CAN_SET : CAN_UNSET}${setting}`](this.displayHints)) {
147
+ // @ts-ignore
148
+ return this.request.request({
149
+ uri: `${this.locusUrl}/${CONTROLS}`,
150
+ body: {
151
+ [camelCase(setting)]: {
152
+ [ENABLED]: enabled,
153
+ },
154
+ },
155
+ method: HTTP_VERBS.PATCH,
156
+ });
157
+ }
158
+
159
+ return Promise.reject(
160
+ new PermissionError(`${setting} [${enabled}] not allowed, due to moderator property.`)
161
+ );
162
+ }
163
+
164
+ /**
165
+ * @public
166
+ * @param {boolean} enabled
167
+ * @memberof ControlsOptionsManager
168
+ * @returns {Promise}
169
+ */
170
+ public setMuteOnEntry(enabled: boolean): Promise<any> {
171
+ return this.setControls(Setting.muteOnEntry, enabled);
172
+ }
173
+
174
+ /**
175
+ * @public
176
+ * @param {boolean} enabled
177
+ * @memberof ControlsOptionsManager
178
+ * @returns {Promise}
179
+ */
180
+ public setDisallowUnmute(enabled: boolean): Promise<any> {
181
+ return this.setControls(Setting.disallowUnmute, enabled);
182
+ }
183
+ }