@webex/plugin-meetings 2.60.0 → 2.60.1-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (539) hide show
  1. package/README.md +58 -8
  2. package/dist/annotation/annotation.types.d.ts +42 -0
  3. package/dist/annotation/annotation.types.js +7 -0
  4. package/dist/annotation/annotation.types.js.map +1 -0
  5. package/dist/annotation/constants.d.ts +31 -0
  6. package/dist/annotation/constants.js +41 -0
  7. package/dist/annotation/constants.js.map +1 -0
  8. package/dist/annotation/index.d.ts +117 -0
  9. package/dist/annotation/index.js +357 -0
  10. package/dist/annotation/index.js.map +1 -0
  11. package/dist/breakouts/breakout.d.ts +8 -0
  12. package/dist/breakouts/breakout.js +215 -0
  13. package/dist/breakouts/breakout.js.map +1 -0
  14. package/dist/breakouts/collection.d.ts +5 -0
  15. package/dist/breakouts/collection.js +22 -0
  16. package/dist/breakouts/collection.js.map +1 -0
  17. package/dist/breakouts/edit-lock-error.d.ts +15 -0
  18. package/dist/breakouts/edit-lock-error.js +51 -0
  19. package/dist/breakouts/edit-lock-error.js.map +1 -0
  20. package/dist/breakouts/events.d.ts +8 -0
  21. package/dist/breakouts/events.js +44 -0
  22. package/dist/breakouts/events.js.map +1 -0
  23. package/dist/breakouts/index.d.ts +5 -0
  24. package/dist/breakouts/index.js +1047 -0
  25. package/dist/breakouts/index.js.map +1 -0
  26. package/dist/breakouts/request.d.ts +22 -0
  27. package/dist/breakouts/request.js +77 -0
  28. package/dist/breakouts/request.js.map +1 -0
  29. package/dist/breakouts/utils.d.ts +15 -0
  30. package/dist/breakouts/utils.js +64 -0
  31. package/dist/breakouts/utils.js.map +1 -0
  32. package/dist/common/browser-detection.js +2 -3
  33. package/dist/common/browser-detection.js.map +1 -1
  34. package/dist/common/collection.js +3 -4
  35. package/dist/common/collection.js.map +1 -1
  36. package/dist/common/config.js +1 -2
  37. package/dist/common/config.js.map +1 -1
  38. package/dist/common/errors/captcha-error.js +1 -2
  39. package/dist/common/errors/captcha-error.js.map +1 -1
  40. package/dist/common/errors/intent-to-join.js +1 -2
  41. package/dist/common/errors/intent-to-join.js.map +1 -1
  42. package/dist/common/errors/join-meeting.js +1 -2
  43. package/dist/common/errors/join-meeting.js.map +1 -1
  44. package/dist/common/errors/media.js +1 -2
  45. package/dist/common/errors/media.js.map +1 -1
  46. package/dist/common/errors/no-meeting-info.d.ts +14 -0
  47. package/dist/common/errors/no-meeting-info.js +50 -0
  48. package/dist/common/errors/no-meeting-info.js.map +1 -0
  49. package/dist/common/errors/parameter.js +3 -4
  50. package/dist/common/errors/parameter.js.map +1 -1
  51. package/dist/common/errors/password-error.js +1 -2
  52. package/dist/common/errors/password-error.js.map +1 -1
  53. package/dist/common/errors/permission.js +1 -2
  54. package/dist/common/errors/permission.js.map +1 -1
  55. package/dist/common/errors/{reclaim-host-role-error.js → reclaim-host-role-errors.js} +7 -11
  56. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  57. package/dist/common/errors/reconnection-in-progress.js +1 -2
  58. package/dist/common/errors/reconnection-in-progress.js.map +1 -1
  59. package/dist/common/errors/reconnection.js +1 -2
  60. package/dist/common/errors/reconnection.js.map +1 -1
  61. package/dist/common/errors/stats.js +1 -2
  62. package/dist/common/errors/stats.js.map +1 -1
  63. package/dist/common/errors/webex-errors.d.ts +20 -8
  64. package/dist/common/errors/webex-errors.js +48 -28
  65. package/dist/common/errors/webex-errors.js.map +1 -1
  66. package/dist/common/errors/webex-meetings-error.js +1 -2
  67. package/dist/common/errors/webex-meetings-error.js.map +1 -1
  68. package/dist/common/events/events-scope.js +1 -2
  69. package/dist/common/events/events-scope.js.map +1 -1
  70. package/dist/common/events/events.js +1 -2
  71. package/dist/common/events/events.js.map +1 -1
  72. package/dist/common/events/trigger-proxy.js +1 -2
  73. package/dist/common/events/trigger-proxy.js.map +1 -1
  74. package/dist/common/events/util.js +1 -2
  75. package/dist/common/events/util.js.map +1 -1
  76. package/dist/common/logs/logger-config.js +1 -2
  77. package/dist/common/logs/logger-config.js.map +1 -1
  78. package/dist/common/logs/logger-proxy.js +2 -3
  79. package/dist/common/logs/logger-proxy.js.map +1 -1
  80. package/dist/common/logs/request.d.ts +3 -1
  81. package/dist/common/logs/request.js +8 -5
  82. package/dist/common/logs/request.js.map +1 -1
  83. package/dist/common/queue.d.ts +9 -7
  84. package/dist/common/queue.js +22 -9
  85. package/dist/common/queue.js.map +1 -1
  86. package/dist/config.d.ts +6 -7
  87. package/dist/config.js +8 -10
  88. package/dist/config.js.map +1 -1
  89. package/dist/constants.d.ts +234 -100
  90. package/dist/constants.js +433 -444
  91. package/dist/constants.js.map +1 -1
  92. package/dist/controls-options-manager/constants.js +3 -6
  93. package/dist/controls-options-manager/constants.js.map +1 -1
  94. package/dist/controls-options-manager/enums.d.ts +11 -1
  95. package/dist/controls-options-manager/enums.js +15 -6
  96. package/dist/controls-options-manager/enums.js.map +1 -1
  97. package/dist/controls-options-manager/index.d.ts +17 -1
  98. package/dist/controls-options-manager/index.js +127 -38
  99. package/dist/controls-options-manager/index.js.map +1 -1
  100. package/dist/controls-options-manager/types.d.ts +43 -0
  101. package/dist/controls-options-manager/types.js +7 -0
  102. package/dist/controls-options-manager/types.js.map +1 -0
  103. package/dist/controls-options-manager/util.d.ts +1 -7
  104. package/dist/controls-options-manager/util.js +309 -19
  105. package/dist/controls-options-manager/util.js.map +1 -1
  106. package/dist/index.d.ts +6 -3
  107. package/dist/index.js +121 -5
  108. package/dist/index.js.map +1 -1
  109. package/dist/interceptors/index.d.ts +2 -0
  110. package/dist/interceptors/index.js +15 -0
  111. package/dist/interceptors/index.js.map +1 -0
  112. package/dist/interceptors/locusRetry.d.ts +27 -0
  113. package/dist/interceptors/locusRetry.js +94 -0
  114. package/dist/interceptors/locusRetry.js.map +1 -0
  115. package/dist/interpretation/collection.d.ts +5 -0
  116. package/dist/interpretation/collection.js +22 -0
  117. package/dist/interpretation/collection.js.map +1 -0
  118. package/dist/interpretation/index.d.ts +5 -0
  119. package/dist/interpretation/index.js +365 -0
  120. package/dist/interpretation/index.js.map +1 -0
  121. package/dist/interpretation/siLanguage.d.ts +5 -0
  122. package/dist/interpretation/siLanguage.js +24 -0
  123. package/dist/interpretation/siLanguage.js.map +1 -0
  124. package/dist/locus-info/controlsUtils.js +100 -11
  125. package/dist/locus-info/controlsUtils.js.map +1 -1
  126. package/dist/locus-info/embeddedAppsUtils.js +3 -4
  127. package/dist/locus-info/embeddedAppsUtils.js.map +1 -1
  128. package/dist/locus-info/fullState.js +1 -2
  129. package/dist/locus-info/fullState.js.map +1 -1
  130. package/dist/locus-info/hostUtils.js +1 -2
  131. package/dist/locus-info/hostUtils.js.map +1 -1
  132. package/dist/locus-info/index.d.ts +57 -4
  133. package/dist/locus-info/index.js +425 -84
  134. package/dist/locus-info/index.js.map +1 -1
  135. package/dist/locus-info/infoUtils.js +13 -5
  136. package/dist/locus-info/infoUtils.js.map +1 -1
  137. package/dist/locus-info/mediaSharesUtils.js +58 -3
  138. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  139. package/dist/locus-info/parser.d.ts +66 -6
  140. package/dist/locus-info/parser.js +253 -80
  141. package/dist/locus-info/parser.js.map +1 -1
  142. package/dist/locus-info/selfUtils.js +97 -13
  143. package/dist/locus-info/selfUtils.js.map +1 -1
  144. package/dist/media/index.d.ts +2 -0
  145. package/dist/media/index.js +107 -319
  146. package/dist/media/index.js.map +1 -1
  147. package/dist/media/properties.d.ts +38 -53
  148. package/dist/media/properties.js +96 -153
  149. package/dist/media/properties.js.map +1 -1
  150. package/dist/media/util.js +1 -22
  151. package/dist/media/util.js.map +1 -1
  152. package/dist/mediaQualityMetrics/config.d.ts +234 -230
  153. package/dist/mediaQualityMetrics/config.js +302 -498
  154. package/dist/mediaQualityMetrics/config.js.map +1 -1
  155. package/dist/meeting/in-meeting-actions.d.ts +88 -0
  156. package/dist/meeting/in-meeting-actions.js +94 -3
  157. package/dist/meeting/in-meeting-actions.js.map +1 -1
  158. package/dist/meeting/index.d.ts +705 -520
  159. package/dist/meeting/index.js +5047 -3089
  160. package/dist/meeting/index.js.map +1 -1
  161. package/dist/meeting/locusMediaRequest.d.ts +74 -0
  162. package/dist/meeting/locusMediaRequest.js +291 -0
  163. package/dist/meeting/locusMediaRequest.js.map +1 -0
  164. package/dist/meeting/muteState.d.ts +93 -25
  165. package/dist/meeting/muteState.js +224 -133
  166. package/dist/meeting/muteState.js.map +1 -1
  167. package/dist/meeting/request.d.ts +82 -47
  168. package/dist/meeting/request.js +304 -199
  169. package/dist/meeting/request.js.map +1 -1
  170. package/dist/meeting/request.type.d.ts +11 -0
  171. package/dist/meeting/request.type.js +7 -0
  172. package/dist/meeting/request.type.js.map +1 -0
  173. package/dist/meeting/state.js +1 -2
  174. package/dist/meeting/state.js.map +1 -1
  175. package/dist/meeting/util.d.ts +118 -1
  176. package/dist/meeting/util.js +676 -435
  177. package/dist/meeting/util.js.map +1 -1
  178. package/dist/meeting/voicea-meeting.d.ts +20 -0
  179. package/dist/meeting/voicea-meeting.js +201 -0
  180. package/dist/meeting/voicea-meeting.js.map +1 -0
  181. package/dist/meeting-info/collection.js +3 -4
  182. package/dist/meeting-info/collection.js.map +1 -1
  183. package/dist/meeting-info/index.d.ts +13 -1
  184. package/dist/meeting-info/index.js +74 -7
  185. package/dist/meeting-info/index.js.map +1 -1
  186. package/dist/meeting-info/meeting-info-v2.d.ts +31 -1
  187. package/dist/meeting-info/meeting-info-v2.js +200 -63
  188. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  189. package/dist/meeting-info/request.js +1 -2
  190. package/dist/meeting-info/request.js.map +1 -1
  191. package/dist/meeting-info/util.js +2 -3
  192. package/dist/meeting-info/util.js.map +1 -1
  193. package/dist/meeting-info/utilv2.js +39 -41
  194. package/dist/meeting-info/utilv2.js.map +1 -1
  195. package/dist/meetings/collection.d.ts +17 -0
  196. package/dist/meetings/collection.js +42 -4
  197. package/dist/meetings/collection.js.map +1 -1
  198. package/dist/meetings/index.d.ts +114 -20
  199. package/dist/meetings/index.js +540 -126
  200. package/dist/meetings/index.js.map +1 -1
  201. package/dist/meetings/meetings.types.d.ts +4 -0
  202. package/dist/meetings/meetings.types.js +7 -0
  203. package/dist/meetings/meetings.types.js.map +1 -0
  204. package/dist/meetings/request.js +4 -3
  205. package/dist/meetings/request.js.map +1 -1
  206. package/dist/meetings/util.js +107 -6
  207. package/dist/meetings/util.js.map +1 -1
  208. package/dist/member/index.d.ts +13 -1
  209. package/dist/member/index.js +45 -2
  210. package/dist/member/index.js.map +1 -1
  211. package/dist/member/member.types.js +3 -4
  212. package/dist/member/member.types.js.map +1 -1
  213. package/dist/member/types.d.ts +32 -0
  214. package/dist/member/types.js +23 -0
  215. package/dist/member/types.js.map +1 -0
  216. package/dist/member/util.js +120 -29
  217. package/dist/member/util.js.map +1 -1
  218. package/dist/members/collection.d.ts +5 -0
  219. package/dist/members/collection.js +11 -2
  220. package/dist/members/collection.js.map +1 -1
  221. package/dist/members/index.d.ts +56 -11
  222. package/dist/members/index.js +174 -47
  223. package/dist/members/index.js.map +1 -1
  224. package/dist/members/request.d.ts +67 -11
  225. package/dist/members/request.js +102 -54
  226. package/dist/members/request.js.map +1 -1
  227. package/dist/members/types.js +3 -4
  228. package/dist/members/types.js.map +1 -1
  229. package/dist/members/util.d.ts +214 -1
  230. package/dist/members/util.js +327 -284
  231. package/dist/members/util.js.map +1 -1
  232. package/dist/metrics/constants.d.ts +15 -6
  233. package/dist/metrics/constants.js +17 -9
  234. package/dist/metrics/constants.js.map +1 -1
  235. package/dist/metrics/index.d.ts +4 -111
  236. package/dist/metrics/index.js +4 -452
  237. package/dist/metrics/index.js.map +1 -1
  238. package/dist/multistream/mediaRequestManager.d.ts +118 -0
  239. package/dist/multistream/mediaRequestManager.js +344 -0
  240. package/dist/multistream/mediaRequestManager.js.map +1 -0
  241. package/dist/multistream/receiveSlot.d.ts +68 -0
  242. package/dist/multistream/receiveSlot.js +200 -0
  243. package/dist/multistream/receiveSlot.js.map +1 -0
  244. package/dist/multistream/receiveSlotManager.d.ts +56 -0
  245. package/dist/multistream/receiveSlotManager.js +174 -0
  246. package/dist/multistream/receiveSlotManager.js.map +1 -0
  247. package/dist/multistream/remoteMedia.d.ts +72 -0
  248. package/dist/multistream/remoteMedia.js +268 -0
  249. package/dist/multistream/remoteMedia.js.map +1 -0
  250. package/dist/multistream/remoteMediaGroup.d.ts +47 -0
  251. package/dist/multistream/remoteMediaGroup.js +267 -0
  252. package/dist/multistream/remoteMediaGroup.js.map +1 -0
  253. package/dist/multistream/remoteMediaManager.d.ts +285 -0
  254. package/dist/multistream/remoteMediaManager.js +1211 -0
  255. package/dist/multistream/remoteMediaManager.js.map +1 -0
  256. package/dist/multistream/sendSlotManager.d.ts +61 -0
  257. package/dist/multistream/sendSlotManager.js +236 -0
  258. package/dist/multistream/sendSlotManager.js.map +1 -0
  259. package/dist/networkQualityMonitor/index.js +5 -4
  260. package/dist/networkQualityMonitor/index.js.map +1 -1
  261. package/dist/personal-meeting-room/index.js +2 -3
  262. package/dist/personal-meeting-room/index.js.map +1 -1
  263. package/dist/personal-meeting-room/request.js +2 -3
  264. package/dist/personal-meeting-room/request.js.map +1 -1
  265. package/dist/personal-meeting-room/util.js +1 -2
  266. package/dist/personal-meeting-room/util.js.map +1 -1
  267. package/dist/reachability/clusterReachability.d.ts +109 -0
  268. package/dist/reachability/clusterReachability.js +357 -0
  269. package/dist/reachability/clusterReachability.js.map +1 -0
  270. package/dist/reachability/index.d.ts +61 -95
  271. package/dist/reachability/index.js +304 -392
  272. package/dist/reachability/index.js.map +1 -1
  273. package/dist/reachability/request.d.ts +7 -3
  274. package/dist/reachability/request.js +18 -10
  275. package/dist/reachability/request.js.map +1 -1
  276. package/dist/reachability/util.d.ts +8 -0
  277. package/dist/reachability/util.js +29 -0
  278. package/dist/reachability/util.js.map +1 -0
  279. package/dist/reactions/constants.d.ts +3 -0
  280. package/dist/reactions/constants.js +12 -0
  281. package/dist/reactions/constants.js.map +1 -0
  282. package/dist/reactions/reactions.d.ts +2 -2
  283. package/dist/reactions/reactions.js +4 -6
  284. package/dist/reactions/reactions.js.map +1 -1
  285. package/dist/reactions/reactions.type.d.ts +23 -3
  286. package/dist/reactions/reactions.type.js +21 -23
  287. package/dist/reactions/reactions.type.js.map +1 -1
  288. package/dist/reconnection-manager/index.d.ts +32 -8
  289. package/dist/reconnection-manager/index.js +285 -232
  290. package/dist/reconnection-manager/index.js.map +1 -1
  291. package/dist/recording-controller/enums.js +4 -5
  292. package/dist/recording-controller/enums.js.map +1 -1
  293. package/dist/recording-controller/index.d.ts +15 -1
  294. package/dist/recording-controller/index.js +57 -46
  295. package/dist/recording-controller/index.js.map +1 -1
  296. package/dist/recording-controller/util.d.ts +5 -4
  297. package/dist/recording-controller/util.js +10 -10
  298. package/dist/recording-controller/util.js.map +1 -1
  299. package/dist/roap/index.d.ts +9 -47
  300. package/dist/roap/index.js +100 -238
  301. package/dist/roap/index.js.map +1 -1
  302. package/dist/roap/request.d.ts +18 -12
  303. package/dist/roap/request.js +126 -180
  304. package/dist/roap/request.js.map +1 -1
  305. package/dist/roap/turnDiscovery.d.ts +27 -16
  306. package/dist/roap/turnDiscovery.js +115 -105
  307. package/dist/roap/turnDiscovery.js.map +1 -1
  308. package/dist/rtcMetrics/constants.d.ts +4 -0
  309. package/dist/rtcMetrics/constants.js +11 -0
  310. package/dist/rtcMetrics/constants.js.map +1 -0
  311. package/dist/rtcMetrics/index.d.ts +54 -0
  312. package/dist/rtcMetrics/index.js +140 -0
  313. package/dist/rtcMetrics/index.js.map +1 -0
  314. package/dist/statsAnalyzer/global.d.ts +1 -83
  315. package/dist/statsAnalyzer/global.js +2 -85
  316. package/dist/statsAnalyzer/global.js.map +1 -1
  317. package/dist/statsAnalyzer/index.d.ts +50 -30
  318. package/dist/statsAnalyzer/index.js +436 -511
  319. package/dist/statsAnalyzer/index.js.map +1 -1
  320. package/dist/statsAnalyzer/mqaUtil.d.ts +8 -6
  321. package/dist/statsAnalyzer/mqaUtil.js +130 -90
  322. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  323. package/dist/transcription/index.js +1 -2
  324. package/dist/transcription/index.js.map +1 -1
  325. package/dist/webinar/collection.d.ts +16 -0
  326. package/dist/webinar/collection.js +43 -0
  327. package/dist/webinar/collection.js.map +1 -0
  328. package/dist/webinar/index.d.ts +5 -0
  329. package/dist/webinar/index.js +68 -0
  330. package/dist/webinar/index.js.map +1 -0
  331. package/package.json +39 -26
  332. package/src/annotation/annotation.types.ts +50 -0
  333. package/src/annotation/constants.ts +36 -0
  334. package/src/annotation/index.ts +328 -0
  335. package/src/breakouts/README.md +220 -0
  336. package/src/breakouts/breakout.ts +188 -0
  337. package/src/breakouts/collection.ts +19 -0
  338. package/src/breakouts/edit-lock-error.ts +25 -0
  339. package/src/breakouts/events.ts +56 -0
  340. package/src/breakouts/index.ts +925 -0
  341. package/src/breakouts/request.ts +55 -0
  342. package/src/breakouts/utils.ts +57 -0
  343. package/src/common/errors/no-meeting-info.ts +24 -0
  344. package/src/common/errors/webex-errors.ts +36 -12
  345. package/src/common/logs/logger-proxy.ts +1 -1
  346. package/src/common/logs/request.ts +5 -1
  347. package/src/common/queue.ts +22 -8
  348. package/src/config.ts +6 -7
  349. package/src/constants.ts +265 -100
  350. package/src/controls-options-manager/enums.ts +12 -0
  351. package/src/controls-options-manager/index.ts +116 -21
  352. package/src/controls-options-manager/types.ts +59 -0
  353. package/src/controls-options-manager/util.ts +294 -14
  354. package/src/index.ts +44 -0
  355. package/src/interceptors/index.ts +3 -0
  356. package/src/interceptors/locusRetry.ts +67 -0
  357. package/src/interpretation/README.md +60 -0
  358. package/src/interpretation/collection.ts +19 -0
  359. package/src/interpretation/index.ts +332 -0
  360. package/src/interpretation/siLanguage.ts +18 -0
  361. package/src/locus-info/controlsUtils.ts +110 -0
  362. package/src/locus-info/index.ts +450 -61
  363. package/src/locus-info/infoUtils.ts +14 -2
  364. package/src/locus-info/mediaSharesUtils.ts +64 -0
  365. package/src/locus-info/parser.ts +258 -47
  366. package/src/locus-info/selfUtils.ts +85 -2
  367. package/src/media/index.ts +153 -370
  368. package/src/media/properties.ts +106 -136
  369. package/src/media/util.ts +0 -21
  370. package/src/mediaQualityMetrics/config.ts +244 -377
  371. package/src/meeting/in-meeting-actions.ts +176 -0
  372. package/src/meeting/index.ts +4306 -2581
  373. package/src/meeting/locusMediaRequest.ts +313 -0
  374. package/src/meeting/muteState.ts +224 -138
  375. package/src/meeting/request.ts +214 -127
  376. package/src/meeting/request.type.ts +13 -0
  377. package/src/meeting/util.ts +687 -423
  378. package/src/meeting/voicea-meeting.ts +161 -0
  379. package/src/meeting-info/index.ts +81 -8
  380. package/src/meeting-info/meeting-info-v2.ts +163 -13
  381. package/src/meeting-info/util.ts +1 -1
  382. package/src/meeting-info/utilv2.ts +28 -28
  383. package/src/meetings/collection.ts +33 -0
  384. package/src/meetings/index.ts +529 -127
  385. package/src/meetings/meetings.types.ts +12 -0
  386. package/src/meetings/request.ts +2 -0
  387. package/src/meetings/util.ts +116 -5
  388. package/src/member/index.ts +43 -1
  389. package/src/member/types.ts +38 -0
  390. package/src/member/util.ts +125 -28
  391. package/src/members/collection.ts +8 -0
  392. package/src/members/index.ts +187 -52
  393. package/src/members/request.ts +87 -27
  394. package/src/members/util.ts +332 -291
  395. package/src/metrics/constants.ts +15 -6
  396. package/src/metrics/index.ts +1 -471
  397. package/src/multistream/mediaRequestManager.ts +440 -0
  398. package/src/multistream/receiveSlot.ts +184 -0
  399. package/src/multistream/receiveSlotManager.ts +166 -0
  400. package/src/multistream/remoteMedia.ts +254 -0
  401. package/src/multistream/remoteMediaGroup.ts +284 -0
  402. package/src/multistream/remoteMediaManager.ts +1145 -0
  403. package/src/multistream/sendSlotManager.ts +170 -0
  404. package/src/networkQualityMonitor/index.ts +6 -6
  405. package/src/reachability/clusterReachability.ts +320 -0
  406. package/src/reachability/index.ts +246 -347
  407. package/src/reachability/request.ts +17 -8
  408. package/src/reachability/util.ts +24 -0
  409. package/src/reactions/constants.ts +4 -0
  410. package/src/reactions/reactions.ts +4 -4
  411. package/src/reactions/reactions.type.ts +30 -4
  412. package/src/reconnection-manager/index.ts +168 -156
  413. package/src/recording-controller/index.ts +20 -3
  414. package/src/recording-controller/util.ts +26 -9
  415. package/src/roap/index.ts +96 -241
  416. package/src/roap/request.ts +74 -148
  417. package/src/roap/turnDiscovery.ts +62 -56
  418. package/src/rtcMetrics/constants.ts +3 -0
  419. package/src/rtcMetrics/index.ts +124 -0
  420. package/src/statsAnalyzer/global.ts +1 -84
  421. package/src/statsAnalyzer/index.ts +479 -645
  422. package/src/statsAnalyzer/mqaUtil.ts +128 -126
  423. package/src/webinar/collection.ts +31 -0
  424. package/src/webinar/index.ts +62 -0
  425. package/test/integration/spec/converged-space-meetings.js +233 -0
  426. package/test/integration/spec/journey.js +320 -264
  427. package/test/integration/spec/space-meeting.js +77 -4
  428. package/test/unit/spec/annotation/index.ts +418 -0
  429. package/test/unit/spec/breakouts/breakout.ts +237 -0
  430. package/test/unit/spec/breakouts/collection.ts +15 -0
  431. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  432. package/test/unit/spec/breakouts/events.ts +89 -0
  433. package/test/unit/spec/breakouts/index.ts +1790 -0
  434. package/test/unit/spec/breakouts/request.ts +104 -0
  435. package/test/unit/spec/breakouts/utils.js +72 -0
  436. package/test/unit/spec/common/queue.js +31 -2
  437. package/test/unit/spec/controls-options-manager/index.js +163 -0
  438. package/test/unit/spec/controls-options-manager/util.js +576 -60
  439. package/test/unit/spec/fixture/locus.js +1 -0
  440. package/test/unit/spec/interceptors/locusRetry.ts +131 -0
  441. package/test/unit/spec/interpretation/collection.ts +15 -0
  442. package/test/unit/spec/interpretation/index.ts +589 -0
  443. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  444. package/test/unit/spec/locus-info/controlsUtils.js +323 -30
  445. package/test/unit/spec/locus-info/index.js +1438 -16
  446. package/test/unit/spec/locus-info/infoUtils.js +54 -16
  447. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  448. package/test/unit/spec/locus-info/lib/selfConstant.js +48 -0
  449. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  450. package/test/unit/spec/locus-info/parser.js +116 -35
  451. package/test/unit/spec/locus-info/selfUtils.js +275 -0
  452. package/test/unit/spec/media/index.ts +290 -0
  453. package/test/unit/spec/media/properties.ts +75 -84
  454. package/test/unit/spec/meeting/in-meeting-actions.ts +86 -0
  455. package/test/unit/spec/meeting/index.js +8886 -2815
  456. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  457. package/test/unit/spec/meeting/muteState.js +409 -213
  458. package/test/unit/spec/meeting/request.js +523 -43
  459. package/test/unit/spec/meeting/utils.js +834 -24
  460. package/test/unit/spec/meeting-info/index.js +300 -0
  461. package/test/unit/spec/meeting-info/meetinginfov2.js +527 -5
  462. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  463. package/test/unit/spec/meetings/collection.js +26 -0
  464. package/test/unit/spec/meetings/index.js +1446 -217
  465. package/test/unit/spec/meetings/utils.js +202 -2
  466. package/test/unit/spec/member/index.js +32 -9
  467. package/test/unit/spec/member/util.js +499 -61
  468. package/test/unit/spec/members/index.js +394 -5
  469. package/test/unit/spec/members/request.js +206 -27
  470. package/test/unit/spec/members/utils.js +173 -38
  471. package/test/unit/spec/metrics/index.js +1 -50
  472. package/test/unit/spec/multistream/mediaRequestManager.ts +1418 -0
  473. package/test/unit/spec/multistream/receiveSlot.ts +163 -0
  474. package/test/unit/spec/multistream/receiveSlotManager.ts +203 -0
  475. package/test/unit/spec/multistream/remoteMedia.ts +255 -0
  476. package/test/unit/spec/multistream/remoteMediaGroup.ts +662 -0
  477. package/test/unit/spec/multistream/remoteMediaManager.ts +1924 -0
  478. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  479. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  480. package/test/unit/spec/reachability/clusterReachability.ts +279 -0
  481. package/test/unit/spec/reachability/index.ts +532 -24
  482. package/test/unit/spec/reachability/request.js +68 -0
  483. package/test/unit/spec/reachability/util.ts +40 -0
  484. package/test/unit/spec/reconnection-manager/index.js +163 -24
  485. package/test/unit/spec/recording-controller/index.js +293 -218
  486. package/test/unit/spec/recording-controller/util.js +223 -96
  487. package/test/unit/spec/roap/index.ts +187 -77
  488. package/test/unit/spec/roap/request.ts +255 -0
  489. package/test/unit/spec/roap/turnDiscovery.ts +86 -48
  490. package/test/unit/spec/rtcMetrics/index.ts +93 -0
  491. package/test/unit/spec/stats-analyzer/index.js +644 -165
  492. package/test/unit/spec/webinar/collection.ts +13 -0
  493. package/test/unit/spec/webinar/index.ts +60 -0
  494. package/test/utils/constants.js +9 -0
  495. package/test/utils/integrationTestUtils.js +46 -0
  496. package/test/utils/testUtils.js +0 -45
  497. package/test/utils/webex-config.js +4 -0
  498. package/test/utils/webex-test-users.js +7 -3
  499. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  500. package/dist/meeting/effectsState.d.ts +0 -42
  501. package/dist/meeting/effectsState.js +0 -260
  502. package/dist/meeting/effectsState.js.map +0 -1
  503. package/dist/metrics/config.d.ts +0 -169
  504. package/dist/metrics/config.js +0 -289
  505. package/dist/metrics/config.js.map +0 -1
  506. package/dist/peer-connection-manager/index.d.ts +0 -6
  507. package/dist/peer-connection-manager/index.js +0 -671
  508. package/dist/peer-connection-manager/index.js.map +0 -1
  509. package/dist/peer-connection-manager/util.d.ts +0 -6
  510. package/dist/peer-connection-manager/util.js +0 -110
  511. package/dist/peer-connection-manager/util.js.map +0 -1
  512. package/dist/roap/collection.d.ts +0 -10
  513. package/dist/roap/collection.js +0 -63
  514. package/dist/roap/collection.js.map +0 -1
  515. package/dist/roap/handler.d.ts +0 -47
  516. package/dist/roap/handler.js +0 -279
  517. package/dist/roap/handler.js.map +0 -1
  518. package/dist/roap/state.d.ts +0 -9
  519. package/dist/roap/state.js +0 -127
  520. package/dist/roap/state.js.map +0 -1
  521. package/dist/roap/util.d.ts +0 -2
  522. package/dist/roap/util.js +0 -76
  523. package/dist/roap/util.js.map +0 -1
  524. package/src/index.js +0 -15
  525. package/src/meeting/effectsState.ts +0 -209
  526. package/src/metrics/config.ts +0 -485
  527. package/src/peer-connection-manager/index.ts +0 -847
  528. package/src/peer-connection-manager/util.ts +0 -119
  529. package/src/roap/collection.ts +0 -62
  530. package/src/roap/handler.ts +0 -294
  531. package/src/roap/state.ts +0 -156
  532. package/src/roap/util.ts +0 -100
  533. package/test/unit/spec/meeting/effectsState.js +0 -281
  534. package/test/unit/spec/peerconnection-manager/index.js +0 -218
  535. package/test/unit/spec/peerconnection-manager/utils.js +0 -49
  536. package/test/unit/spec/peerconnection-manager/utils.test-fixtures.ts +0 -388
  537. package/test/unit/spec/roap/util.js +0 -30
  538. /package/dist/common/errors/{reclaim-host-role-error.d.ts → reclaim-host-role-errors.d.ts} +0 -0
  539. /package/src/common/errors/{reclaim-host-role-error.ts → reclaim-host-role-errors.ts} +0 -0
@@ -1,9 +1,7 @@
1
- import {isEmpty} from 'lodash';
1
+ import {LocalCameraStream, LocalMicrophoneStream} from '@webex/media-helpers';
2
2
 
3
+ import {cloneDeep} from 'lodash';
3
4
  import {MeetingNotActiveError, UserNotJoinedError} from '../common/errors/webex-errors';
4
- import Metrics from '../metrics';
5
- import {eventType, trigger} from '../metrics/config';
6
- import Media from '../media';
7
5
  import LoggerProxy from '../common/logs/logger-proxy';
8
6
  import {
9
7
  INTENT_TO_JOIN,
@@ -13,518 +11,784 @@ import {
13
11
  PASSWORD_STATUS,
14
12
  DISPLAY_HINTS,
15
13
  FULL_STATE,
14
+ SELF_POLICY,
15
+ EVENT_TRIGGERS,
16
+ LOCAL_SHARE_ERRORS,
17
+ IP_VERSION,
16
18
  } from '../constants';
19
+ import BrowserDetection from '../common/browser-detection';
17
20
  import IntentToJoinError from '../common/errors/intent-to-join';
18
21
  import JoinMeetingError from '../common/errors/join-meeting';
19
22
  import ParameterError from '../common/errors/parameter';
20
23
  import PermissionError from '../common/errors/permission';
21
24
  import PasswordError from '../common/errors/password-error';
22
25
  import CaptchaError from '../common/errors/captcha-error';
26
+ import Trigger from '../common/events/trigger-proxy';
27
+
28
+ const MeetingUtil = {
29
+ parseLocusJoin: (response) => {
30
+ const parsed: any = {};
31
+
32
+ // First todo: add check for existance
33
+ parsed.locus = response.body.locus;
34
+ parsed.mediaConnections = response.body.mediaConnections;
35
+ parsed.locusUrl = parsed.locus.url;
36
+ parsed.locusId = parsed.locus.url.split('/').pop();
37
+ parsed.selfId = parsed.locus.self.id;
38
+
39
+ // we need mediaId before making roap calls
40
+ parsed.mediaConnections.forEach((mediaConnection) => {
41
+ if (mediaConnection.mediaId) {
42
+ parsed.mediaId = mediaConnection.mediaId;
43
+ }
44
+ });
23
45
 
24
- const MeetingUtil: any = {};
25
-
26
- MeetingUtil.parseLocusJoin = (response) => {
27
- const parsed: any = {};
46
+ return parsed;
47
+ },
28
48
 
29
- // First todo: add check for existance
30
- parsed.locus = response.body.locus;
31
- parsed.mediaConnections = response.body.mediaConnections;
32
- parsed.locusUrl = parsed.locus.url;
33
- parsed.locusId = parsed.locus.url.split('/').pop();
34
- parsed.selfId = parsed.locus.self.id;
49
+ remoteUpdateAudioVideo: (meeting, audioMuted?: boolean, videoMuted?: boolean) => {
50
+ const webex = meeting.getWebexObject();
51
+ if (!meeting) {
52
+ return Promise.reject(new ParameterError('You need a meeting object.'));
53
+ }
35
54
 
36
- // we need mediaId before making roap calls
37
- parsed.mediaConnections.forEach((mediaConnection) => {
38
- if (mediaConnection.mediaId) {
39
- parsed.mediaId = mediaConnection.mediaId;
55
+ if (!meeting.locusMediaRequest) {
56
+ return Promise.reject(
57
+ new ParameterError(
58
+ 'You need a meeting with a media connection, call Meeting.addMedia() first.'
59
+ )
60
+ );
40
61
  }
41
- });
42
62
 
43
- return parsed;
44
- };
63
+ // @ts-ignore
64
+ webex.internal.newMetrics.submitClientEvent({
65
+ name: 'client.locus.media.request',
66
+ options: {meetingId: meeting.id},
67
+ });
45
68
 
46
- MeetingUtil.remoteUpdateAudioVideo = (audioMuted, videoMuted, meeting) => {
47
- if (!meeting) {
48
- return Promise.reject(new ParameterError('You need a meeting object.'));
49
- }
50
- const localMedias = Media.generateLocalMedias(meeting.mediaId, audioMuted, videoMuted);
69
+ return meeting.locusMediaRequest
70
+ .send({
71
+ type: 'LocalMute',
72
+ selfUrl: meeting.selfUrl,
73
+ mediaId: meeting.mediaId,
74
+ sequence: meeting.locusInfo.sequence,
75
+ muteOptions: {
76
+ audioMuted,
77
+ videoMuted,
78
+ },
79
+ })
80
+ .then((response) => {
81
+ // @ts-ignore
82
+ webex.internal.newMetrics.submitClientEvent({
83
+ name: 'client.locus.media.response',
84
+ options: {meetingId: meeting.id},
85
+ });
51
86
 
52
- if (isEmpty(localMedias)) {
53
- return Promise.reject(
54
- new ParameterError('You need a media id on the meeting to change remote audio.')
55
- );
56
- }
87
+ return response?.body?.locus;
88
+ });
89
+ },
57
90
 
58
- Metrics.postEvent({event: eventType.MEDIA_REQUEST, meeting});
91
+ hasOwner: (info) => info && info.owner,
59
92
 
60
- return meeting.meetingRequest
61
- .remoteAudioVideoToggle({
62
- locusUrl: meeting.locusUrl,
63
- selfId: meeting.selfId,
64
- localMedias,
65
- deviceUrl: meeting.deviceUrl,
66
- correlationId: meeting.correlationId,
67
- })
68
- .then((response) => {
69
- Metrics.postEvent({event: eventType.MEDIA_RESPONSE, meeting});
93
+ isOwnerSelf: (owner, selfId) => owner === selfId,
70
94
 
71
- return response.body.locus;
72
- });
73
- };
95
+ isPinOrGuest: (err) => err?.body?.errorCode && INTENT_TO_JOIN.includes(err.body.errorCode),
74
96
 
75
- MeetingUtil.hasOwner = (info) => info && info.owner;
97
+ /**
98
+ * Returns the current state of knowledge about whether we are on an ipv4-only or ipv6-only or mixed (ipv4 and ipv6) network.
99
+ * The return value matches the possible values of "ipver" parameter used by the backend APIs.
100
+ *
101
+ * @param {Object} webex webex instance
102
+ * @returns {IP_VERSION|undefined} ipver value to be passed to the backend APIs or undefined if we should not pass any value to the backend
103
+ */
104
+ getIpVersion(webex: any): IP_VERSION | undefined {
105
+ const {supportsIpV4, supportsIpV6} = webex.internal.device.ipNetworkDetector;
76
106
 
77
- MeetingUtil.isOwnerSelf = (owner, selfId) => owner === selfId;
107
+ if (BrowserDetection().isBrowser('firefox')) {
108
+ // our ipv6 solution relies on FQDN ICE candidates, but Firefox doesn't support them,
109
+ // see https://bugzilla.mozilla.org/show_bug.cgi?id=1713128
110
+ // so for Firefox we don't want the backend to activate the "ipv6 feature"
111
+ return undefined;
112
+ }
78
113
 
79
- MeetingUtil.isPinOrGuest = (err) =>
80
- err?.body?.errorCode && INTENT_TO_JOIN.includes(err.body.errorCode);
114
+ if (supportsIpV4 && supportsIpV6) {
115
+ return IP_VERSION.ipv4_and_ipv6;
116
+ }
81
117
 
82
- MeetingUtil.joinMeeting = (meeting, options) => {
83
- if (!meeting) {
84
- return Promise.reject(new ParameterError('You need a meeting object.'));
85
- }
118
+ if (supportsIpV4) {
119
+ return IP_VERSION.only_ipv4;
120
+ }
86
121
 
87
- Metrics.postEvent({event: eventType.LOCUS_JOIN_REQUEST, meeting});
122
+ if (supportsIpV6) {
123
+ return IP_VERSION.only_ipv6;
124
+ }
88
125
 
89
- // eslint-disable-next-line no-warning-comments
90
- // TODO: check if the meeting is in JOINING state
91
- // if Joining state termintate the request as user might click multiple times
92
- return meeting.meetingRequest
93
- .joinMeeting({
94
- inviteeAddress: meeting.meetingJoinUrl || meeting.sipUri,
95
- meetingNumber: meeting.meetingNumber,
96
- deviceUrl: meeting.deviceUrl,
97
- locusUrl: meeting.locusUrl,
98
- correlationId: meeting.correlationId,
99
- roapMessage: options.roapMessage,
100
- permissionToken: meeting.permissionToken,
101
- resourceId: options.resourceId || null,
102
- moderator: options.moderator,
103
- pin: options.pin,
104
- moveToResource: options.moveToResource,
105
- preferTranscoding: options.preferTranscoding,
106
- asResourceOccupant: options.asResourceOccupant,
107
- })
108
- .then((res) => {
109
- Metrics.postEvent({
110
- event: eventType.LOCUS_JOIN_RESPONSE,
111
- meeting,
112
- data: {
113
- trigger: trigger.LOCI_UPDATE,
114
- locus: res.body.locus,
115
- mediaConnections: res.body.mediaConnections,
116
- trackingId: res.headers.trackingid,
117
- },
118
- });
126
+ return IP_VERSION.unknown;
127
+ },
128
+
129
+ joinMeeting: (meeting, options) => {
130
+ if (!meeting) {
131
+ return Promise.reject(new ParameterError('You need a meeting object.'));
132
+ }
133
+ const webex = meeting.getWebexObject();
119
134
 
120
- return MeetingUtil.parseLocusJoin(res);
135
+ // @ts-ignore
136
+ webex.internal.newMetrics.submitClientEvent({
137
+ name: 'client.locus.join.request',
138
+ options: {meetingId: meeting.id},
121
139
  });
122
- };
123
140
 
124
- MeetingUtil.cleanUp = (meeting) => {
125
- // make sure we send last metrics before we close the peerconnection
126
- const stopStatsAnalyzer = meeting.statsAnalyzer
127
- ? meeting.statsAnalyzer.stopAnalyzer()
128
- : Promise.resolve();
129
-
130
- return stopStatsAnalyzer
131
- .then(() => meeting.closeLocalStream())
132
- .then(() => meeting.closeLocalShare())
133
- .then(() => meeting.closeRemoteTracks())
134
- .then(() => meeting.closePeerConnections())
135
- .then(() => {
136
- meeting.unsetLocalVideoTrack();
137
- meeting.unsetLocalShareTrack();
138
- meeting.unsetRemoteTracks();
139
- meeting.unsetPeerConnections();
140
- meeting.reconnectionManager.cleanUp();
141
- })
142
- .then(() => meeting.roap.stop(meeting.correlationId, meeting.roapSeq))
143
- .then(() => meeting.stopKeepAlive());
144
- };
141
+ // eslint-disable-next-line no-warning-comments
142
+ // TODO: check if the meeting is in JOINING state
143
+ // if Joining state termintate the request as user might click multiple times
144
+ return meeting.meetingRequest
145
+ .joinMeeting({
146
+ inviteeAddress: meeting.meetingJoinUrl || meeting.sipUri,
147
+ meetingNumber: meeting.meetingNumber,
148
+ deviceUrl: meeting.deviceUrl,
149
+ locusUrl: meeting.locusUrl,
150
+ locusClusterUrl: meeting.meetingInfo?.locusClusterUrl,
151
+ correlationId: meeting.correlationId,
152
+ roapMessage: options.roapMessage,
153
+ permissionToken: meeting.permissionToken,
154
+ resourceId: options.resourceId || null,
155
+ moderator: options.moderator,
156
+ pin: options.pin,
157
+ moveToResource: options.moveToResource,
158
+ preferTranscoding: !meeting.isMultistream,
159
+ asResourceOccupant: options.asResourceOccupant,
160
+ breakoutsSupported: options.breakoutsSupported,
161
+ locale: options.locale,
162
+ deviceCapabilities: options.deviceCapabilities,
163
+ liveAnnotationSupported: options.liveAnnotationSupported,
164
+ ipVersion: MeetingUtil.getIpVersion(meeting.getWebexObject()),
165
+ })
166
+ .then((res) => {
167
+ // @ts-ignore
168
+ webex.internal.newMetrics.submitClientEvent({
169
+ name: 'client.locus.join.response',
170
+ payload: {
171
+ trigger: 'loci-update',
172
+ identifiers: {
173
+ trackingId: res.headers.trackingid,
174
+ },
175
+ },
176
+ options: {
177
+ meetingId: meeting.id,
178
+ mediaConnections: res.body.mediaConnections,
179
+ },
180
+ });
145
181
 
146
- MeetingUtil.disconnectPhoneAudio = (meeting, phoneUrl) => {
147
- if (meeting.meetingState === FULL_STATE.INACTIVE) {
148
- return Promise.reject(new MeetingNotActiveError());
149
- }
150
-
151
- const options = {
152
- locusUrl: meeting.locusUrl,
153
- selfId: meeting.selfId,
154
- correlationId: meeting.correlationId,
155
- phoneUrl,
156
- };
157
-
158
- return meeting.meetingRequest
159
- .disconnectPhoneAudio(options)
160
- .then((response) => {
161
- if (response?.body?.locus) {
162
- meeting.locusInfo.onFullLocus(response.body.locus);
163
- }
164
- })
165
- .catch((err) => {
182
+ return MeetingUtil.parseLocusJoin(res);
183
+ });
184
+ },
185
+
186
+ cleanUp: (meeting) => {
187
+ meeting.breakouts.cleanUp();
188
+ meeting.simultaneousInterpretation.cleanUp();
189
+
190
+ // make sure we send last metrics before we close the peerconnection
191
+ const stopStatsAnalyzer = meeting.statsAnalyzer
192
+ ? meeting.statsAnalyzer.stopAnalyzer()
193
+ : Promise.resolve();
194
+
195
+ return stopStatsAnalyzer
196
+ .then(() => meeting.closeRemoteStreams())
197
+ .then(() => meeting.closePeerConnections())
198
+ .then(() => {
199
+ meeting.cleanupLocalStreams();
200
+ meeting.unsetRemoteStreams();
201
+ meeting.unsetPeerConnections();
202
+ meeting.reconnectionManager.cleanUp();
203
+ })
204
+ .then(() => meeting.stopKeepAlive())
205
+ .then(() => meeting.updateLLMConnection());
206
+ },
207
+
208
+ disconnectPhoneAudio: (meeting, phoneUrl) => {
209
+ if (meeting.meetingState === FULL_STATE.INACTIVE) {
210
+ return Promise.reject(new MeetingNotActiveError());
211
+ }
212
+
213
+ const options = {
214
+ locusUrl: meeting.locusUrl,
215
+ selfId: meeting.selfId,
216
+ correlationId: meeting.correlationId,
217
+ phoneUrl,
218
+ };
219
+
220
+ return meeting.meetingRequest.disconnectPhoneAudio(options).catch((err) => {
166
221
  LoggerProxy.logger.error(
167
222
  `Meeting:util#disconnectPhoneAudio --> An error occured while disconnecting phone audio in meeting ${meeting.id}, error: ${err}`
168
223
  );
169
224
 
170
225
  return Promise.reject(err);
171
226
  });
172
- };
173
-
174
- // by default will leave on meeting's resourceId
175
- // if you explicity want it not to leave on resource id, pass
176
- // {resourceId: null}
177
- // TODO: chris, you can modify this however you want
178
- MeetingUtil.leaveMeeting = (meeting, options: any = {}) => {
179
- if (meeting.meetingState === FULL_STATE.INACTIVE) {
180
- // TODO: clean up if the meeting is already inactive
181
- return Promise.reject(new MeetingNotActiveError());
182
- }
183
-
184
- if (MeetingUtil.isUserInLeftState(meeting.locusInfo)) {
185
- return Promise.reject(new UserNotJoinedError());
186
- }
187
-
188
- const defaultOptions = {
189
- locusUrl: meeting.locusUrl,
190
- selfId: meeting.selfId,
191
- correlationId: meeting.correlationId,
192
- resourceId: meeting.resourceId,
193
- deviceUrl: meeting.deviceUrl,
194
- };
195
-
196
- const leaveOptions = {...defaultOptions, ...options};
197
-
198
- return meeting.meetingRequest
199
- .leaveMeeting(leaveOptions)
200
- .then((response) => {
201
- if (response && response.body && response.body.locus) {
202
- // && !options.moveMeeting) {
203
- meeting.locusInfo.onFullLocus(response.body.locus);
204
- }
205
-
206
- return Promise.resolve();
207
- })
208
- .then(() => {
209
- if (options.moveMeeting) {
210
- return Promise.resolve();
211
- }
227
+ },
228
+
229
+ /**
230
+ * Returns options for leaving a meeting.
231
+ * @param {any} meeting
232
+ * @param {any} options
233
+ * @returns {any} leave options
234
+ */
235
+ prepareLeaveMeetingOptions: (meeting, options: any = {}) => {
236
+ const defaultOptions = {
237
+ locusUrl: meeting.locusUrl,
238
+ selfId: meeting.selfId,
239
+ correlationId: meeting.correlationId,
240
+ resourceId: meeting.resourceId,
241
+ deviceUrl: meeting.deviceUrl,
242
+ };
243
+
244
+ return {...defaultOptions, ...options};
245
+ },
246
+
247
+ // by default will leave on meeting's resourceId
248
+ // if you explicity want it not to leave on resource id, pass
249
+ // {resourceId: null}
250
+ // TODO: chris, you can modify this however you want
251
+ leaveMeeting: (meeting, options: any = {}) => {
252
+ if (meeting.meetingState === FULL_STATE.INACTIVE) {
253
+ // TODO: clean up if the meeting is already inactive
254
+ return Promise.reject(new MeetingNotActiveError());
255
+ }
212
256
 
213
- return MeetingUtil.cleanUp(meeting);
214
- })
215
- .catch((err) => {
216
- // TODO: If the meeting state comes as LEFT or INACTIVE as response then
217
- // 1) on leave clean up the meeting or simply do a sync on the meeting
218
- // 2) If the error says meeting is inactive then destroy the meeting object
219
- LoggerProxy.logger.error(
220
- `Meeting:util#leaveMeeting --> An error occured while trying to leave meeting with an id of ${meeting.id}, error: ${err}`
221
- );
257
+ if (MeetingUtil.isUserInLeftState(meeting.locusInfo)) {
258
+ return Promise.reject(new UserNotJoinedError());
259
+ }
222
260
 
223
- return Promise.reject(err);
224
- });
225
- };
226
- MeetingUtil.declineMeeting = (meeting, reason) =>
227
- meeting.meetingRequest.declineMeeting({
228
- locusUrl: meeting.locusUrl,
229
- deviceUrl: meeting.deviceUrl,
230
- reason,
231
- });
261
+ const leaveOptions = MeetingUtil.prepareLeaveMeetingOptions(meeting, options);
262
+
263
+ return meeting.meetingRequest
264
+ .leaveMeeting(leaveOptions)
265
+ .then(() => {
266
+ if (options.moveMeeting) {
267
+ return Promise.resolve();
268
+ }
269
+
270
+ return MeetingUtil.cleanUp(meeting);
271
+ })
272
+ .catch((err) => {
273
+ // TODO: If the meeting state comes as LEFT or INACTIVE as response then
274
+ // 1) on leave clean up the meeting or simply do a sync on the meeting
275
+ // 2) If the error says meeting is inactive then destroy the meeting object
276
+ LoggerProxy.logger.error(
277
+ `Meeting:util#leaveMeeting --> An error occured while trying to leave meeting with an id of ${meeting.id}, error: ${err}`
278
+ );
232
279
 
233
- MeetingUtil.isUserInLeftState = (locusInfo) => locusInfo.parsedLocus?.self?.state === _LEFT_;
280
+ return Promise.reject(err);
281
+ });
282
+ },
283
+ declineMeeting: (meeting, reason) =>
284
+ meeting.meetingRequest.declineMeeting({
285
+ locusUrl: meeting.locusUrl,
286
+ deviceUrl: meeting.deviceUrl,
287
+ reason,
288
+ }),
234
289
 
235
- MeetingUtil.isUserInIdleState = (locusInfo) => locusInfo.parsedLocus?.self?.state === _IDLE_;
290
+ isUserInLeftState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _LEFT_,
236
291
 
237
- MeetingUtil.isUserInJoinedState = (locusInfo) => locusInfo.parsedLocus?.self?.state === _JOINED_;
292
+ isUserInIdleState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _IDLE_,
238
293
 
239
- MeetingUtil.isMediaEstablished = (currentMediaStatus) =>
240
- currentMediaStatus &&
241
- (currentMediaStatus.audio || currentMediaStatus.video || currentMediaStatus.share);
294
+ isUserInJoinedState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _JOINED_,
242
295
 
243
- MeetingUtil.joinMeetingOptions = (meeting, options: any = {}) => {
244
- meeting.resourceId = meeting.resourceId || options.resourceId;
296
+ isMediaEstablished: (currentMediaStatus) =>
297
+ currentMediaStatus &&
298
+ (currentMediaStatus.audio || currentMediaStatus.video || currentMediaStatus.share),
245
299
 
246
- if (meeting.requiredCaptcha) {
247
- return Promise.reject(new CaptchaError());
248
- }
249
- if (meeting.passwordStatus === PASSWORD_STATUS.REQUIRED) {
250
- return Promise.reject(new PasswordError());
251
- }
300
+ joinMeetingOptions: (meeting, options: any = {}) => {
301
+ const webex = meeting.getWebexObject();
252
302
 
253
- if (options.pin) {
254
- Metrics.postEvent({
255
- event: eventType.PIN_COLLECTED,
256
- meeting,
257
- });
258
- }
259
-
260
- // normal join meeting, scenario A, D
261
- return MeetingUtil.joinMeeting(meeting, options)
262
- .then((response) => {
263
- meeting.setLocus(response);
264
-
265
- return Promise.resolve(response);
266
- })
267
- .catch((err) => {
268
- // joining a claimed PMR that is not my own, scenario B
269
- if (MeetingUtil.isPinOrGuest(err)) {
270
- Metrics.postEvent({
271
- event: eventType.PIN_PROMPT,
272
- meeting,
273
- });
303
+ meeting.resourceId = meeting.resourceId || options.resourceId;
274
304
 
275
- // request host pin or non host for unclaimed PMR, start of Scenario C
276
- // see https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-Lobby-and--IVR-Feature
277
- return Promise.reject(new IntentToJoinError('Error Joining Meeting', err));
278
- }
279
- LoggerProxy.logger.error('Meeting:util#joinMeetingOptions --> Error joining the call, ', err);
305
+ if (meeting.requiredCaptcha) {
306
+ return Promise.reject(new CaptchaError());
307
+ }
308
+ if (meeting.passwordStatus === PASSWORD_STATUS.REQUIRED) {
309
+ return Promise.reject(new PasswordError());
310
+ }
280
311
 
281
- return Promise.reject(new JoinMeetingError(options, 'Error Joining Meeting', err));
282
- });
283
- };
312
+ if (options.pin) {
313
+ // @ts-ignore
314
+ webex.internal.newMetrics.submitClientEvent({
315
+ name: 'client.pin.collected',
316
+ options: {
317
+ meetingId: meeting.id,
318
+ },
319
+ });
320
+ }
284
321
 
285
- MeetingUtil.updateTransceiver = (options, meetingOptions) => {
286
- const {
287
- type,
288
- sendTrack,
289
- receiveTrack,
290
- track,
291
- transceiver,
292
- peerConnection,
293
- previousMediaDirection,
294
- } = options;
295
-
296
- if (
297
- (sendTrack !== undefined && sendTrack !== previousMediaDirection.sendTrack) ||
298
- (receiveTrack !== undefined && receiveTrack !== previousMediaDirection.receiveTrack)
299
- ) {
300
- return Media.updateTransceiver(
301
- {
302
- meetingId: meetingOptions.meeting.id,
303
- remoteQualityLevel: meetingOptions.mediaProperties.remoteQualityLevel,
304
- enableRtx: meetingOptions.meeting.config.enableRtx,
305
- enableExtmap: meetingOptions.meeting.config.enableExtmap,
306
- },
307
- peerConnection,
308
- transceiver,
309
- {
310
- track,
311
- type,
312
- receiveTrack,
313
- sendTrack,
314
- }
315
- )
316
- .then(() =>
317
- meetingOptions.meeting.roap.sendRoapMediaRequest({
318
- sdp: meetingOptions.mediaProperties.peerConnection.sdp,
319
- roapSeq: meetingOptions.meeting.roapSeq,
320
- meeting: meetingOptions.meeting, // or can pass meeting ID
321
- })
322
- )
323
- .catch((e) => {
322
+ // normal join meeting, scenario A, D
323
+ return MeetingUtil.joinMeeting(meeting, options)
324
+ .then((response) => {
325
+ meeting.setLocus(response);
326
+
327
+ return Promise.resolve(response);
328
+ })
329
+ .catch((err) => {
330
+ // joining a claimed PMR that is not my own, scenario B
331
+ if (MeetingUtil.isPinOrGuest(err)) {
332
+ // @ts-ignore
333
+ webex.internal.newMetrics.submitClientEvent({
334
+ name: 'client.pin.prompt',
335
+ options: {
336
+ meetingId: meeting.id,
337
+ },
338
+ });
339
+
340
+ // request host pin or non host for unclaimed PMR, start of Scenario C
341
+ // see https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-Lobby-and--IVR-Feature
342
+ return Promise.reject(new IntentToJoinError('Error Joining Meeting', err));
343
+ }
324
344
  LoggerProxy.logger.error(
325
- `Meeting:util#updateTransceiver --> Error updating the ${type} streams with error: ${e}`
345
+ 'Meeting:util#joinMeetingOptions --> Error joining the call, ',
346
+ err
326
347
  );
348
+
349
+ return Promise.reject(new JoinMeetingError(options, 'Error Joining Meeting', err));
327
350
  });
328
- }
329
- if (track) {
330
- transceiver.sender.replaceTrack(track);
351
+ },
352
+
353
+ /**
354
+ * Returns request options for leaving a meeting.
355
+ * @param {any} meeting
356
+ * @param {any} options
357
+ * @returns {any} request options
358
+ */
359
+ buildLeaveFetchRequestOptions: (meeting, options: any = {}) => {
360
+ const leaveOptions = MeetingUtil.prepareLeaveMeetingOptions(meeting, options);
361
+
362
+ return meeting.meetingRequest.buildLeaveMeetingRequestOptions(leaveOptions);
363
+ },
364
+
365
+ getTrack: (stream) => {
366
+ let audioTrack = null;
367
+ let videoTrack = null;
368
+ let audioTracks = null;
369
+ let videoTracks = null;
370
+
371
+ if (!stream) {
372
+ return {audioTrack: null, videoTrack: null};
373
+ }
374
+ if (stream.getAudioTracks) {
375
+ audioTracks = stream.getAudioTracks();
376
+ }
377
+ if (stream.getVideoTracks) {
378
+ videoTracks = stream.getVideoTracks();
379
+ }
331
380
 
332
- return Promise.resolve();
333
- }
381
+ if (audioTracks && audioTracks.length > 0) {
382
+ [audioTrack] = audioTracks;
383
+ }
334
384
 
335
- return Promise.reject(new ParameterError('update Failed: please pass valid parameter'));
336
- };
385
+ if (videoTracks && videoTracks.length > 0) {
386
+ [videoTrack] = videoTracks;
387
+ }
337
388
 
338
- MeetingUtil.validateOptions = (options) => {
339
- const {sendVideo, sendAudio, sendShare, localStream, localShare} = options;
389
+ return {audioTrack, videoTrack};
390
+ },
340
391
 
341
- if (sendVideo && !MeetingUtil.getTrack(localStream).videoTrack) {
342
- return Promise.reject(new ParameterError('please pass valid video streams'));
343
- }
392
+ getModeratorFromLocusInfo: (locusInfo) =>
393
+ locusInfo &&
394
+ locusInfo.parsedLocus &&
395
+ locusInfo.parsedLocus.info &&
396
+ locusInfo.parsedLocus.info &&
397
+ locusInfo.parsedLocus.info.moderator,
344
398
 
345
- if (sendAudio && !MeetingUtil.getTrack(localStream).audioTrack) {
346
- return Promise.reject(new ParameterError('please pass valid audio streams'));
347
- }
399
+ getPolicyFromLocusInfo: (locusInfo) =>
400
+ locusInfo &&
401
+ locusInfo.parsedLocus &&
402
+ locusInfo.parsedLocus.info &&
403
+ locusInfo.parsedLocus.info &&
404
+ locusInfo.parsedLocus.info.policy,
348
405
 
349
- if (sendShare && !MeetingUtil.getTrack(localShare).videoTrack) {
350
- return Promise.reject(new ParameterError('please pass valid share streams'));
351
- }
406
+ getUserDisplayHintsFromLocusInfo: (locusInfo) =>
407
+ locusInfo?.parsedLocus?.info?.userDisplayHints || [],
352
408
 
353
- return Promise.resolve();
354
- };
409
+ canInviteNewParticipants: (displayHints) => displayHints.includes(DISPLAY_HINTS.ADD_GUEST),
355
410
 
356
- MeetingUtil.getTrack = (stream) => {
357
- let audioTrack = null;
358
- let videoTrack = null;
359
- let audioTracks = null;
360
- let videoTracks = null;
361
-
362
- if (!stream) {
363
- return {audioTrack: null, videoTrack: null};
364
- }
365
- if (stream.getAudioTracks) {
366
- audioTracks = stream.getAudioTracks();
367
- }
368
- if (stream.getVideoTracks) {
369
- videoTracks = stream.getVideoTracks();
370
- }
371
-
372
- if (audioTracks && audioTracks.length > 0) {
373
- [audioTrack] = audioTracks;
374
- }
375
-
376
- if (videoTracks && videoTracks.length > 0) {
377
- [videoTrack] = videoTracks;
378
- }
379
-
380
- return {audioTrack, videoTrack};
381
- };
411
+ canAdmitParticipant: (displayHints) =>
412
+ displayHints.includes(DISPLAY_HINTS.ROSTER_WAITING_TO_JOIN),
382
413
 
383
- MeetingUtil.getModeratorFromLocusInfo = (locusInfo) =>
384
- locusInfo &&
385
- locusInfo.parsedLocus &&
386
- locusInfo.parsedLocus.info &&
387
- locusInfo.parsedLocus.info &&
388
- locusInfo.parsedLocus.info.moderator;
414
+ canUserLock: (displayHints) =>
415
+ displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_LOCK) &&
416
+ displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_UNLOCKED),
389
417
 
390
- MeetingUtil.getPolicyFromLocusInfo = (locusInfo) =>
391
- locusInfo &&
392
- locusInfo.parsedLocus &&
393
- locusInfo.parsedLocus.info &&
394
- locusInfo.parsedLocus.info &&
395
- locusInfo.parsedLocus.info.policy;
418
+ canUserUnlock: (displayHints) =>
419
+ displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_UNLOCK) &&
420
+ displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_LOCKED),
396
421
 
397
- MeetingUtil.getUserDisplayHintsFromLocusInfo = (locusInfo) =>
398
- locusInfo?.parsedLocus?.info?.userDisplayHints || [];
422
+ canUserRaiseHand: (displayHints) => displayHints.includes(DISPLAY_HINTS.RAISE_HAND),
399
423
 
400
- MeetingUtil.canInviteNewParticipants = (displayHints) =>
401
- displayHints.includes(DISPLAY_HINTS.ADD_GUEST);
424
+ canUserLowerAllHands: (displayHints) => displayHints.includes(DISPLAY_HINTS.LOWER_ALL_HANDS),
402
425
 
403
- MeetingUtil.canAdmitParticipant = (displayHints) =>
404
- displayHints.includes(DISPLAY_HINTS.ROSTER_WAITING_TO_JOIN);
426
+ canUserLowerSomeoneElsesHand: (displayHints) =>
427
+ displayHints.includes(DISPLAY_HINTS.LOWER_SOMEONE_ELSES_HAND),
405
428
 
406
- MeetingUtil.canUserLock = (displayHints) =>
407
- displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_LOCK) &&
408
- displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_UNLOCKED);
429
+ bothLeaveAndEndMeetingAvailable: (displayHints) =>
430
+ displayHints.includes(DISPLAY_HINTS.LEAVE_TRANSFER_HOST_END_MEETING) ||
431
+ displayHints.includes(DISPLAY_HINTS.LEAVE_END_MEETING),
409
432
 
410
- MeetingUtil.canUserUnlock = (displayHints) =>
411
- displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_UNLOCK) &&
412
- displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_LOCKED);
433
+ canManageBreakout: (displayHints) => displayHints.includes(DISPLAY_HINTS.BREAKOUT_MANAGEMENT),
434
+ canBroadcastMessageToBreakout: (displayHints, policies = {}) =>
435
+ displayHints.includes(DISPLAY_HINTS.BROADCAST_MESSAGE_TO_BREAKOUT) &&
436
+ !!policies[SELF_POLICY.SUPPORT_BROADCAST_MESSAGE],
413
437
 
414
- MeetingUtil.canUserRaiseHand = (displayHints) => displayHints.includes(DISPLAY_HINTS.RAISE_HAND);
438
+ isSuppressBreakoutSupport: (displayHints) =>
439
+ displayHints.includes(DISPLAY_HINTS.UCF_SUPPRESS_BREAKOUTS_SUPPORT),
415
440
 
416
- MeetingUtil.canUserLowerAllHands = (displayHints) =>
417
- displayHints.includes(DISPLAY_HINTS.LOWER_ALL_HANDS);
441
+ canAdmitLobbyToBreakout: (displayHints) =>
442
+ !displayHints.includes(DISPLAY_HINTS.DISABLE_LOBBY_TO_BREAKOUT),
418
443
 
419
- MeetingUtil.canUserLowerSomeoneElsesHand = (displayHints) =>
420
- displayHints.includes(DISPLAY_HINTS.LOWER_SOMEONE_ELSES_HAND);
444
+ isBreakoutPreassignmentsEnabled: (displayHints) =>
445
+ !displayHints.includes(DISPLAY_HINTS.DISABLE_BREAKOUT_PREASSIGNMENTS),
421
446
 
422
- MeetingUtil.bothLeaveAndEndMeetingAvailable = (displayHints) =>
423
- displayHints.includes(DISPLAY_HINTS.LEAVE_TRANSFER_HOST_END_MEETING) ||
424
- displayHints.includes(DISPLAY_HINTS.LEAVE_END_MEETING);
447
+ canUserAskForHelp: (displayHints) => !displayHints.includes(DISPLAY_HINTS.DISABLE_ASK_FOR_HELP),
425
448
 
426
- MeetingUtil.lockMeeting = (actions, request, locusUrl) => {
427
- if (actions && actions.canLock) {
428
- return request.lockMeeting({locusUrl, lock: true});
429
- }
449
+ lockMeeting: (actions, request, locusUrl) => {
450
+ if (actions && actions.canLock) {
451
+ return request.lockMeeting({locusUrl, lock: true});
452
+ }
430
453
 
431
- return Promise.reject(new PermissionError('Lock not allowed, due to joined property.'));
432
- };
454
+ return Promise.reject(new PermissionError('Lock not allowed, due to joined property.'));
455
+ },
433
456
 
434
- MeetingUtil.unlockMeeting = (actions, request, locusUrl) => {
435
- if (actions && actions.canUnlock) {
436
- return request.lockMeeting({locusUrl, lock: false});
437
- }
457
+ unlockMeeting: (actions, request, locusUrl) => {
458
+ if (actions && actions.canUnlock) {
459
+ return request.lockMeeting({locusUrl, lock: false});
460
+ }
438
461
 
439
- return Promise.reject(new PermissionError('Unlock not allowed, due to joined property.'));
440
- };
462
+ return Promise.reject(new PermissionError('Unlock not allowed, due to joined property.'));
463
+ },
441
464
 
442
- MeetingUtil.handleAudioLogging = (audioTrack) => {
443
- const LOG_HEADER = 'MeetingUtil#handleAudioLogging -->';
465
+ handleAudioLogging: (audioStream?: LocalMicrophoneStream) => {
466
+ const LOG_HEADER = 'MeetingUtil#handleAudioLogging -->';
444
467
 
445
- if (audioTrack) {
446
- const settings = audioTrack.getSettings();
447
- const {deviceId} = settings;
468
+ if (audioStream) {
469
+ const settings = audioStream.getSettings();
470
+ const {deviceId} = settings;
448
471
 
449
- LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
450
- LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
451
- }
452
- };
472
+ LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
473
+ LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
474
+ }
475
+ },
453
476
 
454
- MeetingUtil.handleVideoLogging = (videoTrack) => {
455
- const LOG_HEADER = 'MeetingUtil#handleVideoLogging -->';
477
+ handleVideoLogging: (videoStream?: LocalCameraStream) => {
478
+ const LOG_HEADER = 'MeetingUtil#handleVideoLogging -->';
456
479
 
457
- if (videoTrack) {
458
- const settings = videoTrack.getSettings();
459
- const {deviceId} = settings;
480
+ if (videoStream) {
481
+ const settings = videoStream.getSettings();
482
+ const {deviceId} = settings;
460
483
 
461
- LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
462
- LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
463
- }
464
- };
484
+ LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
485
+ LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
486
+ }
487
+ },
465
488
 
466
- MeetingUtil.handleDeviceLogging = (devices = []) => {
467
- const LOG_HEADER = 'MeetingUtil#handleDeviceLogging -->';
489
+ handleDeviceLogging: (devices = []) => {
490
+ const LOG_HEADER = 'MeetingUtil#handleDeviceLogging -->';
468
491
 
469
- devices.forEach((device) => {
470
- LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${device.deviceId}`);
471
- LoggerProxy.logger.log(LOG_HEADER, 'settings', JSON.stringify(device));
472
- });
473
- };
492
+ devices.forEach((device) => {
493
+ LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${device.deviceId}`);
494
+ LoggerProxy.logger.log(LOG_HEADER, 'settings', JSON.stringify(device));
495
+ });
496
+ },
497
+
498
+ endMeetingForAll: (meeting) => {
499
+ if (meeting.meetingState === FULL_STATE.INACTIVE) {
500
+ return Promise.reject(new MeetingNotActiveError());
501
+ }
502
+
503
+ const endOptions = {
504
+ locusUrl: meeting.locusUrl,
505
+ };
506
+
507
+ return meeting.meetingRequest
508
+ .endMeetingForAll(endOptions)
509
+ .then(() => MeetingUtil.cleanUp(meeting))
510
+ .catch((err) => {
511
+ LoggerProxy.logger.error(
512
+ `Meeting:util#endMeetingForAll An error occured while trying to end meeting for all with an id of ${meeting.id}, error: ${err}`
513
+ );
514
+
515
+ return Promise.reject(err);
516
+ });
517
+ },
518
+
519
+ canEnableClosedCaption: (displayHints) => displayHints.includes(DISPLAY_HINTS.CAPTION_START),
520
+
521
+ isSaveTranscriptsEnabled: (displayHints) =>
522
+ displayHints.includes(DISPLAY_HINTS.SAVE_TRANSCRIPTS_ENABLED),
523
+
524
+ canStartTranscribing: (displayHints) =>
525
+ displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_START),
526
+
527
+ canStopTranscribing: (displayHints) =>
528
+ displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_STOP),
529
+
530
+ isClosedCaptionActive: (displayHints) =>
531
+ displayHints.includes(DISPLAY_HINTS.CAPTION_STATUS_ACTIVE),
474
532
 
475
- MeetingUtil.endMeetingForAll = (meeting) => {
476
- if (meeting.meetingState === FULL_STATE.INACTIVE) {
477
- return Promise.reject(new MeetingNotActiveError());
478
- }
533
+ isWebexAssistantActive: (displayHints) =>
534
+ displayHints.includes(DISPLAY_HINTS.WEBEX_ASSISTANT_STATUS_ACTIVE),
479
535
 
480
- const endOptions = {
481
- locusUrl: meeting.locusUrl,
482
- };
536
+ canViewCaptionPanel: (displayHints) => displayHints.includes(DISPLAY_HINTS.ENABLE_CAPTION_PANEL),
483
537
 
484
- return meeting.meetingRequest
485
- .endMeetingForAll(endOptions)
486
- .then((response) => {
487
- if (response && response.body && response.body.locus) {
488
- meeting.locusInfo.onFullLocus(response.body.locus);
538
+ isRealTimeTranslationEnabled: (displayHints) =>
539
+ displayHints.includes(DISPLAY_HINTS.DISPLAY_REAL_TIME_TRANSLATION),
540
+
541
+ canSelectSpokenLanguages: (displayHints) =>
542
+ displayHints.includes(DISPLAY_HINTS.DISPLAY_NON_ENGLISH_ASR),
543
+
544
+ waitingForOthersToJoin: (displayHints) => displayHints.includes(DISPLAY_HINTS.WAITING_FOR_OTHERS),
545
+
546
+ canSendReactions: (originalValue, displayHints) => {
547
+ if (displayHints.includes(DISPLAY_HINTS.REACTIONS_ACTIVE)) {
548
+ return true;
549
+ }
550
+ if (displayHints.includes(DISPLAY_HINTS.REACTIONS_INACTIVE)) {
551
+ return false;
552
+ }
553
+
554
+ return originalValue;
555
+ },
556
+ canUserRenameSelfAndObserved: (displayHints) =>
557
+ displayHints.includes(DISPLAY_HINTS.CAN_RENAME_SELF_AND_OBSERVED),
558
+
559
+ canUserRenameOthers: (displayHints) => displayHints.includes(DISPLAY_HINTS.CAN_RENAME_OTHERS),
560
+
561
+ canShareWhiteBoard: (displayHints) => displayHints.includes(DISPLAY_HINTS.SHARE_WHITEBOARD),
562
+
563
+ /**
564
+ * Adds the current locus sequence information to a request body
565
+ * @param {Object} meeting The meeting object
566
+ * @param {Object} requestBody The body of a request to locus
567
+ * @returns {void}
568
+ */
569
+ addSequence: (meeting, requestBody) => {
570
+ const sequence = meeting?.locusInfo?.sequence;
571
+
572
+ if (!sequence) {
573
+ return;
574
+ }
575
+
576
+ requestBody.sequence = sequence;
577
+ },
578
+
579
+ /**
580
+ * Updates the locus info for the meeting with the delta locus
581
+ * returned from requests that include the sequence information
582
+ * Returns the original response object
583
+ * @param {Object} meeting The meeting object
584
+ * @param {Object} response The response of the http request
585
+ * @returns {Object}
586
+ */
587
+ updateLocusWithDelta: (meeting, response) => {
588
+ if (!meeting) {
589
+ return response;
590
+ }
591
+
592
+ const locus = response?.body?.locus;
593
+
594
+ if (locus) {
595
+ meeting.locusInfo.handleLocusDelta(locus, meeting);
596
+ }
597
+
598
+ return response;
599
+ },
600
+
601
+ generateBuildLocusDeltaRequestOptions: (originalMeeting) => {
602
+ const meetingRef = new WeakRef(originalMeeting);
603
+
604
+ const buildLocusDeltaRequestOptions = (originalOptions) => {
605
+ const meeting = meetingRef.deref();
606
+
607
+ if (!meeting) {
608
+ return originalOptions;
489
609
  }
490
610
 
491
- return Promise.resolve();
492
- })
493
- .then(() => MeetingUtil.cleanUp(meeting))
494
- .catch((err) => {
495
- LoggerProxy.logger.error(
496
- `Meeting:util#endMeetingForAll An error occured while trying to end meeting for all with an id of ${meeting.id}, error: ${err}`
497
- );
611
+ const options = cloneDeep(originalOptions);
498
612
 
499
- return Promise.reject(err);
500
- });
501
- };
613
+ if (!options.body) {
614
+ options.body = {};
615
+ }
616
+
617
+ MeetingUtil.addSequence(meeting, options.body);
502
618
 
503
- MeetingUtil.canEnableClosedCaption = (displayHints) =>
504
- displayHints.includes(DISPLAY_HINTS.CAPTION_START);
619
+ return options;
620
+ };
505
621
 
506
- MeetingUtil.canStartTranscribing = (displayHints) =>
507
- displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_START);
622
+ return buildLocusDeltaRequestOptions;
623
+ },
624
+
625
+ generateLocusDeltaRequest: (originalMeeting) => {
626
+ const meetingRef = new WeakRef(originalMeeting);
627
+
628
+ const buildLocusDeltaRequestOptions =
629
+ MeetingUtil.generateBuildLocusDeltaRequestOptions(originalMeeting);
630
+
631
+ const locusDeltaRequest = (originalOptions) => {
632
+ const meeting = meetingRef.deref();
633
+
634
+ if (!meeting) {
635
+ return Promise.resolve();
636
+ }
508
637
 
509
- MeetingUtil.canStopTranscribing = (displayHints) =>
510
- displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_STOP);
638
+ const options = buildLocusDeltaRequestOptions(originalOptions);
511
639
 
512
- MeetingUtil.isClosedCaptionActive = (displayHints) =>
513
- displayHints.includes(DISPLAY_HINTS.CAPTION_STATUS_ACTIVE);
640
+ return meeting
641
+ .request(options)
642
+ .then((response) => MeetingUtil.updateLocusWithDelta(meeting, response));
643
+ };
514
644
 
515
- MeetingUtil.isWebexAssistantActive = (displayHints) =>
516
- displayHints.includes(DISPLAY_HINTS.WEBEX_ASSISTANT_STATUS_ACTIVE);
645
+ return locusDeltaRequest;
646
+ },
517
647
 
518
- MeetingUtil.canViewCaptionPanel = (displayHints) =>
519
- displayHints.includes(DISPLAY_HINTS.ENABLE_CAPTION_PANEL);
648
+ selfSupportsFeature: (feature: SELF_POLICY, userPolicies: Record<SELF_POLICY, boolean>) => {
649
+ if (!userPolicies) {
650
+ return true;
651
+ }
520
652
 
521
- MeetingUtil.isRealTimeTranslationEnabled = (displayHints) =>
522
- displayHints.includes(DISPLAY_HINTS.DISPLAY_REAL_TIME_TRANSLATION);
653
+ return userPolicies[feature];
654
+ },
523
655
 
524
- MeetingUtil.canSelectSpokenLanguages = (displayHints) =>
525
- displayHints.includes(DISPLAY_HINTS.DISPLAY_NON_ENGLISH_ASR);
656
+ parseInterpretationInfo: (meeting, meetingInfo) => {
657
+ if (!meeting || !meetingInfo) {
658
+ return;
659
+ }
660
+ const siInfo = meetingInfo.simultaneousInterpretation;
661
+ meeting.simultaneousInterpretation.updateMeetingSIEnabled(
662
+ !!meetingInfo.turnOnSimultaneousInterpretation,
663
+ !!siInfo?.currentSIInterpreter
664
+ );
665
+ const hostSIEnabled = !!(
666
+ meetingInfo.turnOnSimultaneousInterpretation &&
667
+ meetingInfo?.meetingSiteSetting?.enableHostInterpreterControlSI
668
+ );
669
+ meeting.simultaneousInterpretation.updateHostSIEnabled(hostSIEnabled);
526
670
 
527
- MeetingUtil.waitingForOthersToJoin = (displayHints) =>
528
- displayHints.includes(DISPLAY_HINTS.WAITING_FOR_OTHERS);
671
+ function renameKey(obj, oldKey, newKey) {
672
+ if (oldKey in obj) {
673
+ obj[newKey] = obj[oldKey];
674
+ delete obj[oldKey];
675
+ }
676
+ }
677
+ if (siInfo) {
678
+ const lanuagesInfo = cloneDeep(siInfo.siLanguages);
679
+ for (const language of lanuagesInfo) {
680
+ renameKey(language, 'languageCode', 'languageName');
681
+ renameKey(language, 'languageGroupId', 'languageCode');
682
+ }
683
+ if (!meeting.simultaneousInterpretation?.siLanguages?.length) {
684
+ meeting.simultaneousInterpretation.updateInterpretation({siLanguages: lanuagesInfo});
685
+ }
686
+ }
687
+ Trigger.trigger(
688
+ meeting,
689
+ {
690
+ file: 'meeting/util',
691
+ function: 'parseInterpretationInfo',
692
+ },
693
+ EVENT_TRIGGERS.MEETING_INTERPRETATION_UPDATE
694
+ );
695
+ },
696
+
697
+ /**
698
+ * Returns a CA-recognized error payload for the specified raw error message/reason.
699
+ *
700
+ * New errors can be added to this function for handling in the future
701
+ *
702
+ * @param {String} reason the raw error message
703
+ * @returns {Array<object>} an array of payload objects
704
+ */
705
+ getChangeMeetingFloorErrorPayload: (reason: string) => {
706
+ const errorPayload = {
707
+ errorDescription: reason,
708
+ name: 'locus.response',
709
+ shownToUser: false,
710
+ };
711
+ if (reason.includes(LOCAL_SHARE_ERRORS.UNDEFINED)) {
712
+ return [
713
+ {
714
+ ...errorPayload,
715
+ fatal: true,
716
+ category: 'signaling',
717
+ errorCode: 1100,
718
+ },
719
+ ];
720
+ }
721
+ if (reason.includes(LOCAL_SHARE_ERRORS.DEVICE_NOT_JOINED)) {
722
+ return [
723
+ {
724
+ ...errorPayload,
725
+ fatal: true,
726
+ category: 'signaling',
727
+ errorCode: 4050,
728
+ },
729
+ ];
730
+ }
731
+ if (reason.includes(LOCAL_SHARE_ERRORS.NO_MEDIA_FOR_DEVICE)) {
732
+ return [
733
+ {
734
+ ...errorPayload,
735
+ fatal: true,
736
+ category: 'media',
737
+ errorCode: 2048,
738
+ },
739
+ ];
740
+ }
741
+ if (reason.includes(LOCAL_SHARE_ERRORS.NO_CONFLUENCE_ID)) {
742
+ return [
743
+ {
744
+ ...errorPayload,
745
+ fatal: true,
746
+ category: 'signaling',
747
+ errorCode: 4064,
748
+ },
749
+ ];
750
+ }
751
+ if (reason.includes(LOCAL_SHARE_ERRORS.CONTENT_SHARING_DISABLED)) {
752
+ return [
753
+ {
754
+ ...errorPayload,
755
+ fatal: true,
756
+ category: 'expected',
757
+ errorCode: 4065,
758
+ },
759
+ ];
760
+ }
761
+ if (reason.includes(LOCAL_SHARE_ERRORS.LOCUS_PARTICIPANT_DNE)) {
762
+ return [
763
+ {
764
+ ...errorPayload,
765
+ fatal: true,
766
+ category: 'signaling',
767
+ errorCode: 4066,
768
+ },
769
+ ];
770
+ }
771
+ if (reason.includes(LOCAL_SHARE_ERRORS.CONTENT_REQUEST_WHILE_PENDING_WHITEBOARD)) {
772
+ return [
773
+ {
774
+ ...errorPayload,
775
+ fatal: true,
776
+ category: 'expected',
777
+ errorCode: 4067,
778
+ },
779
+ ];
780
+ }
781
+
782
+ // return unknown error
783
+ return [
784
+ {
785
+ ...errorPayload,
786
+ fatal: true,
787
+ category: 'signaling',
788
+ errorCode: 1100,
789
+ },
790
+ ];
791
+ },
792
+ };
529
793
 
530
794
  export default MeetingUtil;