@webex/plugin-meetings 3.0.0-beta.13 → 3.0.0-beta.15

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 (252) hide show
  1. package/UPGRADING.md +9 -9
  2. package/browsers.js +19 -24
  3. package/dist/common/browser-detection.js +1 -0
  4. package/dist/common/browser-detection.js.map +1 -1
  5. package/dist/common/collection.js.map +1 -1
  6. package/dist/common/errors/captcha-error.js +5 -5
  7. package/dist/common/errors/captcha-error.js.map +1 -1
  8. package/dist/common/errors/intent-to-join.js +5 -5
  9. package/dist/common/errors/intent-to-join.js.map +1 -1
  10. package/dist/common/errors/join-meeting.js +6 -6
  11. package/dist/common/errors/join-meeting.js.map +1 -1
  12. package/dist/common/errors/media.js +5 -5
  13. package/dist/common/errors/media.js.map +1 -1
  14. package/dist/common/errors/parameter.js +5 -5
  15. package/dist/common/errors/parameter.js.map +1 -1
  16. package/dist/common/errors/password-error.js +5 -5
  17. package/dist/common/errors/password-error.js.map +1 -1
  18. package/dist/common/errors/permission.js +4 -4
  19. package/dist/common/errors/permission.js.map +1 -1
  20. package/dist/common/errors/reconnection.js +5 -5
  21. package/dist/common/errors/reconnection.js.map +1 -1
  22. package/dist/common/errors/stats.js +5 -5
  23. package/dist/common/errors/stats.js.map +1 -1
  24. package/dist/common/errors/webex-errors.js.map +1 -1
  25. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  26. package/dist/common/events/events-scope.js.map +1 -1
  27. package/dist/common/events/events.js.map +1 -1
  28. package/dist/common/events/trigger-proxy.js.map +1 -1
  29. package/dist/common/events/util.js.map +1 -1
  30. package/dist/common/logs/logger-proxy.js.map +1 -1
  31. package/dist/common/logs/request.js.map +1 -1
  32. package/dist/config.js.map +1 -1
  33. package/dist/constants.js.map +1 -1
  34. package/dist/index.js.map +1 -1
  35. package/dist/locus-info/controlsUtils.js.map +1 -1
  36. package/dist/locus-info/fullState.js.map +1 -1
  37. package/dist/locus-info/hostUtils.js.map +1 -1
  38. package/dist/locus-info/index.js +11 -8
  39. package/dist/locus-info/index.js.map +1 -1
  40. package/dist/locus-info/infoUtils.js.map +1 -1
  41. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  42. package/dist/locus-info/parser.js +2 -1
  43. package/dist/locus-info/parser.js.map +1 -1
  44. package/dist/locus-info/selfUtils.js +2 -1
  45. package/dist/locus-info/selfUtils.js.map +1 -1
  46. package/dist/media/index.js.map +1 -1
  47. package/dist/media/internal-media-core-wrapper.js.map +1 -1
  48. package/dist/media/properties.js.map +1 -1
  49. package/dist/media/util.js +1 -1
  50. package/dist/media/util.js.map +1 -1
  51. package/dist/mediaQualityMetrics/config.js.map +1 -1
  52. package/dist/meeting/effectsState.js +1 -1
  53. package/dist/meeting/effectsState.js.map +1 -1
  54. package/dist/meeting/in-meeting-actions.js.map +1 -1
  55. package/dist/meeting/index.js +118 -89
  56. package/dist/meeting/index.js.map +1 -1
  57. package/dist/meeting/muteState.js +1 -1
  58. package/dist/meeting/muteState.js.map +1 -1
  59. package/dist/meeting/request.js +25 -0
  60. package/dist/meeting/request.js.map +1 -1
  61. package/dist/meeting/request.type.js +8 -0
  62. package/dist/meeting/request.type.js.map +1 -0
  63. package/dist/meeting/state.js +5 -5
  64. package/dist/meeting/state.js.map +1 -1
  65. package/dist/meeting/util.js.map +1 -1
  66. package/dist/meeting-info/collection.js.map +1 -1
  67. package/dist/meeting-info/index.js +2 -2
  68. package/dist/meeting-info/index.js.map +1 -1
  69. package/dist/meeting-info/meeting-info-v2.js +48 -48
  70. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  71. package/dist/meeting-info/request.js.map +1 -1
  72. package/dist/meeting-info/util.js.map +1 -1
  73. package/dist/meeting-info/utilv2.js +1 -1
  74. package/dist/meeting-info/utilv2.js.map +1 -1
  75. package/dist/meetings/collection.js.map +1 -1
  76. package/dist/meetings/index.js +251 -250
  77. package/dist/meetings/index.js.map +1 -1
  78. package/dist/meetings/request.js +2 -2
  79. package/dist/meetings/request.js.map +1 -1
  80. package/dist/meetings/util.js +14 -14
  81. package/dist/meetings/util.js.map +1 -1
  82. package/dist/member/index.js +31 -31
  83. package/dist/member/index.js.map +1 -1
  84. package/dist/member/util.js.map +1 -1
  85. package/dist/members/collection.js.map +1 -1
  86. package/dist/members/index.js +43 -43
  87. package/dist/members/index.js.map +1 -1
  88. package/dist/members/request.js.map +1 -1
  89. package/dist/members/util.js.map +1 -1
  90. package/dist/metrics/config.js.map +1 -1
  91. package/dist/metrics/constants.js.map +1 -1
  92. package/dist/metrics/index.js +23 -20
  93. package/dist/metrics/index.js.map +1 -1
  94. package/dist/multistream/multistreamMedia.js +2 -1
  95. package/dist/multistream/multistreamMedia.js.map +1 -1
  96. package/dist/multistream/receiveSlot.js.map +1 -1
  97. package/dist/multistream/receiveSlotManager.js +2 -0
  98. package/dist/multistream/receiveSlotManager.js.map +1 -1
  99. package/dist/multistream/remoteMedia.js.map +1 -1
  100. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  101. package/dist/multistream/remoteMediaManager.js.map +1 -1
  102. package/dist/networkQualityMonitor/index.js +8 -8
  103. package/dist/networkQualityMonitor/index.js.map +1 -1
  104. package/dist/personal-meeting-room/index.js +7 -7
  105. package/dist/personal-meeting-room/index.js.map +1 -1
  106. package/dist/personal-meeting-room/request.js.map +1 -1
  107. package/dist/personal-meeting-room/util.js.map +1 -1
  108. package/dist/reachability/index.js.map +1 -1
  109. package/dist/reachability/request.js.map +1 -1
  110. package/dist/reactions/reactions.js.map +1 -1
  111. package/dist/reactions/reactions.type.js +3 -1
  112. package/dist/reactions/reactions.type.js.map +1 -1
  113. package/dist/reconnection-manager/index.js +4 -4
  114. package/dist/reconnection-manager/index.js.map +1 -1
  115. package/dist/roap/index.js +5 -5
  116. package/dist/roap/index.js.map +1 -1
  117. package/dist/roap/request.js.map +1 -1
  118. package/dist/roap/turnDiscovery.js.map +1 -1
  119. package/dist/statsAnalyzer/global.js.map +1 -1
  120. package/dist/statsAnalyzer/index.js.map +1 -1
  121. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  122. package/dist/transcription/index.js +4 -1
  123. package/dist/transcription/index.js.map +1 -1
  124. package/internal-README.md +7 -6
  125. package/package.json +18 -18
  126. package/src/common/browser-detection.ts +9 -6
  127. package/src/common/collection.ts +3 -1
  128. package/src/common/errors/captcha-error.ts +6 -6
  129. package/src/common/errors/intent-to-join.ts +6 -6
  130. package/src/common/errors/join-meeting.ts +12 -8
  131. package/src/common/errors/media.ts +6 -6
  132. package/src/common/errors/parameter.ts +9 -6
  133. package/src/common/errors/password-error.ts +6 -6
  134. package/src/common/errors/permission.ts +5 -5
  135. package/src/common/errors/reconnection.ts +6 -6
  136. package/src/common/errors/stats.ts +6 -6
  137. package/src/common/errors/webex-errors.ts +7 -5
  138. package/src/common/errors/webex-meetings-error.ts +1 -1
  139. package/src/common/events/events-scope.ts +5 -1
  140. package/src/common/events/events.ts +5 -1
  141. package/src/common/events/trigger-proxy.ts +8 -3
  142. package/src/common/events/util.ts +1 -2
  143. package/src/common/logs/logger-proxy.ts +21 -10
  144. package/src/common/logs/request.ts +11 -8
  145. package/src/config.ts +11 -11
  146. package/src/constants.ts +1 -1
  147. package/src/index.js +1 -1
  148. package/src/locus-info/controlsUtils.ts +34 -24
  149. package/src/locus-info/fullState.ts +15 -11
  150. package/src/locus-info/hostUtils.ts +4 -3
  151. package/src/locus-info/index.ts +25 -34
  152. package/src/locus-info/infoUtils.ts +12 -4
  153. package/src/locus-info/mediaSharesUtils.ts +4 -4
  154. package/src/locus-info/parser.ts +45 -68
  155. package/src/locus-info/selfUtils.ts +106 -57
  156. package/src/media/index.ts +123 -135
  157. package/src/media/internal-media-core-wrapper.ts +2 -2
  158. package/src/media/properties.ts +30 -20
  159. package/src/media/util.ts +1 -1
  160. package/src/mediaQualityMetrics/config.ts +46 -46
  161. package/src/meeting/effectsState.ts +35 -35
  162. package/src/meeting/in-meeting-actions.ts +7 -3
  163. package/src/meeting/index.ts +1576 -1291
  164. package/src/meeting/muteState.ts +62 -31
  165. package/src/meeting/request.ts +174 -113
  166. package/src/meeting/request.type.ts +11 -0
  167. package/src/meeting/state.ts +45 -30
  168. package/src/meeting/util.ts +101 -70
  169. package/src/meeting-info/collection.ts +2 -1
  170. package/src/meeting-info/index.ts +32 -30
  171. package/src/meeting-info/meeting-info-v2.ts +106 -108
  172. package/src/meeting-info/request.ts +9 -3
  173. package/src/meeting-info/util.ts +54 -46
  174. package/src/meeting-info/utilv2.ts +59 -53
  175. package/src/meetings/collection.ts +1 -1
  176. package/src/meetings/index.ts +512 -440
  177. package/src/meetings/request.ts +26 -24
  178. package/src/meetings/util.ts +29 -29
  179. package/src/member/index.ts +55 -49
  180. package/src/member/util.ts +26 -13
  181. package/src/members/collection.ts +0 -1
  182. package/src/members/index.ts +182 -126
  183. package/src/members/request.ts +46 -14
  184. package/src/members/util.ts +44 -42
  185. package/src/metrics/config.ts +254 -81
  186. package/src/metrics/constants.ts +0 -2
  187. package/src/metrics/index.ts +84 -71
  188. package/src/multistream/multistreamMedia.ts +1 -0
  189. package/src/multistream/receiveSlot.ts +1 -0
  190. package/src/multistream/receiveSlotManager.ts +1 -0
  191. package/src/multistream/remoteMedia.ts +1 -1
  192. package/src/multistream/remoteMediaGroup.ts +2 -1
  193. package/src/multistream/remoteMediaManager.ts +3 -0
  194. package/src/networkQualityMonitor/index.ts +20 -23
  195. package/src/personal-meeting-room/index.ts +12 -16
  196. package/src/personal-meeting-room/request.ts +10 -3
  197. package/src/personal-meeting-room/util.ts +3 -3
  198. package/src/reachability/index.ts +61 -59
  199. package/src/reachability/request.ts +36 -32
  200. package/src/reactions/reactions.ts +4 -4
  201. package/src/reactions/reactions.type.ts +4 -3
  202. package/src/reconnection-manager/index.ts +139 -84
  203. package/src/roap/index.ts +46 -38
  204. package/src/roap/request.ts +44 -31
  205. package/src/roap/turnDiscovery.ts +59 -30
  206. package/src/statsAnalyzer/global.ts +30 -33
  207. package/src/statsAnalyzer/index.ts +432 -175
  208. package/src/statsAnalyzer/mqaUtil.ts +178 -72
  209. package/src/transcription/index.ts +34 -32
  210. package/test/integration/spec/journey.js +663 -462
  211. package/test/integration/spec/space-meeting.js +318 -203
  212. package/test/integration/spec/transcription.js +6 -7
  213. package/test/unit/spec/common/browser-detection.js +9 -28
  214. package/test/unit/spec/fixture/locus.js +92 -90
  215. package/test/unit/spec/locus-info/controlsUtils.js +5 -5
  216. package/test/unit/spec/locus-info/embeddedAppsUtils.js +8 -6
  217. package/test/unit/spec/locus-info/index.js +1 -2
  218. package/test/unit/spec/locus-info/infoUtils.js +26 -33
  219. package/test/unit/spec/locus-info/lib/BasicSeqCmp.json +88 -430
  220. package/test/unit/spec/locus-info/lib/SeqCmp.json +513 -685
  221. package/test/unit/spec/locus-info/parser.js +3 -9
  222. package/test/unit/spec/locus-info/selfConstant.js +72 -103
  223. package/test/unit/spec/locus-info/selfUtils.js +21 -12
  224. package/test/unit/spec/meeting/effectsState.js +36 -46
  225. package/test/unit/spec/meeting/in-meeting-actions.ts +2 -3
  226. package/test/unit/spec/meeting/index.js +1342 -684
  227. package/test/unit/spec/meeting/muteState.js +42 -33
  228. package/test/unit/spec/meeting/request.js +75 -45
  229. package/test/unit/spec/meeting/utils.js +78 -53
  230. package/test/unit/spec/meeting-info/meetinginfov2.js +100 -73
  231. package/test/unit/spec/meeting-info/request.js +7 -9
  232. package/test/unit/spec/meeting-info/util.js +11 -12
  233. package/test/unit/spec/meeting-info/utilv2.js +110 -74
  234. package/test/unit/spec/meetings/collection.js +1 -1
  235. package/test/unit/spec/meetings/index.js +438 -257
  236. package/test/unit/spec/meetings/utils.js +14 -12
  237. package/test/unit/spec/member/index.js +0 -1
  238. package/test/unit/spec/member/util.js +5 -6
  239. package/test/unit/spec/members/index.js +104 -54
  240. package/test/unit/spec/members/request.js +29 -20
  241. package/test/unit/spec/members/utils.js +8 -5
  242. package/test/unit/spec/metrics/index.js +16 -21
  243. package/test/unit/spec/networkQualityMonitor/index.js +21 -15
  244. package/test/unit/spec/personal-meeting-room/personal-meeting-room.js +2 -7
  245. package/test/unit/spec/reachability/index.ts +9 -11
  246. package/test/unit/spec/reconnection-manager/index.js +16 -18
  247. package/test/unit/spec/roap/turnDiscovery.ts +22 -19
  248. package/test/unit/spec/stats-analyzer/index.js +25 -20
  249. package/test/utils/cmr.js +44 -42
  250. package/test/utils/testUtils.js +83 -74
  251. package/test/utils/webex-config.js +18 -18
  252. package/test/utils/webex-test-users.js +53 -50
@@ -5,8 +5,11 @@ import {StatelessWebexPlugin} from '@webex/webex-core';
5
5
  import {Media as WebRTCMedia, MediaConnection as MC} from '@webex/internal-media-core';
6
6
 
7
7
  import {
8
- MeetingNotActiveError, createMeetingsError, UserInLobbyError,
9
- NoMediaEstablishedYetError, UserNotJoinedError
8
+ MeetingNotActiveError,
9
+ createMeetingsError,
10
+ UserInLobbyError,
11
+ NoMediaEstablishedYetError,
12
+ UserNotJoinedError,
10
13
  } from '../common/errors/webex-errors';
11
14
  import {StatsAnalyzer, EVENTS as StatsAnalyzerEvents} from '../statsAnalyzer';
12
15
  import NetworkQualityMonitor from '../networkQualityMonitor';
@@ -15,16 +18,16 @@ import Trigger from '../common/events/trigger-proxy';
15
18
  import Roap from '../roap/index';
16
19
  import Media from '../media';
17
20
  import MediaProperties from '../media/properties';
18
- import MeetingStateMachine from '../meeting/state';
19
- import createMuteState from '../meeting/muteState';
20
- import createEffectsState from '../meeting/effectsState';
21
+ import MeetingStateMachine from './state';
22
+ import createMuteState from './muteState';
23
+ import createEffectsState from './effectsState';
21
24
  import LocusInfo from '../locus-info';
22
25
  import Metrics from '../metrics';
23
26
  import {trigger, mediaType, error as MetricsError, eventType} from '../metrics/config';
24
27
  import ReconnectionManager from '../reconnection-manager';
25
- import MeetingRequest from '../meeting/request';
28
+ import MeetingRequest from './request';
26
29
  import Members from '../members/index';
27
- import MeetingUtil from '../meeting/util';
30
+ import MeetingUtil from './util';
28
31
  import MediaUtil from '../media/util';
29
32
  import Transcription from '../transcription';
30
33
  import PasswordError from '../common/errors/password-error';
@@ -64,26 +67,31 @@ import {
64
67
  VIDEO_RESOLUTIONS,
65
68
  VIDEO,
66
69
  BNR_STATUS,
67
- HTTP_VERBS
70
+ HTTP_VERBS,
68
71
  } from '../constants';
69
72
  import BEHAVIORAL_METRICS from '../metrics/constants';
70
73
  import ParameterError from '../common/errors/parameter';
71
74
  import MediaError from '../common/errors/media';
72
- import {MeetingInfoV2PasswordError, MeetingInfoV2CaptchaError} from '../meeting-info/meeting-info-v2';
75
+ import {
76
+ MeetingInfoV2PasswordError,
77
+ MeetingInfoV2CaptchaError,
78
+ } from '../meeting-info/meeting-info-v2';
73
79
  import BrowserDetection from '../common/browser-detection';
74
80
  import {ReceiveSlotManager} from '../multistream/receiveSlotManager';
75
81
  import {MediaRequestManager} from '../multistream/mediaRequestManager';
76
- import {RemoteMediaManager, Event as RemoteMediaManagerEvent} from '../multistream/remoteMediaManager';
82
+ import {
83
+ RemoteMediaManager,
84
+ Event as RemoteMediaManagerEvent,
85
+ } from '../multistream/remoteMediaManager';
77
86
  import {MultistreamMedia} from '../multistream/multistreamMedia';
78
87
  import {SkinTones, Reactions} from '../reactions/reactions';
79
88
  import {Reaction, ReactionType, SkinToneType} from '../reactions/reactions.type';
80
89
 
81
90
  import InMeetingActions from './in-meeting-actions';
82
91
 
83
-
84
92
  const {isBrowser} = BrowserDetection();
85
93
 
86
- const logRequest = (request: any, { header = '', success = '', failure = '' }) => {
94
+ const logRequest = (request: any, {header = '', success = '', failure = ''}) => {
87
95
  LoggerProxy.logger.info(header);
88
96
 
89
97
  return request
@@ -102,7 +110,7 @@ export const MEDIA_UPDATE_TYPE = {
102
110
  ALL: 'ALL',
103
111
  AUDIO: 'AUDIO',
104
112
  VIDEO: 'VIDEO',
105
- SHARE: 'SHARE'
113
+ SHARE: 'SHARE',
106
114
  };
107
115
 
108
116
  /**
@@ -118,21 +126,21 @@ export const MEDIA_UPDATE_TYPE = {
118
126
  */
119
127
 
120
128
  /**
121
- * AudioVideo
122
- * @typedef {Object} AudioVideo
123
- * @property {Object} audio
124
- * @property {String} audio.deviceId
125
- * @property {Object} video
126
- * @property {String} video.deviceId
127
- * @property {String} video.localVideoQuality // [240p, 360p, 480p, 720p, 1080p]
128
- */
129
+ * AudioVideo
130
+ * @typedef {Object} AudioVideo
131
+ * @property {Object} audio
132
+ * @property {String} audio.deviceId
133
+ * @property {Object} video
134
+ * @property {String} video.deviceId
135
+ * @property {String} video.localVideoQuality // [240p, 360p, 480p, 720p, 1080p]
136
+ */
129
137
 
130
138
  /**
131
- * SharePreferences
132
- * @typedef {Object} SharePreferences
133
- * @property {Object} [shareConstraints]
134
- * @property {Boolean} [highFrameRate]
135
- */
139
+ * SharePreferences
140
+ * @typedef {Object} SharePreferences
141
+ * @property {Object} [shareConstraints]
142
+ * @property {Boolean} [highFrameRate]
143
+ */
136
144
 
137
145
  /**
138
146
  * JoinOptions
@@ -163,36 +171,36 @@ export const MEDIA_UPDATE_TYPE = {
163
171
  */
164
172
 
165
173
  /**
166
- * Meeting State Change Event
167
- * Emitted when ever there is a meeting state change
168
- * @event meeting:stateChange
169
- * @instance
170
- * @type {Object}
171
- * @property {String} currentState current state of the meeting
172
- * @property {String} previousState previous state of the meeting
173
- * @memberof Meeting
174
- */
174
+ * Meeting State Change Event
175
+ * Emitted when ever there is a meeting state change
176
+ * @event meeting:stateChange
177
+ * @instance
178
+ * @type {Object}
179
+ * @property {String} currentState current state of the meeting
180
+ * @property {String} previousState previous state of the meeting
181
+ * @memberof Meeting
182
+ */
175
183
 
176
184
  /**
177
- * Media Ready Event
178
- * Emitted when a stream is ready to be rendered
179
- * @event media:ready
180
- * @instance
181
- * @type {Object}
182
- * @property {MediaStream} stream the media stream
183
- * @property {String} type what type of stream, remote, local
184
- * @memberof Meeting
185
- */
185
+ * Media Ready Event
186
+ * Emitted when a stream is ready to be rendered
187
+ * @event media:ready
188
+ * @instance
189
+ * @type {Object}
190
+ * @property {MediaStream} stream the media stream
191
+ * @property {String} type what type of stream, remote, local
192
+ * @memberof Meeting
193
+ */
186
194
 
187
195
  /**
188
- * Media Stopped Event
189
- * Emitted when a stream has stopped sending
190
- * @event media:stopped
191
- * @instance
192
- * @type {Object}
193
- * @property {String} type what type of stream, remote, local
194
- * @memberof Meeting
195
- */
196
+ * Media Stopped Event
197
+ * Emitted when a stream has stopped sending
198
+ * @event media:stopped
199
+ * @instance
200
+ * @type {Object}
201
+ * @property {String} type what type of stream, remote, local
202
+ * @memberof Meeting
203
+ */
196
204
 
197
205
  /**
198
206
  * Meeting Ringing Event
@@ -319,7 +327,6 @@ export const MEDIA_UPDATE_TYPE = {
319
327
  * @memberof Meeting
320
328
  */
321
329
 
322
-
323
330
  /**
324
331
  * Meeting Self Guest Admitted Event
325
332
  * Emitted when a joined user get admitted to the meeting by another member or host
@@ -351,42 +358,42 @@ export const MEDIA_UPDATE_TYPE = {
351
358
  */
352
359
 
353
360
  /**
354
- * Reconnection Starting Event
355
- * Emitted when reconnection of media to the active meeting was successful
356
- * @event meeting:reconnectionStarting
357
- * @instance
358
- * @memberof Meeting
359
- */
361
+ * Reconnection Starting Event
362
+ * Emitted when reconnection of media to the active meeting was successful
363
+ * @event meeting:reconnectionStarting
364
+ * @instance
365
+ * @memberof Meeting
366
+ */
360
367
 
361
368
  /**
362
- * Reconnection Success Event
363
- * Emitted when reconnection of media to the active meeting was successful
364
- * @event meeting:reconnectionSuccess
365
- * @instance
366
- * @type {Object}
367
- * @property {Object} reconnect
368
- * @memberof Meeting
369
- */
369
+ * Reconnection Success Event
370
+ * Emitted when reconnection of media to the active meeting was successful
371
+ * @event meeting:reconnectionSuccess
372
+ * @instance
373
+ * @type {Object}
374
+ * @property {Object} reconnect
375
+ * @memberof Meeting
376
+ */
370
377
 
371
378
  /**
372
- * Reconnection Failure Event
373
- * Emitted when reconnection of media to the active meeting was successful
374
- * @event meeting:reconnectionFailure
375
- * @instance
376
- * @type {Object}
377
- * @property {Error} error
378
- * @memberof Meeting
379
- */
379
+ * Reconnection Failure Event
380
+ * Emitted when reconnection of media to the active meeting was successful
381
+ * @event meeting:reconnectionFailure
382
+ * @instance
383
+ * @type {Object}
384
+ * @property {Error} error
385
+ * @memberof Meeting
386
+ */
380
387
 
381
388
  /**
382
- * Meeting network quality event
383
- * Emitted on each interval of retrieving stats Analyzer data
384
- * @event network:quality
385
- * @type {Object}
386
- * @property {string} mediaType {video|audio}
387
- * @property {number} networkQualityScore - {1|0} 1 indicates acceptable uplink 0 indicates unacceptable uplink based on threshold
388
- * @memberof Meeting
389
- */
389
+ * Meeting network quality event
390
+ * Emitted on each interval of retrieving stats Analyzer data
391
+ * @event network:quality
392
+ * @type {Object}
393
+ * @property {string} mediaType {video|audio}
394
+ * @property {number} networkQualityScore - {1|0} 1 indicates acceptable uplink 0 indicates unacceptable uplink based on threshold
395
+ * @memberof Meeting
396
+ */
390
397
 
391
398
  /**
392
399
  * @description Meeting is the crux of the plugin
@@ -448,6 +455,7 @@ export default class Meeting extends StatelessWebexPlugin {
448
455
  audio: MediaRequestManager;
449
456
  video: MediaRequestManager;
450
457
  };
458
+
451
459
  meetingInfoFailureReason: string;
452
460
  networkQualityMonitor: NetworkQualityMonitor;
453
461
  networkStatus: string;
@@ -479,6 +487,7 @@ export default class Meeting extends StatelessWebexPlugin {
479
487
  resourceUrl: string;
480
488
  selfId: string;
481
489
  state: any;
490
+
482
491
  namespace = MEETINGS;
483
492
 
484
493
  /**
@@ -486,7 +495,7 @@ export default class Meeting extends StatelessWebexPlugin {
486
495
  * @param {Object} options
487
496
  * @constructor
488
497
  * @memberof Meeting
489
- */
498
+ */
490
499
  constructor(attrs: any, options: object) {
491
500
  super({}, options);
492
501
  /**
@@ -575,20 +584,30 @@ export default class Meeting extends StatelessWebexPlugin {
575
584
  this.mediaRequestManagers = {
576
585
  audio: new MediaRequestManager((mediaRequests) => {
577
586
  if (!this.mediaProperties.webrtcMediaConnection) {
578
- LoggerProxy.logger.warn('Meeting:index#mediaRequestManager --> trying to send audio media request before media connection was created');
587
+ LoggerProxy.logger.warn(
588
+ 'Meeting:index#mediaRequestManager --> trying to send audio media request before media connection was created'
589
+ );
579
590
 
580
591
  return;
581
592
  }
582
- this.mediaProperties.webrtcMediaConnection.requestMedia(MC.MediaType.AudioMain, mediaRequests);
593
+ this.mediaProperties.webrtcMediaConnection.requestMedia(
594
+ MC.MediaType.AudioMain,
595
+ mediaRequests
596
+ );
583
597
  }),
584
598
  video: new MediaRequestManager((mediaRequests) => {
585
599
  if (!this.mediaProperties.webrtcMediaConnection) {
586
- LoggerProxy.logger.warn('Meeting:index#mediaRequestManager --> trying to send video media request before media connection was created');
600
+ LoggerProxy.logger.warn(
601
+ 'Meeting:index#mediaRequestManager --> trying to send video media request before media connection was created'
602
+ );
587
603
 
588
604
  return;
589
605
  }
590
- this.mediaProperties.webrtcMediaConnection.requestMedia(MC.MediaType.VideoMain, mediaRequests);
591
- })
606
+ this.mediaProperties.webrtcMediaConnection.requestMedia(
607
+ MC.MediaType.VideoMain,
608
+ mediaRequests
609
+ );
610
+ }),
592
611
  };
593
612
  /**
594
613
  * @instance
@@ -596,12 +615,15 @@ export default class Meeting extends StatelessWebexPlugin {
596
615
  * @public
597
616
  * @memberof Meeting
598
617
  */
599
- this.members = new Members({
600
- locusUrl: (attrs.locus && attrs.locus.url),
601
- receiveSlotManager: this.receiveSlotManager,
602
- mediaRequestManagers: this.mediaRequestManagers,
603
- // @ts-ignore - Fix type
604
- }, {parent: this.webex});
618
+ this.members = new Members(
619
+ {
620
+ locusUrl: attrs.locus && attrs.locus.url,
621
+ receiveSlotManager: this.receiveSlotManager,
622
+ mediaRequestManagers: this.mediaRequestManagers,
623
+ // @ts-ignore - Fix type
624
+ },
625
+ {parent: this.webex}
626
+ );
605
627
  /**
606
628
  * @instance
607
629
  * @type {Roap}
@@ -800,7 +822,7 @@ export default class Meeting extends StatelessWebexPlugin {
800
822
  * @type {InMeetingActions}
801
823
  * @public
802
824
  * @memberof Meeting
803
- */
825
+ */
804
826
  this.inMeetingActions = new InMeetingActions();
805
827
  /**
806
828
  * This is deprecated, please use shareStatus instead.
@@ -1022,32 +1044,55 @@ export default class Meeting extends StatelessWebexPlugin {
1022
1044
  * @memberof Meeting
1023
1045
  * @returns {Promise}
1024
1046
  */
1025
- public async fetchMeetingInfo({ password = null, captchaCode = null }: { password?: string; captchaCode?: string }) {
1047
+ public async fetchMeetingInfo({
1048
+ password = null,
1049
+ captchaCode = null,
1050
+ }: {
1051
+ password?: string;
1052
+ captchaCode?: string;
1053
+ }) {
1026
1054
  // when fetch meeting info is called directly by the client, we want to clear out the random timer for sdk to do it
1027
1055
  if (this.fetchMeetingInfoTimeoutId) {
1028
1056
  clearTimeout(this.fetchMeetingInfoTimeoutId);
1029
1057
  this.fetchMeetingInfoTimeoutId = undefined;
1030
1058
  }
1031
1059
  if (captchaCode && !this.requiredCaptcha) {
1032
- return Promise.reject(new Error('fetchMeetingInfo() called with captchaCode when captcha was not required'));
1060
+ return Promise.reject(
1061
+ new Error('fetchMeetingInfo() called with captchaCode when captcha was not required')
1062
+ );
1033
1063
  }
1034
- if (password && (this.passwordStatus !== PASSWORD_STATUS.REQUIRED && this.passwordStatus !== PASSWORD_STATUS.UNKNOWN)) {
1035
- return Promise.reject(new Error('fetchMeetingInfo() called with password when password was not required'));
1064
+ if (
1065
+ password &&
1066
+ this.passwordStatus !== PASSWORD_STATUS.REQUIRED &&
1067
+ this.passwordStatus !== PASSWORD_STATUS.UNKNOWN
1068
+ ) {
1069
+ return Promise.reject(
1070
+ new Error('fetchMeetingInfo() called with password when password was not required')
1071
+ );
1036
1072
  }
1037
1073
 
1038
1074
  try {
1039
- const captchaInfo = captchaCode ? {code: captchaCode, id: this.requiredCaptcha.captchaId} : null;
1040
-
1041
- const info = await this.attrs.meetingInfoProvider.fetchMeetingInfo(this.destination, this.destinationType, password, captchaInfo);
1075
+ const captchaInfo = captchaCode
1076
+ ? {code: captchaCode, id: this.requiredCaptcha.captchaId}
1077
+ : null;
1078
+
1079
+ const info = await this.attrs.meetingInfoProvider.fetchMeetingInfo(
1080
+ this.destination,
1081
+ this.destinationType,
1082
+ password,
1083
+ captchaInfo
1084
+ );
1042
1085
 
1043
1086
  this.parseMeetingInfo(info, this.destination);
1044
1087
  this.meetingInfo = info ? info.body : null;
1045
1088
  this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.NONE;
1046
1089
  this.requiredCaptcha = null;
1047
- if ((this.passwordStatus === PASSWORD_STATUS.REQUIRED) || (this.passwordStatus === PASSWORD_STATUS.VERIFIED)) {
1090
+ if (
1091
+ this.passwordStatus === PASSWORD_STATUS.REQUIRED ||
1092
+ this.passwordStatus === PASSWORD_STATUS.VERIFIED
1093
+ ) {
1048
1094
  this.passwordStatus = PASSWORD_STATUS.VERIFIED;
1049
- }
1050
- else {
1095
+ } else {
1051
1096
  this.passwordStatus = PASSWORD_STATUS.NOT_REQUIRED;
1052
1097
  }
1053
1098
 
@@ -1055,17 +1100,18 @@ export default class Meeting extends StatelessWebexPlugin {
1055
1100
  this,
1056
1101
  {
1057
1102
  file: 'meetings',
1058
- function: 'fetchMeetingInfo'
1103
+ function: 'fetchMeetingInfo',
1059
1104
  },
1060
1105
  EVENT_TRIGGERS.MEETING_INFO_AVAILABLE
1061
1106
  );
1062
1107
 
1063
1108
  return Promise.resolve();
1064
- }
1065
- catch (err) {
1109
+ } catch (err) {
1066
1110
  if (err instanceof MeetingInfoV2PasswordError) {
1067
1111
  // @ts-ignore
1068
- LoggerProxy.logger.info(`Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - password required (code=${err?.body?.code}).`);
1112
+ LoggerProxy.logger.info(
1113
+ `Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - password required (code=${err?.body?.code}).`
1114
+ );
1069
1115
 
1070
1116
  // when wbxappapi requires password it still populates partial meeting info in the response
1071
1117
  if (err.meetingInfo) {
@@ -1080,26 +1126,26 @@ export default class Meeting extends StatelessWebexPlugin {
1080
1126
  await this.refreshCaptcha();
1081
1127
  }
1082
1128
 
1083
- throw (new PasswordError());
1084
- }
1085
- else if (err instanceof MeetingInfoV2CaptchaError) {
1129
+ throw new PasswordError();
1130
+ } else if (err instanceof MeetingInfoV2CaptchaError) {
1086
1131
  // @ts-ignore
1087
- LoggerProxy.logger.info(`Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - captcha required (code=${err?.body?.code}).`);
1132
+ LoggerProxy.logger.info(
1133
+ `Meeting:index#fetchMeetingInfo --> Info Unable to fetch meeting info for ${this.destination} - captcha required (code=${err?.body?.code}).`
1134
+ );
1088
1135
 
1089
- this.meetingInfoFailureReason = (this.requiredCaptcha) ?
1090
- MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA :
1091
- MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD;
1136
+ this.meetingInfoFailureReason = this.requiredCaptcha
1137
+ ? MEETING_INFO_FAILURE_REASON.WRONG_CAPTCHA
1138
+ : MEETING_INFO_FAILURE_REASON.WRONG_PASSWORD;
1092
1139
 
1093
1140
  if (err.isPasswordRequired) {
1094
1141
  this.passwordStatus = PASSWORD_STATUS.REQUIRED;
1095
1142
  }
1096
1143
 
1097
1144
  this.requiredCaptcha = err.captchaInfo;
1098
- throw (new CaptchaError());
1099
- }
1100
- else {
1145
+ throw new CaptchaError();
1146
+ } else {
1101
1147
  this.meetingInfoFailureReason = MEETING_INFO_FAILURE_REASON.OTHER;
1102
- throw (err);
1148
+ throw err;
1103
1149
  }
1104
1150
  }
1105
1151
  }
@@ -1115,24 +1161,27 @@ export default class Meeting extends StatelessWebexPlugin {
1115
1161
  */
1116
1162
  public verifyPassword(password: string, captchaCode: string) {
1117
1163
  return this.fetchMeetingInfo({
1118
- password, captchaCode
1164
+ password,
1165
+ captchaCode,
1119
1166
  })
1120
1167
  .then(() => {
1121
- Metrics.sendBehavioralMetric(
1122
- BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS
1123
- );
1168
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.VERIFY_PASSWORD_SUCCESS);
1124
1169
 
1125
- return {isPasswordValid: true, requiredCaptcha: null, failureReason: MEETING_INFO_FAILURE_REASON.NONE};
1170
+ return {
1171
+ isPasswordValid: true,
1172
+ requiredCaptcha: null,
1173
+ failureReason: MEETING_INFO_FAILURE_REASON.NONE,
1174
+ };
1126
1175
  })
1127
1176
  .catch((error) => {
1128
1177
  if (error instanceof PasswordError || error instanceof CaptchaError) {
1129
1178
  return {
1130
1179
  isPasswordValid: this.passwordStatus === PASSWORD_STATUS.VERIFIED,
1131
1180
  requiredCaptcha: this.requiredCaptcha,
1132
- failureReason: this.meetingInfoFailureReason
1181
+ failureReason: this.meetingInfoFailureReason,
1133
1182
  };
1134
1183
  }
1135
- throw (error);
1184
+ throw error;
1136
1185
  });
1137
1186
  }
1138
1187
 
@@ -1152,18 +1201,21 @@ export default class Meeting extends StatelessWebexPlugin {
1152
1201
  // we have to pass the wbxappapi hostname as the siteFullName parameter
1153
1202
  const {hostname} = new URL(this.requiredCaptcha.refreshURL);
1154
1203
 
1155
- return this.meetingRequest.refreshCaptcha({
1156
- captchaRefreshUrl: `${this.requiredCaptcha.refreshURL}&siteFullName=${hostname}`,
1157
- captchaId: this.requiredCaptcha.captchaId
1158
- })
1204
+ return this.meetingRequest
1205
+ .refreshCaptcha({
1206
+ captchaRefreshUrl: `${this.requiredCaptcha.refreshURL}&siteFullName=${hostname}`,
1207
+ captchaId: this.requiredCaptcha.captchaId,
1208
+ })
1159
1209
  .then((response) => {
1160
1210
  this.requiredCaptcha.captchaId = response.body.captchaID;
1161
1211
  this.requiredCaptcha.verificationImageURL = response.body.verificationImageURL;
1162
1212
  this.requiredCaptcha.verificationAudioURL = response.body.verificationAudioURL;
1163
1213
  })
1164
1214
  .catch((error) => {
1165
- LoggerProxy.logger.error(`Meeting:index#refreshCaptcha --> Error Unable to refresh captcha for ${this.destination} - ${error}`);
1166
- throw (error);
1215
+ LoggerProxy.logger.error(
1216
+ `Meeting:index#refreshCaptcha --> Error Unable to refresh captcha for ${this.destination} - ${error}`
1217
+ );
1218
+ throw error;
1167
1219
  });
1168
1220
  }
1169
1221
 
@@ -1203,13 +1255,10 @@ export default class Meeting extends StatelessWebexPlugin {
1203
1255
  // https:// jira-eng-gpk2.cisco.com/jira/browse/SPARK-240520
1204
1256
  // TODO: send custom parameter explaining why the inactivity happened
1205
1257
  // refresh , no media or network got dsconnected or something else
1206
- Metrics.sendBehavioralMetric(
1207
- BEHAVIORAL_METRICS.DISCONNECT_DUE_TO_INACTIVITY,
1208
- {
1209
- correlation_id: this.correlationId,
1210
- locus_id: this.locusId
1211
- }
1212
- );
1258
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.DISCONNECT_DUE_TO_INACTIVITY, {
1259
+ correlation_id: this.correlationId,
1260
+ locus_id: this.locusId,
1261
+ });
1213
1262
 
1214
1263
  // Upload logs on media inactivity
1215
1264
  // Normally media should not be inactive
@@ -1217,24 +1266,25 @@ export default class Meeting extends StatelessWebexPlugin {
1217
1266
  this,
1218
1267
  {
1219
1268
  file: 'meeting/index',
1220
- function: 'setUpLocusInfoMediaInactiveListener'
1269
+ function: 'setUpLocusInfoMediaInactiveListener',
1221
1270
  },
1222
1271
  EVENTS.REQUEST_UPLOAD_LOGS,
1223
1272
  this
1224
1273
  );
1225
1274
 
1226
- LoggerProxy.logger.error(`Meeting:index#setUpLocusInfoMediaInactiveListener --> Meeting disconnected due to inactivity: ${res.reason}`);
1275
+ LoggerProxy.logger.error(
1276
+ `Meeting:index#setUpLocusInfoMediaInactiveListener --> Meeting disconnected due to inactivity: ${res.reason}`
1277
+ );
1227
1278
 
1228
1279
  // @ts-ignore - config coming from registerPlugin
1229
1280
  if (this.config.reconnection.autoRejoin) {
1230
1281
  this.reconnect();
1231
- }
1232
- else {
1282
+ } else {
1233
1283
  Trigger.trigger(
1234
1284
  this,
1235
1285
  {
1236
1286
  file: 'meeting/index',
1237
- function: 'setUpLocusInfoMediaInactiveListener'
1287
+ function: 'setUpLocusInfoMediaInactiveListener',
1238
1288
  },
1239
1289
  EVENT_TRIGGERS.MEETING_SELF_LEFT,
1240
1290
  res.reason
@@ -1260,7 +1310,7 @@ export default class Meeting extends StatelessWebexPlugin {
1260
1310
  this,
1261
1311
  {
1262
1312
  file: 'meeting/index',
1263
- function: 'setUpLocusInfoAssignHostListener'
1313
+ function: 'setUpLocusInfoAssignHostListener',
1264
1314
  },
1265
1315
  EVENT_TRIGGERS.MEETING_ACTIONS_UPDATE,
1266
1316
  this.inMeetingActions.get()
@@ -1281,11 +1331,11 @@ export default class Meeting extends StatelessWebexPlugin {
1281
1331
  this,
1282
1332
  {
1283
1333
  file: 'meeting/index',
1284
- function: 'setUpLocusFullStateListener'
1334
+ function: 'setUpLocusFullStateListener',
1285
1335
  },
1286
1336
  EVENT_TRIGGERS.MEETING_STATE_CHANGE,
1287
1337
  {
1288
- payload
1338
+ payload,
1289
1339
  }
1290
1340
  );
1291
1341
  });
@@ -1306,22 +1356,26 @@ export default class Meeting extends StatelessWebexPlugin {
1306
1356
  * @returns {Object}
1307
1357
  * @memberof Meeting
1308
1358
  */
1309
- getAnalyzerMetricsPrePayload(options: {
1310
- event: string;
1311
- trackingId: string;
1312
- locus: object;
1313
- mediaConnections: Array<any>;
1314
- errors: object;
1315
- } | any) {
1359
+ getAnalyzerMetricsPrePayload(
1360
+ options:
1361
+ | {
1362
+ event: string;
1363
+ trackingId: string;
1364
+ locus: object;
1365
+ mediaConnections: Array<any>;
1366
+ errors: object;
1367
+ }
1368
+ | any
1369
+ ) {
1316
1370
  if (options) {
1317
- const {
1318
- event,
1319
- trackingId,
1320
- mediaConnections
1321
- } = options;
1371
+ const {event, trackingId, mediaConnections} = options;
1322
1372
 
1323
1373
  if (!event) {
1324
- LoggerProxy.logger.error('Meeting:index#getAnalyzerMetricsPrePayload --> Error [Call Analyzer Event', event || '', `]: invalid identifers or event type! ${this.correlationId}`);
1374
+ LoggerProxy.logger.error(
1375
+ 'Meeting:index#getAnalyzerMetricsPrePayload --> Error [Call Analyzer Event',
1376
+ event || '',
1377
+ `]: invalid identifers or event type! ${this.correlationId}`
1378
+ );
1325
1379
 
1326
1380
  return null;
1327
1381
  }
@@ -1332,13 +1386,14 @@ export default class Meeting extends StatelessWebexPlugin {
1332
1386
  deviceId: this.deviceUrl,
1333
1387
  orgId: this.orgId,
1334
1388
  // @ts-ignore fix type
1335
- locusUrl: this.webex.internal.services.get('locus')
1389
+ locusUrl: this.webex.internal.services.get('locus'),
1336
1390
  };
1337
1391
 
1338
1392
  if (this.locusUrl && this.locusInfo.fullState) {
1339
1393
  identifiers.locusUrl = this.locusUrl;
1340
1394
  identifiers.locusId = this.locusUrl && this.locusUrl.split('/').pop();
1341
- identifiers.locusStartTime = this.locusInfo.fullState && this.locusInfo.fullState.lastActive;
1395
+ identifiers.locusStartTime =
1396
+ this.locusInfo.fullState && this.locusInfo.fullState.lastActive;
1342
1397
  }
1343
1398
 
1344
1399
  // Check if mediaConnections has been passed in or else use this.mediaConnections
@@ -1346,8 +1401,7 @@ export default class Meeting extends StatelessWebexPlugin {
1346
1401
  identifiers.mediaAgentAlias = mediaConnections?.[0].mediaAgentAlias;
1347
1402
  identifiers.mediaAgentGroupId = mediaConnections?.[0].mediaAgentGroupId;
1348
1403
  identifiers.mediaAgentCluster = mediaConnections?.[0].mediaAgentCluster;
1349
- }
1350
- else if (this.mediaConnections) {
1404
+ } else if (this.mediaConnections) {
1351
1405
  identifiers.mediaAgentAlias = this.mediaConnections?.[0].mediaAgentAlias;
1352
1406
  identifiers.mediaAgentGroupId = this.mediaConnections?.[0].mediaAgentGroupId;
1353
1407
  identifiers.mediaAgentCluster = this.mediaConnections?.[0].mediaAgentCluster;
@@ -1363,7 +1417,7 @@ export default class Meeting extends StatelessWebexPlugin {
1363
1417
 
1364
1418
  if (joinRespRxStartAudio) {
1365
1419
  options.audioSetupDelay = {
1366
- joinRespRxStart: joinRespRxStartAudio
1420
+ joinRespRxStart: joinRespRxStartAudio,
1367
1421
  };
1368
1422
  }
1369
1423
 
@@ -1371,7 +1425,7 @@ export default class Meeting extends StatelessWebexPlugin {
1371
1425
 
1372
1426
  if (joinRespRxStartAudio) {
1373
1427
  options.videoSetupDelay = {
1374
- joinRespRxStart: joinRespRxStartVideo
1428
+ joinRespRxStart: joinRespRxStartVideo,
1375
1429
  };
1376
1430
  }
1377
1431
 
@@ -1380,7 +1434,7 @@ export default class Meeting extends StatelessWebexPlugin {
1380
1434
  if (joinRespTxStartAudio) {
1381
1435
  options.audioSetupDelay = {
1382
1436
  ...options.audioSetupDelay,
1383
- joinRespTxStart: joinRespTxStartAudio
1437
+ joinRespTxStart: joinRespTxStartAudio,
1384
1438
  };
1385
1439
  }
1386
1440
 
@@ -1389,7 +1443,7 @@ export default class Meeting extends StatelessWebexPlugin {
1389
1443
  if (joinRespTxStartVideo) {
1390
1444
  options.videoSetupDelay = {
1391
1445
  ...options.videoSetupDelay,
1392
- joinRespTxStart: joinRespTxStartVideo
1446
+ joinRespTxStart: joinRespTxStartVideo,
1393
1447
  };
1394
1448
  }
1395
1449
 
@@ -1398,7 +1452,7 @@ export default class Meeting extends StatelessWebexPlugin {
1398
1452
  if (localSDPGenRemoteSDPRecv) {
1399
1453
  options.joinTimes = {
1400
1454
  ...options.joinTimes,
1401
- localSDPGenRemoteSDPRecv
1455
+ localSDPGenRemoteSDPRecv,
1402
1456
  };
1403
1457
  }
1404
1458
 
@@ -1407,7 +1461,7 @@ export default class Meeting extends StatelessWebexPlugin {
1407
1461
  if (callInitiateJoinReq) {
1408
1462
  options.joinTimes = {
1409
1463
  ...options.joinTimes,
1410
- callInitiateJoinReq
1464
+ callInitiateJoinReq,
1411
1465
  };
1412
1466
  }
1413
1467
 
@@ -1416,7 +1470,7 @@ export default class Meeting extends StatelessWebexPlugin {
1416
1470
  if (joinReqResp) {
1417
1471
  options.joinTimes = {
1418
1472
  ...options.joinTimes,
1419
- joinReqResp
1473
+ joinReqResp,
1420
1474
  };
1421
1475
  }
1422
1476
 
@@ -1425,14 +1479,13 @@ export default class Meeting extends StatelessWebexPlugin {
1425
1479
  if (getTotalJmt) {
1426
1480
  options.joinTimes = {
1427
1481
  ...options.joinTimes,
1428
- getTotalJmt
1482
+ getTotalJmt,
1429
1483
  };
1430
1484
  }
1431
1485
 
1432
1486
  if (options.type === MQA_STATS.CA_TYPE) {
1433
1487
  payload = Metrics.initMediaPayload(options.event, identifiers, options);
1434
- }
1435
- else {
1488
+ } else {
1436
1489
  payload = Metrics.initPayload(options.event, identifiers, options);
1437
1490
  }
1438
1491
 
@@ -1453,11 +1506,16 @@ export default class Meeting extends StatelessWebexPlugin {
1453
1506
  * @private
1454
1507
  * @memberof Meeting
1455
1508
  */
1456
- private sendCallAnalyzerMetrics(options: { event: string; trackingId: string; locus: object; errors: object }) {
1509
+ private sendCallAnalyzerMetrics(options: {
1510
+ event: string;
1511
+ trackingId: string;
1512
+ locus: object;
1513
+ errors: object;
1514
+ }) {
1457
1515
  const payload = this.getAnalyzerMetricsPrePayload({
1458
1516
  // @ts-ignore - config coming from registerPlugin
1459
1517
  ...pick(this.config.metrics, ['clientType', 'subClientType']),
1460
- ...options
1518
+ ...options,
1461
1519
  });
1462
1520
 
1463
1521
  // @ts-ignore - fix type
@@ -1474,12 +1532,16 @@ export default class Meeting extends StatelessWebexPlugin {
1474
1532
  * @private
1475
1533
  * @memberof Meeting
1476
1534
  */
1477
- private sendMediaQualityAnalyzerMetrics(options: { event: string; trackingId: string; locus: object }) {
1535
+ private sendMediaQualityAnalyzerMetrics(options: {
1536
+ event: string;
1537
+ trackingId: string;
1538
+ locus: object;
1539
+ }) {
1478
1540
  const payload = this.getAnalyzerMetricsPrePayload({
1479
1541
  type: MQA_STATS.CA_TYPE,
1480
1542
  // @ts-ignore - config coming from registerPlugin
1481
1543
  ...pick(this.config.metrics, ['clientType', 'subClientType']),
1482
- ...options
1544
+ ...options,
1483
1545
  });
1484
1546
 
1485
1547
  // @ts-ignore
@@ -1499,19 +1561,21 @@ export default class Meeting extends StatelessWebexPlugin {
1499
1561
  this,
1500
1562
  {
1501
1563
  file: 'meeting/index',
1502
- function: 'setNetworkStatus'
1564
+ function: 'setNetworkStatus',
1503
1565
  },
1504
- EVENT_TRIGGERS.MEETINGS_NETWORK_DISCONNECTED,
1566
+ EVENT_TRIGGERS.MEETINGS_NETWORK_DISCONNECTED
1505
1567
  );
1506
- }
1507
- else if (networkStatus === NETWORK_STATUS.CONNECTED && this.networkStatus === NETWORK_STATUS.DISCONNECTED) {
1568
+ } else if (
1569
+ networkStatus === NETWORK_STATUS.CONNECTED &&
1570
+ this.networkStatus === NETWORK_STATUS.DISCONNECTED
1571
+ ) {
1508
1572
  Trigger.trigger(
1509
1573
  this,
1510
1574
  {
1511
1575
  file: 'meeting/index',
1512
- function: 'setNetworkStatus'
1576
+ function: 'setNetworkStatus',
1513
1577
  },
1514
- EVENT_TRIGGERS.MEETINGS_NETWORK_CONNECTED,
1578
+ EVENT_TRIGGERS.MEETINGS_NETWORK_CONNECTED
1515
1579
  );
1516
1580
  }
1517
1581
 
@@ -1533,8 +1597,9 @@ export default class Meeting extends StatelessWebexPlugin {
1533
1597
 
1534
1598
  // If user moved to a JOINED state and there is a pending floor grant trigger it
1535
1599
  if (this.floorGrantPending && payload.newSelf.state === MEETING_STATE.STATES.JOINED) {
1536
- this.requestScreenShareFloor()
1537
- .then(() => { this.floorGrantPending = false; });
1600
+ this.requestScreenShareFloor().then(() => {
1601
+ this.floorGrantPending = false;
1602
+ });
1538
1603
  }
1539
1604
  });
1540
1605
  }
@@ -1548,8 +1613,12 @@ export default class Meeting extends StatelessWebexPlugin {
1548
1613
  */
1549
1614
  private pstnUpdate(payload: any) {
1550
1615
  if (this.locusInfo.self) {
1551
- const dialInPstnDevice = payload.newSelf?.pstnDevices.find((device) => device.url === this.dialInUrl);
1552
- const dialOutPstnDevice = payload.newSelf?.pstnDevices.find((device) => device.url === this.dialOutUrl);
1616
+ const dialInPstnDevice = payload.newSelf?.pstnDevices.find(
1617
+ (device) => device.url === this.dialInUrl
1618
+ );
1619
+ const dialOutPstnDevice = payload.newSelf?.pstnDevices.find(
1620
+ (device) => device.url === this.dialOutUrl
1621
+ );
1553
1622
  let changed = false;
1554
1623
 
1555
1624
  if (dialInPstnDevice) {
@@ -1575,18 +1644,18 @@ export default class Meeting extends StatelessWebexPlugin {
1575
1644
  this,
1576
1645
  {
1577
1646
  file: 'meeting/index',
1578
- function: 'setUpLocusSelfListener'
1647
+ function: 'setUpLocusSelfListener',
1579
1648
  },
1580
1649
  EVENT_TRIGGERS.MEETING_SELF_PHONE_AUDIO_UPDATE,
1581
1650
  {
1582
1651
  dialIn: {
1583
1652
  status: this.dialInDeviceStatus,
1584
- attendeeId: dialInPstnDevice?.attendeeId
1653
+ attendeeId: dialInPstnDevice?.attendeeId,
1585
1654
  },
1586
1655
  dialOut: {
1587
1656
  status: this.dialOutDeviceStatus,
1588
- attendeeId: dialOutPstnDevice?.attendeeId
1589
- }
1657
+ attendeeId: dialOutPstnDevice?.attendeeId,
1658
+ },
1590
1659
  }
1591
1660
  );
1592
1661
  }
@@ -1639,8 +1708,9 @@ export default class Meeting extends StatelessWebexPlugin {
1639
1708
  * @private
1640
1709
  * @memberof Meeting
1641
1710
  */
1642
- private setupLocusControlsListener() {
1643
- this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_RECORDING_UPDATED,
1711
+ private setupLocusControlsListener() {
1712
+ this.locusInfo.on(
1713
+ LOCUSINFO.EVENTS.CONTROLS_RECORDING_UPDATED,
1644
1714
  ({state, modifiedBy, lastModified}) => {
1645
1715
  let event;
1646
1716
 
@@ -1666,65 +1736,67 @@ export default class Meeting extends StatelessWebexPlugin {
1666
1736
  this.recording = {
1667
1737
  state: state === RECORDING_STATE.RESUMED ? RECORDING_STATE.RECORDING : state,
1668
1738
  modifiedBy,
1669
- lastModified
1739
+ lastModified,
1670
1740
  };
1671
1741
 
1672
1742
  Trigger.trigger(
1673
1743
  this,
1674
1744
  {
1675
1745
  file: 'meeting/index',
1676
- function: 'setupLocusControlsListener'
1746
+ function: 'setupLocusControlsListener',
1677
1747
  },
1678
1748
  event,
1679
1749
  this.recording
1680
1750
  );
1681
- });
1751
+ }
1752
+ );
1682
1753
 
1683
- this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_MEETING_CONTAINER_UPDATED,
1754
+ this.locusInfo.on(
1755
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_CONTAINER_UPDATED,
1684
1756
  ({meetingContainerUrl}) => {
1685
1757
  Trigger.trigger(
1686
1758
  this,
1687
1759
  {
1688
1760
  file: 'meeting/index',
1689
- function: 'setupLocusControlsListener'
1761
+ function: 'setupLocusControlsListener',
1690
1762
  },
1691
1763
  EVENT_TRIGGERS.MEETING_MEETING_CONTAINER_UPDATE,
1692
1764
  {meetingContainerUrl}
1693
1765
  );
1694
- });
1766
+ }
1767
+ );
1695
1768
 
1696
- this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIBE_UPDATED,
1769
+ this.locusInfo.on(
1770
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIBE_UPDATED,
1697
1771
  ({caption, transcribing}) => {
1698
-
1699
1772
  // @ts-ignore - config coming from registerPlugin
1700
1773
  if (transcribing && this.transcription && this.config.receiveTranscription) {
1701
1774
  this.receiveTranscription();
1702
- }
1703
- else if (!transcribing && this.transcription) {
1775
+ } else if (!transcribing && this.transcription) {
1704
1776
  Trigger.trigger(
1705
1777
  this,
1706
1778
  {
1707
1779
  file: 'meeting/index',
1708
- function: 'setupLocusControlsListener'
1780
+ function: 'setupLocusControlsListener',
1709
1781
  },
1710
1782
  EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION,
1711
1783
  {caption, transcribing}
1712
1784
  );
1713
1785
  }
1714
- });
1786
+ }
1787
+ );
1715
1788
 
1716
- this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED,
1717
- ({entryExitTone}) => {
1718
- Trigger.trigger(
1719
- this,
1720
- {
1721
- file: 'meeting/index',
1722
- function: 'setupLocusControlsListener'
1723
- },
1724
- EVENT_TRIGGERS.MEETING_ENTRY_EXIT_TONE_UPDATE,
1725
- {entryExitTone}
1726
- );
1727
- });
1789
+ this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_ENTRY_EXIT_TONE_UPDATED, ({entryExitTone}) => {
1790
+ Trigger.trigger(
1791
+ this,
1792
+ {
1793
+ file: 'meeting/index',
1794
+ function: 'setupLocusControlsListener',
1795
+ },
1796
+ EVENT_TRIGGERS.MEETING_ENTRY_EXIT_TONE_UPDATE,
1797
+ {entryExitTone}
1798
+ );
1799
+ });
1728
1800
  }
1729
1801
 
1730
1802
  /**
@@ -1735,7 +1807,7 @@ export default class Meeting extends StatelessWebexPlugin {
1735
1807
  * @private
1736
1808
  * @memberof Meeting
1737
1809
  */
1738
- private setUpLocusMediaSharesListener() {
1810
+ private setUpLocusMediaSharesListener() {
1739
1811
  // Will get triggered on local and remote share
1740
1812
  this.locusInfo.on(EVENTS.LOCUS_INFO_UPDATE_MEDIA_SHARES, (payload) => {
1741
1813
  const {content: contentShare, whiteboard: whiteboardShare} = payload.current;
@@ -1743,11 +1815,11 @@ export default class Meeting extends StatelessWebexPlugin {
1743
1815
  const previousWhiteboardShare = payload.previous?.whiteboard;
1744
1816
 
1745
1817
  if (
1746
- (contentShare.beneficiaryId === previousContentShare?.beneficiaryId &&
1747
- contentShare.disposition === previousContentShare?.disposition) &&
1748
- (whiteboardShare.beneficiaryId === previousWhiteboardShare?.beneficiaryId &&
1749
- whiteboardShare.disposition === previousWhiteboardShare?.disposition &&
1750
- whiteboardShare.resourceUrl === previousWhiteboardShare?.resourceUrl)
1818
+ contentShare.beneficiaryId === previousContentShare?.beneficiaryId &&
1819
+ contentShare.disposition === previousContentShare?.disposition &&
1820
+ whiteboardShare.beneficiaryId === previousWhiteboardShare?.beneficiaryId &&
1821
+ whiteboardShare.disposition === previousWhiteboardShare?.disposition &&
1822
+ whiteboardShare.resourceUrl === previousWhiteboardShare?.resourceUrl
1751
1823
  ) {
1752
1824
  // nothing changed, so ignore
1753
1825
  // (this happens when we steal presentation from remote)
@@ -1771,13 +1843,14 @@ export default class Meeting extends StatelessWebexPlugin {
1771
1843
  ) {
1772
1844
  if (this.mediaProperties.shareTrack?.readyState === 'ended') {
1773
1845
  this.stopShare({
1774
- skipSignalingCheck: true
1775
- })
1776
- .catch((error) => {
1777
- LoggerProxy.logger.log('Meeting:index#setUpLocusMediaSharesListener --> Error stopping share: ', error);
1778
- });
1779
- }
1780
- else {
1846
+ skipSignalingCheck: true,
1847
+ }).catch((error) => {
1848
+ LoggerProxy.logger.log(
1849
+ 'Meeting:index#setUpLocusMediaSharesListener --> Error stopping share: ',
1850
+ error
1851
+ );
1852
+ });
1853
+ } else {
1781
1854
  // CONTENT - sharing content local
1782
1855
  newShareStatus = SHARE_STATUS.LOCAL_SHARE_ACTIVE;
1783
1856
  }
@@ -1791,10 +1864,10 @@ export default class Meeting extends StatelessWebexPlugin {
1791
1864
  }
1792
1865
  // or if content share is either released or null and whiteboard share is either released or null, no one is sharing
1793
1866
  else if (
1794
- (previousContentShare &&
1795
- (contentShare.disposition === FLOOR_ACTION.RELEASED) || (contentShare.disposition === null)) &&
1796
- (previousWhiteboardShare &&
1797
- (whiteboardShare.disposition === FLOOR_ACTION.RELEASED) || (whiteboardShare.disposition === null))
1867
+ ((previousContentShare && contentShare.disposition === FLOOR_ACTION.RELEASED) ||
1868
+ contentShare.disposition === null) &&
1869
+ ((previousWhiteboardShare && whiteboardShare.disposition === FLOOR_ACTION.RELEASED) ||
1870
+ whiteboardShare.disposition === null)
1798
1871
  ) {
1799
1872
  newShareStatus = SHARE_STATUS.NO_SHARE;
1800
1873
  }
@@ -1812,7 +1885,7 @@ export default class Meeting extends StatelessWebexPlugin {
1812
1885
  this,
1813
1886
  {
1814
1887
  file: 'meetings/index',
1815
- function: 'remoteShare'
1888
+ function: 'remoteShare',
1816
1889
  },
1817
1890
  EVENT_TRIGGERS.MEETING_STOPPED_SHARING_REMOTE
1818
1891
  );
@@ -1823,11 +1896,11 @@ export default class Meeting extends StatelessWebexPlugin {
1823
1896
  this,
1824
1897
  {
1825
1898
  file: 'meeting/index',
1826
- function: 'localShare'
1899
+ function: 'localShare',
1827
1900
  },
1828
1901
  EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
1829
1902
  {
1830
- reason: SHARE_STOPPED_REASON.SELF_STOPPED
1903
+ reason: SHARE_STOPPED_REASON.SELF_STOPPED,
1831
1904
  }
1832
1905
  );
1833
1906
  break;
@@ -1837,7 +1910,7 @@ export default class Meeting extends StatelessWebexPlugin {
1837
1910
  this,
1838
1911
  {
1839
1912
  file: 'meeting/index',
1840
- function: 'stopWhiteboardShare'
1913
+ function: 'stopWhiteboardShare',
1841
1914
  },
1842
1915
  EVENT_TRIGGERS.MEETING_STOPPED_SHARING_WHITEBOARD
1843
1916
  );
@@ -1859,27 +1932,28 @@ export default class Meeting extends StatelessWebexPlugin {
1859
1932
  this,
1860
1933
  {
1861
1934
  file: 'meetings/index',
1862
- function: 'remoteShare'
1935
+ function: 'remoteShare',
1863
1936
  },
1864
1937
  EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
1865
1938
  {
1866
- memberId: contentShare.beneficiaryId
1939
+ memberId: contentShare.beneficiaryId,
1867
1940
  }
1868
1941
  );
1869
1942
  };
1870
1943
 
1871
1944
  // if a remote participant is stealing the presentation from us
1872
- if (!this.mediaProperties.mediaDirection?.sendShare || oldShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE) {
1945
+ if (
1946
+ !this.mediaProperties.mediaDirection?.sendShare ||
1947
+ oldShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE
1948
+ ) {
1873
1949
  sendStartedSharingRemote();
1874
- }
1875
- else {
1950
+ } else {
1876
1951
  this.updateShare({
1877
1952
  sendShare: false,
1878
- receiveShare: this.mediaProperties.mediaDirection.receiveShare
1879
- })
1880
- .finally(() => {
1881
- sendStartedSharingRemote();
1882
- });
1953
+ receiveShare: this.mediaProperties.mediaDirection.receiveShare,
1954
+ }).finally(() => {
1955
+ sendStartedSharingRemote();
1956
+ });
1883
1957
  }
1884
1958
  break;
1885
1959
  }
@@ -1889,9 +1963,9 @@ export default class Meeting extends StatelessWebexPlugin {
1889
1963
  this,
1890
1964
  {
1891
1965
  file: 'meeting/index',
1892
- function: 'share'
1966
+ function: 'share',
1893
1967
  },
1894
- EVENT_TRIGGERS.MEETING_STARTED_SHARING_LOCAL,
1968
+ EVENT_TRIGGERS.MEETING_STARTED_SHARING_LOCAL
1895
1969
  );
1896
1970
  Metrics.postEvent({event: eventType.LOCAL_SHARE_FLOOR_GRANTED, meeting: this});
1897
1971
  break;
@@ -1901,19 +1975,19 @@ export default class Meeting extends StatelessWebexPlugin {
1901
1975
  this,
1902
1976
  {
1903
1977
  file: 'meeting/index',
1904
- function: 'startWhiteboardShare'
1978
+ function: 'startWhiteboardShare',
1905
1979
  },
1906
1980
  EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
1907
1981
  {
1908
1982
  resourceUrl: whiteboardShare.resourceUrl,
1909
- memberId: whiteboardShare.beneficiaryId
1983
+ memberId: whiteboardShare.beneficiaryId,
1910
1984
  }
1911
1985
  );
1912
1986
  Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_FLOOR_GRANTED, meeting: this});
1913
1987
  break;
1914
1988
 
1915
1989
  case SHARE_STATUS.NO_SHARE:
1916
- // nothing to do
1990
+ // nothing to do
1917
1991
  break;
1918
1992
 
1919
1993
  default:
@@ -1921,36 +1995,34 @@ export default class Meeting extends StatelessWebexPlugin {
1921
1995
  }
1922
1996
 
1923
1997
  this.members.locusMediaSharesUpdate(payload);
1924
- }
1925
- else if (newShareStatus === SHARE_STATUS.REMOTE_SHARE_ACTIVE) {
1998
+ } else if (newShareStatus === SHARE_STATUS.REMOTE_SHARE_ACTIVE) {
1926
1999
  // if we got here, then some remote participant has stolen
1927
2000
  // the presentation from another remote participant
1928
2001
  Trigger.trigger(
1929
2002
  this,
1930
2003
  {
1931
2004
  file: 'meetings/index',
1932
- function: 'remoteShare'
2005
+ function: 'remoteShare',
1933
2006
  },
1934
2007
  EVENT_TRIGGERS.MEETING_STARTED_SHARING_REMOTE,
1935
2008
  {
1936
- memberId: contentShare.beneficiaryId
2009
+ memberId: contentShare.beneficiaryId,
1937
2010
  }
1938
2011
  );
1939
2012
  this.members.locusMediaSharesUpdate(payload);
1940
- }
1941
- else if (newShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE) {
2013
+ } else if (newShareStatus === SHARE_STATUS.WHITEBOARD_SHARE_ACTIVE) {
1942
2014
  // if we got here, then some remote participant has stolen
1943
2015
  // the presentation from another remote participant
1944
2016
  Trigger.trigger(
1945
2017
  this,
1946
2018
  {
1947
2019
  file: 'meeting/index',
1948
- function: 'startWhiteboardShare'
2020
+ function: 'startWhiteboardShare',
1949
2021
  },
1950
2022
  EVENT_TRIGGERS.MEETING_STARTED_SHARING_WHITEBOARD,
1951
2023
  {
1952
2024
  resourceUrl: whiteboardShare.resourceUrl,
1953
- memberId: whiteboardShare.beneficiaryId
2025
+ memberId: whiteboardShare.beneficiaryId,
1954
2026
  }
1955
2027
  );
1956
2028
  Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_FLOOR_GRANTED, meeting: this});
@@ -1987,11 +2059,11 @@ export default class Meeting extends StatelessWebexPlugin {
1987
2059
  this,
1988
2060
  {
1989
2061
  file: 'meeting/index',
1990
- function: 'setUpLocusInfoMeetingInfoListener'
2062
+ function: 'setUpLocusInfoMeetingInfoListener',
1991
2063
  },
1992
2064
  EVENT_TRIGGERS.MEETING_LOCKED,
1993
2065
  {
1994
- payload
2066
+ payload,
1995
2067
  }
1996
2068
  );
1997
2069
  }
@@ -2002,11 +2074,11 @@ export default class Meeting extends StatelessWebexPlugin {
2002
2074
  this,
2003
2075
  {
2004
2076
  file: 'meeting/index',
2005
- function: 'setUpLocusInfoMeetingInfoListener'
2077
+ function: 'setUpLocusInfoMeetingInfoListener',
2006
2078
  },
2007
2079
  EVENT_TRIGGERS.MEETING_UNLOCKED,
2008
2080
  {
2009
- payload
2081
+ payload,
2010
2082
  }
2011
2083
  );
2012
2084
  }
@@ -2014,7 +2086,9 @@ export default class Meeting extends StatelessWebexPlugin {
2014
2086
  this.locusInfo.on(LOCUSINFO.EVENTS.MEETING_INFO_UPDATED, (payload) => {
2015
2087
  if (payload && payload.info) {
2016
2088
  const changed = this.inMeetingActions.set({
2017
- canInviteNewParticipants: MeetingUtil.canInviteNewParticipants(payload.info.userDisplayHints),
2089
+ canInviteNewParticipants: MeetingUtil.canInviteNewParticipants(
2090
+ payload.info.userDisplayHints
2091
+ ),
2018
2092
  canAdmitParticipant: MeetingUtil.canAdmitParticipant(payload.info.userDisplayHints),
2019
2093
  canLock: MeetingUtil.canUserLock(payload.info.userDisplayHints),
2020
2094
  canUnlock: MeetingUtil.canUserUnlock(payload.info.userDisplayHints),
@@ -2024,16 +2098,24 @@ export default class Meeting extends StatelessWebexPlugin {
2024
2098
  canResumeRecording: MeetingUtil.canUserResume(payload.info.userDisplayHints),
2025
2099
  canRaiseHand: MeetingUtil.canUserRaiseHand(payload.info.userDisplayHints),
2026
2100
  canLowerAllHands: MeetingUtil.canUserLowerAllHands(payload.info.userDisplayHints),
2027
- canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(payload.info.userDisplayHints),
2028
- bothLeaveAndEndMeetingAvailable: MeetingUtil.bothLeaveAndEndMeetingAvailable(payload.info.userDisplayHints),
2101
+ canLowerSomeoneElsesHand: MeetingUtil.canUserLowerSomeoneElsesHand(
2102
+ payload.info.userDisplayHints
2103
+ ),
2104
+ bothLeaveAndEndMeetingAvailable: MeetingUtil.bothLeaveAndEndMeetingAvailable(
2105
+ payload.info.userDisplayHints
2106
+ ),
2029
2107
  canEnableClosedCaption: MeetingUtil.canEnableClosedCaption(payload.info.userDisplayHints),
2030
2108
  canStartTranscribing: MeetingUtil.canStartTranscribing(payload.info.userDisplayHints),
2031
2109
  canStopTranscribing: MeetingUtil.canStopTranscribing(payload.info.userDisplayHints),
2032
2110
  isClosedCaptionActive: MeetingUtil.isClosedCaptionActive(payload.info.userDisplayHints),
2033
2111
  isWebexAssistantActive: MeetingUtil.isWebexAssistantActive(payload.info.userDisplayHints),
2034
2112
  canViewCaptionPanel: MeetingUtil.canViewCaptionPanel(payload.info.userDisplayHints),
2035
- isRealTimeTranslationEnabled: MeetingUtil.isRealTimeTranslationEnabled(payload.info.userDisplayHints),
2036
- canSelectSpokenLanguages: MeetingUtil.canSelectSpokenLanguages(payload.info.userDisplayHints),
2113
+ isRealTimeTranslationEnabled: MeetingUtil.isRealTimeTranslationEnabled(
2114
+ payload.info.userDisplayHints
2115
+ ),
2116
+ canSelectSpokenLanguages: MeetingUtil.canSelectSpokenLanguages(
2117
+ payload.info.userDisplayHints
2118
+ ),
2037
2119
  waitingForOthersToJoin: MeetingUtil.waitingForOthersToJoin(payload.info.userDisplayHints),
2038
2120
  });
2039
2121
 
@@ -2042,7 +2124,7 @@ export default class Meeting extends StatelessWebexPlugin {
2042
2124
  this,
2043
2125
  {
2044
2126
  file: 'meeting/index',
2045
- function: 'setUpLocusInfoMeetingInfoListener'
2127
+ function: 'setUpLocusInfoMeetingInfoListener',
2046
2128
  },
2047
2129
  EVENT_TRIGGERS.MEETING_ACTIONS_UPDATE,
2048
2130
  this.inMeetingActions.get()
@@ -2082,7 +2164,7 @@ export default class Meeting extends StatelessWebexPlugin {
2082
2164
  this,
2083
2165
  {
2084
2166
  file: 'meeting/index',
2085
- function: 'setUpLocusEmbeddedAppsListener'
2167
+ function: 'setUpLocusEmbeddedAppsListener',
2086
2168
  },
2087
2169
  EVENT_TRIGGERS.MEETING_EMBEDDED_APPS_UPDATE,
2088
2170
  embeddedApps
@@ -2105,11 +2187,11 @@ export default class Meeting extends StatelessWebexPlugin {
2105
2187
  this,
2106
2188
  {
2107
2189
  file: 'meeting/index',
2108
- function: 'setUpLocusInfoSelfListener'
2190
+ function: 'setUpLocusInfoSelfListener',
2109
2191
  },
2110
2192
  EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
2111
2193
  {
2112
- payload
2194
+ payload,
2113
2195
  }
2114
2196
  );
2115
2197
  }
@@ -2122,17 +2204,19 @@ export default class Meeting extends StatelessWebexPlugin {
2122
2204
  // with "mute on entry" server will send us remote mute even if we don't have media configured,
2123
2205
  // so if being muted by others, always send the notification,
2124
2206
  // but if being unmuted, only send it if we are also locally unmuted
2125
- if (payload.muted || (!this.audio?.isMuted())) {
2207
+ if (payload.muted || !this.audio?.isMuted()) {
2126
2208
  Trigger.trigger(
2127
2209
  this,
2128
2210
  {
2129
2211
  file: 'meeting/index',
2130
- function: 'setUpLocusInfoSelfListener'
2212
+ function: 'setUpLocusInfoSelfListener',
2131
2213
  },
2132
- payload.muted ? EVENT_TRIGGERS.MEETING_SELF_MUTED_BY_OTHERS : EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
2214
+ payload.muted
2215
+ ? EVENT_TRIGGERS.MEETING_SELF_MUTED_BY_OTHERS
2216
+ : EVENT_TRIGGERS.MEETING_SELF_UNMUTED_BY_OTHERS,
2133
2217
  {
2134
- payload
2135
- },
2218
+ payload,
2219
+ }
2136
2220
  );
2137
2221
  }
2138
2222
  }
@@ -2142,11 +2226,11 @@ export default class Meeting extends StatelessWebexPlugin {
2142
2226
  this,
2143
2227
  {
2144
2228
  file: 'meeting/index',
2145
- function: 'setUpLocusInfoSelfListener'
2229
+ function: 'setUpLocusInfoSelfListener',
2146
2230
  },
2147
2231
  EVENT_TRIGGERS.MEETING_SELF_REQUESTED_TO_UNMUTE,
2148
2232
  {
2149
- payload
2233
+ payload,
2150
2234
  }
2151
2235
  );
2152
2236
  });
@@ -2158,17 +2242,17 @@ export default class Meeting extends StatelessWebexPlugin {
2158
2242
  this,
2159
2243
  {
2160
2244
  file: 'meeting/index',
2161
- function: 'setUpLocusInfoSelfListener'
2245
+ function: 'setUpLocusInfoSelfListener',
2162
2246
  },
2163
2247
  EVENT_TRIGGERS.MEETING_SELF_LOBBY_WAITING,
2164
2248
  {
2165
- payload
2249
+ payload,
2166
2250
  }
2167
2251
  );
2168
2252
 
2169
2253
  Metrics.postEvent({
2170
2254
  event: eventType.LOBBY_ENTERED,
2171
- meeting: this
2255
+ meeting: this,
2172
2256
  });
2173
2257
  }
2174
2258
  });
@@ -2180,30 +2264,27 @@ export default class Meeting extends StatelessWebexPlugin {
2180
2264
  this,
2181
2265
  {
2182
2266
  file: 'meeting/index',
2183
- function: 'setUpLocusInfoSelfListener'
2267
+ function: 'setUpLocusInfoSelfListener',
2184
2268
  },
2185
2269
  EVENT_TRIGGERS.MEETING_SELF_GUEST_ADMITTED,
2186
2270
  {
2187
- payload
2271
+ payload,
2188
2272
  }
2189
2273
  );
2190
2274
 
2191
2275
  Metrics.postEvent({
2192
2276
  event: eventType.LOBBY_EXITED,
2193
- meeting: this
2277
+ meeting: this,
2194
2278
  });
2195
2279
  }
2196
2280
  });
2197
2281
 
2198
2282
  // @ts-ignore - check if MEDIA_INACTIVITY exists
2199
2283
  this.locusInfo.on(LOCUSINFO.EVENTS.MEDIA_INACTIVITY, () => {
2200
- Metrics.sendBehavioralMetric(
2201
- BEHAVIORAL_METRICS.MEETING_MEDIA_INACTIVE,
2202
- {
2203
- correlation_id: this.correlationId,
2204
- locus_id: this.locusId
2205
- }
2206
- );
2284
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_MEDIA_INACTIVE, {
2285
+ correlation_id: this.correlationId,
2286
+ locus_id: this.locusId,
2287
+ });
2207
2288
  this.reconnect();
2208
2289
  });
2209
2290
 
@@ -2221,8 +2302,8 @@ export default class Meeting extends StatelessWebexPlugin {
2221
2302
  sendShare: this.mediaProperties.mediaDirection?.sendShare,
2222
2303
  receiveAudio: this.mediaProperties.mediaDirection?.receiveAudio,
2223
2304
  receiveVideo: this.mediaProperties.mediaDirection?.receiveVideo,
2224
- receiveShare: this.mediaProperties.mediaDirection?.receiveShare
2225
- }
2305
+ receiveShare: this.mediaProperties.mediaDirection?.receiveShare,
2306
+ },
2226
2307
  });
2227
2308
  }
2228
2309
  });
@@ -2232,11 +2313,11 @@ export default class Meeting extends StatelessWebexPlugin {
2232
2313
  this,
2233
2314
  {
2234
2315
  file: 'meeting/index',
2235
- function: 'setUpLocusInfoSelfListener'
2316
+ function: 'setUpLocusInfoSelfListener',
2236
2317
  },
2237
2318
  EVENT_TRIGGERS.MEETING_SELF_CANNOT_VIEW_PARTICIPANT_LIST,
2238
2319
  {
2239
- payload
2320
+ payload,
2240
2321
  }
2241
2322
  );
2242
2323
  });
@@ -2246,11 +2327,11 @@ export default class Meeting extends StatelessWebexPlugin {
2246
2327
  this,
2247
2328
  {
2248
2329
  file: 'meeting/index',
2249
- function: 'setUpLocusInfoSelfListener'
2330
+ function: 'setUpLocusInfoSelfListener',
2250
2331
  },
2251
2332
  EVENT_TRIGGERS.MEETING_SELF_IS_SHARING_BLOCKED,
2252
2333
  {
2253
- payload
2334
+ payload,
2254
2335
  }
2255
2336
  );
2256
2337
  });
@@ -2267,12 +2348,18 @@ export default class Meeting extends StatelessWebexPlugin {
2267
2348
  this.meetingFiniteStateMachine.remote(payload);
2268
2349
 
2269
2350
  if (payload.remoteDeclined) {
2270
- this.leave({reason: payload.reason}).then(() => {
2271
- LoggerProxy.logger.info('Meeting:index#setUpLocusInfoMeetingListener --> REMOTE_RESPONSE. Attempting to leave meeting.');
2272
- }).catch((error) => {
2273
- // @ts-ignore
2274
- LoggerProxy.logger.error(`Meeting:index#setUpLocusInfoMeetingListener --> REMOTE_RESPONSE. Issue with leave for meeting, meeting still in collection: ${this.meeting}, error: ${error}`);
2275
- });
2351
+ this.leave({reason: payload.reason})
2352
+ .then(() => {
2353
+ LoggerProxy.logger.info(
2354
+ 'Meeting:index#setUpLocusInfoMeetingListener --> REMOTE_RESPONSE. Attempting to leave meeting.'
2355
+ );
2356
+ })
2357
+ .catch((error) => {
2358
+ // @ts-ignore
2359
+ LoggerProxy.logger.error(
2360
+ `Meeting:index#setUpLocusInfoMeetingListener --> REMOTE_RESPONSE. Issue with leave for meeting, meeting still in collection: ${this.meeting}, error: ${error}`
2361
+ );
2362
+ });
2276
2363
  }
2277
2364
  });
2278
2365
  this.locusInfo.on(EVENTS.DESTROY_MEETING, (payload) => {
@@ -2296,27 +2383,35 @@ export default class Meeting extends StatelessWebexPlugin {
2296
2383
  if (payload.shouldLeave) {
2297
2384
  // TODO: We should do cleaning of meeting object if the shouldLeave: false because there might be meeting object which we are not cleaning
2298
2385
 
2299
- this.leave({reason: payload.reason}).then(() => {
2300
- LoggerProxy.logger.warn('Meeting:index#setUpLocusInfoMeetingListener --> DESTROY_MEETING. The meeting has been left, but has not been destroyed, you should see a later event for leave.');
2301
- }).catch((error) => {
2302
- // @ts-ignore
2303
- LoggerProxy.logger.error(`Meeting:index#setUpLocusInfoMeetingListener --> DESTROY_MEETING. Issue with leave for meeting, meeting still in collection: ${this.meeting}, error: ${error}`);
2304
- });
2305
- }
2306
- else {
2307
- LoggerProxy.logger.info('Meeting:index#setUpLocusInfoMeetingListener --> MEETING_REMOVED_REASON', payload.reason);
2386
+ this.leave({reason: payload.reason})
2387
+ .then(() => {
2388
+ LoggerProxy.logger.warn(
2389
+ 'Meeting:index#setUpLocusInfoMeetingListener --> DESTROY_MEETING. The meeting has been left, but has not been destroyed, you should see a later event for leave.'
2390
+ );
2391
+ })
2392
+ .catch((error) => {
2393
+ // @ts-ignore
2394
+ LoggerProxy.logger.error(
2395
+ `Meeting:index#setUpLocusInfoMeetingListener --> DESTROY_MEETING. Issue with leave for meeting, meeting still in collection: ${this.meeting}, error: ${error}`
2396
+ );
2397
+ });
2398
+ } else {
2399
+ LoggerProxy.logger.info(
2400
+ 'Meeting:index#setUpLocusInfoMeetingListener --> MEETING_REMOVED_REASON',
2401
+ payload.reason
2402
+ );
2308
2403
 
2309
2404
  MeetingUtil.cleanUp(this);
2310
2405
  Trigger.trigger(
2311
2406
  this,
2312
2407
  {
2313
2408
  file: 'meeting/index',
2314
- function: 'setUpLocusInfoMeetingListener'
2409
+ function: 'setUpLocusInfoMeetingListener',
2315
2410
  },
2316
2411
  EVENTS.DESTROY_MEETING,
2317
2412
  {
2318
2413
  reason: payload.reason,
2319
- meetingId: this.id
2414
+ meetingId: this.id,
2320
2415
  }
2321
2416
  );
2322
2417
  }
@@ -2359,7 +2454,7 @@ export default class Meeting extends StatelessWebexPlugin {
2359
2454
  email: string;
2360
2455
  phoneNumber: string;
2361
2456
  },
2362
- alertIfActive: boolean = true
2457
+ alertIfActive = true
2363
2458
  ) {
2364
2459
  return this.members.addMember(invitee, alertIfActive);
2365
2460
  }
@@ -2372,7 +2467,7 @@ export default class Meeting extends StatelessWebexPlugin {
2372
2467
  * @public
2373
2468
  * @memberof Meeting
2374
2469
  */
2375
- public cancelPhoneInvite(invitee: { phoneNumber: string }) {
2470
+ public cancelPhoneInvite(invitee: {phoneNumber: string}) {
2376
2471
  return this.members.cancelPhoneInvite(invitee);
2377
2472
  }
2378
2473
 
@@ -2406,7 +2501,7 @@ export default class Meeting extends StatelessWebexPlugin {
2406
2501
  * @public
2407
2502
  * @memberof Meeting
2408
2503
  */
2409
- public mute(memberId: string, mute: boolean = true) {
2504
+ public mute(memberId: string, mute = true) {
2410
2505
  return this.members.muteMember(memberId, mute);
2411
2506
  }
2412
2507
 
@@ -2418,7 +2513,7 @@ export default class Meeting extends StatelessWebexPlugin {
2418
2513
  * @public
2419
2514
  * @memberof Meeting
2420
2515
  */
2421
- public transfer(memberId: string, moderator: boolean = true) {
2516
+ public transfer(memberId: string, moderator = true) {
2422
2517
  return this.members.transferHostToMember(memberId, moderator);
2423
2518
  }
2424
2519
 
@@ -2506,14 +2601,16 @@ export default class Meeting extends StatelessWebexPlugin {
2506
2601
  * @memberof Meeting
2507
2602
  */
2508
2603
  parseMeetingInfo(
2509
- meetingInfo: {
2510
- body: {
2511
- conversationUrl: string;
2512
- locusUrl: string;
2513
- sipUri: string;
2514
- owner: object;
2515
- };
2516
- } | any,
2604
+ meetingInfo:
2605
+ | {
2606
+ body: {
2607
+ conversationUrl: string;
2608
+ locusUrl: string;
2609
+ sipUri: string;
2610
+ owner: object;
2611
+ };
2612
+ }
2613
+ | any,
2517
2614
  destination: object | string | null = null
2518
2615
  ) {
2519
2616
  const webexMeetingInfo = meetingInfo?.body;
@@ -2526,17 +2623,32 @@ export default class Meeting extends StatelessWebexPlugin {
2526
2623
  }
2527
2624
 
2528
2625
  // MeetingInfo will be undefined for 1:1 calls
2529
- if (locusMeetingObject || (webexMeetingInfo && !(meetingInfo?.errors && meetingInfo?.errors.length > 0))) {
2530
- this.conversationUrl = locusMeetingObject?.conversationUrl || webexMeetingInfo?.conversationUrl || this.conversationUrl;
2626
+ if (
2627
+ locusMeetingObject ||
2628
+ (webexMeetingInfo && !(meetingInfo?.errors && meetingInfo?.errors.length > 0))
2629
+ ) {
2630
+ this.conversationUrl =
2631
+ locusMeetingObject?.conversationUrl ||
2632
+ webexMeetingInfo?.conversationUrl ||
2633
+ this.conversationUrl;
2531
2634
  this.locusUrl = locusMeetingObject?.url || webexMeetingInfo?.locusUrl || this.locusUrl;
2532
2635
  // @ts-ignore - config coming from registerPlugin
2533
- this.setSipUri(this.config.experimental.enableUnifiedMeetings ? locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipUrl : locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipMeetingUri || this.sipUri);
2636
+ this.setSipUri(
2637
+ this.config.experimental.enableUnifiedMeetings
2638
+ ? locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipUrl
2639
+ : locusMeetingObject?.info.sipUri || webexMeetingInfo?.sipMeetingUri || this.sipUri
2640
+ );
2534
2641
  // @ts-ignore - config coming from registerPlugin
2535
2642
  if (this.config.experimental.enableUnifiedMeetings) {
2536
- this.meetingNumber = locusMeetingObject?.info.webExMeetingId || webexMeetingInfo?.meetingNumber;
2643
+ this.meetingNumber =
2644
+ locusMeetingObject?.info.webExMeetingId || webexMeetingInfo?.meetingNumber;
2537
2645
  this.meetingJoinUrl = webexMeetingInfo?.meetingJoinUrl;
2538
2646
  }
2539
- this.owner = locusMeetingObject?.info.owner || webexMeetingInfo?.owner || webexMeetingInfo?.hostId || this.owner;
2647
+ this.owner =
2648
+ locusMeetingObject?.info.owner ||
2649
+ webexMeetingInfo?.owner ||
2650
+ webexMeetingInfo?.hostId ||
2651
+ this.owner;
2540
2652
  this.permissionToken = webexMeetingInfo?.permissionToken;
2541
2653
  }
2542
2654
  }
@@ -2551,7 +2663,7 @@ export default class Meeting extends StatelessWebexPlugin {
2551
2663
  * @private
2552
2664
  * @memberof Meeting
2553
2665
  */
2554
- private parseLocus(locus: { url: string; participants: Array<any>; self: object }) {
2666
+ private parseLocus(locus: {url: string; participants: Array<any>; self: object}) {
2555
2667
  if (locus) {
2556
2668
  this.locusUrl = locus.url;
2557
2669
  // TODO: move this to parse participants module
@@ -2596,13 +2708,17 @@ export default class Meeting extends StatelessWebexPlugin {
2596
2708
  * @private
2597
2709
  * @memberof Meeting
2598
2710
  */
2599
- private setLocus(locus: {
2600
- mediaConnections: Array<any>;
2601
- locusUrl: string;
2602
- locusId: string;
2603
- mediaId: string;
2604
- host: object;
2605
- } | any) {
2711
+ private setLocus(
2712
+ locus:
2713
+ | {
2714
+ mediaConnections: Array<any>;
2715
+ locusUrl: string;
2716
+ locusId: string;
2717
+ mediaId: string;
2718
+ host: object;
2719
+ }
2720
+ | any
2721
+ ) {
2606
2722
  const mtgLocus: any = locus.locus || locus;
2607
2723
 
2608
2724
  // LocusInfo object saves the locus object
@@ -2623,13 +2739,8 @@ export default class Meeting extends StatelessWebexPlugin {
2623
2739
  * @public
2624
2740
  * @memberof Meeting
2625
2741
  */
2626
- public uploadLogs(options: object = { file: 'meeting/index', function: 'uploadLogs' }) {
2627
- Trigger.trigger(
2628
- this,
2629
- options,
2630
- EVENTS.REQUEST_UPLOAD_LOGS,
2631
- this
2632
- );
2742
+ public uploadLogs(options: object = {file: 'meeting/index', function: 'uploadLogs'}) {
2743
+ Trigger.trigger(this, options, EVENTS.REQUEST_UPLOAD_LOGS, this);
2633
2744
  }
2634
2745
 
2635
2746
  /**
@@ -2641,7 +2752,9 @@ export default class Meeting extends StatelessWebexPlugin {
2641
2752
  * @deprecated after v1.89.3
2642
2753
  */
2643
2754
  public unsetRemoteStream() {
2644
- LoggerProxy.logger.warn('Meeting:index#unsetRemoteStream --> [DEPRECATION WARNING]: unsetRemoteStream has been deprecated after v1.89.3');
2755
+ LoggerProxy.logger.warn(
2756
+ 'Meeting:index#unsetRemoteStream --> [DEPRECATION WARNING]: unsetRemoteStream has been deprecated after v1.89.3'
2757
+ );
2645
2758
  this.mediaProperties.unsetRemoteMedia();
2646
2759
  }
2647
2760
 
@@ -2662,7 +2775,9 @@ export default class Meeting extends StatelessWebexPlugin {
2662
2775
  * @deprecated after v1.89.3
2663
2776
  */
2664
2777
  public closeRemoteStream() {
2665
- LoggerProxy.logger.warn('Meeting:index#closeRemoteStream --> [DEPRECATION WARNING]: closeRemoteStream has been deprecated after v1.89.3');
2778
+ LoggerProxy.logger.warn(
2779
+ 'Meeting:index#closeRemoteStream --> [DEPRECATION WARNING]: closeRemoteStream has been deprecated after v1.89.3'
2780
+ );
2666
2781
  this.closeRemoteTracks();
2667
2782
  }
2668
2783
 
@@ -2673,11 +2788,7 @@ export default class Meeting extends StatelessWebexPlugin {
2673
2788
  * @memberof Meeting
2674
2789
  */
2675
2790
  closeRemoteTracks() {
2676
- const {
2677
- remoteAudioTrack,
2678
- remoteVideoTrack,
2679
- remoteShare
2680
- } = this.mediaProperties;
2791
+ const {remoteAudioTrack, remoteVideoTrack, remoteShare} = this.mediaProperties;
2681
2792
 
2682
2793
  /**
2683
2794
  * Triggers an event to the developer
@@ -2685,16 +2796,17 @@ export default class Meeting extends StatelessWebexPlugin {
2685
2796
  * @returns {void}
2686
2797
  * @inner
2687
2798
  */
2799
+ // eslint-disable-next-line @typescript-eslint/no-shadow
2688
2800
  const triggerMediaStoppedEvent = (mediaType: string) => {
2689
2801
  Trigger.trigger(
2690
2802
  this,
2691
2803
  {
2692
2804
  file: 'meeting/index',
2693
- function: 'closeRemoteTracks'
2805
+ function: 'closeRemoteTracks',
2694
2806
  },
2695
2807
  EVENT_TRIGGERS.MEDIA_STOPPED,
2696
2808
  {
2697
- type: mediaType
2809
+ type: mediaType,
2698
2810
  }
2699
2811
  );
2700
2812
  };
@@ -2708,24 +2820,24 @@ export default class Meeting extends StatelessWebexPlugin {
2708
2820
  */
2709
2821
  // eslint-disable-next-line arrow-body-style
2710
2822
  const stopTrack = (track: MediaStreamTrack, type: string) => {
2711
- return Media.stopTracks(track)
2712
- .then(() => {
2713
- const isTrackStopped = track && track.readyState === ENDED;
2714
- const isWrongReadyState = track && !isTrackStopped;
2823
+ return Media.stopTracks(track).then(() => {
2824
+ const isTrackStopped = track && track.readyState === ENDED;
2825
+ const isWrongReadyState = track && !isTrackStopped;
2715
2826
 
2716
- if (isTrackStopped) {
2717
- triggerMediaStoppedEvent(type);
2718
- }
2719
- else if (isWrongReadyState) {
2720
- LoggerProxy.logger.warn(`Meeting:index#closeRemoteTracks --> Error: MediaStreamTrack.readyState is ${track.readyState} for ${type}`);
2721
- }
2722
- });
2827
+ if (isTrackStopped) {
2828
+ triggerMediaStoppedEvent(type);
2829
+ } else if (isWrongReadyState) {
2830
+ LoggerProxy.logger.warn(
2831
+ `Meeting:index#closeRemoteTracks --> Error: MediaStreamTrack.readyState is ${track.readyState} for ${type}`
2832
+ );
2833
+ }
2834
+ });
2723
2835
  };
2724
2836
 
2725
2837
  return Promise.all([
2726
2838
  stopTrack(remoteAudioTrack, EVENT_TYPES.REMOTE_AUDIO),
2727
2839
  stopTrack(remoteVideoTrack, EVENT_TYPES.REMOTE_VIDEO),
2728
- stopTrack(remoteShare, EVENT_TYPES.REMOTE_SHARE)
2840
+ stopTrack(remoteShare, EVENT_TYPES.REMOTE_SHARE),
2729
2841
  ]);
2730
2842
  }
2731
2843
 
@@ -2740,12 +2852,15 @@ export default class Meeting extends StatelessWebexPlugin {
2740
2852
  this,
2741
2853
  {
2742
2854
  file: 'meeting/index',
2743
- function: 'setLocalTracks'
2855
+ function: 'setLocalTracks',
2744
2856
  },
2745
2857
  EVENT_TRIGGERS.MEDIA_READY,
2746
2858
  {
2747
2859
  type: EVENT_TYPES.LOCAL,
2748
- stream: MediaUtil.createMediaStream([this.mediaProperties.audioTrack, this.mediaProperties.videoTrack])
2860
+ stream: MediaUtil.createMediaStream([
2861
+ this.mediaProperties.audioTrack,
2862
+ this.mediaProperties.videoTrack,
2863
+ ]),
2749
2864
  }
2750
2865
  );
2751
2866
  }
@@ -2758,16 +2873,19 @@ export default class Meeting extends StatelessWebexPlugin {
2758
2873
  * @private
2759
2874
  * @memberof Meeting
2760
2875
  */
2761
- private setLocalAudioTrack(audioTrack: MediaStreamTrack, emitEvent: boolean = true) {
2876
+ private setLocalAudioTrack(audioTrack: MediaStreamTrack, emitEvent = true) {
2762
2877
  if (audioTrack) {
2763
2878
  const settings = audioTrack.getSettings();
2764
2879
 
2765
2880
  this.mediaProperties.setMediaSettings('audio', {
2766
2881
  echoCancellation: settings.echoCancellation,
2767
- noiseSuppression: settings.noiseSuppression
2882
+ noiseSuppression: settings.noiseSuppression,
2768
2883
  });
2769
2884
 
2770
- LoggerProxy.logger.log('Meeting:index#setLocalAudioTrack --> Audio settings.', JSON.stringify(this.mediaProperties.mediaSettings.audio));
2885
+ LoggerProxy.logger.log(
2886
+ 'Meeting:index#setLocalAudioTrack --> Audio settings.',
2887
+ JSON.stringify(this.mediaProperties.mediaSettings.audio)
2888
+ );
2771
2889
  this.mediaProperties.setLocalAudioTrack(audioTrack);
2772
2890
  if (this.audio) this.audio.applyClientStateLocally(this);
2773
2891
  }
@@ -2785,16 +2903,15 @@ export default class Meeting extends StatelessWebexPlugin {
2785
2903
  * @private
2786
2904
  * @memberof Meeting
2787
2905
  */
2788
- private setLocalVideoTrack(videoTrack: MediaStreamTrack, emitEvent: boolean = true) {
2906
+ private setLocalVideoTrack(videoTrack: MediaStreamTrack, emitEvent = true) {
2789
2907
  if (videoTrack) {
2790
- const {
2791
- aspectRatio, frameRate, height, width, deviceId
2792
- } = videoTrack.getSettings();
2908
+ const {aspectRatio, frameRate, height, width, deviceId} = videoTrack.getSettings();
2793
2909
 
2794
2910
  const {localQualityLevel} = this.mediaProperties;
2795
2911
 
2796
2912
  if (Number(localQualityLevel.slice(0, -1)) > height) {
2797
- LoggerProxy.logger.warn(`Meeting:index#setLocalVideoTrack --> Local video quality of ${localQualityLevel} not supported,
2913
+ LoggerProxy.logger
2914
+ .warn(`Meeting:index#setLocalVideoTrack --> Local video quality of ${localQualityLevel} not supported,
2798
2915
  downscaling to highest possible resolution of ${height}p`);
2799
2916
 
2800
2917
  this.mediaProperties.setLocalQualityLevel(`${height}p`);
@@ -2804,13 +2921,19 @@ export default class Meeting extends StatelessWebexPlugin {
2804
2921
  if (this.video) this.video.applyClientStateLocally(this);
2805
2922
 
2806
2923
  this.mediaProperties.setMediaSettings('video', {
2807
- aspectRatio, frameRate, height, width
2924
+ aspectRatio,
2925
+ frameRate,
2926
+ height,
2927
+ width,
2808
2928
  });
2809
2929
  // store and save the selected video input device
2810
2930
  if (deviceId) {
2811
2931
  this.mediaProperties.setVideoDeviceId(deviceId);
2812
2932
  }
2813
- LoggerProxy.logger.log('Meeting:index#setLocalVideoTrack --> Video settings.', JSON.stringify(this.mediaProperties.mediaSettings.video));
2933
+ LoggerProxy.logger.log(
2934
+ 'Meeting:index#setLocalVideoTrack --> Video settings.',
2935
+ JSON.stringify(this.mediaProperties.mediaSettings.video)
2936
+ );
2814
2937
  }
2815
2938
 
2816
2939
  if (emitEvent) {
@@ -2858,9 +2981,12 @@ export default class Meeting extends StatelessWebexPlugin {
2858
2981
  height: settings.height,
2859
2982
  width: settings.width,
2860
2983
  displaySurface: settings.displaySurface,
2861
- cursor: settings.cursor
2984
+ cursor: settings.cursor,
2862
2985
  });
2863
- LoggerProxy.logger.log('Meeting:index#setLocalShareTrack --> Screen settings.', JSON.stringify(this.mediaProperties.mediaSettings.screen));
2986
+ LoggerProxy.logger.log(
2987
+ 'Meeting:index#setLocalShareTrack --> Screen settings.',
2988
+ JSON.stringify(this.mediaProperties.mediaSettings.screen)
2989
+ );
2864
2990
  }
2865
2991
 
2866
2992
  contentTracks.onended = () => this.handleShareTrackEnded(localShare);
@@ -2869,12 +2995,12 @@ export default class Meeting extends StatelessWebexPlugin {
2869
2995
  this,
2870
2996
  {
2871
2997
  file: 'meeting/index',
2872
- function: 'setLocalShareTrack'
2998
+ function: 'setLocalShareTrack',
2873
2999
  },
2874
3000
  EVENT_TRIGGERS.MEDIA_READY,
2875
3001
  {
2876
3002
  type: EVENT_TYPES.LOCAL_SHARE,
2877
- stream: localShare
3003
+ stream: localShare,
2878
3004
  }
2879
3005
  );
2880
3006
  }
@@ -2902,15 +3028,17 @@ export default class Meeting extends StatelessWebexPlugin {
2902
3028
  this,
2903
3029
  {
2904
3030
  file: 'meeting/index',
2905
- function: 'closeLocalStream'
3031
+ function: 'closeLocalStream',
2906
3032
  },
2907
- EVENT_TRIGGERS.MEDIA_STOPPED, {
2908
- type: EVENT_TYPES.LOCAL
3033
+ EVENT_TRIGGERS.MEDIA_STOPPED,
3034
+ {
3035
+ type: EVENT_TYPES.LOCAL,
2909
3036
  }
2910
3037
  );
2911
- }
2912
- else if (audioTrack || videoTrack) {
2913
- LoggerProxy.logger.warn('Meeting:index#closeLocalStream --> Warning: track might already been ended or unavaliable.');
3038
+ } else if (audioTrack || videoTrack) {
3039
+ LoggerProxy.logger.warn(
3040
+ 'Meeting:index#closeLocalStream --> Warning: track might already been ended or unavaliable.'
3041
+ );
2914
3042
  }
2915
3043
  });
2916
3044
  }
@@ -2931,16 +3059,18 @@ export default class Meeting extends StatelessWebexPlugin {
2931
3059
  this,
2932
3060
  {
2933
3061
  file: 'meeting/index',
2934
- function: 'closeLocalShare'
3062
+ function: 'closeLocalShare',
2935
3063
  },
2936
- EVENT_TRIGGERS.MEDIA_STOPPED, {
2937
- type: EVENT_TYPES.LOCAL_SHARE
3064
+ EVENT_TRIGGERS.MEDIA_STOPPED,
3065
+ {
3066
+ type: EVENT_TYPES.LOCAL_SHARE,
2938
3067
  }
2939
3068
  );
2940
- }
2941
- else if (track) {
3069
+ } else if (track) {
2942
3070
  // Track exists but with wrong readyState
2943
- LoggerProxy.logger.warn(`Meeting:index#closeLocalShare --> Error: MediaStreamTrack.readyState is ${track.readyState} for localShare`);
3071
+ LoggerProxy.logger.warn(
3072
+ `Meeting:index#closeLocalShare --> Error: MediaStreamTrack.readyState is ${track.readyState} for localShare`
3073
+ );
2944
3074
  }
2945
3075
  });
2946
3076
  }
@@ -2982,14 +3112,11 @@ export default class Meeting extends StatelessWebexPlugin {
2982
3112
  if (!this.hasWebsocketConnected) {
2983
3113
  Metrics.postEvent({
2984
3114
  event: eventType.MERCURY_CONNECTION_RESTORED,
2985
- meeting: this
3115
+ meeting: this,
3116
+ });
3117
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MERCURY_CONNECTION_RESTORED, {
3118
+ correlation_id: this.correlationId,
2986
3119
  });
2987
- Metrics.sendBehavioralMetric(
2988
- BEHAVIORAL_METRICS.MERCURY_CONNECTION_RESTORED,
2989
- {
2990
- correlation_id: this.correlationId
2991
- }
2992
- );
2993
3120
  }
2994
3121
  this.hasWebsocketConnected = true;
2995
3122
  });
@@ -2999,14 +3126,11 @@ export default class Meeting extends StatelessWebexPlugin {
2999
3126
  LoggerProxy.logger.error('Meeting:index#setMercuryListener --> Web socket offline');
3000
3127
  Metrics.postEvent({
3001
3128
  event: eventType.MERCURY_CONNECTION_LOST,
3002
- meeting: this
3129
+ meeting: this,
3130
+ });
3131
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MERCURY_CONNECTION_FAILURE, {
3132
+ correlation_id: this.correlationId,
3003
3133
  });
3004
- Metrics.sendBehavioralMetric(
3005
- BEHAVIORAL_METRICS.MERCURY_CONNECTION_FAILURE,
3006
- {
3007
- correlation_id: this.correlationId
3008
- }
3009
- );
3010
3134
  });
3011
3135
  }
3012
3136
 
@@ -3025,7 +3149,9 @@ export default class Meeting extends StatelessWebexPlugin {
3025
3149
  this.remoteMediaManager = null;
3026
3150
  }
3027
3151
 
3028
- Object.values(this.mediaRequestManagers).forEach((mediaRequestManager) => mediaRequestManager.reset());
3152
+ Object.values(this.mediaRequestManagers).forEach((mediaRequestManager) =>
3153
+ mediaRequestManager.reset()
3154
+ );
3029
3155
 
3030
3156
  this.receiveSlotManager.reset();
3031
3157
  this.mediaProperties.webrtcMediaConnection.close();
@@ -3085,32 +3211,33 @@ export default class Meeting extends StatelessWebexPlugin {
3085
3211
  const LOG_HEADER = 'Meeting:index#muteAudio -->';
3086
3212
 
3087
3213
  // First, stop sending the local audio media
3088
- return logRequest(this.audio.handleClientRequest(this, true)
3089
- .then(() => {
3090
- MeetingUtil.handleAudioLogging(this.mediaProperties.audioTrack);
3091
- Metrics.postEvent({
3092
- event: eventType.MUTED,
3093
- meeting: this,
3094
- data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.AUDIO}
3095
- });
3096
- }).catch((error) => {
3097
- Metrics.sendBehavioralMetric(
3098
- BEHAVIORAL_METRICS.MUTE_AUDIO_FAILURE,
3099
- {
3214
+ return logRequest(
3215
+ this.audio
3216
+ .handleClientRequest(this, true)
3217
+ .then(() => {
3218
+ MeetingUtil.handleAudioLogging(this.mediaProperties.audioTrack);
3219
+ Metrics.postEvent({
3220
+ event: eventType.MUTED,
3221
+ meeting: this,
3222
+ data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.AUDIO},
3223
+ });
3224
+ })
3225
+ .catch((error) => {
3226
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MUTE_AUDIO_FAILURE, {
3100
3227
  correlation_id: this.correlationId,
3101
3228
  locus_id: this.locusUrl.split('/').pop(),
3102
3229
  reason: error.message,
3103
- stack: error.stack
3104
- }
3105
- );
3230
+ stack: error.stack,
3231
+ });
3106
3232
 
3107
- throw error;
3108
- }),
3109
- {
3110
- header: `${LOG_HEADER} muting audio`,
3111
- success: `${LOG_HEADER} muted audio successfully`,
3112
- failure: `${LOG_HEADER} muting audio failed, `
3113
- });
3233
+ throw error;
3234
+ }),
3235
+ {
3236
+ header: `${LOG_HEADER} muting audio`,
3237
+ success: `${LOG_HEADER} muted audio successfully`,
3238
+ failure: `${LOG_HEADER} muting audio failed, `,
3239
+ }
3240
+ );
3114
3241
  }
3115
3242
 
3116
3243
  /**
@@ -3137,32 +3264,33 @@ export default class Meeting extends StatelessWebexPlugin {
3137
3264
  const LOG_HEADER = 'Meeting:index#unmuteAudio -->';
3138
3265
 
3139
3266
  // First, send the control to unmute the participant on the server
3140
- return logRequest(this.audio.handleClientRequest(this, false)
3141
- .then(() => {
3142
- MeetingUtil.handleAudioLogging(this.mediaProperties.audioTrack);
3143
- Metrics.postEvent({
3144
- event: eventType.UNMUTED,
3145
- meeting: this,
3146
- data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.AUDIO}
3147
- });
3148
- }).catch((error) => {
3149
- Metrics.sendBehavioralMetric(
3150
- BEHAVIORAL_METRICS.UNMUTE_AUDIO_FAILURE,
3151
- {
3267
+ return logRequest(
3268
+ this.audio
3269
+ .handleClientRequest(this, false)
3270
+ .then(() => {
3271
+ MeetingUtil.handleAudioLogging(this.mediaProperties.audioTrack);
3272
+ Metrics.postEvent({
3273
+ event: eventType.UNMUTED,
3274
+ meeting: this,
3275
+ data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.AUDIO},
3276
+ });
3277
+ })
3278
+ .catch((error) => {
3279
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UNMUTE_AUDIO_FAILURE, {
3152
3280
  correlation_id: this.correlationId,
3153
3281
  locus_id: this.locusUrl.split('/').pop(),
3154
3282
  reason: error.message,
3155
- stack: error.stack
3156
- }
3157
- );
3283
+ stack: error.stack,
3284
+ });
3158
3285
 
3159
- throw error;
3160
- }),
3161
- {
3162
- header: `${LOG_HEADER} unmuting audio`,
3163
- success: `${LOG_HEADER} unmuted audio successfully`,
3164
- failure: `${LOG_HEADER} unmuting audio failed, `
3165
- });
3286
+ throw error;
3287
+ }),
3288
+ {
3289
+ header: `${LOG_HEADER} unmuting audio`,
3290
+ success: `${LOG_HEADER} unmuted audio successfully`,
3291
+ failure: `${LOG_HEADER} unmuting audio failed, `,
3292
+ }
3293
+ );
3166
3294
  }
3167
3295
 
3168
3296
  /**
@@ -3188,32 +3316,33 @@ export default class Meeting extends StatelessWebexPlugin {
3188
3316
 
3189
3317
  const LOG_HEADER = 'Meeting:index#muteVideo -->';
3190
3318
 
3191
- return logRequest(this.video.handleClientRequest(this, true)
3192
- .then(() => {
3193
- MeetingUtil.handleVideoLogging(this.mediaProperties.videoTrack);
3194
- Metrics.postEvent({
3195
- event: eventType.MUTED,
3196
- meeting: this,
3197
- data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.VIDEO}
3198
- });
3199
- }).catch((error) => {
3200
- Metrics.sendBehavioralMetric(
3201
- BEHAVIORAL_METRICS.MUTE_VIDEO_FAILURE,
3202
- {
3319
+ return logRequest(
3320
+ this.video
3321
+ .handleClientRequest(this, true)
3322
+ .then(() => {
3323
+ MeetingUtil.handleVideoLogging(this.mediaProperties.videoTrack);
3324
+ Metrics.postEvent({
3325
+ event: eventType.MUTED,
3326
+ meeting: this,
3327
+ data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.VIDEO},
3328
+ });
3329
+ })
3330
+ .catch((error) => {
3331
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MUTE_VIDEO_FAILURE, {
3203
3332
  correlation_id: this.correlationId,
3204
3333
  locus_id: this.locusUrl.split('/').pop(),
3205
3334
  reason: error.message,
3206
- stack: error.stack
3207
- }
3208
- );
3335
+ stack: error.stack,
3336
+ });
3209
3337
 
3210
- throw error;
3211
- }),
3212
- {
3213
- header: `${LOG_HEADER} muting video`,
3214
- success: `${LOG_HEADER} muted video successfully`,
3215
- failure: `${LOG_HEADER} muting video failed, `
3216
- });
3338
+ throw error;
3339
+ }),
3340
+ {
3341
+ header: `${LOG_HEADER} muting video`,
3342
+ success: `${LOG_HEADER} muted video successfully`,
3343
+ failure: `${LOG_HEADER} muting video failed, `,
3344
+ }
3345
+ );
3217
3346
  }
3218
3347
 
3219
3348
  /**
@@ -3239,32 +3368,33 @@ export default class Meeting extends StatelessWebexPlugin {
3239
3368
 
3240
3369
  const LOG_HEADER = 'Meeting:index#unmuteVideo -->';
3241
3370
 
3242
- return logRequest(this.video.handleClientRequest(this, false)
3243
- .then(() => {
3244
- MeetingUtil.handleVideoLogging(this.mediaProperties.videoTrack);
3245
- Metrics.postEvent({
3246
- event: eventType.UNMUTED,
3247
- meeting: this,
3248
- data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.VIDEO}
3249
- });
3250
- }).catch((error) => {
3251
- Metrics.sendBehavioralMetric(
3252
- BEHAVIORAL_METRICS.UNMUTE_VIDEO_FAILURE,
3253
- {
3371
+ return logRequest(
3372
+ this.video
3373
+ .handleClientRequest(this, false)
3374
+ .then(() => {
3375
+ MeetingUtil.handleVideoLogging(this.mediaProperties.videoTrack);
3376
+ Metrics.postEvent({
3377
+ event: eventType.UNMUTED,
3378
+ meeting: this,
3379
+ data: {trigger: trigger.USER_INTERACTION, mediaType: mediaType.VIDEO},
3380
+ });
3381
+ })
3382
+ .catch((error) => {
3383
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UNMUTE_VIDEO_FAILURE, {
3254
3384
  correlation_id: this.correlationId,
3255
3385
  locus_id: this.locusUrl.split('/').pop(),
3256
3386
  reason: error.message,
3257
- stack: error.stack
3258
- }
3259
- );
3387
+ stack: error.stack,
3388
+ });
3260
3389
 
3261
- throw error;
3262
- }),
3263
- {
3264
- header: `${LOG_HEADER} unmuting video`,
3265
- success: `${LOG_HEADER} unmuted video successfully`,
3266
- failure: `${LOG_HEADER} unmuting video failed, `
3267
- });
3390
+ throw error;
3391
+ }),
3392
+ {
3393
+ header: `${LOG_HEADER} unmuting video`,
3394
+ success: `${LOG_HEADER} unmuted video successfully`,
3395
+ failure: `${LOG_HEADER} unmuting video failed, `,
3396
+ }
3397
+ );
3268
3398
  }
3269
3399
 
3270
3400
  /**
@@ -3308,12 +3438,14 @@ export default class Meeting extends StatelessWebexPlugin {
3308
3438
  this.addMedia({
3309
3439
  mediaSettings,
3310
3440
  localShare,
3311
- localStream
3441
+ localStream,
3312
3442
  }).then((mediaResponse) => ({
3313
3443
  join: joinResponse,
3314
3444
  media: mediaResponse,
3315
- local: [localStream, localShare]
3316
- }))))
3445
+ local: [localStream, localShare],
3446
+ }))
3447
+ )
3448
+ )
3317
3449
  .catch((error) => {
3318
3450
  LoggerProxy.logger.error('Meeting:index#joinWithMedia --> ', error);
3319
3451
 
@@ -3323,10 +3455,10 @@ export default class Meeting extends StatelessWebexPlugin {
3323
3455
  correlation_id: this.correlationId,
3324
3456
  locus_id: this.locusUrl.split('/').pop(),
3325
3457
  reason: error.message,
3326
- stack: error.stack
3458
+ stack: error.stack,
3327
3459
  },
3328
3460
  {
3329
- type: error.name
3461
+ type: error.name,
3330
3462
  }
3331
3463
  );
3332
3464
 
@@ -3343,28 +3475,34 @@ export default class Meeting extends StatelessWebexPlugin {
3343
3475
  * @memberof Meeting
3344
3476
  */
3345
3477
  public reconnect(options?: object) {
3346
- LoggerProxy.logger.log(`Meeting:index#reconnect --> attempting to reconnect meeting ${this.id}`);
3478
+ LoggerProxy.logger.log(
3479
+ `Meeting:index#reconnect --> attempting to reconnect meeting ${this.id}`
3480
+ );
3347
3481
 
3348
3482
  if (!this.reconnectionManager || !this.reconnectionManager.reconnect) {
3349
- return Promise.reject(new ParameterError('Cannot reconnect, ReconnectionManager must first be defined.'));
3483
+ return Promise.reject(
3484
+ new ParameterError('Cannot reconnect, ReconnectionManager must first be defined.')
3485
+ );
3350
3486
  }
3351
3487
 
3352
3488
  // @ts-ignore - currentMediaStatus coming from SelfUtil
3353
3489
  if (!MeetingUtil.isMediaEstablished(this.currentMediaStatus)) {
3354
- return Promise.reject(new ParameterError('Cannot reconnect, Media has not established to reconnect'));
3490
+ return Promise.reject(
3491
+ new ParameterError('Cannot reconnect, Media has not established to reconnect')
3492
+ );
3355
3493
  }
3356
3494
 
3357
3495
  try {
3358
3496
  LoggerProxy.logger.info('Meeting:index#reconnect --> Validating reconnect ability.');
3359
3497
  // @ts-ignore
3360
3498
  this.reconnectionManager.validate();
3361
- }
3362
- catch (error) {
3499
+ } catch (error) {
3363
3500
  // Unable to reconnect this call
3364
3501
  if (error instanceof ReconnectInProgress) {
3365
- LoggerProxy.logger.info('Meeting:index#reconnect --> Unable to reconnect, reconnection in progress.');
3366
- }
3367
- else {
3502
+ LoggerProxy.logger.info(
3503
+ 'Meeting:index#reconnect --> Unable to reconnect, reconnection in progress.'
3504
+ );
3505
+ } else {
3368
3506
  LoggerProxy.logger.log('Meeting:index#reconnect --> Unable to reconnect.', error);
3369
3507
  }
3370
3508
 
@@ -3375,7 +3513,7 @@ export default class Meeting extends StatelessWebexPlugin {
3375
3513
  this,
3376
3514
  {
3377
3515
  file: 'meeting/index',
3378
- function: 'reconnect'
3516
+ function: 'reconnect',
3379
3517
  },
3380
3518
  EVENT_TRIGGERS.MEETING_RECONNECTION_STARTING
3381
3519
  );
@@ -3387,7 +3525,7 @@ export default class Meeting extends StatelessWebexPlugin {
3387
3525
  this,
3388
3526
  {
3389
3527
  file: 'meeting/index',
3390
- function: 'reconnect'
3528
+ function: 'reconnect',
3391
3529
  },
3392
3530
  EVENT_TRIGGERS.MEETING_RECONNECTION_SUCCESS
3393
3531
  );
@@ -3398,29 +3536,26 @@ export default class Meeting extends StatelessWebexPlugin {
3398
3536
  this,
3399
3537
  {
3400
3538
  file: 'meeting/index',
3401
- function: 'reconnect'
3539
+ function: 'reconnect',
3402
3540
  },
3403
3541
  EVENT_TRIGGERS.MEETING_RECONNECTION_FAILURE,
3404
3542
  {
3405
- error: new ReconnectionError('Reconnection failure event', error)
3543
+ error: new ReconnectionError('Reconnection failure event', error),
3406
3544
  }
3407
3545
  );
3408
3546
 
3409
3547
  LoggerProxy.logger.error('Meeting:index#reconnect --> Meeting reconnect failed', error);
3410
3548
 
3411
- Metrics.sendBehavioralMetric(
3412
- BEHAVIORAL_METRICS.MEETING_RECONNECT_FAILURE,
3413
- {
3414
- correlation_id: this.correlationId,
3415
- locus_id: this.locusUrl.split('/').pop(),
3416
- reason: error.message,
3417
- stack: error.stack
3418
- }
3419
- );
3549
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_RECONNECT_FAILURE, {
3550
+ correlation_id: this.correlationId,
3551
+ locus_id: this.locusUrl.split('/').pop(),
3552
+ reason: error.message,
3553
+ stack: error.stack,
3554
+ });
3420
3555
 
3421
3556
  this.uploadLogs({
3422
3557
  file: 'meeting/index',
3423
- function: 'reconnect'
3558
+ function: 'reconnect',
3424
3559
  });
3425
3560
 
3426
3561
  return Promise.reject(new ReconnectionError('Reconnection failure event', error));
@@ -3474,14 +3609,11 @@ export default class Meeting extends StatelessWebexPlugin {
3474
3609
 
3475
3610
  this.triggerStopReceivingTranscriptionEvent();
3476
3611
 
3477
- Metrics.sendBehavioralMetric(
3478
- BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE,
3479
- {
3480
- correlation_id: this.correlationId,
3481
- reason: 'unexpected error: transcription LLM web socket connection error had occured.',
3482
- event
3483
- }
3484
- );
3612
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE, {
3613
+ correlation_id: this.correlationId,
3614
+ reason: 'unexpected error: transcription LLM web socket connection error had occured.',
3615
+ event,
3616
+ });
3485
3617
  });
3486
3618
  }
3487
3619
 
@@ -3499,10 +3631,12 @@ export default class Meeting extends StatelessWebexPlugin {
3499
3631
  try {
3500
3632
  const {datachannelUrl} = this.locusInfo.info;
3501
3633
  // @ts-ignore - fix type
3502
- const {body: {webSocketUrl}} = await this.request({
3634
+ const {
3635
+ body: {webSocketUrl},
3636
+ } = await this.request({
3503
3637
  method: HTTP_VERBS.POST,
3504
3638
  uri: datachannelUrl,
3505
- body: {deviceUrl: this.deviceUrl}
3639
+ body: {deviceUrl: this.deviceUrl},
3506
3640
  });
3507
3641
 
3508
3642
  LoggerProxy.logger.info(
@@ -3514,7 +3648,7 @@ export default class Meeting extends StatelessWebexPlugin {
3514
3648
  webSocketUrl,
3515
3649
  // @ts-ignore - fix type
3516
3650
  this.webex.sessionId,
3517
- this.members,
3651
+ this.members
3518
3652
  );
3519
3653
 
3520
3654
  LoggerProxy.logger.info(
@@ -3528,7 +3662,7 @@ export default class Meeting extends StatelessWebexPlugin {
3528
3662
  this,
3529
3663
  {
3530
3664
  file: 'meeting/index',
3531
- function: 'join'
3665
+ function: 'join',
3532
3666
  },
3533
3667
  EVENT_TRIGGERS.MEETING_STARTED_RECEIVING_TRANSCRIPTION,
3534
3668
  payload
@@ -3538,17 +3672,13 @@ export default class Meeting extends StatelessWebexPlugin {
3538
3672
  this.monitorTranscriptionSocketConnection();
3539
3673
  // @ts-ignore - fix type
3540
3674
  this.transcription.connect(this.webex.credentials.supertoken.access_token);
3541
- }
3542
- catch (error) {
3675
+ } catch (error) {
3543
3676
  LoggerProxy.logger.error(`Meeting:index#receiveTranscription --> ${error}`);
3544
- Metrics.sendBehavioralMetric(
3545
- BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE,
3546
- {
3547
- correlation_id: this.correlationId,
3548
- reason: error.message,
3549
- stack: error.stack
3550
- }
3551
- );
3677
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.RECEIVE_TRANSCRIPTION_FAILURE, {
3678
+ correlation_id: this.correlationId,
3679
+ reason: error.message,
3680
+ stack: error.stack,
3681
+ });
3552
3682
  }
3553
3683
  }
3554
3684
 
@@ -3578,7 +3708,7 @@ export default class Meeting extends StatelessWebexPlugin {
3578
3708
  this,
3579
3709
  {
3580
3710
  file: 'meeting',
3581
- function: 'triggerStopReceivingTranscriptionEvent'
3711
+ function: 'triggerStopReceivingTranscriptionEvent',
3582
3712
  },
3583
3713
  EVENT_TRIGGERS.MEETING_STOPPED_RECEIVING_TRANSCRIPTION
3584
3714
  );
@@ -3625,10 +3755,13 @@ export default class Meeting extends StatelessWebexPlugin {
3625
3755
 
3626
3756
  if (!this.hasJoinedOnce) {
3627
3757
  this.hasJoinedOnce = true;
3628
- }
3629
- else {
3630
- LoggerProxy.logger.log(`Meeting:index#join --> Generating a new correlation id for meeting ${this.id}`);
3631
- LoggerProxy.logger.log(`Meeting:index#join --> Previous correlation id ${this.correlationId}`);
3758
+ } else {
3759
+ LoggerProxy.logger.log(
3760
+ `Meeting:index#join --> Generating a new correlation id for meeting ${this.id}`
3761
+ );
3762
+ LoggerProxy.logger.log(
3763
+ `Meeting:index#join --> Previous correlation id ${this.correlationId}`
3764
+ );
3632
3765
  this.setCorrelationId(uuid.v4());
3633
3766
  LoggerProxy.logger.log(`Meeting:index#join --> New correlation id ${this.correlationId}`);
3634
3767
  }
@@ -3640,7 +3773,7 @@ export default class Meeting extends StatelessWebexPlugin {
3640
3773
  Metrics.postEvent({
3641
3774
  event: eventType.CALL_INITIATED,
3642
3775
  meeting: this,
3643
- data: {trigger: trigger.USER_INTERACTION, isRoapCallEnabled: true}
3776
+ data: {trigger: trigger.USER_INTERACTION, isRoapCallEnabled: true},
3644
3777
  });
3645
3778
 
3646
3779
  LoggerProxy.logger.log('Meeting:index#join --> Joining a meeting');
@@ -3715,12 +3848,9 @@ export default class Meeting extends StatelessWebexPlugin {
3715
3848
  .then((join) => {
3716
3849
  joinSuccess(join);
3717
3850
  this.deferJoin = undefined;
3718
- Metrics.sendBehavioralMetric(
3719
- BEHAVIORAL_METRICS.JOIN_SUCCESS,
3720
- {
3721
- correlation_id: this.correlationId
3722
- }
3723
- );
3851
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_SUCCESS, {
3852
+ correlation_id: this.correlationId,
3853
+ });
3724
3854
 
3725
3855
  return join;
3726
3856
  })
@@ -3740,9 +3870,10 @@ export default class Meeting extends StatelessWebexPlugin {
3740
3870
  LoggerProxy.logger.info('Meeting:index#join --> enabled to recieve transcription!');
3741
3871
  }
3742
3872
  }
3743
- }
3744
- else {
3745
- LoggerProxy.logger.error('Meeting:index#join --> Receving transcription is not supported on this platform');
3873
+ } else {
3874
+ LoggerProxy.logger.error(
3875
+ 'Meeting:index#join --> Receving transcription is not supported on this platform'
3876
+ );
3746
3877
  }
3747
3878
 
3748
3879
  return join;
@@ -3756,28 +3887,23 @@ export default class Meeting extends StatelessWebexPlugin {
3756
3887
  meeting: this,
3757
3888
  meetingId: this.id,
3758
3889
  data: {
3759
- errors: [
3760
- Metrics.parseLocusError(error.error, true)
3761
- ]
3762
- }
3890
+ errors: [Metrics.parseLocusError(error.error, true)],
3891
+ },
3763
3892
  });
3764
3893
 
3765
3894
  // TODO: change this to error codes and pre defined dictionary
3766
- Metrics.sendBehavioralMetric(
3767
- BEHAVIORAL_METRICS.JOIN_FAILURE,
3768
- {
3769
- correlation_id: this.correlationId,
3770
- reason: error.error?.message,
3771
- stack: error.stack
3772
- }
3773
- );
3895
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.JOIN_FAILURE, {
3896
+ correlation_id: this.correlationId,
3897
+ reason: error.error?.message,
3898
+ stack: error.stack,
3899
+ });
3774
3900
 
3775
3901
  // Upload logs on join Failure
3776
3902
  Trigger.trigger(
3777
3903
  this,
3778
3904
  {
3779
3905
  file: 'meeting/index',
3780
- function: 'join'
3906
+ function: 'join',
3781
3907
  },
3782
3908
  EVENTS.REQUEST_UPLOAD_LOGS,
3783
3909
  this
@@ -3854,28 +3980,28 @@ export default class Meeting extends StatelessWebexPlugin {
3854
3980
 
3855
3981
  if (!this.dialInUrl) this.dialInUrl = `dialin:///${uuid.v4()}`;
3856
3982
 
3857
- return this.meetingRequest.dialIn({
3858
- correlationId,
3859
- dialInUrl: this.dialInUrl,
3860
- locusUrl,
3861
- clientUrl: this.deviceUrl
3862
- }).then((res) => {
3863
- this.locusInfo.onFullLocus(res.body.locus);
3864
- }).catch((error) => {
3865
- Metrics.sendBehavioralMetric(
3866
- BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE,
3867
- {
3983
+ return this.meetingRequest
3984
+ .dialIn({
3985
+ correlationId,
3986
+ dialInUrl: this.dialInUrl,
3987
+ locusUrl,
3988
+ clientUrl: this.deviceUrl,
3989
+ })
3990
+ .then((res) => {
3991
+ this.locusInfo.onFullLocus(res.body.locus);
3992
+ })
3993
+ .catch((error) => {
3994
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_IN_FAILURE, {
3868
3995
  correlation_id: this.correlationId,
3869
3996
  dial_in_url: this.dialInUrl,
3870
3997
  locus_id: locusUrl.split('/').pop(),
3871
3998
  client_url: this.deviceUrl,
3872
3999
  reason: error.error?.message,
3873
- stack: error.stack
3874
- }
3875
- );
4000
+ stack: error.stack,
4001
+ });
3876
4002
 
3877
- return Promise.reject(error);
3878
- });
4003
+ return Promise.reject(error);
4004
+ });
3879
4005
  }
3880
4006
 
3881
4007
  /**
@@ -3892,29 +4018,29 @@ export default class Meeting extends StatelessWebexPlugin {
3892
4018
 
3893
4019
  if (!this.dialOutUrl) this.dialOutUrl = `dialout:///${uuid.v4()}`;
3894
4020
 
3895
- return this.meetingRequest.dialOut({
3896
- correlationId,
3897
- dialOutUrl: this.dialOutUrl,
3898
- phoneNumber,
3899
- locusUrl,
3900
- clientUrl: this.deviceUrl
3901
- }).then((res) => {
3902
- this.locusInfo.onFullLocus(res.body.locus);
3903
- }).catch((error) => {
3904
- Metrics.sendBehavioralMetric(
3905
- BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE,
3906
- {
4021
+ return this.meetingRequest
4022
+ .dialOut({
4023
+ correlationId,
4024
+ dialOutUrl: this.dialOutUrl,
4025
+ phoneNumber,
4026
+ locusUrl,
4027
+ clientUrl: this.deviceUrl,
4028
+ })
4029
+ .then((res) => {
4030
+ this.locusInfo.onFullLocus(res.body.locus);
4031
+ })
4032
+ .catch((error) => {
4033
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_DIAL_OUT_FAILURE, {
3907
4034
  correlation_id: this.correlationId,
3908
4035
  dial_out_url: this.dialOutUrl,
3909
4036
  locus_id: locusUrl.split('/').pop(),
3910
4037
  client_url: this.deviceUrl,
3911
4038
  reason: error.error?.message,
3912
- stack: error.stack
3913
- }
3914
- );
4039
+ stack: error.stack,
4040
+ });
3915
4041
 
3916
- return Promise.reject(error);
3917
- });
4042
+ return Promise.reject(error);
4043
+ });
3918
4044
  }
3919
4045
 
3920
4046
  /**
@@ -3926,12 +4052,12 @@ export default class Meeting extends StatelessWebexPlugin {
3926
4052
  */
3927
4053
  public disconnectPhoneAudio() {
3928
4054
  return Promise.all([
3929
- this.isPhoneProvisioned(this.dialInDeviceStatus) ?
3930
- MeetingUtil.disconnectPhoneAudio(this, this.dialInUrl) :
3931
- Promise.resolve(),
3932
- this.isPhoneProvisioned(this.dialOutDeviceStatus) ?
3933
- MeetingUtil.disconnectPhoneAudio(this, this.dialOutUrl) :
3934
- Promise.resolve()
4055
+ this.isPhoneProvisioned(this.dialInDeviceStatus)
4056
+ ? MeetingUtil.disconnectPhoneAudio(this, this.dialInUrl)
4057
+ : Promise.resolve(),
4058
+ this.isPhoneProvisioned(this.dialOutDeviceStatus)
4059
+ ? MeetingUtil.disconnectPhoneAudio(this, this.dialOutUrl)
4060
+ : Promise.resolve(),
3935
4061
  ]);
3936
4062
  }
3937
4063
 
@@ -3957,17 +4083,17 @@ export default class Meeting extends StatelessWebexPlugin {
3957
4083
  share: true,
3958
4084
  share_audio: false,
3959
4085
  video: false,
3960
- whiteboard: false
4086
+ whiteboard: false,
3961
4087
  },
3962
4088
  tx: {
3963
4089
  audio: false,
3964
4090
  share: false,
3965
4091
  share_audio: false,
3966
4092
  video: false,
3967
- whiteboard: false
3968
- }
3969
- }
3970
- }
4093
+ whiteboard: false,
4094
+ },
4095
+ },
4096
+ },
3971
4097
  });
3972
4098
 
3973
4099
  Metrics.postEvent({event: eventType.MOVE_MEDIA, meeting: this});
@@ -3986,8 +4112,8 @@ export default class Meeting extends StatelessWebexPlugin {
3986
4112
  sendAudio: false,
3987
4113
  receiveAudio: false,
3988
4114
  sendShare: false,
3989
- receiveShare: true
3990
- }
4115
+ receiveShare: true,
4116
+ },
3991
4117
  };
3992
4118
 
3993
4119
  // clean up the local tracks
@@ -3999,50 +4125,44 @@ export default class Meeting extends StatelessWebexPlugin {
3999
4125
 
4000
4126
  this.mediaProperties.unsetMediaTracks();
4001
4127
 
4002
-
4003
4128
  // when a move to is intiated by the client , Locus delets the existing media node from the server as soon the DX answers the meeting
4004
4129
  // once the DX answers we establish connection back the media server with only receiveShare enabled
4005
4130
  // @ts-ignore - reconnectMedia does not accept any argument
4006
- await this.reconnectionManager.reconnectMedia(mediaSettings)
4007
- .then(() => {
4008
- Metrics.sendBehavioralMetric(
4009
- BEHAVIORAL_METRICS.MOVE_TO_SUCCESS,
4010
- );
4011
- });
4012
- }
4013
- catch (error) {
4131
+ await this.reconnectionManager.reconnectMedia(mediaSettings).then(() => {
4132
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_SUCCESS);
4133
+ });
4134
+ } catch (error) {
4014
4135
  LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
4015
- Metrics.sendBehavioralMetric(
4016
- BEHAVIORAL_METRICS.MOVE_TO_FAILURE,
4017
- {
4018
- correlation_id: this.correlationId,
4019
- locus_id: this.locusUrl.split('/').pop(),
4020
- reason: error.message,
4021
- stack: error.stack
4022
- }
4023
- );
4136
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
4137
+ correlation_id: this.correlationId,
4138
+ locus_id: this.locusUrl.split('/').pop(),
4139
+ reason: error.message,
4140
+ stack: error.stack,
4141
+ });
4024
4142
  }
4025
4143
  });
4026
4144
 
4027
- LoggerProxy.logger.info('Meeting:index#moveTo --> Initated moved to using resourceId', resourceId);
4145
+ LoggerProxy.logger.info(
4146
+ 'Meeting:index#moveTo --> Initated moved to using resourceId',
4147
+ resourceId
4148
+ );
4028
4149
 
4029
- return MeetingUtil.joinMeetingOptions(this, {resourceId, moveToResource: true}).then(() => {
4030
- this.meetingFiniteStateMachine.join();
4031
- }).catch((error) => {
4032
- this.meetingFiniteStateMachine.fail(error);
4033
- Metrics.sendBehavioralMetric(
4034
- BEHAVIORAL_METRICS.MOVE_TO_FAILURE,
4035
- {
4150
+ return MeetingUtil.joinMeetingOptions(this, {resourceId, moveToResource: true})
4151
+ .then(() => {
4152
+ this.meetingFiniteStateMachine.join();
4153
+ })
4154
+ .catch((error) => {
4155
+ this.meetingFiniteStateMachine.fail(error);
4156
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
4036
4157
  correlation_id: this.correlationId,
4037
4158
  locus_id: this.locusUrl.split('/').pop(),
4038
4159
  reason: error.message,
4039
- stack: error.stack
4040
- }
4041
- );
4042
- LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
4160
+ stack: error.stack,
4161
+ });
4162
+ LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
4043
4163
 
4044
- return Promise.reject(error);
4045
- });
4164
+ return Promise.reject(error);
4165
+ });
4046
4166
  }
4047
4167
 
4048
4168
  /**
@@ -4062,26 +4182,24 @@ export default class Meeting extends StatelessWebexPlugin {
4062
4182
  Metrics.postEvent({event: eventType.MOVE_MEDIA, meeting: this});
4063
4183
 
4064
4184
  return MeetingUtil.joinMeetingOptions(this)
4065
- .then(() => MeetingUtil.leaveMeeting(this, {
4066
- resourceId,
4067
- correlationId: oldCorrelationId,
4068
- moveMeeting: true
4069
- }).then(() => {
4070
- this.resourceId = '';
4071
- Metrics.sendBehavioralMetric(
4072
- BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS,
4073
- );
4074
- })).catch((error) => {
4185
+ .then(() =>
4186
+ MeetingUtil.leaveMeeting(this, {
4187
+ resourceId,
4188
+ correlationId: oldCorrelationId,
4189
+ moveMeeting: true,
4190
+ }).then(() => {
4191
+ this.resourceId = '';
4192
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_FROM_SUCCESS);
4193
+ })
4194
+ )
4195
+ .catch((error) => {
4075
4196
  this.meetingFiniteStateMachine.fail(error);
4076
- Metrics.sendBehavioralMetric(
4077
- BEHAVIORAL_METRICS.MOVE_FROM_FAILURE,
4078
- {
4079
- correlation_id: this.correlationId,
4080
- locus_id: this.locusUrl.split('/').pop(),
4081
- reason: error.message,
4082
- stack: error.stack
4083
- }
4084
- );
4197
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_FROM_FAILURE, {
4198
+ correlation_id: this.correlationId,
4199
+ locus_id: this.locusUrl.split('/').pop(),
4200
+ reason: error.message,
4201
+ stack: error.stack,
4202
+ });
4085
4203
  LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
4086
4204
 
4087
4205
  return Promise.reject(error);
@@ -4104,55 +4222,63 @@ export default class Meeting extends StatelessWebexPlugin {
4104
4222
  getMediaStreams = (
4105
4223
  mediaDirection: any,
4106
4224
  // This return an OBJECT {video: {height, widght}}
4225
+ // eslint-disable-next-line default-param-last
4107
4226
  audioVideo: any = VIDEO_RESOLUTIONS[this.mediaProperties.localQualityLevel],
4108
4227
  sharePreferences?: any
4109
4228
  ) => {
4110
4229
  if (
4111
4230
  mediaDirection &&
4112
- (
4113
- mediaDirection.sendAudio ||
4114
- mediaDirection.sendVideo ||
4115
- mediaDirection.sendShare
4116
- )
4231
+ (mediaDirection.sendAudio || mediaDirection.sendVideo || mediaDirection.sendShare)
4117
4232
  ) {
4118
- if (mediaDirection &&
4119
- (
4120
- mediaDirection.sendAudio &&
4121
- mediaDirection.sendVideo &&
4122
- mediaDirection.sendShare
4123
- ) &&
4233
+ if (
4234
+ mediaDirection &&
4235
+ mediaDirection.sendAudio &&
4236
+ mediaDirection.sendVideo &&
4237
+ mediaDirection.sendShare &&
4124
4238
  isBrowser('safari')
4125
4239
  ) {
4126
- LoggerProxy.logger.warn('Meeting:index#getMediaStreams --> Setting `sendShare` to FALSE, due to complications with Safari');
4240
+ LoggerProxy.logger.warn(
4241
+ 'Meeting:index#getMediaStreams --> Setting `sendShare` to FALSE, due to complications with Safari'
4242
+ );
4127
4243
 
4128
4244
  mediaDirection.sendShare = false;
4129
4245
 
4130
- LoggerProxy.logger.warn('Meeting:index#getMediaStreams --> Enabling `sendShare` along with `sendAudio` & `sendVideo`, on Safari, causes a failure while setting up a screen share at the same time as the camera+mic stream');
4131
- LoggerProxy.logger.warn('Meeting:index#getMediaStreams --> Please use `meeting.shareScreen()` to manually start the screen share after successfully joining the meeting');
4246
+ LoggerProxy.logger.warn(
4247
+ 'Meeting:index#getMediaStreams --> Enabling `sendShare` along with `sendAudio` & `sendVideo`, on Safari, causes a failure while setting up a screen share at the same time as the camera+mic stream'
4248
+ );
4249
+ LoggerProxy.logger.warn(
4250
+ 'Meeting:index#getMediaStreams --> Please use `meeting.shareScreen()` to manually start the screen share after successfully joining the meeting'
4251
+ );
4132
4252
  }
4133
4253
 
4134
4254
  if (audioVideo && isString(audioVideo)) {
4135
4255
  if (Object.keys(VIDEO_RESOLUTIONS).includes(audioVideo)) {
4136
4256
  this.mediaProperties.setLocalQualityLevel(audioVideo);
4137
4257
  audioVideo = {video: VIDEO_RESOLUTIONS[audioVideo].video};
4138
- }
4139
- else {
4140
- throw new ParameterError(`${audioVideo} not supported. Either pass level from pre-defined resolutions or pass complete audioVideo object`);
4258
+ } else {
4259
+ throw new ParameterError(
4260
+ `${audioVideo} not supported. Either pass level from pre-defined resolutions or pass complete audioVideo object`
4261
+ );
4141
4262
  }
4142
4263
  }
4143
4264
 
4144
4265
  if (!audioVideo.video) {
4145
- audioVideo = {...audioVideo, video: {...audioVideo.video, ...VIDEO_RESOLUTIONS[this.mediaProperties.localQualityLevel].video}};
4266
+ audioVideo = {
4267
+ ...audioVideo,
4268
+ video: {
4269
+ ...audioVideo.video,
4270
+ ...VIDEO_RESOLUTIONS[this.mediaProperties.localQualityLevel].video,
4271
+ },
4272
+ };
4146
4273
  }
4147
4274
  // extract deviceId if exists otherwise default to null.
4148
- const {deviceId: preferredVideoDevice} = (audioVideo && audioVideo.video || {deviceId: null});
4275
+ const {deviceId: preferredVideoDevice} = (audioVideo && audioVideo.video) || {deviceId: null};
4149
4276
  const lastVideoDeviceId = this.mediaProperties.getVideoDeviceId();
4150
4277
 
4151
4278
  if (preferredVideoDevice) {
4152
4279
  // Store new preferred video input device
4153
4280
  this.mediaProperties.setVideoDeviceId(preferredVideoDevice);
4154
- }
4155
- else if (lastVideoDeviceId) {
4281
+ } else if (lastVideoDeviceId) {
4156
4282
  // no new video preference specified so use last stored value,
4157
4283
  // works with empty object {} or media constraint.
4158
4284
  // eslint-disable-next-line no-param-reassign
@@ -4160,50 +4286,55 @@ export default class Meeting extends StatelessWebexPlugin {
4160
4286
  ...audioVideo,
4161
4287
  video: {
4162
4288
  ...audioVideo.video,
4163
- deviceId: lastVideoDeviceId
4164
- }
4289
+ deviceId: lastVideoDeviceId,
4290
+ },
4165
4291
  };
4166
4292
  }
4167
4293
 
4168
4294
  return Media.getSupportedDevice({
4169
4295
  sendAudio: mediaDirection.sendAudio,
4170
- sendVideo: mediaDirection.sendVideo
4296
+ sendVideo: mediaDirection.sendVideo,
4171
4297
  })
4172
- .catch((error) => Promise.reject(
4173
- new MediaError('Given constraints do not match permission set for either camera or microphone', error)
4174
- ))
4298
+ .catch((error) =>
4299
+ Promise.reject(
4300
+ new MediaError(
4301
+ 'Given constraints do not match permission set for either camera or microphone',
4302
+ error
4303
+ )
4304
+ )
4305
+ )
4175
4306
  .then((devicePermissions) =>
4176
4307
  Media.getUserMedia(
4177
4308
  {
4178
4309
  ...mediaDirection,
4179
4310
  sendAudio: devicePermissions.sendAudio,
4180
4311
  sendVideo: devicePermissions.sendVideo,
4181
- isSharing: this.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE
4312
+ isSharing: this.shareStatus === SHARE_STATUS.LOCAL_SHARE_ACTIVE,
4182
4313
  },
4183
4314
  audioVideo,
4184
4315
  sharePreferences,
4185
4316
  // @ts-ignore - config coming from registerPlugin
4186
4317
  this.config
4187
- )
4188
- .catch((error) => {
4189
- // Whenever there is a failure when trying to access a user's device
4190
- // report it as an Behavioral metric
4191
- // This gives visibility into common errors and can help
4192
- // with further troubleshooting
4193
- const metricName = BEHAVIORAL_METRICS.GET_USER_MEDIA_FAILURE;
4194
- const data = {
4195
- correlation_id: this.correlationId,
4196
- locus_id: this.locusUrl?.split('/').pop(),
4197
- reason: error.message,
4198
- stack: error.stack
4199
- };
4200
- const metadata = {
4201
- type: error.name
4202
- };
4203
-
4204
- Metrics.sendBehavioralMetric(metricName, data, metadata);
4205
- throw new MediaError('Unable to retrieve media streams', error);
4206
- }));
4318
+ ).catch((error) => {
4319
+ // Whenever there is a failure when trying to access a user's device
4320
+ // report it as an Behavioral metric
4321
+ // This gives visibility into common errors and can help
4322
+ // with further troubleshooting
4323
+ const metricName = BEHAVIORAL_METRICS.GET_USER_MEDIA_FAILURE;
4324
+ const data = {
4325
+ correlation_id: this.correlationId,
4326
+ locus_id: this.locusUrl?.split('/').pop(),
4327
+ reason: error.message,
4328
+ stack: error.stack,
4329
+ };
4330
+ const metadata = {
4331
+ type: error.name,
4332
+ };
4333
+
4334
+ Metrics.sendBehavioralMetric(metricName, data, metadata);
4335
+ throw new MediaError('Unable to retrieve media streams', error);
4336
+ })
4337
+ );
4207
4338
  }
4208
4339
 
4209
4340
  return Promise.reject(
@@ -4211,7 +4342,6 @@ export default class Meeting extends StatelessWebexPlugin {
4211
4342
  );
4212
4343
  };
4213
4344
 
4214
-
4215
4345
  /**
4216
4346
  * Checks if the machine has at least one audio or video device
4217
4347
  * @param {Object} options
@@ -4220,7 +4350,13 @@ export default class Meeting extends StatelessWebexPlugin {
4220
4350
  * @returns {Object}
4221
4351
  * @memberof Meetings
4222
4352
  */
4223
- getSupportedDevices = ({ sendAudio = true, sendVideo = true }: { sendAudio: boolean; sendVideo: boolean }) => Media.getSupportedDevice({ sendAudio, sendVideo });
4353
+ getSupportedDevices = ({
4354
+ sendAudio = true,
4355
+ sendVideo = true,
4356
+ }: {
4357
+ sendAudio: boolean;
4358
+ sendVideo: boolean;
4359
+ }) => Media.getSupportedDevice({sendAudio, sendVideo});
4224
4360
 
4225
4361
  /**
4226
4362
  * Get the devices from the Media module
@@ -4236,21 +4372,21 @@ export default class Meeting extends StatelessWebexPlugin {
4236
4372
  * @returns {void}
4237
4373
  */
4238
4374
  handleRoapFailure = (error) => {
4375
+ // eslint-disable-next-line @typescript-eslint/no-shadow
4239
4376
  const sendBehavioralMetric = (metricName, error, correlationId) => {
4240
4377
  const data = {
4241
4378
  code: error.code,
4242
4379
  correlation_id: correlationId,
4243
4380
  reason: error.message,
4244
- stack: error.stack
4381
+ stack: error.stack,
4245
4382
  };
4246
4383
  const metadata = {
4247
- type: error.cause?.name || error.name
4384
+ type: error.cause?.name || error.name,
4248
4385
  };
4249
4386
 
4250
4387
  Metrics.sendBehavioralMetric(metricName, data, metadata);
4251
4388
  };
4252
4389
 
4253
-
4254
4390
  if (error instanceof MC.Errors.SdpOfferCreationError) {
4255
4391
  sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.id);
4256
4392
 
@@ -4260,11 +4396,14 @@ export default class Meeting extends StatelessWebexPlugin {
4260
4396
  data: {
4261
4397
  canProceed: false,
4262
4398
  errors: [
4263
- Metrics.generateErrorPayload(2001, true, MetricsError.name.MEDIA_ENGINE, undefined)]
4264
- }
4399
+ Metrics.generateErrorPayload(2001, true, MetricsError.name.MEDIA_ENGINE, undefined),
4400
+ ],
4401
+ },
4265
4402
  });
4266
- }
4267
- else if ((error instanceof MC.Errors.SdpOfferHandlingError) || (error instanceof MC.Errors.SdpAnswerHandlingError)) {
4403
+ } else if (
4404
+ error instanceof MC.Errors.SdpOfferHandlingError ||
4405
+ error instanceof MC.Errors.SdpAnswerHandlingError
4406
+ ) {
4268
4407
  sendBehavioralMetric(BEHAVIORAL_METRICS.PEERCONNECTION_FAILURE, error, this.id);
4269
4408
 
4270
4409
  Metrics.postEvent({
@@ -4272,11 +4411,13 @@ export default class Meeting extends StatelessWebexPlugin {
4272
4411
  meetingId: this.id,
4273
4412
  data: {
4274
4413
  canProceed: false,
4275
- errors: [Metrics.generateErrorPayload(2001, true, MetricsError.name.MEDIA_ENGINE, undefined)]
4276
- }
4414
+ errors: [
4415
+ Metrics.generateErrorPayload(2001, true, MetricsError.name.MEDIA_ENGINE, undefined),
4416
+ ],
4417
+ },
4277
4418
  });
4278
- }
4279
- else if (error instanceof MC.Errors.SdpError) { // this covers also the case of MC.Errors.IceGatheringError which extends MC.Errors.SdpError
4419
+ } else if (error instanceof MC.Errors.SdpError) {
4420
+ // this covers also the case of MC.Errors.IceGatheringError which extends MC.Errors.SdpError
4280
4421
  sendBehavioralMetric(BEHAVIORAL_METRICS.INVALID_ICE_CANDIDATE, error, this.id);
4281
4422
 
4282
4423
  Metrics.postEvent({
@@ -4285,8 +4426,9 @@ export default class Meeting extends StatelessWebexPlugin {
4285
4426
  data: {
4286
4427
  canProceed: false,
4287
4428
  errors: [
4288
- Metrics.generateErrorPayload(2001, true, MetricsError.name.MEDIA_ENGINE, undefined)]
4289
- }
4429
+ Metrics.generateErrorPayload(2001, true, MetricsError.name.MEDIA_ENGINE, undefined),
4430
+ ],
4431
+ },
4290
4432
  });
4291
4433
  }
4292
4434
  };
@@ -4314,15 +4456,18 @@ export default class Meeting extends StatelessWebexPlugin {
4314
4456
  meetingId: this.id,
4315
4457
  });
4316
4458
 
4317
- logRequest(this.roap.sendRoapOK({
4318
- seq: event.roapMessage.seq,
4319
- mediaId: this.mediaId,
4320
- correlationId: this.correlationId
4321
- }), {
4322
- header: `${LOG_HEADER} Send Roap OK`,
4323
- success: `${LOG_HEADER} Successfully send roap OK`,
4324
- failure: `${LOG_HEADER} Error joining the call on send roap OK, `
4325
- });
4459
+ logRequest(
4460
+ this.roap.sendRoapOK({
4461
+ seq: event.roapMessage.seq,
4462
+ mediaId: this.mediaId,
4463
+ correlationId: this.correlationId,
4464
+ }),
4465
+ {
4466
+ header: `${LOG_HEADER} Send Roap OK`,
4467
+ success: `${LOG_HEADER} Successfully send roap OK`,
4468
+ failure: `${LOG_HEADER} Error joining the call on send roap OK, `,
4469
+ }
4470
+ );
4326
4471
  break;
4327
4472
 
4328
4473
  case 'OFFER':
@@ -4331,18 +4476,20 @@ export default class Meeting extends StatelessWebexPlugin {
4331
4476
  meetingId: this.id,
4332
4477
  });
4333
4478
 
4334
- logRequest(this.roap
4335
- .sendRoapMediaRequest({
4479
+ logRequest(
4480
+ this.roap.sendRoapMediaRequest({
4336
4481
  sdp: event.roapMessage.sdp,
4337
4482
  seq: event.roapMessage.seq,
4338
4483
  tieBreaker: event.roapMessage.tieBreaker,
4339
4484
  meeting: this, // or can pass meeting ID
4340
- reconnect: this.reconnectionManager.isReconnectInProgress()
4341
- }), {
4342
- header: `${LOG_HEADER} Send Roap Offer`,
4343
- success: `${LOG_HEADER} Successfully send roap offer`,
4344
- failure: `${LOG_HEADER} Error joining the call on send roap offer, `
4345
- });
4485
+ reconnect: this.reconnectionManager.isReconnectInProgress(),
4486
+ }),
4487
+ {
4488
+ header: `${LOG_HEADER} Send Roap Offer`,
4489
+ success: `${LOG_HEADER} Successfully send roap offer`,
4490
+ failure: `${LOG_HEADER} Error joining the call on send roap offer, `,
4491
+ }
4492
+ );
4346
4493
  break;
4347
4494
 
4348
4495
  case 'ANSWER':
@@ -4351,64 +4498,79 @@ export default class Meeting extends StatelessWebexPlugin {
4351
4498
  meetingId: this.id,
4352
4499
  });
4353
4500
 
4354
- logRequest(this.roap.sendRoapAnswer({
4355
- sdp: event.roapMessage.sdp,
4356
- seq: event.roapMessage.seq,
4357
- mediaId: this.mediaId,
4358
- correlationId: this.correlationId
4359
- }), {
4360
- header: `${LOG_HEADER} Send Roap Answer.`,
4361
- success: `${LOG_HEADER} Successfully send roap answer`,
4362
- failure: `${LOG_HEADER} Error joining the call on send roap answer, `
4363
- })
4364
- .catch((error) => {
4365
- const metricName = BEHAVIORAL_METRICS.ROAP_ANSWER_FAILURE;
4366
- const data = {
4367
- correlation_id: this.correlationId,
4368
- locus_id: this.locusUrl.split('/').pop(),
4369
- reason: error.message,
4370
- stack: error.stack
4371
- };
4372
- const metadata = {
4373
- type: error.name
4374
- };
4375
-
4376
- Metrics.sendBehavioralMetric(metricName, data, metadata);
4377
- });
4501
+ logRequest(
4502
+ this.roap.sendRoapAnswer({
4503
+ sdp: event.roapMessage.sdp,
4504
+ seq: event.roapMessage.seq,
4505
+ mediaId: this.mediaId,
4506
+ correlationId: this.correlationId,
4507
+ }),
4508
+ {
4509
+ header: `${LOG_HEADER} Send Roap Answer.`,
4510
+ success: `${LOG_HEADER} Successfully send roap answer`,
4511
+ failure: `${LOG_HEADER} Error joining the call on send roap answer, `,
4512
+ }
4513
+ ).catch((error) => {
4514
+ const metricName = BEHAVIORAL_METRICS.ROAP_ANSWER_FAILURE;
4515
+ const data = {
4516
+ correlation_id: this.correlationId,
4517
+ locus_id: this.locusUrl.split('/').pop(),
4518
+ reason: error.message,
4519
+ stack: error.stack,
4520
+ };
4521
+ const metadata = {
4522
+ type: error.name,
4523
+ };
4524
+
4525
+ Metrics.sendBehavioralMetric(metricName, data, metadata);
4526
+ });
4378
4527
  break;
4379
4528
 
4380
4529
  case 'ERROR':
4381
- if (event.roapMessage.errorType === MC.ErrorType.CONFLICT || event.roapMessage.errorType === MC.ErrorType.DOUBLECONFLICT) {
4530
+ if (
4531
+ event.roapMessage.errorType === MC.ErrorType.CONFLICT ||
4532
+ event.roapMessage.errorType === MC.ErrorType.DOUBLECONFLICT
4533
+ ) {
4382
4534
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ROAP_GLARE_CONDITION, {
4383
4535
  correlation_id: this.correlationId,
4384
4536
  locus_id: this.locusUrl.split('/').pop(),
4385
- sequence: event.roapMessage.seq
4537
+ sequence: event.roapMessage.seq,
4386
4538
  });
4387
4539
  }
4388
- logRequest(this.roap.sendRoapError({
4389
- seq: event.roapMessage.seq,
4390
- errorType: event.roapMessage.errorType,
4391
- mediaId: this.mediaId,
4392
- correlationId: this.correlationId
4393
- }), {
4394
- header: `${LOG_HEADER} Send Roap Error.`,
4395
- success: `${LOG_HEADER} Successfully send roap error`,
4396
- failure: `${LOG_HEADER} Failed to send roap error, `
4397
- });
4540
+ logRequest(
4541
+ this.roap.sendRoapError({
4542
+ seq: event.roapMessage.seq,
4543
+ errorType: event.roapMessage.errorType,
4544
+ mediaId: this.mediaId,
4545
+ correlationId: this.correlationId,
4546
+ }),
4547
+ {
4548
+ header: `${LOG_HEADER} Send Roap Error.`,
4549
+ success: `${LOG_HEADER} Successfully send roap error`,
4550
+ failure: `${LOG_HEADER} Failed to send roap error, `,
4551
+ }
4552
+ );
4398
4553
  break;
4399
4554
 
4400
4555
  default:
4401
- LoggerProxy.logger.error(`${LOG_HEADER} Unsupported message type: ${event.roapMessage.messageType}`);
4556
+ LoggerProxy.logger.error(
4557
+ `${LOG_HEADER} Unsupported message type: ${event.roapMessage.messageType}`
4558
+ );
4402
4559
  break;
4403
4560
  }
4404
4561
  });
4405
4562
 
4406
4563
  // eslint-disable-next-line no-param-reassign
4407
4564
  this.mediaProperties.webrtcMediaConnection.on(MC.Event.REMOTE_TRACK_ADDED, (event) => {
4408
- LoggerProxy.logger.log(`Meeting:index#setupMediaConnectionListeners --> REMOTE_TRACK_ADDED event received for webrtcMediaConnection: ${JSON.stringify(event)}`);
4565
+ LoggerProxy.logger.log(
4566
+ `Meeting:index#setupMediaConnectionListeners --> REMOTE_TRACK_ADDED event received for webrtcMediaConnection: ${JSON.stringify(
4567
+ event
4568
+ )}`
4569
+ );
4409
4570
 
4410
4571
  const mediaTrack = event.track;
4411
4572
 
4573
+ // eslint-disable-next-line @typescript-eslint/no-shadow
4412
4574
  let eventType;
4413
4575
 
4414
4576
  switch (event.type) {
@@ -4427,7 +4589,9 @@ export default class Meeting extends StatelessWebexPlugin {
4427
4589
  }
4428
4590
  break;
4429
4591
  default: {
4430
- LoggerProxy.logger.log('Meeting:index#setupMediaConnectionListeners --> unexpected track');
4592
+ LoggerProxy.logger.log(
4593
+ 'Meeting:index#setupMediaConnectionListeners --> unexpected track'
4594
+ );
4431
4595
  }
4432
4596
  }
4433
4597
 
@@ -4440,12 +4604,12 @@ export default class Meeting extends StatelessWebexPlugin {
4440
4604
  this,
4441
4605
  {
4442
4606
  file: 'meeting/index',
4443
- function: 'setupRemoteTrackListener:Event.REMOTE_TRACK_ADDED'
4607
+ function: 'setupRemoteTrackListener:Event.REMOTE_TRACK_ADDED',
4444
4608
  },
4445
4609
  EVENT_TRIGGERS.MEDIA_READY,
4446
4610
  {
4447
4611
  type: eventType,
4448
- stream: MediaUtil.createMediaStream([mediaTrack])
4612
+ stream: MediaUtil.createMediaStream([mediaTrack]),
4449
4613
  }
4450
4614
  );
4451
4615
  }
@@ -4464,51 +4628,47 @@ export default class Meeting extends StatelessWebexPlugin {
4464
4628
  data: {
4465
4629
  canProceed: false,
4466
4630
  errors: [
4467
- Metrics.generateErrorPayload(
4468
- 2004, false, MetricsError.name.MEDIA_ENGINE, undefined
4469
- )]
4470
- }
4631
+ Metrics.generateErrorPayload(2004, false, MetricsError.name.MEDIA_ENGINE, undefined),
4632
+ ],
4633
+ },
4471
4634
  });
4472
4635
 
4473
4636
  this.uploadLogs({
4474
4637
  file: 'peer-connection-manager/index',
4475
- function: 'connectionFailed'
4638
+ function: 'connectionFailed',
4476
4639
  });
4477
4640
 
4478
- Metrics.sendBehavioralMetric(
4479
- BEHAVIORAL_METRICS.CONNECTION_FAILURE,
4480
- {
4481
- correlation_id: this.correlationId,
4482
- locus_id: this.locusId
4483
- }
4484
- );
4641
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.CONNECTION_FAILURE, {
4642
+ correlation_id: this.correlationId,
4643
+ locus_id: this.locusId,
4644
+ });
4485
4645
  };
4486
4646
 
4487
- LoggerProxy.logger.info(`Meeting:index#setupMediaConnectionListeners --> connection state changed to ${event.state}`);
4647
+ LoggerProxy.logger.info(
4648
+ `Meeting:index#setupMediaConnectionListeners --> connection state changed to ${event.state}`
4649
+ );
4488
4650
  switch (event.state) {
4489
4651
  case MC.ConnectionState.Connecting:
4490
4652
  Metrics.postEvent({event: eventType.ICE_START, meeting: this});
4491
4653
  break;
4492
4654
  case MC.ConnectionState.Connected:
4493
4655
  Metrics.postEvent({event: eventType.ICE_END, meeting: this});
4494
- Metrics.sendBehavioralMetric(
4495
- BEHAVIORAL_METRICS.CONNECTION_SUCCESS,
4496
- {
4497
- correlation_id: this.correlationId,
4498
- locus_id: this.locusId
4499
- }
4500
- );
4656
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.CONNECTION_SUCCESS, {
4657
+ correlation_id: this.correlationId,
4658
+ locus_id: this.locusId,
4659
+ });
4501
4660
  this.setNetworkStatus(NETWORK_STATUS.CONNECTED);
4502
4661
  this.reconnectionManager.iceReconnected();
4503
4662
  break;
4504
4663
  case MC.ConnectionState.Disconnected:
4505
4664
  this.setNetworkStatus(NETWORK_STATUS.DISCONNECTED);
4506
- this.reconnectionManager.waitForIceReconnect()
4507
- .catch(() => {
4508
- LoggerProxy.logger.info('Meeting:index#setupMediaConnectionListeners --> state DISCONNECTED, automatic reconnection timed out.');
4665
+ this.reconnectionManager.waitForIceReconnect().catch(() => {
4666
+ LoggerProxy.logger.info(
4667
+ 'Meeting:index#setupMediaConnectionListeners --> state DISCONNECTED, automatic reconnection timed out.'
4668
+ );
4509
4669
 
4510
- connectionFailed();
4511
- });
4670
+ connectionFailed();
4671
+ });
4512
4672
  break;
4513
4673
  case MC.ConnectionState.Failed:
4514
4674
  connectionFailed();
@@ -4518,53 +4678,58 @@ export default class Meeting extends StatelessWebexPlugin {
4518
4678
  }
4519
4679
  });
4520
4680
 
4521
- this.mediaProperties.webrtcMediaConnection.on(MC.Event.ACTIVE_SPEAKERS_CHANGED,
4522
- (msg) => {
4523
- Trigger.trigger(
4524
- this,
4525
- {
4526
- file: 'meeting/index',
4527
- function: 'setupMediaConnectionListeners'
4528
- },
4529
- EVENT_TRIGGERS.ACTIVE_SPEAKER_CHANGED,
4530
- {
4531
- seqNum: msg.seqNum,
4532
- memberIds: msg.csis.map((csi) => this.members.findMemberByCsi(csi)?.id).filter((item) => (item !== undefined))
4533
- }
4534
- );
4535
- });
4681
+ this.mediaProperties.webrtcMediaConnection.on(MC.Event.ACTIVE_SPEAKERS_CHANGED, (msg) => {
4682
+ Trigger.trigger(
4683
+ this,
4684
+ {
4685
+ file: 'meeting/index',
4686
+ function: 'setupMediaConnectionListeners',
4687
+ },
4688
+ EVENT_TRIGGERS.ACTIVE_SPEAKER_CHANGED,
4689
+ {
4690
+ seqNum: msg.seqNum,
4691
+ memberIds: msg.csis
4692
+ .map((csi) => this.members.findMemberByCsi(csi)?.id)
4693
+ .filter((item) => item !== undefined),
4694
+ }
4695
+ );
4696
+ });
4536
4697
 
4537
- this.mediaProperties.webrtcMediaConnection.on(MC.Event.VIDEO_SOURCES_COUNT_CHANGED,
4698
+ this.mediaProperties.webrtcMediaConnection.on(
4699
+ MC.Event.VIDEO_SOURCES_COUNT_CHANGED,
4538
4700
  (numTotalSources, numLiveSources) => {
4539
4701
  Trigger.trigger(
4540
4702
  this,
4541
4703
  {
4542
4704
  file: 'meeting/index',
4543
- function: 'setupMediaConnectionListeners'
4705
+ function: 'setupMediaConnectionListeners',
4544
4706
  },
4545
4707
  EVENT_TRIGGERS.REMOTE_VIDEO_SOURCE_COUNT_CHANGED,
4546
4708
  {
4547
4709
  numTotalSources,
4548
- numLiveSources
4710
+ numLiveSources,
4549
4711
  }
4550
4712
  );
4551
- });
4713
+ }
4714
+ );
4552
4715
 
4553
- this.mediaProperties.webrtcMediaConnection.on(MC.Event.AUDIO_SOURCES_COUNT_CHANGED,
4716
+ this.mediaProperties.webrtcMediaConnection.on(
4717
+ MC.Event.AUDIO_SOURCES_COUNT_CHANGED,
4554
4718
  (numTotalSources, numLiveSources) => {
4555
4719
  Trigger.trigger(
4556
4720
  this,
4557
4721
  {
4558
4722
  file: 'meeting/index',
4559
- function: 'setupMediaConnectionListeners'
4723
+ function: 'setupMediaConnectionListeners',
4560
4724
  },
4561
4725
  EVENT_TRIGGERS.REMOTE_AUDIO_SOURCE_COUNT_CHANGED,
4562
4726
  {
4563
4727
  numTotalSources,
4564
- numLiveSources
4728
+ numLiveSources,
4565
4729
  }
4566
4730
  );
4567
- });
4731
+ }
4732
+ );
4568
4733
  };
4569
4734
 
4570
4735
  /**
@@ -4578,15 +4743,22 @@ export default class Meeting extends StatelessWebexPlugin {
4578
4743
  // TODO: might have to send the same event to the developer
4579
4744
  // Add ip address info if geo hint is present
4580
4745
  // @ts-ignore fix type
4581
- options.data.intervalMetadata.peerReflexiveIP = this.webex.meetings.geoHintInfo?.clientAddress || options.data.intervalMetadata.peerReflexiveIP || MQA_STATS.DEFAULT_IP;
4582
- Metrics.postEvent({event: eventType.MEDIA_QUALITY, meeting: this, data: {intervalData: options.data, networkType: options.networkType}});
4746
+ options.data.intervalMetadata.peerReflexiveIP =
4747
+ this.webex.meetings.geoHintInfo?.clientAddress ||
4748
+ options.data.intervalMetadata.peerReflexiveIP ||
4749
+ MQA_STATS.DEFAULT_IP;
4750
+ Metrics.postEvent({
4751
+ event: eventType.MEDIA_QUALITY,
4752
+ meeting: this,
4753
+ data: {intervalData: options.data, networkType: options.networkType},
4754
+ });
4583
4755
  });
4584
4756
  this.statsAnalyzer.on(StatsAnalyzerEvents.LOCAL_MEDIA_STARTED, (data) => {
4585
4757
  Trigger.trigger(
4586
4758
  this,
4587
4759
  {
4588
4760
  file: 'meeting/index',
4589
- function: 'addMedia'
4761
+ function: 'addMedia',
4590
4762
  },
4591
4763
  EVENT_TRIGGERS.MEETING_MEDIA_LOCAL_STARTED,
4592
4764
  data
@@ -4595,8 +4767,8 @@ export default class Meeting extends StatelessWebexPlugin {
4595
4767
  event: eventType.SENDING_MEDIA_START,
4596
4768
  meeting: this,
4597
4769
  data: {
4598
- mediaType: data.type
4599
- }
4770
+ mediaType: data.type,
4771
+ },
4600
4772
  });
4601
4773
  });
4602
4774
  this.statsAnalyzer.on(StatsAnalyzerEvents.LOCAL_MEDIA_STOPPED, (data) => {
@@ -4604,8 +4776,8 @@ export default class Meeting extends StatelessWebexPlugin {
4604
4776
  event: eventType.SENDING_MEDIA_STOP,
4605
4777
  meeting: this,
4606
4778
  data: {
4607
- mediaType: data.type
4608
- }
4779
+ mediaType: data.type,
4780
+ },
4609
4781
  });
4610
4782
  });
4611
4783
  this.statsAnalyzer.on(StatsAnalyzerEvents.REMOTE_MEDIA_STARTED, (data) => {
@@ -4613,7 +4785,7 @@ export default class Meeting extends StatelessWebexPlugin {
4613
4785
  this,
4614
4786
  {
4615
4787
  file: 'meeting/index',
4616
- function: 'addMedia'
4788
+ function: 'addMedia',
4617
4789
  },
4618
4790
  EVENT_TRIGGERS.MEETING_MEDIA_REMOTE_STARTED,
4619
4791
  data
@@ -4622,8 +4794,8 @@ export default class Meeting extends StatelessWebexPlugin {
4622
4794
  event: eventType.RECEIVING_MEDIA_START,
4623
4795
  meeting: this,
4624
4796
  data: {
4625
- mediaType: data.type
4626
- }
4797
+ mediaType: data.type,
4798
+ },
4627
4799
  });
4628
4800
  });
4629
4801
  this.statsAnalyzer.on(StatsAnalyzerEvents.REMOTE_MEDIA_STOPPED, (data) => {
@@ -4631,8 +4803,8 @@ export default class Meeting extends StatelessWebexPlugin {
4631
4803
  event: eventType.RECEIVING_MEDIA_STOP,
4632
4804
  meeting: this,
4633
4805
  data: {
4634
- mediaType: data.type
4635
- }
4806
+ mediaType: data.type,
4807
+ },
4636
4808
  });
4637
4809
  });
4638
4810
  };
@@ -4642,19 +4814,15 @@ export default class Meeting extends StatelessWebexPlugin {
4642
4814
  }
4643
4815
 
4644
4816
  createMediaConnection(turnServerInfo) {
4645
- const mc = Media.createMediaConnection(
4646
- this.isMultistream,
4647
- this.getMediaConnectionDebugId(),
4648
- {
4649
- mediaProperties: this.mediaProperties,
4650
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
4651
- // @ts-ignore - config coming from registerPlugin
4652
- enableRtx: this.config.enableRtx,
4653
- // @ts-ignore - config coming from registerPlugin
4654
- enableExtmap: this.config.enableExtmap,
4655
- turnServerInfo
4656
- }
4657
- );
4817
+ const mc = Media.createMediaConnection(this.isMultistream, this.getMediaConnectionDebugId(), {
4818
+ mediaProperties: this.mediaProperties,
4819
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
4820
+ // @ts-ignore - config coming from registerPlugin
4821
+ enableRtx: this.config.enableRtx,
4822
+ // @ts-ignore - config coming from registerPlugin
4823
+ enableExtmap: this.config.enableExtmap,
4824
+ turnServerInfo,
4825
+ });
4658
4826
 
4659
4827
  this.mediaProperties.setMediaPeerConnection(mc);
4660
4828
  this.setupMediaConnectionListeners();
@@ -4672,15 +4840,17 @@ export default class Meeting extends StatelessWebexPlugin {
4672
4840
  * @returns {void}
4673
4841
  */
4674
4842
  forwardEvent(eventEmitter, eventTypeToForward, meetingEventType) {
4675
- eventEmitter.on(eventTypeToForward, (data) => Trigger.trigger(
4676
- this,
4677
- {
4678
- file: 'meetings',
4679
- function: 'addMedia'
4680
- },
4681
- meetingEventType,
4682
- data
4683
- ));
4843
+ eventEmitter.on(eventTypeToForward, (data) =>
4844
+ Trigger.trigger(
4845
+ this,
4846
+ {
4847
+ file: 'meetings',
4848
+ function: 'addMedia',
4849
+ },
4850
+ meetingEventType,
4851
+ data
4852
+ )
4853
+ );
4684
4854
  }
4685
4855
 
4686
4856
  /**
@@ -4714,9 +4884,7 @@ export default class Meeting extends StatelessWebexPlugin {
4714
4884
  return Promise.reject(new UserInLobbyError());
4715
4885
  }
4716
4886
 
4717
- const {
4718
- localStream, localShare, mediaSettings, remoteMediaManagerConfig
4719
- } = options;
4887
+ const {localStream, localShare, mediaSettings, remoteMediaManagerConfig} = options;
4720
4888
 
4721
4889
  LoggerProxy.logger.info(`${LOG_HEADER} Adding Media.`);
4722
4890
 
@@ -4730,17 +4898,17 @@ export default class Meeting extends StatelessWebexPlugin {
4730
4898
  share: false,
4731
4899
  share_audio: false,
4732
4900
  video: false,
4733
- whiteboard: false
4901
+ whiteboard: false,
4734
4902
  },
4735
4903
  tx: {
4736
4904
  audio: false,
4737
4905
  share: false,
4738
4906
  share_audio: false,
4739
4907
  video: false,
4740
- whiteboard: false
4741
- }
4742
- }
4743
- }
4908
+ whiteboard: false,
4909
+ },
4910
+ },
4911
+ },
4744
4912
  });
4745
4913
 
4746
4914
  return MeetingUtil.validateOptions(options)
@@ -4762,12 +4930,23 @@ export default class Meeting extends StatelessWebexPlugin {
4762
4930
  remoteMediaManagerConfig
4763
4931
  );
4764
4932
 
4765
- this.forwardEvent(this.remoteMediaManager, RemoteMediaManagerEvent.AudioCreated, EVENT_TRIGGERS.REMOTE_MEDIA_AUDIO_CREATED);
4766
- this.forwardEvent(this.remoteMediaManager, RemoteMediaManagerEvent.ScreenShareAudioCreated, EVENT_TRIGGERS.REMOTE_MEDIA_SCREEN_SHARE_AUDIO_CREATED);
4767
- this.forwardEvent(this.remoteMediaManager, RemoteMediaManagerEvent.VideoLayoutChanged, EVENT_TRIGGERS.REMOTE_MEDIA_VIDEO_LAYOUT_CHANGED);
4933
+ this.forwardEvent(
4934
+ this.remoteMediaManager,
4935
+ RemoteMediaManagerEvent.AudioCreated,
4936
+ EVENT_TRIGGERS.REMOTE_MEDIA_AUDIO_CREATED
4937
+ );
4938
+ this.forwardEvent(
4939
+ this.remoteMediaManager,
4940
+ RemoteMediaManagerEvent.ScreenShareAudioCreated,
4941
+ EVENT_TRIGGERS.REMOTE_MEDIA_SCREEN_SHARE_AUDIO_CREATED
4942
+ );
4943
+ this.forwardEvent(
4944
+ this.remoteMediaManager,
4945
+ RemoteMediaManagerEvent.VideoLayoutChanged,
4946
+ EVENT_TRIGGERS.REMOTE_MEDIA_VIDEO_LAYOUT_CHANGED
4947
+ );
4768
4948
 
4769
- return this.remoteMediaManager.start()
4770
- .then(() => mc.initiateOffer());
4949
+ return this.remoteMediaManager.start().then(() => mc.initiateOffer());
4771
4950
  }
4772
4951
 
4773
4952
  return mc.initiateOffer();
@@ -4775,9 +4954,11 @@ export default class Meeting extends StatelessWebexPlugin {
4775
4954
  .then(() => {
4776
4955
  this.setMercuryListener();
4777
4956
  })
4778
- .then(() => this.getDevices().then((devices) => {
4779
- MeetingUtil.handleDeviceLogging(devices);
4780
- }))
4957
+ .then(() =>
4958
+ this.getDevices().then((devices) => {
4959
+ MeetingUtil.handleDeviceLogging(devices);
4960
+ })
4961
+ )
4781
4962
  .then(() => {
4782
4963
  this.handleMediaLogging(this.mediaProperties);
4783
4964
  LoggerProxy.logger.info(`${LOG_HEADER} media connection created`);
@@ -4789,41 +4970,49 @@ export default class Meeting extends StatelessWebexPlugin {
4789
4970
  // @ts-ignore - config coming from registerPlugin
4790
4971
  this.statsAnalyzer = new StatsAnalyzer(this.config.stats, this.networkQualityMonitor);
4791
4972
  this.setupStatsAnalyzerEventHandlers();
4792
- this.networkQualityMonitor.on(EVENT_TRIGGERS.NETWORK_QUALITY, this.sendNetworkQualityEvent.bind(this));
4973
+ this.networkQualityMonitor.on(
4974
+ EVENT_TRIGGERS.NETWORK_QUALITY,
4975
+ this.sendNetworkQualityEvent.bind(this)
4976
+ );
4793
4977
  }
4794
4978
  })
4795
4979
  .catch((error) => {
4796
- LoggerProxy.logger.error(`${LOG_HEADER} Error adding media , setting up peerconnection, `, error);
4980
+ LoggerProxy.logger.error(
4981
+ `${LOG_HEADER} Error adding media , setting up peerconnection, `,
4982
+ error
4983
+ );
4797
4984
 
4798
4985
  throw error;
4799
4986
  })
4800
- .then(() => new Promise<void>((resolve, reject) => {
4801
- let timerCount = 0;
4802
-
4803
- // eslint-disable-next-line func-names
4804
- // eslint-disable-next-line prefer-arrow-callback
4805
- if (this.type === _CALL_) {
4806
- resolve();
4807
- }
4808
- const joiningTimer = setInterval(() => {
4809
- timerCount += 1;
4810
- if (this.meetingState === FULL_STATE.ACTIVE) {
4811
- clearInterval(joiningTimer);
4812
- resolve();
4813
- }
4814
-
4815
- if (timerCount === 4) {
4816
- clearInterval(joiningTimer);
4817
- reject(new Error('Meeting is still not active '));
4818
- }
4819
- }, 1000);
4820
- }))
4821
4987
  .then(
4822
- () => this.mediaProperties.waitForMediaConnectionConnected()
4823
- .catch(() => {
4824
- throw createMeetingsError(30202, 'Meeting connection failed');
4988
+ () =>
4989
+ new Promise<void>((resolve, reject) => {
4990
+ let timerCount = 0;
4991
+
4992
+ // eslint-disable-next-line func-names
4993
+ // eslint-disable-next-line prefer-arrow-callback
4994
+ if (this.type === _CALL_) {
4995
+ resolve();
4996
+ }
4997
+ const joiningTimer = setInterval(() => {
4998
+ timerCount += 1;
4999
+ if (this.meetingState === FULL_STATE.ACTIVE) {
5000
+ clearInterval(joiningTimer);
5001
+ resolve();
5002
+ }
5003
+
5004
+ if (timerCount === 4) {
5005
+ clearInterval(joiningTimer);
5006
+ reject(new Error('Meeting is still not active '));
5007
+ }
5008
+ }, 1000);
4825
5009
  })
4826
5010
  )
5011
+ .then(() =>
5012
+ this.mediaProperties.waitForMediaConnectionConnected().catch(() => {
5013
+ throw createMeetingsError(30202, 'Meeting connection failed');
5014
+ })
5015
+ )
4827
5016
  .then(() => {
4828
5017
  LoggerProxy.logger.info(`${LOG_HEADER} PeerConnection CONNECTED`);
4829
5018
  if (mediaSettings && mediaSettings.sendShare && localShare) {
@@ -4839,60 +5028,58 @@ export default class Meeting extends StatelessWebexPlugin {
4839
5028
  })
4840
5029
  .then(() => this.mediaProperties.getCurrentConnectionType())
4841
5030
  .then((connectionType) => {
4842
- Metrics.sendBehavioralMetric(
4843
- BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS,
4844
- {
4845
- correlation_id: this.correlationId,
4846
- locus_id: this.locusUrl.split('/').pop(),
4847
- connectionType
4848
- }
4849
- );
5031
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_SUCCESS, {
5032
+ correlation_id: this.correlationId,
5033
+ locus_id: this.locusUrl.split('/').pop(),
5034
+ connectionType,
5035
+ });
4850
5036
  })
4851
5037
  .catch((error) => {
4852
5038
  // Clean up stats analyzer, peer connection, and turn off listeners
4853
- const stopStatsAnalyzer = (this.statsAnalyzer) ? this.statsAnalyzer.stopAnalyzer() : Promise.resolve();
5039
+ const stopStatsAnalyzer = this.statsAnalyzer
5040
+ ? this.statsAnalyzer.stopAnalyzer()
5041
+ : Promise.resolve();
4854
5042
 
4855
- return stopStatsAnalyzer
4856
- .then(() => {
4857
- this.statsAnalyzer = null;
5043
+ return stopStatsAnalyzer.then(() => {
5044
+ this.statsAnalyzer = null;
4858
5045
 
4859
- if (this.mediaProperties.webrtcMediaConnection) {
4860
- this.closePeerConnections();
4861
- this.unsetPeerConnections();
4862
- }
5046
+ if (this.mediaProperties.webrtcMediaConnection) {
5047
+ this.closePeerConnections();
5048
+ this.unsetPeerConnections();
5049
+ }
4863
5050
 
4864
- LoggerProxy.logger.error(`${LOG_HEADER} Error adding media failed to initiate PC and send request, `, error);
5051
+ LoggerProxy.logger.error(
5052
+ `${LOG_HEADER} Error adding media failed to initiate PC and send request, `,
5053
+ error
5054
+ );
4865
5055
 
4866
- Metrics.sendBehavioralMetric(
4867
- BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE,
4868
- {
4869
- correlation_id: this.correlationId,
4870
- locus_id: this.locusUrl.split('/').pop(),
4871
- reason: error.message,
4872
- stack: error.stack,
4873
- code: error.code,
4874
- turnDiscoverySkippedReason,
4875
- turnServerUsed
4876
- }
4877
- );
5056
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.ADD_MEDIA_FAILURE, {
5057
+ correlation_id: this.correlationId,
5058
+ locus_id: this.locusUrl.split('/').pop(),
5059
+ reason: error.message,
5060
+ stack: error.stack,
5061
+ code: error.code,
5062
+ turnDiscoverySkippedReason,
5063
+ turnServerUsed,
5064
+ });
4878
5065
 
4879
- // Upload logs on error while adding media
4880
- Trigger.trigger(
4881
- this,
4882
- {
4883
- file: 'meeting/index',
4884
- function: 'addMedia'
4885
- },
4886
- EVENTS.REQUEST_UPLOAD_LOGS,
4887
- this
4888
- );
5066
+ // Upload logs on error while adding media
5067
+ Trigger.trigger(
5068
+ this,
5069
+ {
5070
+ file: 'meeting/index',
5071
+ function: 'addMedia',
5072
+ },
5073
+ EVENTS.REQUEST_UPLOAD_LOGS,
5074
+ this
5075
+ );
4889
5076
 
4890
- if (error instanceof MC.Errors.SdpError) {
4891
- this.leave({reason: MEETING_REMOVED_REASON.MEETING_CONNECTION_FAILED});
4892
- }
5077
+ if (error instanceof MC.Errors.SdpError) {
5078
+ this.leave({reason: MEETING_REMOVED_REASON.MEETING_CONNECTION_FAILED});
5079
+ }
4893
5080
 
4894
- throw error;
4895
- });
5081
+ throw error;
5082
+ });
4896
5083
  });
4897
5084
  }
4898
5085
 
@@ -4918,10 +5105,15 @@ export default class Meeting extends StatelessWebexPlugin {
4918
5105
  private enqueueMediaUpdate(mediaUpdateType: string, options: object) {
4919
5106
  return new Promise((resolve, reject) => {
4920
5107
  const queueItem = {
4921
- pendingPromiseResolve: resolve, pendingPromiseReject: reject, mediaUpdateType, options
5108
+ pendingPromiseResolve: resolve,
5109
+ pendingPromiseReject: reject,
5110
+ mediaUpdateType,
5111
+ options,
4922
5112
  };
4923
5113
 
4924
- LoggerProxy.logger.log(`Meeting:index#enqueueMediaUpdate --> enqueuing media update type=${mediaUpdateType}`);
5114
+ LoggerProxy.logger.log(
5115
+ `Meeting:index#enqueueMediaUpdate --> enqueuing media update type=${mediaUpdateType}`
5116
+ );
4925
5117
  this.queuedMediaUpdates.push(queueItem);
4926
5118
  });
4927
5119
  }
@@ -4940,9 +5132,9 @@ export default class Meeting extends StatelessWebexPlugin {
4940
5132
  this,
4941
5133
  {
4942
5134
  file: 'meeting/index',
4943
- function: 'mediaNegotiatedEvent'
5135
+ function: 'mediaNegotiatedEvent',
4944
5136
  },
4945
- EVENT_TRIGGERS.MEDIA_NEGOTIATED,
5137
+ EVENT_TRIGGERS.MEDIA_NEGOTIATED
4946
5138
  );
4947
5139
  }
4948
5140
  };
@@ -4955,12 +5147,13 @@ export default class Meeting extends StatelessWebexPlugin {
4955
5147
  * @memberof Meeting
4956
5148
  */
4957
5149
  processNextQueuedMediaUpdate = () => {
4958
- if (this.canUpdateMedia() && (this.queuedMediaUpdates.length > 0)) {
4959
- const {
4960
- pendingPromiseResolve, pendingPromiseReject, mediaUpdateType, options
4961
- } = this.queuedMediaUpdates.shift();
5150
+ if (this.canUpdateMedia() && this.queuedMediaUpdates.length > 0) {
5151
+ const {pendingPromiseResolve, pendingPromiseReject, mediaUpdateType, options} =
5152
+ this.queuedMediaUpdates.shift();
4962
5153
 
4963
- LoggerProxy.logger.log(`Meeting:index#processNextQueuedMediaUpdate --> performing delayed media update type=${mediaUpdateType}`);
5154
+ LoggerProxy.logger.log(
5155
+ `Meeting:index#processNextQueuedMediaUpdate --> performing delayed media update type=${mediaUpdateType}`
5156
+ );
4964
5157
  switch (mediaUpdateType) {
4965
5158
  case MEDIA_UPDATE_TYPE.ALL:
4966
5159
  this.updateMedia(options).then(pendingPromiseResolve, pendingPromiseReject);
@@ -4975,7 +5168,9 @@ export default class Meeting extends StatelessWebexPlugin {
4975
5168
  this.updateShare(options).then(pendingPromiseResolve, pendingPromiseReject);
4976
5169
  break;
4977
5170
  default:
4978
- LoggerProxy.logger.error(`Peer-connection-manager:index#processNextQueuedMediaUpdate --> unsupported media update type ${mediaUpdateType} found in the queue`);
5171
+ LoggerProxy.logger.error(
5172
+ `Peer-connection-manager:index#processNextQueuedMediaUpdate --> unsupported media update type ${mediaUpdateType} found in the queue`
5173
+ );
4979
5174
  break;
4980
5175
  }
4981
5176
  }
@@ -5004,9 +5199,7 @@ export default class Meeting extends StatelessWebexPlugin {
5004
5199
  if (!this.canUpdateMedia()) {
5005
5200
  return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.ALL, options);
5006
5201
  }
5007
- const {
5008
- localStream, localShare, mediaSettings
5009
- } = options;
5202
+ const {localStream, localShare, mediaSettings} = options;
5010
5203
 
5011
5204
  const previousSendShareStatus = this.mediaProperties.mediaDirection.sendShare;
5012
5205
 
@@ -5016,52 +5209,60 @@ export default class Meeting extends StatelessWebexPlugin {
5016
5209
 
5017
5210
  return MeetingUtil.validateOptions(options)
5018
5211
  .then(() => this.preMedia(localStream, localShare, mediaSettings))
5019
- .then(() => this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5020
- send: {
5021
- audio: this.mediaProperties.mediaDirection.sendAudio ? this.mediaProperties.audioTrack : null,
5022
- video: this.mediaProperties.mediaDirection.sendVideo ? this.mediaProperties.videoTrack : null,
5023
- screenShareVideo: this.mediaProperties.mediaDirection.sendShare ? this.mediaProperties.shareTrack : null
5024
- },
5025
- receive: {
5026
- audio: this.mediaProperties.mediaDirection.receiveAudio,
5027
- video: this.mediaProperties.mediaDirection.receiveVideo,
5028
- screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
5029
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel
5030
- }
5031
- })
5032
- .then(() => {
5033
- LoggerProxy.logger.info(`${LOG_HEADER} webrtcMediaConnection.updateSendReceiveOptions done`);
5034
- })
5035
- .catch((error) => {
5036
- LoggerProxy.logger.error(`${LOG_HEADER} Error updatedMedia, `, error);
5212
+ .then(() =>
5213
+ this.mediaProperties.webrtcMediaConnection
5214
+ .updateSendReceiveOptions({
5215
+ send: {
5216
+ audio: this.mediaProperties.mediaDirection.sendAudio
5217
+ ? this.mediaProperties.audioTrack
5218
+ : null,
5219
+ video: this.mediaProperties.mediaDirection.sendVideo
5220
+ ? this.mediaProperties.videoTrack
5221
+ : null,
5222
+ screenShareVideo: this.mediaProperties.mediaDirection.sendShare
5223
+ ? this.mediaProperties.shareTrack
5224
+ : null,
5225
+ },
5226
+ receive: {
5227
+ audio: this.mediaProperties.mediaDirection.receiveAudio,
5228
+ video: this.mediaProperties.mediaDirection.receiveVideo,
5229
+ screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
5230
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
5231
+ },
5232
+ })
5233
+ .then(() => {
5234
+ LoggerProxy.logger.info(
5235
+ `${LOG_HEADER} webrtcMediaConnection.updateSendReceiveOptions done`
5236
+ );
5237
+ })
5238
+ .catch((error) => {
5239
+ LoggerProxy.logger.error(`${LOG_HEADER} Error updatedMedia, `, error);
5037
5240
 
5038
- Metrics.sendBehavioralMetric(
5039
- BEHAVIORAL_METRICS.UPDATE_MEDIA_FAILURE,
5040
- {
5241
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPDATE_MEDIA_FAILURE, {
5041
5242
  correlation_id: this.correlationId,
5042
5243
  locus_id: this.locusUrl.split('/').pop(),
5043
5244
  reason: error.message,
5044
- stack: error.stack
5045
- }
5046
- );
5245
+ stack: error.stack,
5246
+ });
5047
5247
 
5048
- throw error;
5049
- })
5050
- // todo: the following code used to be called always after sending the roap message with the new SDP
5051
- // now it's called independently from the roap message (so might be before it), check if that's OK
5052
- // if not, ensure it's called after (now it's called after roap message is sent out, but we're not
5053
- // waiting for sendRoapMediaRequest() to be resolved)
5054
- .then(() => this.checkForStopShare(mediaSettings.sendShare, previousSendShareStatus))
5055
- .then((startShare) => {
5056
- // This is a special case if we do an /floor grant followed by /media
5057
- // we actually get a OFFER from the server and a GLAR condition happens
5058
- if (startShare) {
5059
- // We are assuming that the clients are connected when doing an update
5060
- return this.requestScreenShareFloor();
5061
- }
5248
+ throw error;
5249
+ })
5250
+ // todo: the following code used to be called always after sending the roap message with the new SDP
5251
+ // now it's called independently from the roap message (so might be before it), check if that's OK
5252
+ // if not, ensure it's called after (now it's called after roap message is sent out, but we're not
5253
+ // waiting for sendRoapMediaRequest() to be resolved)
5254
+ .then(() => this.checkForStopShare(mediaSettings.sendShare, previousSendShareStatus))
5255
+ .then((startShare) => {
5256
+ // This is a special case if we do an /floor grant followed by /media
5257
+ // we actually get a OFFER from the server and a GLAR condition happens
5258
+ if (startShare) {
5259
+ // We are assuming that the clients are connected when doing an update
5260
+ return this.requestScreenShareFloor();
5261
+ }
5062
5262
 
5063
- return Promise.resolve();
5064
- }));
5263
+ return Promise.resolve();
5264
+ })
5265
+ );
5065
5266
  }
5066
5267
 
5067
5268
  /**
@@ -5077,7 +5278,11 @@ export default class Meeting extends StatelessWebexPlugin {
5077
5278
  * @public
5078
5279
  * @memberof Meeting
5079
5280
  */
5080
- public async updateAudio(options: { sendAudio: boolean; receiveAudio: boolean; stream: MediaStream }) {
5281
+ public async updateAudio(options: {
5282
+ sendAudio: boolean;
5283
+ receiveAudio: boolean;
5284
+ stream: MediaStream;
5285
+ }) {
5081
5286
  if (!this.canUpdateMedia()) {
5082
5287
  return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.AUDIO, options);
5083
5288
  }
@@ -5095,7 +5300,11 @@ export default class Meeting extends StatelessWebexPlugin {
5095
5300
  if (this.effects && this.effects.state) {
5096
5301
  const bnrEnabled = this.effects.state.bnr.enabled;
5097
5302
 
5098
- if (sendAudio && !this.isAudioMuted() && (bnrEnabled === BNR_STATUS.ENABLED || bnrEnabled === BNR_STATUS.SHOULD_ENABLE)) {
5303
+ if (
5304
+ sendAudio &&
5305
+ !this.isAudioMuted() &&
5306
+ (bnrEnabled === BNR_STATUS.ENABLED || bnrEnabled === BNR_STATUS.SHOULD_ENABLE)
5307
+ ) {
5099
5308
  LoggerProxy.logger.info('Meeting:index#updateAudio. Calling WebRTC enable bnr method');
5100
5309
  track = await this.internal_enableBNR(track);
5101
5310
  LoggerProxy.logger.info('Meeting:index#updateAudio. WebRTC enable bnr request completed');
@@ -5103,15 +5312,17 @@ export default class Meeting extends StatelessWebexPlugin {
5103
5312
  }
5104
5313
 
5105
5314
  return MeetingUtil.validateOptions({sendAudio, localStream: stream})
5106
- .then(() => this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5107
- send: {audio: track},
5108
- receive: {
5109
- audio: options.receiveAudio,
5110
- video: this.mediaProperties.mediaDirection.receiveVideo,
5111
- screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
5112
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel
5113
- }
5114
- }))
5315
+ .then(() =>
5316
+ this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5317
+ send: {audio: track},
5318
+ receive: {
5319
+ audio: options.receiveAudio,
5320
+ video: this.mediaProperties.mediaDirection.receiveVideo,
5321
+ screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
5322
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
5323
+ },
5324
+ })
5325
+ )
5115
5326
  .then(() => {
5116
5327
  this.setLocalAudioTrack(track);
5117
5328
  // todo: maybe this.mediaProperties.mediaDirection could be removed? it's duplicating stuff from webrtcMediaConnection
@@ -5119,7 +5330,8 @@ export default class Meeting extends StatelessWebexPlugin {
5119
5330
  this.mediaProperties.mediaDirection.receiveAudio = receiveAudio;
5120
5331
 
5121
5332
  // audio state could be undefined if you have not sent audio before
5122
- this.audio = this.audio || createMuteState(AUDIO, this, this.mediaProperties.mediaDirection);
5333
+ this.audio =
5334
+ this.audio || createMuteState(AUDIO, this, this.mediaProperties.mediaDirection);
5123
5335
  });
5124
5336
  }
5125
5337
 
@@ -5136,7 +5348,7 @@ export default class Meeting extends StatelessWebexPlugin {
5136
5348
  * @public
5137
5349
  * @memberof Meeting
5138
5350
  */
5139
- public updateVideo(options: { sendVideo: boolean; receiveVideo: boolean; stream: MediaStream }) {
5351
+ public updateVideo(options: {sendVideo: boolean; receiveVideo: boolean; stream: MediaStream}) {
5140
5352
  if (!this.canUpdateMedia()) {
5141
5353
  return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.VIDEO, options);
5142
5354
  }
@@ -5152,22 +5364,25 @@ export default class Meeting extends StatelessWebexPlugin {
5152
5364
  }
5153
5365
 
5154
5366
  return MeetingUtil.validateOptions({sendVideo, localStream: stream})
5155
- .then(() => this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5156
- send: {video: track},
5157
- receive: {
5158
- audio: this.mediaProperties.mediaDirection.receiveAudio,
5159
- video: options.receiveVideo,
5160
- screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
5161
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel
5162
- }
5163
- }))
5367
+ .then(() =>
5368
+ this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5369
+ send: {video: track},
5370
+ receive: {
5371
+ audio: this.mediaProperties.mediaDirection.receiveAudio,
5372
+ video: options.receiveVideo,
5373
+ screenShareVideo: this.mediaProperties.mediaDirection.receiveShare,
5374
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
5375
+ },
5376
+ })
5377
+ )
5164
5378
  .then(() => {
5165
5379
  this.setLocalVideoTrack(track);
5166
5380
  this.mediaProperties.mediaDirection.sendVideo = sendVideo;
5167
5381
  this.mediaProperties.mediaDirection.receiveVideo = receiveVideo;
5168
5382
 
5169
5383
  // video state could be undefined if you have not sent video before
5170
- this.video = this.video || createMuteState(VIDEO, this, this.mediaProperties.mediaDirection);
5384
+ this.video =
5385
+ this.video || createMuteState(VIDEO, this, this.mediaProperties.mediaDirection);
5171
5386
  });
5172
5387
  }
5173
5388
 
@@ -5187,8 +5402,7 @@ export default class Meeting extends StatelessWebexPlugin {
5187
5402
 
5188
5403
  if (!sendShare && previousShareStatus) {
5189
5404
  // When user stops sharing
5190
- return this.releaseScreenShareFloor()
5191
- .then(() => Promise.resolve(false));
5405
+ return this.releaseScreenShareFloor().then(() => Promise.resolve(false));
5192
5406
  }
5193
5407
 
5194
5408
  return Promise.resolve();
@@ -5206,7 +5420,12 @@ export default class Meeting extends StatelessWebexPlugin {
5206
5420
  * @public
5207
5421
  * @memberof Meeting
5208
5422
  */
5209
- public updateShare(options: { sendShare?: boolean; receiveShare?: boolean, stream?: any, skipSignalingCheck?: boolean }) {
5423
+ public updateShare(options: {
5424
+ sendShare?: boolean;
5425
+ receiveShare?: boolean;
5426
+ stream?: any;
5427
+ skipSignalingCheck?: boolean;
5428
+ }) {
5210
5429
  if (!options.skipSignalingCheck && !this.canUpdateMedia()) {
5211
5430
  return this.enqueueMediaUpdate(MEDIA_UPDATE_TYPE.SHARE, options);
5212
5431
  }
@@ -5227,22 +5446,25 @@ export default class Meeting extends StatelessWebexPlugin {
5227
5446
 
5228
5447
  return MeetingUtil.validateOptions({sendShare, localShare: stream})
5229
5448
  .then(() => this.checkForStopShare(sendShare, previousSendShareStatus))
5230
- .then((startShare) => this.mediaProperties.webrtcMediaConnection.updateSendReceiveOptions({
5231
- send: {screenShareVideo: track},
5232
- receive: {
5233
- audio: this.mediaProperties.mediaDirection.receiveAudio,
5234
- video: this.mediaProperties.mediaDirection.receiveVideo,
5235
- screenShareVideo: options.receiveShare,
5236
- remoteQualityLevel: this.mediaProperties.remoteQualityLevel
5237
- }
5238
- })
5239
- .then(() => {
5240
- if (startShare) {
5241
- return this.requestScreenShareFloor();
5242
- }
5449
+ .then((startShare) =>
5450
+ this.mediaProperties.webrtcMediaConnection
5451
+ .updateSendReceiveOptions({
5452
+ send: {screenShareVideo: track},
5453
+ receive: {
5454
+ audio: this.mediaProperties.mediaDirection.receiveAudio,
5455
+ video: this.mediaProperties.mediaDirection.receiveVideo,
5456
+ screenShareVideo: options.receiveShare,
5457
+ remoteQualityLevel: this.mediaProperties.remoteQualityLevel,
5458
+ },
5459
+ })
5460
+ .then(() => {
5461
+ if (startShare) {
5462
+ return this.requestScreenShareFloor();
5463
+ }
5243
5464
 
5244
- return Promise.resolve();
5245
- }))
5465
+ return Promise.resolve();
5466
+ })
5467
+ )
5246
5468
  .then(() => {
5247
5469
  this.mediaProperties.mediaDirection.sendShare = sendShare;
5248
5470
  this.mediaProperties.mediaDirection.receiveShare = receiveShare;
@@ -5292,7 +5514,7 @@ export default class Meeting extends StatelessWebexPlugin {
5292
5514
  .acknowledgeMeeting({
5293
5515
  locusUrl: this.locusUrl,
5294
5516
  deviceUrl: this.deviceUrl,
5295
- correlationId: this.correlationId
5517
+ correlationId: this.correlationId,
5296
5518
  })
5297
5519
  .then((response) => Promise.resolve(response))
5298
5520
  .then((response) => {
@@ -5300,14 +5522,14 @@ export default class Meeting extends StatelessWebexPlugin {
5300
5522
  Metrics.postEvent({event: eventType.ALERT_DISPLAYED, meeting: this});
5301
5523
 
5302
5524
  return Promise.resolve({
5303
- response
5525
+ response,
5304
5526
  });
5305
5527
  });
5306
5528
  }
5307
5529
 
5308
5530
  // TODO: outside of 1:1 incoming, and all outgoing calls
5309
5531
  return Promise.resolve({
5310
- message: 'noop'
5532
+ message: 'noop',
5311
5533
  });
5312
5534
  }
5313
5535
 
@@ -5319,15 +5541,17 @@ export default class Meeting extends StatelessWebexPlugin {
5319
5541
  * @memberof Meeting
5320
5542
  */
5321
5543
  public decline(reason: string) {
5322
- return MeetingUtil.declineMeeting(this, reason).then((decline) => {
5323
- this.meetingFiniteStateMachine.decline();
5544
+ return MeetingUtil.declineMeeting(this, reason)
5545
+ .then((decline) => {
5546
+ this.meetingFiniteStateMachine.decline();
5324
5547
 
5325
- return Promise.resolve(decline);
5326
- }).catch((error) => {
5327
- this.meetingFiniteStateMachine.fail(error);
5548
+ return Promise.resolve(decline);
5549
+ })
5550
+ .catch((error) => {
5551
+ this.meetingFiniteStateMachine.fail(error);
5328
5552
 
5329
- return Promise.reject(error);
5330
- });
5553
+ return Promise.reject(error);
5554
+ });
5331
5555
  }
5332
5556
 
5333
5557
  /**
@@ -5338,8 +5562,12 @@ export default class Meeting extends StatelessWebexPlugin {
5338
5562
  * @public
5339
5563
  * @memberof Meeting
5340
5564
  */
5341
- public leave(options: { resourceId?: string, reason?: any } = {} as any) {
5342
- Metrics.postEvent({event: eventType.LEAVE, meeting: this, data: {trigger: trigger.USER_INTERACTION, canProceed: false}});
5565
+ public leave(options: {resourceId?: string; reason?: any} = {} as any) {
5566
+ Metrics.postEvent({
5567
+ event: eventType.LEAVE,
5568
+ meeting: this,
5569
+ data: {trigger: trigger.USER_INTERACTION, canProceed: false},
5570
+ });
5343
5571
  const leaveReason = options.reason || MEETING_REMOVED_REASON.CLIENT_LEAVE_REQUEST;
5344
5572
 
5345
5573
  LoggerProxy.logger.log('Meeting:index#leave --> Leaving a meeting');
@@ -5354,7 +5582,7 @@ export default class Meeting extends StatelessWebexPlugin {
5354
5582
  this,
5355
5583
  {
5356
5584
  file: 'meeting/index',
5357
- function: 'leave'
5585
+ function: 'leave',
5358
5586
  },
5359
5587
  EVENTS.REQUEST_UPLOAD_LOGS,
5360
5588
  this
@@ -5367,19 +5595,20 @@ export default class Meeting extends StatelessWebexPlugin {
5367
5595
  this,
5368
5596
  {
5369
5597
  file: 'meeting/index',
5370
- function: 'leave'
5598
+ function: 'leave',
5371
5599
  },
5372
5600
  EVENTS.DESTROY_MEETING,
5373
5601
  {
5374
5602
  reason: options.reason,
5375
- meetingId: this.id
5603
+ meetingId: this.id,
5376
5604
  }
5377
5605
  );
5378
5606
  }
5379
5607
  LoggerProxy.logger.log('Meeting:index#leave --> LEAVE REASON ', leaveReason);
5380
5608
 
5381
5609
  return leave;
5382
- }).catch((error) => {
5610
+ })
5611
+ .catch((error) => {
5383
5612
  this.meetingFiniteStateMachine.fail(error);
5384
5613
  LoggerProxy.logger.error('Meeting:index#leave --> Failed to leave ', error);
5385
5614
  // upload logs on leave irrespective of meeting delete
@@ -5387,21 +5616,18 @@ export default class Meeting extends StatelessWebexPlugin {
5387
5616
  this,
5388
5617
  {
5389
5618
  file: 'meeting/index',
5390
- function: 'leave'
5619
+ function: 'leave',
5391
5620
  },
5392
5621
  EVENTS.REQUEST_UPLOAD_LOGS,
5393
5622
  this
5394
5623
  );
5395
- Metrics.sendBehavioralMetric(
5396
- BEHAVIORAL_METRICS.MEETING_LEAVE_FAILURE,
5397
- {
5398
- correlation_id: this.correlationId,
5399
- locus_id: this.locusUrl.split('/').pop(),
5400
- reason: error.message,
5401
- stack: error.stack,
5402
- code: error.code
5403
- }
5404
- );
5624
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_LEAVE_FAILURE, {
5625
+ correlation_id: this.correlationId,
5626
+ locus_id: this.locusUrl.split('/').pop(),
5627
+ reason: error.message,
5628
+ stack: error.stack,
5629
+ code: error.code,
5630
+ });
5405
5631
 
5406
5632
  return Promise.reject(error);
5407
5633
  });
@@ -5430,14 +5656,15 @@ export default class Meeting extends StatelessWebexPlugin {
5430
5656
  personUrl: this.locusInfo.self.url,
5431
5657
  deviceUrl: this.deviceUrl,
5432
5658
  uri: whiteboard.url,
5433
- resourceUrl: channelUrl
5659
+ resourceUrl: channelUrl,
5434
5660
  };
5435
5661
 
5436
5662
  if (resourceToken) {
5437
5663
  body.resourceToken = resourceToken;
5438
5664
  }
5439
5665
 
5440
- return this.meetingRequest.changeMeetingFloor(body)
5666
+ return this.meetingRequest
5667
+ .changeMeetingFloor(body)
5441
5668
  .then(() => {
5442
5669
  this.isSharing = false;
5443
5670
 
@@ -5446,16 +5673,13 @@ export default class Meeting extends StatelessWebexPlugin {
5446
5673
  .catch((error) => {
5447
5674
  LoggerProxy.logger.error('Meeting:index#startWhiteboardShare --> Error ', error);
5448
5675
 
5449
- Metrics.sendBehavioralMetric(
5450
- BEHAVIORAL_METRICS.MEETING_START_WHITEBOARD_SHARE_FAILURE,
5451
- {
5452
- correlation_id: this.correlationId,
5453
- locus_id: this.locusUrl.split('/').pop(),
5454
- reason: error.message,
5455
- stack: error.stack,
5456
- board: {channelUrl}
5457
- }
5458
- );
5676
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_START_WHITEBOARD_SHARE_FAILURE, {
5677
+ correlation_id: this.correlationId,
5678
+ locus_id: this.locusUrl.split('/').pop(),
5679
+ reason: error.message,
5680
+ stack: error.stack,
5681
+ board: {channelUrl},
5682
+ });
5459
5683
 
5460
5684
  return Promise.reject(error);
5461
5685
  });
@@ -5477,12 +5701,13 @@ export default class Meeting extends StatelessWebexPlugin {
5477
5701
  if (whiteboard) {
5478
5702
  Metrics.postEvent({event: eventType.WHITEBOARD_SHARE_STOPPED, meeting: this});
5479
5703
 
5480
- return this.meetingRequest.changeMeetingFloor({
5481
- disposition: FLOOR_ACTION.RELEASED,
5482
- personUrl: this.locusInfo.self.url,
5483
- deviceUrl: this.deviceUrl,
5484
- uri: whiteboard.url
5485
- })
5704
+ return this.meetingRequest
5705
+ .changeMeetingFloor({
5706
+ disposition: FLOOR_ACTION.RELEASED,
5707
+ personUrl: this.locusInfo.self.url,
5708
+ deviceUrl: this.deviceUrl,
5709
+ uri: whiteboard.url,
5710
+ })
5486
5711
  .catch((error) => {
5487
5712
  LoggerProxy.logger.error('Meeting:index#stopWhiteboardShare --> Error ', error);
5488
5713
 
@@ -5494,14 +5719,13 @@ export default class Meeting extends StatelessWebexPlugin {
5494
5719
  locus_id: this.locusUrl.split('/').pop(),
5495
5720
  reason: error.message,
5496
5721
  stack: error.stack,
5497
- board: {channelUrl}
5722
+ board: {channelUrl},
5498
5723
  }
5499
5724
  );
5500
5725
 
5501
5726
  return Promise.reject(error);
5502
5727
  })
5503
- .finally(() => {
5504
- });
5728
+ .finally(() => {});
5505
5729
  }
5506
5730
 
5507
5731
  return Promise.reject(new ParameterError('Cannot stop share without whiteboard.'));
@@ -5516,16 +5740,17 @@ export default class Meeting extends StatelessWebexPlugin {
5516
5740
  private requestScreenShareFloor() {
5517
5741
  const content = this.locusInfo.mediaShares.find((element) => element.name === CONTENT);
5518
5742
 
5519
- if (content && (this.shareStatus !== SHARE_STATUS.LOCAL_SHARE_ACTIVE)) {
5743
+ if (content && this.shareStatus !== SHARE_STATUS.LOCAL_SHARE_ACTIVE) {
5520
5744
  Metrics.postEvent({event: eventType.SHARE_INITIATED, meeting: this});
5521
5745
 
5522
- return this.meetingRequest.changeMeetingFloor({
5523
- disposition: FLOOR_ACTION.GRANTED,
5524
- personUrl: this.locusInfo.self.url,
5525
- deviceUrl: this.deviceUrl,
5526
- uri: content.url,
5527
- resourceUrl: this.resourceUrl
5528
- })
5746
+ return this.meetingRequest
5747
+ .changeMeetingFloor({
5748
+ disposition: FLOOR_ACTION.GRANTED,
5749
+ personUrl: this.locusInfo.self.url,
5750
+ deviceUrl: this.deviceUrl,
5751
+ uri: content.url,
5752
+ resourceUrl: this.resourceUrl,
5753
+ })
5529
5754
  .then(() => {
5530
5755
  this.isSharing = true;
5531
5756
 
@@ -5534,15 +5759,12 @@ export default class Meeting extends StatelessWebexPlugin {
5534
5759
  .catch((error) => {
5535
5760
  LoggerProxy.logger.error('Meeting:index#share --> Error ', error);
5536
5761
 
5537
- Metrics.sendBehavioralMetric(
5538
- BEHAVIORAL_METRICS.MEETING_SHARE_FAILURE,
5539
- {
5540
- correlation_id: this.correlationId,
5541
- locus_id: this.locusUrl.split('/').pop(),
5542
- reason: error.message,
5543
- stack: error.stack
5544
- }
5545
- );
5762
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_SHARE_FAILURE, {
5763
+ correlation_id: this.correlationId,
5764
+ locus_id: this.locusUrl.split('/').pop(),
5765
+ reason: error.message,
5766
+ stack: error.stack,
5767
+ });
5546
5768
 
5547
5769
  return Promise.reject(error);
5548
5770
  });
@@ -5563,7 +5785,7 @@ export default class Meeting extends StatelessWebexPlugin {
5563
5785
  return this.updateShare({
5564
5786
  sendShare: false,
5565
5787
  receiveShare: this.mediaProperties.mediaDirection.receiveShare,
5566
- ...options
5788
+ ...options,
5567
5789
  });
5568
5790
  }
5569
5791
 
@@ -5576,7 +5798,7 @@ export default class Meeting extends StatelessWebexPlugin {
5576
5798
  private releaseScreenShareFloor() {
5577
5799
  const content = this.locusInfo.mediaShares.find((element) => element.name === CONTENT);
5578
5800
 
5579
- if (content && (this.mediaProperties.mediaDirection.sendShare)) {
5801
+ if (content && this.mediaProperties.mediaDirection.sendShare) {
5580
5802
  Metrics.postEvent({event: eventType.SHARE_STOPPED, meeting: this});
5581
5803
  Media.stopTracks(this.mediaProperties.shareTrack);
5582
5804
 
@@ -5587,25 +5809,23 @@ export default class Meeting extends StatelessWebexPlugin {
5587
5809
  return Promise.resolve();
5588
5810
  }
5589
5811
 
5590
- return this.meetingRequest.changeMeetingFloor({
5591
- disposition: FLOOR_ACTION.RELEASED,
5592
- personUrl: this.locusInfo.self.url,
5593
- deviceUrl: this.deviceUrl,
5594
- uri: content.url,
5595
- resourceUrl: this.resourceUrl
5596
- })
5812
+ return this.meetingRequest
5813
+ .changeMeetingFloor({
5814
+ disposition: FLOOR_ACTION.RELEASED,
5815
+ personUrl: this.locusInfo.self.url,
5816
+ deviceUrl: this.deviceUrl,
5817
+ uri: content.url,
5818
+ resourceUrl: this.resourceUrl,
5819
+ })
5597
5820
  .catch((error) => {
5598
5821
  LoggerProxy.logger.error('Meeting:index#releaseScreenShareFloor --> Error ', error);
5599
5822
 
5600
- Metrics.sendBehavioralMetric(
5601
- BEHAVIORAL_METRICS.STOP_FLOOR_REQUEST_FAILURE,
5602
- {
5603
- correlation_id: this.correlationId,
5604
- locus_id: this.locusUrl.split('/').pop(),
5605
- reason: error.message,
5606
- stack: error.stack
5607
- }
5608
- );
5823
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.STOP_FLOOR_REQUEST_FAILURE, {
5824
+ correlation_id: this.correlationId,
5825
+ locus_id: this.locusUrl.split('/').pop(),
5826
+ reason: error.message,
5827
+ stack: error.stack,
5828
+ });
5609
5829
 
5610
5830
  return Promise.reject(error);
5611
5831
  })
@@ -5700,18 +5920,21 @@ export default class Meeting extends StatelessWebexPlugin {
5700
5920
  public sendDTMF(tones: string) {
5701
5921
  if (this.locusInfo && this.locusInfo.self) {
5702
5922
  if (this.locusInfo.self.enableDTMF) {
5703
- return this.meetingRequest
5704
- .sendDTMF({
5705
- locusUrl: this.locusInfo.self.url,
5706
- deviceUrl: this.deviceUrl,
5707
- tones
5708
- });
5923
+ return this.meetingRequest.sendDTMF({
5924
+ locusUrl: this.locusInfo.self.url,
5925
+ deviceUrl: this.deviceUrl,
5926
+ tones,
5927
+ });
5709
5928
  }
5710
5929
 
5711
- return this.rejectWithErrorLog('Meeting:index#sendDTMF --> cannot send DTMF, meeting does not have DTMF enabled');
5930
+ return this.rejectWithErrorLog(
5931
+ 'Meeting:index#sendDTMF --> cannot send DTMF, meeting does not have DTMF enabled'
5932
+ );
5712
5933
  }
5713
5934
 
5714
- return this.rejectWithErrorLog('Meeting:index#sendDTMF --> cannot send DTMF, meeting does not have a connection to the "locus" call control service. Have you joined?');
5935
+ return this.rejectWithErrorLog(
5936
+ 'Meeting:index#sendDTMF --> cannot send DTMF, meeting does not have a connection to the "locus" call control service. Have you joined?'
5937
+ );
5715
5938
  }
5716
5939
 
5717
5940
  /**
@@ -5748,12 +5971,16 @@ export default class Meeting extends StatelessWebexPlugin {
5748
5971
 
5749
5972
  // TODO: We need a real time value for Audio, Video and Share send indicator
5750
5973
  if (mediaDirection.receiveVideo !== true || !remoteVideoTrack) {
5751
- return this.rejectWithErrorLog('Meeting:index#changeVideoLayout --> cannot change video layout, you are not recieving any video/share stream');
5974
+ return this.rejectWithErrorLog(
5975
+ 'Meeting:index#changeVideoLayout --> cannot change video layout, you are not recieving any video/share stream'
5976
+ );
5752
5977
  }
5753
5978
 
5754
5979
  if (layoutType) {
5755
5980
  if (!LAYOUT_TYPES.includes(layoutType)) {
5756
- this.rejectWithErrorLog('Meeting:index#changeVideoLayout --> cannot change video layout, invalid layoutType recieved.');
5981
+ this.rejectWithErrorLog(
5982
+ 'Meeting:index#changeVideoLayout --> cannot change video layout, invalid layoutType recieved.'
5983
+ );
5757
5984
  }
5758
5985
 
5759
5986
  layoutInfo.layoutType = layoutType;
@@ -5779,15 +6006,17 @@ export default class Meeting extends StatelessWebexPlugin {
5779
6006
  const contentHeight = Math.round(content.height);
5780
6007
 
5781
6008
  // Stop any "twitching" caused by very slight size changes
5782
- if (!this.lastVideoLayoutInfo.content ||
6009
+ if (
6010
+ !this.lastVideoLayoutInfo.content ||
5783
6011
  Math.abs(this.lastVideoLayoutInfo.content.height - contentHeight) > 2 ||
5784
6012
  Math.abs(this.lastVideoLayoutInfo.content.width - contentWidth) > 2
5785
6013
  ) {
5786
6014
  layoutInfo.content = {width: contentWidth, height: contentHeight};
5787
6015
  }
5788
- }
5789
- else {
5790
- return this.rejectWithErrorLog('Meeting:index#changeVideoLayout --> unable to send renderInfo for content, you are not receiving remote share');
6016
+ } else {
6017
+ return this.rejectWithErrorLog(
6018
+ 'Meeting:index#changeVideoLayout --> unable to send renderInfo for content, you are not receiving remote share'
6019
+ );
5791
6020
  }
5792
6021
  }
5793
6022
 
@@ -5806,7 +6035,7 @@ export default class Meeting extends StatelessWebexPlugin {
5806
6035
  },
5807
6036
  EVENT_TRIGGERS.MEETING_CONTROLS_LAYOUT_UPDATE,
5808
6037
  {
5809
- layout: envelope.layout
6038
+ layout: envelope.layout,
5810
6039
  }
5811
6040
  );
5812
6041
  });
@@ -5817,7 +6046,7 @@ export default class Meeting extends StatelessWebexPlugin {
5817
6046
  deviceUrl: this.deviceUrl,
5818
6047
  layoutType,
5819
6048
  main: layoutInfo.main,
5820
- content: layoutInfo.content
6049
+ content: layoutInfo.content,
5821
6050
  })
5822
6051
  .then((response) => {
5823
6052
  if (response && response.body && response.body.locus) {
@@ -5844,12 +6073,16 @@ export default class Meeting extends StatelessWebexPlugin {
5844
6073
  }
5845
6074
 
5846
6075
  if (!this.mediaProperties.mediaDirection.sendVideo) {
5847
- return this.rejectWithErrorLog('Meeting:index#setLocalVideoQuality --> unable to change video quality, sendVideo is disabled');
6076
+ return this.rejectWithErrorLog(
6077
+ 'Meeting:index#setLocalVideoQuality --> unable to change video quality, sendVideo is disabled'
6078
+ );
5848
6079
  }
5849
6080
 
5850
6081
  // If level is already the same, don't do anything
5851
6082
  if (level === this.mediaProperties.localQualityLevel) {
5852
- LoggerProxy.logger.warn(`Meeting:index#setLocalQualityLevel --> Quality already set to ${level}`);
6083
+ LoggerProxy.logger.warn(
6084
+ `Meeting:index#setLocalQualityLevel --> Quality already set to ${level}`
6085
+ );
5853
6086
 
5854
6087
  return Promise.resolve();
5855
6088
  }
@@ -5860,25 +6093,27 @@ export default class Meeting extends StatelessWebexPlugin {
5860
6093
  const mediaDirection = {
5861
6094
  sendAudio: this.mediaProperties.mediaDirection.sendAudio,
5862
6095
  sendVideo: this.mediaProperties.mediaDirection.sendVideo,
5863
- sendShare: this.mediaProperties.mediaDirection.sendShare
6096
+ sendShare: this.mediaProperties.mediaDirection.sendShare,
5864
6097
  };
5865
6098
 
5866
6099
  // When changing local video quality level
5867
6100
  // Need to stop current track first as chrome doesn't support resolution upscaling(for eg. changing 480p to 720p)
5868
6101
  // Without feeding it a new track
5869
6102
  // open bug link: https://bugs.chromium.org/p/chromium/issues/detail?id=943469
5870
- if (isBrowser('chrome') && this.mediaProperties.videoTrack) Media.stopTracks(this.mediaProperties.videoTrack);
6103
+ if (isBrowser('chrome') && this.mediaProperties.videoTrack)
6104
+ Media.stopTracks(this.mediaProperties.videoTrack);
5871
6105
 
5872
- return this.getMediaStreams(mediaDirection, VIDEO_RESOLUTIONS[level])
5873
- .then(async ([localStream]) => {
6106
+ return this.getMediaStreams(mediaDirection, VIDEO_RESOLUTIONS[level]).then(
6107
+ async ([localStream]) => {
5874
6108
  await this.updateVideo({
5875
6109
  sendVideo: true,
5876
6110
  receiveVideo: true,
5877
- stream: localStream
6111
+ stream: localStream,
5878
6112
  });
5879
6113
 
5880
6114
  return localStream;
5881
- });
6115
+ }
6116
+ );
5882
6117
  }
5883
6118
 
5884
6119
  /**
@@ -5890,16 +6125,25 @@ export default class Meeting extends StatelessWebexPlugin {
5890
6125
  LoggerProxy.logger.log(`Meeting:index#setRemoteQualityLevel --> Setting quality to ${level}`);
5891
6126
 
5892
6127
  if (!QUALITY_LEVELS[level]) {
5893
- return this.rejectWithErrorLog(`Meeting:index#setRemoteQualityLevel --> ${level} not defined`);
6128
+ return this.rejectWithErrorLog(
6129
+ `Meeting:index#setRemoteQualityLevel --> ${level} not defined`
6130
+ );
5894
6131
  }
5895
6132
 
5896
- if (!this.mediaProperties.mediaDirection.receiveAudio && !this.mediaProperties.mediaDirection.receiveVideo) {
5897
- return this.rejectWithErrorLog('Meeting:index#setRemoteQualityLevel --> unable to change remote quality, receiveVideo and receiveAudio is disabled');
6133
+ if (
6134
+ !this.mediaProperties.mediaDirection.receiveAudio &&
6135
+ !this.mediaProperties.mediaDirection.receiveVideo
6136
+ ) {
6137
+ return this.rejectWithErrorLog(
6138
+ 'Meeting:index#setRemoteQualityLevel --> unable to change remote quality, receiveVideo and receiveAudio is disabled'
6139
+ );
5898
6140
  }
5899
6141
 
5900
6142
  // If level is already the same, don't do anything
5901
6143
  if (level === this.mediaProperties.remoteQualityLevel) {
5902
- LoggerProxy.logger.warn(`Meeting:index#setRemoteQualityLevel --> Quality already set to ${level}`);
6144
+ LoggerProxy.logger.warn(
6145
+ `Meeting:index#setRemoteQualityLevel --> Quality already set to ${level}`
6146
+ );
5903
6147
 
5904
6148
  return Promise.resolve();
5905
6149
  }
@@ -5925,7 +6169,7 @@ export default class Meeting extends StatelessWebexPlugin {
5925
6169
 
5926
6170
  const previousLevel = {
5927
6171
  local: this.mediaProperties.localQualityLevel,
5928
- remote: this.mediaProperties.remoteQualityLevel
6172
+ remote: this.mediaProperties.remoteQualityLevel,
5929
6173
  };
5930
6174
 
5931
6175
  // If level is already the same, don't do anything
@@ -5933,7 +6177,9 @@ export default class Meeting extends StatelessWebexPlugin {
5933
6177
  level === this.mediaProperties.localQualityLevel &&
5934
6178
  level === this.mediaProperties.remoteQualityLevel
5935
6179
  ) {
5936
- LoggerProxy.logger.warn(`Meeting:index#setMeetingQuality --> Quality already set to ${level}`);
6180
+ LoggerProxy.logger.warn(
6181
+ `Meeting:index#setMeetingQuality --> Quality already set to ${level}`
6182
+ );
5937
6183
 
5938
6184
  return Promise.resolve();
5939
6185
  }
@@ -5943,9 +6189,8 @@ export default class Meeting extends StatelessWebexPlugin {
5943
6189
 
5944
6190
  return (sendVideo ? this.setLocalVideoQuality(level) : Promise.resolve())
5945
6191
  .then(() =>
5946
- ((receiveAudio || receiveVideo) ?
5947
- this.setRemoteQualityLevel(level) :
5948
- Promise.resolve()))
6192
+ receiveAudio || receiveVideo ? this.setRemoteQualityLevel(level) : Promise.resolve()
6193
+ )
5949
6194
  .catch((error) => {
5950
6195
  // From troubleshooting it seems that the stream itself doesn't change the max-fs if the peer connection isn't stable
5951
6196
  this.mediaProperties.setLocalQualityLevel(previousLevel.local);
@@ -5959,10 +6204,10 @@ export default class Meeting extends StatelessWebexPlugin {
5959
6204
  correlation_id: this.correlationId,
5960
6205
  locus_id: this.locusUrl.split('/').pop(),
5961
6206
  reason: error.message,
5962
- stack: error.stack
6207
+ stack: error.stack,
5963
6208
  },
5964
6209
  {
5965
- type: error.name
6210
+ type: error.name,
5966
6211
  }
5967
6212
  );
5968
6213
 
@@ -5971,23 +6216,23 @@ export default class Meeting extends StatelessWebexPlugin {
5971
6216
  }
5972
6217
 
5973
6218
  /**
5974
- *
5975
- * NOTE: this method can only be used with transcoded meetings, for multistream use publishTrack()
5976
- *
5977
- * @param {Object} options parameter
5978
- * @param {Boolean} options.sendAudio send audio from the display share
5979
- * @param {Boolean} options.sendShare send video from the display share
5980
- * @param {Object} options.sharePreferences
5981
- * @param {MediaTrackConstraints} options.sharePreferences.shareConstraints constraints to apply to video
5982
- * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints}
5983
- * @param {Boolean} options.sharePreferences.highFrameRate if shareConstraints isn't provided, set default values based off of this boolean
5984
- * @returns {Promise}
5985
- */
6219
+ *
6220
+ * NOTE: this method can only be used with transcoded meetings, for multistream use publishTrack()
6221
+ *
6222
+ * @param {Object} options parameter
6223
+ * @param {Boolean} options.sendAudio send audio from the display share
6224
+ * @param {Boolean} options.sendShare send video from the display share
6225
+ * @param {Object} options.sharePreferences
6226
+ * @param {MediaTrackConstraints} options.sharePreferences.shareConstraints constraints to apply to video
6227
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints}
6228
+ * @param {Boolean} options.sharePreferences.highFrameRate if shareConstraints isn't provided, set default values based off of this boolean
6229
+ * @returns {Promise}
6230
+ */
5986
6231
  shareScreen(
5987
6232
  options: {
5988
6233
  sendAudio: boolean;
5989
6234
  sendShare: boolean;
5990
- sharePreferences: { shareConstraints: MediaTrackConstraints };
6235
+ sharePreferences: {shareConstraints: MediaTrackConstraints};
5991
6236
  } = {} as any
5992
6237
  ) {
5993
6238
  LoggerProxy.logger.log('Meeting:index#shareScreen --> Getting local share');
@@ -5995,16 +6240,18 @@ export default class Meeting extends StatelessWebexPlugin {
5995
6240
  const shareConstraints = {
5996
6241
  sendShare: true,
5997
6242
  sendAudio: false,
5998
- ...options
6243
+ ...options,
5999
6244
  };
6000
6245
 
6001
6246
  // @ts-ignore - config coming from registerPlugin
6002
6247
  return Media.getDisplayMedia(shareConstraints, this.config)
6003
- .then((shareStream) => this.updateShare({
6004
- sendShare: true,
6005
- receiveShare: this.mediaProperties.mediaDirection.receiveShare,
6006
- stream: shareStream
6007
- }))
6248
+ .then((shareStream) =>
6249
+ this.updateShare({
6250
+ sendShare: true,
6251
+ receiveShare: this.mediaProperties.mediaDirection.receiveShare,
6252
+ stream: shareStream,
6253
+ })
6254
+ )
6008
6255
  .catch((error) => {
6009
6256
  // Whenever there is a failure when trying to access a user's display
6010
6257
  // report it as an Behavioral metric
@@ -6018,10 +6265,10 @@ export default class Meeting extends StatelessWebexPlugin {
6018
6265
  correlation_id: this.correlationId,
6019
6266
  locus_id: this.locusUrl.split('/').pop(),
6020
6267
  reason: error.message,
6021
- stack: error.stack
6268
+ stack: error.stack,
6022
6269
  };
6023
6270
  const metadata = {
6024
- type: error.name
6271
+ type: error.name,
6025
6272
  };
6026
6273
 
6027
6274
  Metrics.sendBehavioralMetric(metricName, data, metadata);
@@ -6039,28 +6286,29 @@ export default class Meeting extends StatelessWebexPlugin {
6039
6286
  private handleShareTrackEnded(localShare: MediaStream) {
6040
6287
  if (this.wirelessShare) {
6041
6288
  this.leave({reason: MEETING_REMOVED_REASON.USER_ENDED_SHARE_STREAMS});
6042
- }
6043
- else {
6289
+ } else {
6044
6290
  // Skip checking for a stable peerConnection
6045
6291
  // to allow immediately stopping screenshare
6046
6292
  this.stopShare({
6047
- skipSignalingCheck: true
6048
- })
6049
- .catch((error) => {
6050
- LoggerProxy.logger.log('Meeting:index#handleShareTrackEnded --> Error stopping share: ', error);
6051
- });
6293
+ skipSignalingCheck: true,
6294
+ }).catch((error) => {
6295
+ LoggerProxy.logger.log(
6296
+ 'Meeting:index#handleShareTrackEnded --> Error stopping share: ',
6297
+ error
6298
+ );
6299
+ });
6052
6300
  }
6053
6301
 
6054
6302
  Trigger.trigger(
6055
6303
  this,
6056
6304
  {
6057
6305
  file: 'meeting/index',
6058
- function: 'handleShareTrackEnded'
6306
+ function: 'handleShareTrackEnded',
6059
6307
  },
6060
6308
  EVENT_TRIGGERS.MEETING_STOPPED_SHARING_LOCAL,
6061
6309
  {
6062
6310
  type: EVENT_TYPES.LOCAL_SHARE,
6063
- stream: localShare
6311
+ stream: localShare,
6064
6312
  }
6065
6313
  );
6066
6314
  }
@@ -6081,12 +6329,12 @@ export default class Meeting extends StatelessWebexPlugin {
6081
6329
  this,
6082
6330
  {
6083
6331
  file: 'meeting/index',
6084
- function: 'addMedia'
6332
+ function: 'addMedia',
6085
6333
  },
6086
6334
  EVENT_TRIGGERS.NETWORK_QUALITY,
6087
6335
  {
6088
6336
  networkQualityScore: res.networkQualityScore,
6089
- mediaType: res.mediaType
6337
+ mediaType: res.mediaType,
6090
6338
  }
6091
6339
  );
6092
6340
  }
@@ -6098,7 +6346,7 @@ export default class Meeting extends StatelessWebexPlugin {
6098
6346
  * @private
6099
6347
  * @returns {undefined}
6100
6348
  */
6101
- private handleMediaLogging({ audioTrack, videoTrack }: any) {
6349
+ private handleMediaLogging({audioTrack, videoTrack}: any) {
6102
6350
  MeetingUtil.handleVideoLogging(videoTrack);
6103
6351
  MeetingUtil.handleAudioLogging(audioTrack);
6104
6352
  }
@@ -6128,7 +6376,7 @@ export default class Meeting extends StatelessWebexPlugin {
6128
6376
  const start = this[`startSetupDelay${typeMedia}`];
6129
6377
  const end = this[`endSetupDelay${typeMedia}`];
6130
6378
 
6131
- return (start && end) ? end - start : undefined;
6379
+ return start && end ? end - start : undefined;
6132
6380
  }
6133
6381
 
6134
6382
  /**
@@ -6156,14 +6404,14 @@ export default class Meeting extends StatelessWebexPlugin {
6156
6404
  const start = this[`startSendingMediaDelay${typeMedia}`];
6157
6405
  const end = this[`endSendingMediaDelay${typeMedia}`];
6158
6406
 
6159
- return (start && end) ? end - start : undefined;
6407
+ return start && end ? end - start : undefined;
6160
6408
  }
6161
6409
 
6162
6410
  /**
6163
6411
  *
6164
6412
  * @returns {undefined}
6165
6413
  */
6166
- setStartLocalSDPGenRemoteSDPRecvDelay() {
6414
+ setStartLocalSDPGenRemoteSDPRecvDelay() {
6167
6415
  if (!this.startLocalSDPGenRemoteSDPRecvDelay) {
6168
6416
  this.startLocalSDPGenRemoteSDPRecvDelay = performance.now();
6169
6417
  this.endLocalSDPGenRemoteSDPRecvDelay = undefined;
@@ -6191,9 +6439,7 @@ export default class Meeting extends StatelessWebexPlugin {
6191
6439
  if (start && end) {
6192
6440
  const calculatedDelay = end - start;
6193
6441
 
6194
- return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
6195
- undefined :
6196
- calculatedDelay;
6442
+ return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ? undefined : calculatedDelay;
6197
6443
  }
6198
6444
 
6199
6445
  return undefined;
@@ -6227,9 +6473,7 @@ export default class Meeting extends StatelessWebexPlugin {
6227
6473
  if (start && end) {
6228
6474
  const calculatedDelay = end - start;
6229
6475
 
6230
- return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
6231
- undefined :
6232
- calculatedDelay;
6476
+ return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ? undefined : calculatedDelay;
6233
6477
  }
6234
6478
 
6235
6479
  return undefined;
@@ -6263,9 +6507,7 @@ export default class Meeting extends StatelessWebexPlugin {
6263
6507
  if (start && end) {
6264
6508
  const calculatedDelay = end - start;
6265
6509
 
6266
- return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ?
6267
- undefined :
6268
- calculatedDelay;
6510
+ return calculatedDelay > METRICS_JOIN_TIMES_MAX_DURATION ? undefined : calculatedDelay;
6269
6511
  }
6270
6512
 
6271
6513
  return undefined;
@@ -6279,10 +6521,9 @@ export default class Meeting extends StatelessWebexPlugin {
6279
6521
  const start = this.startCallInitiateJoinReq;
6280
6522
  const end = this.endJoinReqResp;
6281
6523
 
6282
- return (start && end) ? end - start : undefined;
6524
+ return start && end ? end - start : undefined;
6283
6525
  }
6284
6526
 
6285
-
6286
6527
  /**
6287
6528
  * End the current meeting for all
6288
6529
  * @returns {Promise}
@@ -6290,16 +6531,17 @@ export default class Meeting extends StatelessWebexPlugin {
6290
6531
  * @memberof Meeting
6291
6532
  */
6292
6533
  public endMeetingForAll() {
6293
- Metrics.postEvent({event: eventType.LEAVE, meeting: this, data: {trigger: trigger.USER_INTERACTION, canProceed: false}});
6534
+ Metrics.postEvent({
6535
+ event: eventType.LEAVE,
6536
+ meeting: this,
6537
+ data: {trigger: trigger.USER_INTERACTION, canProceed: false},
6538
+ });
6294
6539
 
6295
6540
  LoggerProxy.logger.log('Meeting:index#endMeetingForAll --> End meeting for All');
6296
- Metrics.sendBehavioralMetric(
6297
- BEHAVIORAL_METRICS.MEETING_END_ALL_INITIATED,
6298
- {
6299
- correlation_id: this.correlationId,
6300
- locus_id: this.locusId
6301
- }
6302
- );
6541
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_END_ALL_INITIATED, {
6542
+ correlation_id: this.correlationId,
6543
+ locus_id: this.locusId,
6544
+ });
6303
6545
 
6304
6546
  return MeetingUtil.endMeetingForAll(this)
6305
6547
  .then((end) => {
@@ -6311,36 +6553,37 @@ export default class Meeting extends StatelessWebexPlugin {
6311
6553
  this,
6312
6554
  {
6313
6555
  file: 'meeting/index',
6314
- function: 'endMeetingForAll'
6556
+ function: 'endMeetingForAll',
6315
6557
  },
6316
6558
  EVENTS.REQUEST_UPLOAD_LOGS,
6317
6559
  this
6318
6560
  );
6319
6561
 
6320
6562
  return end;
6321
- }).catch((error) => {
6563
+ })
6564
+ .catch((error) => {
6322
6565
  this.meetingFiniteStateMachine.fail(error);
6323
- LoggerProxy.logger.error('Meeting:index#endMeetingForAll --> Failed to end meeting ', error);
6566
+ LoggerProxy.logger.error(
6567
+ 'Meeting:index#endMeetingForAll --> Failed to end meeting ',
6568
+ error
6569
+ );
6324
6570
  // upload logs on leave irrespective of meeting delete
6325
6571
  Trigger.trigger(
6326
6572
  this,
6327
6573
  {
6328
6574
  file: 'meeting/index',
6329
- function: 'endMeetingForAll'
6575
+ function: 'endMeetingForAll',
6330
6576
  },
6331
6577
  EVENTS.REQUEST_UPLOAD_LOGS,
6332
6578
  this
6333
6579
  );
6334
- Metrics.sendBehavioralMetric(
6335
- BEHAVIORAL_METRICS.MEETING_END_ALL_FAILURE,
6336
- {
6337
- correlation_id: this.correlationId,
6338
- locus_id: this.locusUrl.split('/').pop(),
6339
- reason: error.message,
6340
- stack: error.stack,
6341
- code: error.code
6342
- }
6343
- );
6580
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MEETING_END_ALL_FAILURE, {
6581
+ correlation_id: this.correlationId,
6582
+ locus_id: this.locusUrl.split('/').pop(),
6583
+ reason: error.message,
6584
+ stack: error.stack,
6585
+ code: error.code,
6586
+ });
6344
6587
 
6345
6588
  return Promise.reject(error);
6346
6589
  });
@@ -6390,11 +6633,12 @@ export default class Meeting extends StatelessWebexPlugin {
6390
6633
  LoggerProxy.logger.info('Meeting:index#internal_enableBNR. Internal enable BNR called');
6391
6634
  const bnrAudioTrack = await WebRTCMedia.Effects.BNR.enableBNR(audioTrack);
6392
6635
 
6393
- LoggerProxy.logger.info('Meeting:index#internal_enableBNR. BNR enabled track obtained from WebRTC & returned as stream');
6636
+ LoggerProxy.logger.info(
6637
+ 'Meeting:index#internal_enableBNR. BNR enabled track obtained from WebRTC & returned as stream'
6638
+ );
6394
6639
 
6395
6640
  return bnrAudioTrack;
6396
- }
6397
- catch (error) {
6641
+ } catch (error) {
6398
6642
  LoggerProxy.logger.error('Meeting:index#internal_enableBNR.', error);
6399
6643
  throw error;
6400
6644
  }
@@ -6407,7 +6651,10 @@ export default class Meeting extends StatelessWebexPlugin {
6407
6651
  * @memberof Meeting
6408
6652
  */
6409
6653
  public enableBNR() {
6410
- if (typeof this.mediaProperties === 'undefined' || typeof this.mediaProperties.audioTrack === 'undefined') {
6654
+ if (
6655
+ typeof this.mediaProperties === 'undefined' ||
6656
+ typeof this.mediaProperties.audioTrack === 'undefined'
6657
+ ) {
6411
6658
  return Promise.reject(new Error("Meeting doesn't have an audioTrack attached"));
6412
6659
  }
6413
6660
 
@@ -6419,20 +6666,23 @@ export default class Meeting extends StatelessWebexPlugin {
6419
6666
 
6420
6667
  const LOG_HEADER = 'Meeting:index#enableBNR -->';
6421
6668
 
6422
- return logRequest(this.effects.handleClientRequest(true, this)
6423
- .then((res) => {
6424
- LoggerProxy.logger.info('Meeting:index#enableBNR. Enable bnr completed');
6669
+ return logRequest(
6670
+ this.effects
6671
+ .handleClientRequest(true, this)
6672
+ .then((res) => {
6673
+ LoggerProxy.logger.info('Meeting:index#enableBNR. Enable bnr completed');
6425
6674
 
6426
- return res;
6427
- })
6428
- .catch((error) => {
6429
- throw error;
6430
- }),
6431
- {
6432
- header: `${LOG_HEADER} enable bnr`,
6433
- success: `${LOG_HEADER} enable bnr success`,
6434
- failure: `${LOG_HEADER} enable bnr failure, `
6435
- });
6675
+ return res;
6676
+ })
6677
+ .catch((error) => {
6678
+ throw error;
6679
+ }),
6680
+ {
6681
+ header: `${LOG_HEADER} enable bnr`,
6682
+ success: `${LOG_HEADER} enable bnr success`,
6683
+ failure: `${LOG_HEADER} enable bnr failure, `,
6684
+ }
6685
+ );
6436
6686
  }
6437
6687
 
6438
6688
  /**
@@ -6442,7 +6692,10 @@ export default class Meeting extends StatelessWebexPlugin {
6442
6692
  * @memberof Meeting
6443
6693
  */
6444
6694
  public disableBNR() {
6445
- if (typeof this.mediaProperties === 'undefined' || typeof this.mediaProperties.audioTrack === 'undefined') {
6695
+ if (
6696
+ typeof this.mediaProperties === 'undefined' ||
6697
+ typeof this.mediaProperties.audioTrack === 'undefined'
6698
+ ) {
6446
6699
  return Promise.reject(new Error("Meeting doesn't have an audioTrack attached"));
6447
6700
  }
6448
6701
 
@@ -6454,20 +6707,23 @@ export default class Meeting extends StatelessWebexPlugin {
6454
6707
 
6455
6708
  const LOG_HEADER = 'Meeting:index#disableBNR -->';
6456
6709
 
6457
- return logRequest(this.effects.handleClientRequest(false, this)
6458
- .then((res) => {
6459
- LoggerProxy.logger.info('Meeting:index#disableBNR. Disable bnr completed');
6710
+ return logRequest(
6711
+ this.effects
6712
+ .handleClientRequest(false, this)
6713
+ .then((res) => {
6714
+ LoggerProxy.logger.info('Meeting:index#disableBNR. Disable bnr completed');
6460
6715
 
6461
- return res;
6462
- })
6463
- .catch((error) => {
6464
- throw error;
6465
- }),
6466
- {
6467
- header: `${LOG_HEADER} disable bnr`,
6468
- success: `${LOG_HEADER} disable bnr success`,
6469
- failure: `${LOG_HEADER} disable bnr failure, `
6470
- });
6716
+ return res;
6717
+ })
6718
+ .catch((error) => {
6719
+ throw error;
6720
+ }),
6721
+ {
6722
+ header: `${LOG_HEADER} disable bnr`,
6723
+ success: `${LOG_HEADER} disable bnr success`,
6724
+ failure: `${LOG_HEADER} disable bnr failure, `,
6725
+ }
6726
+ );
6471
6727
  }
6472
6728
 
6473
6729
  /**
@@ -6478,22 +6734,30 @@ export default class Meeting extends StatelessWebexPlugin {
6478
6734
  */
6479
6735
  startKeepAlive = () => {
6480
6736
  if (this.keepAliveTimerId) {
6481
- LoggerProxy.logger.warn('Meeting:index#startKeepAlive --> keepAlive not started: keepAliveTimerId already exists');
6737
+ LoggerProxy.logger.warn(
6738
+ 'Meeting:index#startKeepAlive --> keepAlive not started: keepAliveTimerId already exists'
6739
+ );
6482
6740
 
6483
6741
  return;
6484
6742
  }
6485
6743
  if (!this.joinedWith?.keepAliveUrl) {
6486
- LoggerProxy.logger.warn('Meeting:index#startKeepAlive --> keepAlive not started: no keepAliveUrl');
6744
+ LoggerProxy.logger.warn(
6745
+ 'Meeting:index#startKeepAlive --> keepAlive not started: no keepAliveUrl'
6746
+ );
6487
6747
 
6488
6748
  return;
6489
6749
  }
6490
6750
  if (!this.joinedWith?.keepAliveSecs) {
6491
- LoggerProxy.logger.warn('Meeting:index#startKeepAlive --> keepAlive not started: no keepAliveSecs');
6751
+ LoggerProxy.logger.warn(
6752
+ 'Meeting:index#startKeepAlive --> keepAlive not started: no keepAliveSecs'
6753
+ );
6492
6754
 
6493
6755
  return;
6494
6756
  }
6495
6757
  if (this.joinedWith.keepAliveSecs <= 1) {
6496
- LoggerProxy.logger.warn('Meeting:index#startKeepAlive --> keepAlive not started: keepAliveSecs <= 1');
6758
+ LoggerProxy.logger.warn(
6759
+ 'Meeting:index#startKeepAlive --> keepAlive not started: keepAliveSecs <= 1'
6760
+ );
6497
6761
 
6498
6762
  return;
6499
6763
  }
@@ -6501,13 +6765,12 @@ export default class Meeting extends StatelessWebexPlugin {
6501
6765
  const keepAliveInterval = (this.joinedWith.keepAliveSecs - 1) * 750; // taken from UCF
6502
6766
 
6503
6767
  this.keepAliveTimerId = setInterval(() => {
6504
- this.meetingRequest.keepAlive({keepAliveUrl})
6505
- .catch((error) => {
6506
- LoggerProxy.logger.warn(
6507
- `Meeting:index#startKeepAlive --> Stopping sending keepAlives to ${keepAliveUrl} after error ${error}`
6508
- );
6509
- this.stopKeepAlive();
6510
- });
6768
+ this.meetingRequest.keepAlive({keepAliveUrl}).catch((error) => {
6769
+ LoggerProxy.logger.warn(
6770
+ `Meeting:index#startKeepAlive --> Stopping sending keepAlives to ${keepAliveUrl} after error ${error}`
6771
+ );
6772
+ this.stopKeepAlive();
6773
+ });
6511
6774
  }, keepAliveInterval);
6512
6775
  };
6513
6776
 
@@ -6546,7 +6809,7 @@ export default class Meeting extends StatelessWebexPlugin {
6546
6809
  const skinToneData = SkinTones[skinToneType] || SkinTones.normal;
6547
6810
  const reaction: Reaction = {
6548
6811
  ...reactionData,
6549
- tone: skinToneData
6812
+ tone: skinToneData,
6550
6813
  };
6551
6814
 
6552
6815
  if (reactionChannelUrl) {
@@ -6555,4 +6818,26 @@ export default class Meeting extends StatelessWebexPlugin {
6555
6818
 
6556
6819
  return Promise.reject(new Error('Error sending reaction, service url not found.'));
6557
6820
  }
6821
+
6822
+ /**
6823
+ * Method to enable or disable reactions inside the meeting.
6824
+ *
6825
+ * @param {boolean} enable - enable or disable reactions
6826
+ * @returns {Promise}
6827
+ * @public
6828
+ * @memberof Meeting
6829
+ */
6830
+ public toggleReactions(enable: boolean) {
6831
+ const isEnabled = this.locusInfo?.controls?.reactions?.enabled;
6832
+
6833
+ if ((isEnabled && enable) || (!isEnabled && !enable)) {
6834
+ return Promise.resolve(`Reactions are already ${isEnabled ? 'enabled' : 'disabled'}.`);
6835
+ }
6836
+
6837
+ return this.meetingRequest.toggleReactions({
6838
+ enable,
6839
+ locusUrl: this.locusUrl,
6840
+ requestingParticipantId: this.members.selfId,
6841
+ });
6842
+ }
6558
6843
  }