@webex/plugin-meetings 3.0.0-beta.17 → 3.0.0-beta.171

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 (427) hide show
  1. package/README.md +45 -7
  2. package/dist/annotation/annotation.types.js +7 -0
  3. package/dist/annotation/annotation.types.js.map +1 -0
  4. package/dist/annotation/constants.js +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +359 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +216 -0
  9. package/dist/breakouts/breakout.js.map +1 -0
  10. package/dist/breakouts/collection.js +23 -0
  11. package/dist/breakouts/collection.js.map +1 -0
  12. package/dist/breakouts/edit-lock-error.js +52 -0
  13. package/dist/breakouts/edit-lock-error.js.map +1 -0
  14. package/dist/breakouts/events.js +45 -0
  15. package/dist/breakouts/events.js.map +1 -0
  16. package/dist/breakouts/index.js +1048 -0
  17. package/dist/breakouts/index.js.map +1 -0
  18. package/dist/breakouts/request.js +78 -0
  19. package/dist/breakouts/request.js.map +1 -0
  20. package/dist/breakouts/utils.js +67 -0
  21. package/dist/breakouts/utils.js.map +1 -0
  22. package/dist/common/errors/webex-errors.js +3 -2
  23. package/dist/common/errors/webex-errors.js.map +1 -1
  24. package/dist/common/logs/logger-proxy.js +1 -1
  25. package/dist/common/logs/logger-proxy.js.map +1 -1
  26. package/dist/config.js +6 -8
  27. package/dist/config.js.map +1 -1
  28. package/dist/constants.js +194 -28
  29. package/dist/constants.js.map +1 -1
  30. package/dist/controls-options-manager/constants.js +14 -0
  31. package/dist/controls-options-manager/constants.js.map +1 -0
  32. package/dist/controls-options-manager/enums.js +27 -0
  33. package/dist/controls-options-manager/enums.js.map +1 -0
  34. package/dist/controls-options-manager/index.js +297 -0
  35. package/dist/controls-options-manager/index.js.map +1 -0
  36. package/dist/controls-options-manager/types.js +7 -0
  37. package/dist/controls-options-manager/types.js.map +1 -0
  38. package/dist/controls-options-manager/util.js +300 -0
  39. package/dist/controls-options-manager/util.js.map +1 -0
  40. package/dist/index.js +107 -0
  41. package/dist/index.js.map +1 -1
  42. package/dist/interpretation/collection.js +23 -0
  43. package/dist/interpretation/collection.js.map +1 -0
  44. package/dist/interpretation/index.js +214 -0
  45. package/dist/interpretation/index.js.map +1 -0
  46. package/dist/interpretation/siLanguage.js +25 -0
  47. package/dist/interpretation/siLanguage.js.map +1 -0
  48. package/dist/locus-info/controlsUtils.js +92 -2
  49. package/dist/locus-info/controlsUtils.js.map +1 -1
  50. package/dist/locus-info/index.js +350 -41
  51. package/dist/locus-info/index.js.map +1 -1
  52. package/dist/locus-info/mediaSharesUtils.js +43 -1
  53. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  54. package/dist/locus-info/parser.js +2 -1
  55. package/dist/locus-info/parser.js.map +1 -1
  56. package/dist/locus-info/selfUtils.js +97 -14
  57. package/dist/locus-info/selfUtils.js.map +1 -1
  58. package/dist/media/index.js +41 -136
  59. package/dist/media/index.js.map +1 -1
  60. package/dist/media/properties.js +33 -94
  61. package/dist/media/properties.js.map +1 -1
  62. package/dist/mediaQualityMetrics/config.js +505 -493
  63. package/dist/mediaQualityMetrics/config.js.map +1 -1
  64. package/dist/meeting/in-meeting-actions.js +76 -2
  65. package/dist/meeting/in-meeting-actions.js.map +1 -1
  66. package/dist/meeting/index.js +2757 -2439
  67. package/dist/meeting/index.js.map +1 -1
  68. package/dist/meeting/locusMediaRequest.js +291 -0
  69. package/dist/meeting/locusMediaRequest.js.map +1 -0
  70. package/dist/meeting/muteState.js +229 -124
  71. package/dist/meeting/muteState.js.map +1 -1
  72. package/dist/meeting/request.js +191 -167
  73. package/dist/meeting/request.js.map +1 -1
  74. package/dist/meeting/request.type.js.map +1 -1
  75. package/dist/meeting/util.js +477 -466
  76. package/dist/meeting/util.js.map +1 -1
  77. package/dist/meeting-info/index.js +48 -7
  78. package/dist/meeting-info/index.js.map +1 -1
  79. package/dist/meeting-info/meeting-info-v2.js +172 -50
  80. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  81. package/dist/meeting-info/utilv2.js +20 -5
  82. package/dist/meeting-info/utilv2.js.map +1 -1
  83. package/dist/meetings/collection.js +22 -0
  84. package/dist/meetings/collection.js.map +1 -1
  85. package/dist/meetings/index.js +377 -82
  86. package/dist/meetings/index.js.map +1 -1
  87. package/dist/meetings/meetings.types.js +7 -0
  88. package/dist/meetings/meetings.types.js.map +1 -0
  89. package/dist/meetings/request.js +16 -12
  90. package/dist/meetings/request.js.map +1 -1
  91. package/dist/meetings/util.js +88 -1
  92. package/dist/meetings/util.js.map +1 -1
  93. package/dist/member/index.js +43 -0
  94. package/dist/member/index.js.map +1 -1
  95. package/dist/member/types.js +15 -0
  96. package/dist/member/types.js.map +1 -0
  97. package/dist/member/util.js +97 -3
  98. package/dist/member/util.js.map +1 -1
  99. package/dist/members/collection.js +10 -0
  100. package/dist/members/collection.js.map +1 -1
  101. package/dist/members/index.js +94 -11
  102. package/dist/members/index.js.map +1 -1
  103. package/dist/members/request.js +109 -39
  104. package/dist/members/request.js.map +1 -1
  105. package/dist/members/types.js +15 -0
  106. package/dist/members/types.js.map +1 -0
  107. package/dist/members/util.js +316 -233
  108. package/dist/members/util.js.map +1 -1
  109. package/dist/metrics/constants.js +3 -5
  110. package/dist/metrics/constants.js.map +1 -1
  111. package/dist/metrics/index.js +1 -468
  112. package/dist/metrics/index.js.map +1 -1
  113. package/dist/multistream/mediaRequestManager.js +265 -36
  114. package/dist/multistream/mediaRequestManager.js.map +1 -1
  115. package/dist/multistream/receiveSlot.js +52 -19
  116. package/dist/multistream/receiveSlot.js.map +1 -1
  117. package/dist/multistream/receiveSlotManager.js +53 -33
  118. package/dist/multistream/receiveSlotManager.js.map +1 -1
  119. package/dist/multistream/remoteMedia.js +44 -18
  120. package/dist/multistream/remoteMedia.js.map +1 -1
  121. package/dist/multistream/remoteMediaGroup.js +60 -3
  122. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  123. package/dist/multistream/remoteMediaManager.js +322 -103
  124. package/dist/multistream/remoteMediaManager.js.map +1 -1
  125. package/dist/networkQualityMonitor/index.js +4 -2
  126. package/dist/networkQualityMonitor/index.js.map +1 -1
  127. package/dist/reachability/index.js +117 -60
  128. package/dist/reachability/index.js.map +1 -1
  129. package/dist/reachability/request.js +12 -5
  130. package/dist/reachability/request.js.map +1 -1
  131. package/dist/reactions/constants.js +13 -0
  132. package/dist/reactions/constants.js.map +1 -0
  133. package/dist/reactions/reactions.js +2 -2
  134. package/dist/reactions/reactions.js.map +1 -1
  135. package/dist/reactions/reactions.type.js +18 -18
  136. package/dist/reactions/reactions.type.js.map +1 -1
  137. package/dist/reconnection-manager/index.js +216 -162
  138. package/dist/reconnection-manager/index.js.map +1 -1
  139. package/dist/recording-controller/enums.js +17 -0
  140. package/dist/recording-controller/enums.js.map +1 -0
  141. package/dist/recording-controller/index.js +363 -0
  142. package/dist/recording-controller/index.js.map +1 -0
  143. package/dist/recording-controller/util.js +64 -0
  144. package/dist/recording-controller/util.js.map +1 -0
  145. package/dist/roap/index.js +21 -29
  146. package/dist/roap/index.js.map +1 -1
  147. package/dist/roap/request.js +135 -94
  148. package/dist/roap/request.js.map +1 -1
  149. package/dist/roap/turnDiscovery.js +135 -53
  150. package/dist/roap/turnDiscovery.js.map +1 -1
  151. package/dist/statsAnalyzer/global.js +1 -93
  152. package/dist/statsAnalyzer/global.js.map +1 -1
  153. package/dist/statsAnalyzer/index.js +329 -314
  154. package/dist/statsAnalyzer/index.js.map +1 -1
  155. package/dist/statsAnalyzer/mqaUtil.js +103 -54
  156. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  157. package/dist/types/annotation/annotation.types.d.ts +43 -0
  158. package/dist/types/annotation/constants.d.ts +31 -0
  159. package/dist/types/annotation/index.d.ts +124 -0
  160. package/dist/types/breakouts/breakout.d.ts +8 -0
  161. package/dist/types/breakouts/collection.d.ts +5 -0
  162. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  163. package/dist/types/breakouts/events.d.ts +8 -0
  164. package/dist/types/breakouts/index.d.ts +5 -0
  165. package/dist/types/breakouts/request.d.ts +22 -0
  166. package/dist/types/breakouts/utils.d.ts +15 -0
  167. package/dist/types/common/browser-detection.d.ts +9 -0
  168. package/dist/types/common/collection.d.ts +48 -0
  169. package/dist/types/common/config.d.ts +2 -0
  170. package/dist/types/common/errors/captcha-error.d.ts +15 -0
  171. package/dist/types/common/errors/intent-to-join.d.ts +16 -0
  172. package/dist/types/common/errors/join-meeting.d.ts +17 -0
  173. package/dist/types/common/errors/media.d.ts +15 -0
  174. package/dist/types/common/errors/parameter.d.ts +15 -0
  175. package/dist/types/common/errors/password-error.d.ts +15 -0
  176. package/dist/types/common/errors/permission.d.ts +14 -0
  177. package/dist/types/common/errors/reconnection-in-progress.d.ts +9 -0
  178. package/dist/types/common/errors/reconnection.d.ts +15 -0
  179. package/dist/types/common/errors/stats.d.ts +15 -0
  180. package/dist/types/common/errors/webex-errors.d.ts +69 -0
  181. package/dist/types/common/errors/webex-meetings-error.d.ts +20 -0
  182. package/dist/types/common/events/events-scope.d.ts +17 -0
  183. package/dist/types/common/events/events.d.ts +12 -0
  184. package/dist/types/common/events/trigger-proxy.d.ts +2 -0
  185. package/dist/types/common/events/util.d.ts +2 -0
  186. package/dist/types/common/logs/logger-config.d.ts +2 -0
  187. package/dist/types/common/logs/logger-proxy.d.ts +2 -0
  188. package/dist/types/common/logs/request.d.ts +34 -0
  189. package/dist/types/common/queue.d.ts +32 -0
  190. package/dist/types/config.d.ts +72 -0
  191. package/dist/types/constants.d.ts +1007 -0
  192. package/dist/types/controls-options-manager/constants.d.ts +4 -0
  193. package/dist/types/controls-options-manager/enums.d.ts +15 -0
  194. package/dist/types/controls-options-manager/index.d.ts +136 -0
  195. package/dist/types/controls-options-manager/types.d.ts +43 -0
  196. package/dist/types/controls-options-manager/util.d.ts +1 -0
  197. package/dist/types/index.d.ts +7 -0
  198. package/dist/types/interpretation/collection.d.ts +5 -0
  199. package/dist/types/interpretation/index.d.ts +5 -0
  200. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  201. package/dist/types/locus-info/controlsUtils.d.ts +2 -0
  202. package/dist/types/locus-info/embeddedAppsUtils.d.ts +2 -0
  203. package/dist/types/locus-info/fullState.d.ts +2 -0
  204. package/dist/types/locus-info/hostUtils.d.ts +2 -0
  205. package/dist/types/locus-info/index.d.ts +315 -0
  206. package/dist/types/locus-info/infoUtils.d.ts +2 -0
  207. package/dist/types/locus-info/mediaSharesUtils.d.ts +2 -0
  208. package/dist/types/locus-info/parser.d.ts +212 -0
  209. package/dist/types/locus-info/selfUtils.d.ts +2 -0
  210. package/dist/types/media/index.d.ts +34 -0
  211. package/dist/types/media/properties.d.ts +93 -0
  212. package/dist/types/media/util.d.ts +2 -0
  213. package/dist/types/mediaQualityMetrics/config.d.ts +365 -0
  214. package/dist/types/meeting/in-meeting-actions.d.ts +149 -0
  215. package/dist/types/meeting/index.d.ts +1462 -0
  216. package/dist/types/meeting/locusMediaRequest.d.ts +70 -0
  217. package/dist/types/meeting/muteState.d.ts +184 -0
  218. package/dist/types/meeting/request.d.ts +270 -0
  219. package/dist/types/meeting/request.type.d.ts +11 -0
  220. package/dist/types/meeting/state.d.ts +9 -0
  221. package/dist/types/meeting/util.d.ts +77 -0
  222. package/dist/types/meeting-info/collection.d.ts +20 -0
  223. package/dist/types/meeting-info/index.d.ts +62 -0
  224. package/dist/types/meeting-info/meeting-info-v2.d.ts +122 -0
  225. package/dist/types/meeting-info/request.d.ts +22 -0
  226. package/dist/types/meeting-info/util.d.ts +2 -0
  227. package/dist/types/meeting-info/utilv2.d.ts +2 -0
  228. package/dist/types/meetings/collection.d.ts +31 -0
  229. package/dist/types/meetings/index.d.ts +365 -0
  230. package/dist/types/meetings/meetings.types.d.ts +4 -0
  231. package/dist/types/meetings/request.d.ts +27 -0
  232. package/dist/types/meetings/util.d.ts +18 -0
  233. package/dist/types/member/index.d.ts +158 -0
  234. package/dist/types/member/types.d.ts +21 -0
  235. package/dist/types/member/util.d.ts +2 -0
  236. package/dist/types/members/collection.d.ts +29 -0
  237. package/dist/types/members/index.d.ts +353 -0
  238. package/dist/types/members/request.d.ts +114 -0
  239. package/dist/types/members/types.d.ts +24 -0
  240. package/dist/types/members/util.d.ts +210 -0
  241. package/dist/types/metrics/constants.d.ts +55 -0
  242. package/dist/types/metrics/index.d.ts +45 -0
  243. package/dist/types/multistream/mediaRequestManager.d.ts +118 -0
  244. package/dist/types/multistream/receiveSlot.d.ts +68 -0
  245. package/dist/types/multistream/receiveSlotManager.d.ts +56 -0
  246. package/dist/types/multistream/remoteMedia.d.ts +72 -0
  247. package/dist/types/multistream/remoteMediaGroup.d.ts +47 -0
  248. package/dist/types/multistream/remoteMediaManager.d.ts +277 -0
  249. package/dist/types/networkQualityMonitor/index.d.ts +70 -0
  250. package/dist/types/personal-meeting-room/index.d.ts +47 -0
  251. package/dist/types/personal-meeting-room/request.d.ts +14 -0
  252. package/dist/types/personal-meeting-room/util.d.ts +2 -0
  253. package/dist/types/reachability/index.d.ts +152 -0
  254. package/dist/types/reachability/request.d.ts +37 -0
  255. package/dist/types/reactions/constants.d.ts +3 -0
  256. package/dist/types/reactions/reactions.d.ts +4 -0
  257. package/dist/types/reactions/reactions.type.d.ts +52 -0
  258. package/dist/types/reconnection-manager/index.d.ts +126 -0
  259. package/dist/types/recording-controller/enums.d.ts +7 -0
  260. package/dist/types/recording-controller/index.d.ts +208 -0
  261. package/dist/types/recording-controller/util.d.ts +14 -0
  262. package/dist/types/roap/index.d.ts +77 -0
  263. package/dist/types/roap/request.d.ts +36 -0
  264. package/dist/types/roap/turnDiscovery.d.ts +91 -0
  265. package/dist/types/statsAnalyzer/global.d.ts +36 -0
  266. package/dist/types/statsAnalyzer/index.d.ts +200 -0
  267. package/dist/types/statsAnalyzer/mqaUtil.d.ts +24 -0
  268. package/dist/types/transcription/index.d.ts +64 -0
  269. package/package.json +29 -21
  270. package/src/annotation/annotation.types.ts +52 -0
  271. package/src/annotation/constants.ts +36 -0
  272. package/src/annotation/index.ts +343 -0
  273. package/src/breakouts/README.md +220 -0
  274. package/src/breakouts/breakout.ts +188 -0
  275. package/src/breakouts/collection.ts +19 -0
  276. package/src/breakouts/edit-lock-error.ts +25 -0
  277. package/src/breakouts/events.ts +56 -0
  278. package/src/breakouts/index.ts +925 -0
  279. package/src/breakouts/request.ts +55 -0
  280. package/src/breakouts/utils.ts +57 -0
  281. package/src/common/errors/webex-errors.ts +6 -2
  282. package/src/common/logs/logger-proxy.ts +1 -1
  283. package/src/config.ts +5 -7
  284. package/src/constants.ts +183 -22
  285. package/src/controls-options-manager/constants.ts +5 -0
  286. package/src/controls-options-manager/enums.ts +18 -0
  287. package/src/controls-options-manager/index.ts +278 -0
  288. package/src/controls-options-manager/types.ts +59 -0
  289. package/src/controls-options-manager/util.ts +286 -0
  290. package/src/index.ts +39 -0
  291. package/src/interpretation/README.md +51 -0
  292. package/src/interpretation/collection.ts +19 -0
  293. package/src/interpretation/index.ts +182 -0
  294. package/src/interpretation/siLanguage.ts +18 -0
  295. package/src/locus-info/controlsUtils.ts +110 -0
  296. package/src/locus-info/index.ts +374 -38
  297. package/src/locus-info/mediaSharesUtils.ts +48 -0
  298. package/src/locus-info/parser.ts +2 -1
  299. package/src/locus-info/selfUtils.ts +86 -2
  300. package/src/media/index.ts +78 -144
  301. package/src/media/properties.ts +55 -99
  302. package/src/mediaQualityMetrics/config.ts +379 -377
  303. package/src/meeting/in-meeting-actions.ts +151 -3
  304. package/src/meeting/index.ts +2181 -2052
  305. package/src/meeting/locusMediaRequest.ts +309 -0
  306. package/src/meeting/muteState.ts +228 -132
  307. package/src/meeting/request.ts +100 -91
  308. package/src/meeting/request.type.ts +2 -0
  309. package/src/meeting/util.ts +450 -439
  310. package/src/meeting-info/index.ts +54 -8
  311. package/src/meeting-info/meeting-info-v2.ts +150 -14
  312. package/src/meeting-info/utilv2.ts +13 -3
  313. package/src/meetings/collection.ts +20 -0
  314. package/src/meetings/index.ts +396 -89
  315. package/src/meetings/meetings.types.ts +12 -0
  316. package/src/meetings/request.ts +3 -1
  317. package/src/meetings/util.ts +103 -4
  318. package/src/member/index.ts +42 -0
  319. package/src/member/types.ts +24 -0
  320. package/src/member/util.ts +95 -1
  321. package/src/members/collection.ts +8 -0
  322. package/src/members/index.ts +108 -6
  323. package/src/members/request.ts +98 -17
  324. package/src/members/types.ts +28 -0
  325. package/src/members/util.ts +319 -240
  326. package/src/metrics/constants.ts +2 -4
  327. package/src/metrics/index.ts +1 -490
  328. package/src/multistream/mediaRequestManager.ts +337 -63
  329. package/src/multistream/receiveSlot.ts +68 -26
  330. package/src/multistream/receiveSlotManager.ts +61 -38
  331. package/src/multistream/remoteMedia.ts +29 -3
  332. package/src/multistream/remoteMediaGroup.ts +61 -2
  333. package/src/multistream/remoteMediaManager.ts +260 -66
  334. package/src/networkQualityMonitor/index.ts +6 -6
  335. package/src/reachability/index.ts +75 -25
  336. package/src/reachability/request.ts +10 -5
  337. package/src/reactions/constants.ts +4 -0
  338. package/src/reactions/reactions.ts +4 -4
  339. package/src/reactions/reactions.type.ts +28 -3
  340. package/src/reconnection-manager/index.ts +83 -49
  341. package/src/recording-controller/enums.ts +8 -0
  342. package/src/recording-controller/index.ts +333 -0
  343. package/src/recording-controller/util.ts +75 -0
  344. package/src/roap/index.ts +21 -30
  345. package/src/roap/request.ts +72 -61
  346. package/src/roap/turnDiscovery.ts +51 -27
  347. package/src/statsAnalyzer/global.ts +1 -94
  348. package/src/statsAnalyzer/index.ts +380 -390
  349. package/src/statsAnalyzer/mqaUtil.ts +106 -99
  350. package/test/integration/spec/converged-space-meetings.js +233 -0
  351. package/test/integration/spec/journey.js +336 -259
  352. package/test/integration/spec/space-meeting.js +77 -4
  353. package/test/unit/spec/annotation/index.ts +436 -0
  354. package/test/unit/spec/breakouts/breakout.ts +237 -0
  355. package/test/unit/spec/breakouts/collection.ts +15 -0
  356. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  357. package/test/unit/spec/breakouts/events.ts +89 -0
  358. package/test/unit/spec/breakouts/index.ts +1790 -0
  359. package/test/unit/spec/breakouts/request.ts +104 -0
  360. package/test/unit/spec/breakouts/utils.js +72 -0
  361. package/test/unit/spec/controls-options-manager/index.js +287 -0
  362. package/test/unit/spec/controls-options-manager/util.js +518 -0
  363. package/test/unit/spec/fixture/locus.js +1 -0
  364. package/test/unit/spec/interpretation/collection.ts +15 -0
  365. package/test/unit/spec/interpretation/index.ts +329 -0
  366. package/test/unit/spec/interpretation/siLanguage.ts +26 -0
  367. package/test/unit/spec/locus-info/controlsUtils.js +323 -30
  368. package/test/unit/spec/locus-info/index.js +792 -4
  369. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  370. package/test/unit/spec/locus-info/selfConstant.js +48 -0
  371. package/test/unit/spec/locus-info/selfUtils.js +275 -0
  372. package/test/unit/spec/media/index.ts +130 -24
  373. package/test/unit/spec/media/properties.ts +9 -9
  374. package/test/unit/spec/meeting/in-meeting-actions.ts +75 -3
  375. package/test/unit/spec/meeting/index.js +2834 -1442
  376. package/test/unit/spec/meeting/locusMediaRequest.ts +436 -0
  377. package/test/unit/spec/meeting/muteState.js +370 -208
  378. package/test/unit/spec/meeting/request.js +354 -42
  379. package/test/unit/spec/meeting/utils.js +384 -170
  380. package/test/unit/spec/meeting-info/index.js +181 -0
  381. package/test/unit/spec/meeting-info/meetinginfov2.js +383 -5
  382. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  383. package/test/unit/spec/meetings/collection.js +14 -0
  384. package/test/unit/spec/meetings/index.js +847 -121
  385. package/test/unit/spec/meetings/utils.js +206 -2
  386. package/test/unit/spec/member/index.js +31 -0
  387. package/test/unit/spec/member/util.js +408 -32
  388. package/test/unit/spec/members/index.js +320 -1
  389. package/test/unit/spec/members/request.js +206 -27
  390. package/test/unit/spec/members/utils.js +184 -0
  391. package/test/unit/spec/metrics/index.js +1 -50
  392. package/test/unit/spec/multistream/mediaRequestManager.ts +1012 -109
  393. package/test/unit/spec/multistream/receiveSlot.ts +77 -18
  394. package/test/unit/spec/multistream/receiveSlotManager.ts +69 -39
  395. package/test/unit/spec/multistream/remoteMedia.ts +32 -2
  396. package/test/unit/spec/multistream/remoteMediaGroup.ts +271 -5
  397. package/test/unit/spec/multistream/remoteMediaManager.ts +672 -65
  398. package/test/unit/spec/networkQualityMonitor/index.js +4 -4
  399. package/test/unit/spec/reachability/index.ts +176 -25
  400. package/test/unit/spec/reachability/request.js +66 -0
  401. package/test/unit/spec/reconnection-manager/index.js +95 -13
  402. package/test/unit/spec/recording-controller/index.js +307 -0
  403. package/test/unit/spec/recording-controller/util.js +229 -0
  404. package/test/unit/spec/roap/index.ts +28 -52
  405. package/test/unit/spec/roap/request.ts +225 -0
  406. package/test/unit/spec/roap/turnDiscovery.ts +73 -34
  407. package/test/unit/spec/stats-analyzer/index.js +94 -43
  408. package/test/utils/constants.js +9 -0
  409. package/test/utils/integrationTestUtils.js +46 -0
  410. package/test/utils/testUtils.js +0 -45
  411. package/test/utils/webex-config.js +4 -0
  412. package/test/utils/webex-test-users.js +7 -3
  413. package/tsconfig.json +6 -0
  414. package/dist/media/internal-media-core-wrapper.js +0 -18
  415. package/dist/media/internal-media-core-wrapper.js.map +0 -1
  416. package/dist/meeting/effectsState.js +0 -262
  417. package/dist/meeting/effectsState.js.map +0 -1
  418. package/dist/metrics/config.js +0 -299
  419. package/dist/metrics/config.js.map +0 -1
  420. package/dist/multistream/multistreamMedia.js +0 -106
  421. package/dist/multistream/multistreamMedia.js.map +0 -1
  422. package/src/index.js +0 -15
  423. package/src/media/internal-media-core-wrapper.ts +0 -9
  424. package/src/meeting/effectsState.ts +0 -211
  425. package/src/metrics/config.ts +0 -495
  426. package/src/multistream/multistreamMedia.ts +0 -93
  427. package/test/unit/spec/meeting/effectsState.js +0 -281
@@ -1,9 +1,6 @@
1
- import {isEmpty} from 'lodash';
2
-
1
+ import {LocalCameraTrack, LocalMicrophoneTrack} from '@webex/media-helpers';
2
+ import {cloneDeep} from 'lodash';
3
3
  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
4
  import LoggerProxy from '../common/logs/logger-proxy';
8
5
  import {
9
6
  INTENT_TO_JOIN,
@@ -13,6 +10,7 @@ import {
13
10
  PASSWORD_STATUS,
14
11
  DISPLAY_HINTS,
15
12
  FULL_STATE,
13
+ SELF_POLICY,
16
14
  } from '../constants';
17
15
  import IntentToJoinError from '../common/errors/intent-to-join';
18
16
  import JoinMeetingError from '../common/errors/join-meeting';
@@ -21,540 +19,553 @@ import PermissionError from '../common/errors/permission';
21
19
  import PasswordError from '../common/errors/password-error';
22
20
  import CaptchaError from '../common/errors/captcha-error';
23
21
 
24
- const MeetingUtil: any = {};
25
-
26
- MeetingUtil.parseLocusJoin = (response) => {
27
- const parsed: any = {};
22
+ const MeetingUtil = {
23
+ parseLocusJoin: (response) => {
24
+ const parsed: any = {};
25
+
26
+ // First todo: add check for existance
27
+ parsed.locus = response.body.locus;
28
+ parsed.mediaConnections = response.body.mediaConnections;
29
+ parsed.locusUrl = parsed.locus.url;
30
+ parsed.locusId = parsed.locus.url.split('/').pop();
31
+ parsed.selfId = parsed.locus.self.id;
32
+
33
+ // we need mediaId before making roap calls
34
+ parsed.mediaConnections.forEach((mediaConnection) => {
35
+ if (mediaConnection.mediaId) {
36
+ parsed.mediaId = mediaConnection.mediaId;
37
+ }
38
+ });
28
39
 
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;
40
+ return parsed;
41
+ },
35
42
 
36
- // we need mediaId before making roap calls
37
- parsed.mediaConnections.forEach((mediaConnection) => {
38
- if (mediaConnection.mediaId) {
39
- parsed.mediaId = mediaConnection.mediaId;
43
+ remoteUpdateAudioVideo: (meeting, audioMuted?: boolean, videoMuted?: boolean) => {
44
+ const webex = meeting.getWebexObject();
45
+ if (!meeting) {
46
+ return Promise.reject(new ParameterError('You need a meeting object.'));
40
47
  }
41
- });
42
48
 
43
- return parsed;
44
- };
49
+ if (!meeting.locusMediaRequest) {
50
+ return Promise.reject(
51
+ new ParameterError(
52
+ 'You need a meeting with a media connection, call Meeting.addMedia() first.'
53
+ )
54
+ );
55
+ }
45
56
 
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);
57
+ // @ts-ignore
58
+ webex.internal.newMetrics.submitClientEvent({
59
+ name: 'client.locus.media.request',
60
+ options: {meetingId: meeting.id},
61
+ });
51
62
 
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
- }
63
+ return meeting.locusMediaRequest
64
+ .send({
65
+ type: 'LocalMute',
66
+ selfUrl: meeting.selfUrl,
67
+ mediaId: meeting.mediaId,
68
+ sequence: meeting.locusInfo.sequence,
69
+ muteOptions: {
70
+ audioMuted,
71
+ videoMuted,
72
+ },
73
+ })
74
+ .then((response) => {
75
+ // @ts-ignore
76
+ webex.internal.newMetrics.submitClientEvent({
77
+ name: 'client.locus.media.response',
78
+ options: {meetingId: meeting.id},
79
+ });
57
80
 
58
- Metrics.postEvent({event: eventType.MEDIA_REQUEST, meeting});
81
+ return response?.body?.locus;
82
+ });
83
+ },
59
84
 
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
- preferTranscoding: !meeting.isMultistream,
68
- })
69
- .then((response) => {
70
- Metrics.postEvent({event: eventType.MEDIA_RESPONSE, meeting});
85
+ hasOwner: (info) => info && info.owner,
71
86
 
72
- return response.body.locus;
73
- });
74
- };
87
+ isOwnerSelf: (owner, selfId) => owner === selfId,
75
88
 
76
- MeetingUtil.hasOwner = (info) => info && info.owner;
89
+ isPinOrGuest: (err) => err?.body?.errorCode && INTENT_TO_JOIN.includes(err.body.errorCode),
77
90
 
78
- MeetingUtil.isOwnerSelf = (owner, selfId) => owner === selfId;
91
+ joinMeeting: (meeting, options) => {
92
+ if (!meeting) {
93
+ return Promise.reject(new ParameterError('You need a meeting object.'));
94
+ }
95
+ const webex = meeting.getWebexObject();
79
96
 
80
- MeetingUtil.isPinOrGuest = (err) =>
81
- err?.body?.errorCode && INTENT_TO_JOIN.includes(err.body.errorCode);
97
+ // @ts-ignore
98
+ webex.internal.newMetrics.submitClientEvent({
99
+ name: 'client.locus.join.request',
100
+ options: {meetingId: meeting.id},
101
+ });
82
102
 
83
- MeetingUtil.joinMeeting = (meeting, options) => {
84
- if (!meeting) {
85
- return Promise.reject(new ParameterError('You need a meeting object.'));
86
- }
103
+ // eslint-disable-next-line no-warning-comments
104
+ // TODO: check if the meeting is in JOINING state
105
+ // if Joining state termintate the request as user might click multiple times
106
+ return meeting.meetingRequest
107
+ .joinMeeting({
108
+ inviteeAddress: meeting.meetingJoinUrl || meeting.sipUri,
109
+ meetingNumber: meeting.meetingNumber,
110
+ deviceUrl: meeting.deviceUrl,
111
+ locusUrl: meeting.locusUrl,
112
+ correlationId: meeting.correlationId,
113
+ roapMessage: options.roapMessage,
114
+ permissionToken: meeting.permissionToken,
115
+ resourceId: options.resourceId || null,
116
+ moderator: options.moderator,
117
+ pin: options.pin,
118
+ moveToResource: options.moveToResource,
119
+ preferTranscoding: !meeting.isMultistream,
120
+ asResourceOccupant: options.asResourceOccupant,
121
+ breakoutsSupported: options.breakoutsSupported,
122
+ locale: options.locale,
123
+ deviceCapabilities: options.deviceCapabilities,
124
+ liveAnnotationSupported: options.liveAnnotationSupported,
125
+ })
126
+ .then((res) => {
127
+ // @ts-ignore
128
+ webex.internal.newMetrics.submitClientEvent({
129
+ name: 'client.locus.join.response',
130
+ payload: {
131
+ trigger: 'loci-update',
132
+ identifiers: {
133
+ trackingId: res.headers.trackingid,
134
+ },
135
+ },
136
+ options: {
137
+ meetingId: meeting.id,
138
+ mediaConnections: res.body.mediaConnections,
139
+ },
140
+ });
87
141
 
88
- Metrics.postEvent({event: eventType.LOCUS_JOIN_REQUEST, meeting});
142
+ return MeetingUtil.parseLocusJoin(res);
143
+ });
144
+ },
145
+
146
+ cleanUp: (meeting) => {
147
+ meeting.breakouts.cleanUp();
148
+ meeting.simultaneousInterpretation.cleanUp();
149
+
150
+ // make sure we send last metrics before we close the peerconnection
151
+ const stopStatsAnalyzer = meeting.statsAnalyzer
152
+ ? meeting.statsAnalyzer.stopAnalyzer()
153
+ : Promise.resolve();
154
+
155
+ return stopStatsAnalyzer
156
+ .then(() => meeting.closeRemoteTracks())
157
+ .then(() => meeting.closePeerConnections())
158
+ .then(() => {
159
+ meeting.cleanupLocalTracks();
160
+ meeting.unsetRemoteTracks();
161
+ meeting.unsetPeerConnections();
162
+ meeting.reconnectionManager.cleanUp();
163
+ })
164
+ .then(() => meeting.stopKeepAlive())
165
+ .then(() => meeting.updateLLMConnection());
166
+ },
167
+
168
+ disconnectPhoneAudio: (meeting, phoneUrl) => {
169
+ if (meeting.meetingState === FULL_STATE.INACTIVE) {
170
+ return Promise.reject(new MeetingNotActiveError());
171
+ }
89
172
 
90
- // eslint-disable-next-line no-warning-comments
91
- // TODO: check if the meeting is in JOINING state
92
- // if Joining state termintate the request as user might click multiple times
93
- return meeting.meetingRequest
94
- .joinMeeting({
95
- inviteeAddress: meeting.meetingJoinUrl || meeting.sipUri,
96
- meetingNumber: meeting.meetingNumber,
97
- deviceUrl: meeting.deviceUrl,
173
+ const options = {
98
174
  locusUrl: meeting.locusUrl,
175
+ selfId: meeting.selfId,
99
176
  correlationId: meeting.correlationId,
100
- roapMessage: options.roapMessage,
101
- permissionToken: meeting.permissionToken,
102
- resourceId: options.resourceId || null,
103
- moderator: options.moderator,
104
- pin: options.pin,
105
- moveToResource: options.moveToResource,
106
- preferTranscoding: !meeting.isMultistream,
107
- asResourceOccupant: options.asResourceOccupant,
108
- })
109
- .then((res) => {
110
- Metrics.postEvent({
111
- event: eventType.LOCUS_JOIN_RESPONSE,
112
- meeting,
113
- data: {
114
- trigger: trigger.LOCI_UPDATE,
115
- locus: res.body.locus,
116
- mediaConnections: res.body.mediaConnections,
117
- trackingId: res.headers.trackingid,
118
- },
119
- });
177
+ phoneUrl,
178
+ };
120
179
 
121
- return MeetingUtil.parseLocusJoin(res);
122
- });
123
- };
124
-
125
- MeetingUtil.cleanUp = (meeting) => {
126
- // make sure we send last metrics before we close the peerconnection
127
- const stopStatsAnalyzer = meeting.statsAnalyzer
128
- ? meeting.statsAnalyzer.stopAnalyzer()
129
- : Promise.resolve();
130
-
131
- return stopStatsAnalyzer
132
- .then(() => meeting.closeLocalStream())
133
- .then(() => meeting.closeLocalShare())
134
- .then(() => meeting.closeRemoteTracks())
135
- .then(() => meeting.closePeerConnections())
136
- .then(() => {
137
- meeting.unsetLocalVideoTrack();
138
- meeting.unsetLocalShareTrack();
139
- meeting.unsetRemoteTracks();
140
- meeting.unsetPeerConnections();
141
- meeting.reconnectionManager.cleanUp();
142
- })
143
- .then(() => meeting.stopKeepAlive())
144
- .then(() => meeting.updateLLMConnection());
145
- };
146
-
147
- MeetingUtil.disconnectPhoneAudio = (meeting, phoneUrl) => {
148
- if (meeting.meetingState === FULL_STATE.INACTIVE) {
149
- return Promise.reject(new MeetingNotActiveError());
150
- }
151
-
152
- const options = {
153
- locusUrl: meeting.locusUrl,
154
- selfId: meeting.selfId,
155
- correlationId: meeting.correlationId,
156
- phoneUrl,
157
- };
158
-
159
- return meeting.meetingRequest
160
- .disconnectPhoneAudio(options)
161
- .then((response) => {
162
- if (response?.body?.locus) {
163
- meeting.locusInfo.onFullLocus(response.body.locus);
164
- }
165
- })
166
- .catch((err) => {
180
+ return meeting.meetingRequest.disconnectPhoneAudio(options).catch((err) => {
167
181
  LoggerProxy.logger.error(
168
182
  `Meeting:util#disconnectPhoneAudio --> An error occured while disconnecting phone audio in meeting ${meeting.id}, error: ${err}`
169
183
  );
170
184
 
171
185
  return Promise.reject(err);
172
186
  });
173
- };
187
+ },
188
+
189
+ // by default will leave on meeting's resourceId
190
+ // if you explicity want it not to leave on resource id, pass
191
+ // {resourceId: null}
192
+ // TODO: chris, you can modify this however you want
193
+ leaveMeeting: (meeting, options: any = {}) => {
194
+ if (meeting.meetingState === FULL_STATE.INACTIVE) {
195
+ // TODO: clean up if the meeting is already inactive
196
+ return Promise.reject(new MeetingNotActiveError());
197
+ }
174
198
 
175
- // by default will leave on meeting's resourceId
176
- // if you explicity want it not to leave on resource id, pass
177
- // {resourceId: null}
178
- // TODO: chris, you can modify this however you want
179
- MeetingUtil.leaveMeeting = (meeting, options: any = {}) => {
180
- if (meeting.meetingState === FULL_STATE.INACTIVE) {
181
- // TODO: clean up if the meeting is already inactive
182
- return Promise.reject(new MeetingNotActiveError());
183
- }
184
-
185
- if (MeetingUtil.isUserInLeftState(meeting.locusInfo)) {
186
- return Promise.reject(new UserNotJoinedError());
187
- }
188
-
189
- const defaultOptions = {
190
- locusUrl: meeting.locusUrl,
191
- selfId: meeting.selfId,
192
- correlationId: meeting.correlationId,
193
- resourceId: meeting.resourceId,
194
- deviceUrl: meeting.deviceUrl,
195
- };
196
-
197
- const leaveOptions = {...defaultOptions, ...options};
198
-
199
- return meeting.meetingRequest
200
- .leaveMeeting(leaveOptions)
201
- .then((response) => {
202
- if (response && response.body && response.body.locus) {
203
- // && !options.moveMeeting) {
204
- meeting.locusInfo.onFullLocus(response.body.locus);
205
- }
199
+ if (MeetingUtil.isUserInLeftState(meeting.locusInfo)) {
200
+ return Promise.reject(new UserNotJoinedError());
201
+ }
206
202
 
207
- return Promise.resolve();
208
- })
209
- .then(() => {
210
- if (options.moveMeeting) {
211
- return Promise.resolve();
212
- }
203
+ const defaultOptions = {
204
+ locusUrl: meeting.locusUrl,
205
+ selfId: meeting.selfId,
206
+ correlationId: meeting.correlationId,
207
+ resourceId: meeting.resourceId,
208
+ deviceUrl: meeting.deviceUrl,
209
+ };
210
+
211
+ const leaveOptions = {...defaultOptions, ...options};
212
+
213
+ return meeting.meetingRequest
214
+ .leaveMeeting(leaveOptions)
215
+ .then(() => {
216
+ if (options.moveMeeting) {
217
+ return Promise.resolve();
218
+ }
219
+
220
+ return MeetingUtil.cleanUp(meeting);
221
+ })
222
+ .catch((err) => {
223
+ // TODO: If the meeting state comes as LEFT or INACTIVE as response then
224
+ // 1) on leave clean up the meeting or simply do a sync on the meeting
225
+ // 2) If the error says meeting is inactive then destroy the meeting object
226
+ LoggerProxy.logger.error(
227
+ `Meeting:util#leaveMeeting --> An error occured while trying to leave meeting with an id of ${meeting.id}, error: ${err}`
228
+ );
229
+
230
+ return Promise.reject(err);
231
+ });
232
+ },
233
+ declineMeeting: (meeting, reason) =>
234
+ meeting.meetingRequest.declineMeeting({
235
+ locusUrl: meeting.locusUrl,
236
+ deviceUrl: meeting.deviceUrl,
237
+ reason,
238
+ }),
213
239
 
214
- return MeetingUtil.cleanUp(meeting);
215
- })
216
- .catch((err) => {
217
- // TODO: If the meeting state comes as LEFT or INACTIVE as response then
218
- // 1) on leave clean up the meeting or simply do a sync on the meeting
219
- // 2) If the error says meeting is inactive then destroy the meeting object
220
- LoggerProxy.logger.error(
221
- `Meeting:util#leaveMeeting --> An error occured while trying to leave meeting with an id of ${meeting.id}, error: ${err}`
222
- );
240
+ isUserInLeftState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _LEFT_,
223
241
 
224
- return Promise.reject(err);
225
- });
226
- };
227
- MeetingUtil.declineMeeting = (meeting, reason) =>
228
- meeting.meetingRequest.declineMeeting({
229
- locusUrl: meeting.locusUrl,
230
- deviceUrl: meeting.deviceUrl,
231
- reason,
232
- });
242
+ isUserInIdleState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _IDLE_,
243
+
244
+ isUserInJoinedState: (locusInfo) => locusInfo.parsedLocus?.self?.state === _JOINED_,
233
245
 
234
- MeetingUtil.isUserInLeftState = (locusInfo) => locusInfo.parsedLocus?.self?.state === _LEFT_;
246
+ isMediaEstablished: (currentMediaStatus) =>
247
+ currentMediaStatus &&
248
+ (currentMediaStatus.audio || currentMediaStatus.video || currentMediaStatus.share),
235
249
 
236
- MeetingUtil.isUserInIdleState = (locusInfo) => locusInfo.parsedLocus?.self?.state === _IDLE_;
250
+ joinMeetingOptions: (meeting, options: any = {}) => {
251
+ const webex = meeting.getWebexObject();
237
252
 
238
- MeetingUtil.isUserInJoinedState = (locusInfo) => locusInfo.parsedLocus?.self?.state === _JOINED_;
253
+ meeting.resourceId = meeting.resourceId || options.resourceId;
239
254
 
240
- MeetingUtil.isMediaEstablished = (currentMediaStatus) =>
241
- currentMediaStatus &&
242
- (currentMediaStatus.audio || currentMediaStatus.video || currentMediaStatus.share);
255
+ if (meeting.requiredCaptcha) {
256
+ return Promise.reject(new CaptchaError());
257
+ }
258
+ if (meeting.passwordStatus === PASSWORD_STATUS.REQUIRED) {
259
+ return Promise.reject(new PasswordError());
260
+ }
243
261
 
244
- MeetingUtil.joinMeetingOptions = (meeting, options: any = {}) => {
245
- meeting.resourceId = meeting.resourceId || options.resourceId;
262
+ if (options.pin) {
263
+ // @ts-ignore
264
+ webex.internal.newMetrics.submitClientEvent({
265
+ name: 'client.pin.collected',
266
+ options: {
267
+ meetingId: meeting.id,
268
+ },
269
+ });
270
+ }
246
271
 
247
- if (meeting.requiredCaptcha) {
248
- return Promise.reject(new CaptchaError());
249
- }
250
- if (meeting.passwordStatus === PASSWORD_STATUS.REQUIRED) {
251
- return Promise.reject(new PasswordError());
252
- }
272
+ // normal join meeting, scenario A, D
273
+ return MeetingUtil.joinMeeting(meeting, options)
274
+ .then((response) => {
275
+ meeting.setLocus(response);
276
+
277
+ return Promise.resolve(response);
278
+ })
279
+ .catch((err) => {
280
+ // joining a claimed PMR that is not my own, scenario B
281
+ if (MeetingUtil.isPinOrGuest(err)) {
282
+ // @ts-ignore
283
+ webex.internal.newMetrics.submitClientEvent({
284
+ name: 'client.pin.prompt',
285
+ options: {
286
+ meetingId: meeting.id,
287
+ },
288
+ });
289
+
290
+ // request host pin or non host for unclaimed PMR, start of Scenario C
291
+ // see https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-Lobby-and--IVR-Feature
292
+ return Promise.reject(new IntentToJoinError('Error Joining Meeting', err));
293
+ }
294
+ LoggerProxy.logger.error(
295
+ 'Meeting:util#joinMeetingOptions --> Error joining the call, ',
296
+ err
297
+ );
298
+
299
+ return Promise.reject(new JoinMeetingError(options, 'Error Joining Meeting', err));
300
+ });
301
+ },
253
302
 
254
- if (options.pin) {
255
- Metrics.postEvent({
256
- event: eventType.PIN_COLLECTED,
257
- meeting,
258
- });
259
- }
260
-
261
- // normal join meeting, scenario A, D
262
- return MeetingUtil.joinMeeting(meeting, options)
263
- .then((response) => {
264
- meeting.setLocus(response);
265
-
266
- return Promise.resolve(response);
267
- })
268
- .catch((err) => {
269
- // joining a claimed PMR that is not my own, scenario B
270
- if (MeetingUtil.isPinOrGuest(err)) {
271
- Metrics.postEvent({
272
- event: eventType.PIN_PROMPT,
273
- meeting,
274
- });
303
+ getTrack: (stream) => {
304
+ let audioTrack = null;
305
+ let videoTrack = null;
306
+ let audioTracks = null;
307
+ let videoTracks = null;
275
308
 
276
- // request host pin or non host for unclaimed PMR, start of Scenario C
277
- // see https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-Lobby-and--IVR-Feature
278
- return Promise.reject(new IntentToJoinError('Error Joining Meeting', err));
279
- }
280
- LoggerProxy.logger.error('Meeting:util#joinMeetingOptions --> Error joining the call, ', err);
309
+ if (!stream) {
310
+ return {audioTrack: null, videoTrack: null};
311
+ }
312
+ if (stream.getAudioTracks) {
313
+ audioTracks = stream.getAudioTracks();
314
+ }
315
+ if (stream.getVideoTracks) {
316
+ videoTracks = stream.getVideoTracks();
317
+ }
281
318
 
282
- return Promise.reject(new JoinMeetingError(options, 'Error Joining Meeting', err));
283
- });
284
- };
319
+ if (audioTracks && audioTracks.length > 0) {
320
+ [audioTrack] = audioTracks;
321
+ }
285
322
 
286
- MeetingUtil.validateOptions = (options) => {
287
- const {sendVideo, sendAudio, sendShare, localStream, localShare} = options;
323
+ if (videoTracks && videoTracks.length > 0) {
324
+ [videoTrack] = videoTracks;
325
+ }
288
326
 
289
- if (sendVideo && !MeetingUtil.getTrack(localStream).videoTrack) {
290
- return Promise.reject(new ParameterError('please pass valid video streams'));
291
- }
327
+ return {audioTrack, videoTrack};
328
+ },
292
329
 
293
- if (sendAudio && !MeetingUtil.getTrack(localStream).audioTrack) {
294
- return Promise.reject(new ParameterError('please pass valid audio streams'));
295
- }
330
+ getModeratorFromLocusInfo: (locusInfo) =>
331
+ locusInfo &&
332
+ locusInfo.parsedLocus &&
333
+ locusInfo.parsedLocus.info &&
334
+ locusInfo.parsedLocus.info &&
335
+ locusInfo.parsedLocus.info.moderator,
296
336
 
297
- if (sendShare && !MeetingUtil.getTrack(localShare).videoTrack) {
298
- return Promise.reject(new ParameterError('please pass valid share streams'));
299
- }
337
+ getPolicyFromLocusInfo: (locusInfo) =>
338
+ locusInfo &&
339
+ locusInfo.parsedLocus &&
340
+ locusInfo.parsedLocus.info &&
341
+ locusInfo.parsedLocus.info &&
342
+ locusInfo.parsedLocus.info.policy,
300
343
 
301
- return Promise.resolve();
302
- };
344
+ getUserDisplayHintsFromLocusInfo: (locusInfo) =>
345
+ locusInfo?.parsedLocus?.info?.userDisplayHints || [],
303
346
 
304
- MeetingUtil.getTrack = (stream) => {
305
- let audioTrack = null;
306
- let videoTrack = null;
307
- let audioTracks = null;
308
- let videoTracks = null;
309
-
310
- if (!stream) {
311
- return {audioTrack: null, videoTrack: null};
312
- }
313
- if (stream.getAudioTracks) {
314
- audioTracks = stream.getAudioTracks();
315
- }
316
- if (stream.getVideoTracks) {
317
- videoTracks = stream.getVideoTracks();
318
- }
319
-
320
- if (audioTracks && audioTracks.length > 0) {
321
- [audioTrack] = audioTracks;
322
- }
323
-
324
- if (videoTracks && videoTracks.length > 0) {
325
- [videoTrack] = videoTracks;
326
- }
327
-
328
- return {audioTrack, videoTrack};
329
- };
347
+ canInviteNewParticipants: (displayHints) => displayHints.includes(DISPLAY_HINTS.ADD_GUEST),
330
348
 
331
- MeetingUtil.getModeratorFromLocusInfo = (locusInfo) =>
332
- locusInfo &&
333
- locusInfo.parsedLocus &&
334
- locusInfo.parsedLocus.info &&
335
- locusInfo.parsedLocus.info &&
336
- locusInfo.parsedLocus.info.moderator;
349
+ canAdmitParticipant: (displayHints) =>
350
+ displayHints.includes(DISPLAY_HINTS.ROSTER_WAITING_TO_JOIN),
337
351
 
338
- MeetingUtil.getPolicyFromLocusInfo = (locusInfo) =>
339
- locusInfo &&
340
- locusInfo.parsedLocus &&
341
- locusInfo.parsedLocus.info &&
342
- locusInfo.parsedLocus.info &&
343
- locusInfo.parsedLocus.info.policy;
352
+ canUserLock: (displayHints) =>
353
+ displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_LOCK) &&
354
+ displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_UNLOCKED),
344
355
 
345
- MeetingUtil.getUserDisplayHintsFromLocusInfo = (locusInfo) =>
346
- locusInfo?.parsedLocus?.info?.userDisplayHints || [];
356
+ canUserUnlock: (displayHints) =>
357
+ displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_UNLOCK) &&
358
+ displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_LOCKED),
347
359
 
348
- MeetingUtil.canInviteNewParticipants = (displayHints) =>
349
- displayHints.includes(DISPLAY_HINTS.ADD_GUEST);
360
+ canUserRaiseHand: (displayHints) => displayHints.includes(DISPLAY_HINTS.RAISE_HAND),
350
361
 
351
- MeetingUtil.canAdmitParticipant = (displayHints) =>
352
- displayHints.includes(DISPLAY_HINTS.ROSTER_WAITING_TO_JOIN);
362
+ canUserLowerAllHands: (displayHints) => displayHints.includes(DISPLAY_HINTS.LOWER_ALL_HANDS),
353
363
 
354
- MeetingUtil.canUserLock = (displayHints) =>
355
- displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_LOCK) &&
356
- displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_UNLOCKED);
364
+ canUserLowerSomeoneElsesHand: (displayHints) =>
365
+ displayHints.includes(DISPLAY_HINTS.LOWER_SOMEONE_ELSES_HAND),
357
366
 
358
- MeetingUtil.canUserUnlock = (displayHints) =>
359
- displayHints.includes(DISPLAY_HINTS.LOCK_CONTROL_UNLOCK) &&
360
- displayHints.includes(DISPLAY_HINTS.LOCK_STATUS_LOCKED);
367
+ bothLeaveAndEndMeetingAvailable: (displayHints) =>
368
+ displayHints.includes(DISPLAY_HINTS.LEAVE_TRANSFER_HOST_END_MEETING) ||
369
+ displayHints.includes(DISPLAY_HINTS.LEAVE_END_MEETING),
361
370
 
362
- MeetingUtil.canUserRecord = (displayHints) =>
363
- displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_START);
371
+ canManageBreakout: (displayHints) => displayHints.includes(DISPLAY_HINTS.BREAKOUT_MANAGEMENT),
372
+ canBroadcastMessageToBreakout: (displayHints) =>
373
+ displayHints.includes(DISPLAY_HINTS.BROADCAST_MESSAGE_TO_BREAKOUT),
364
374
 
365
- MeetingUtil.canUserPause = (displayHints) =>
366
- displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_PAUSE);
375
+ isSuppressBreakoutSupport: (displayHints) =>
376
+ displayHints.includes(DISPLAY_HINTS.UCF_SUPPRESS_BREAKOUTS_SUPPORT),
367
377
 
368
- MeetingUtil.canUserResume = (displayHints) =>
369
- displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_RESUME);
378
+ canAdmitLobbyToBreakout: (displayHints) =>
379
+ !displayHints.includes(DISPLAY_HINTS.DISABLE_LOBBY_TO_BREAKOUT),
370
380
 
371
- MeetingUtil.canUserStop = (displayHints) =>
372
- displayHints.includes(DISPLAY_HINTS.RECORDING_CONTROL_STOP);
381
+ isBreakoutPreassignmentsEnabled: (displayHints) =>
382
+ !displayHints.includes(DISPLAY_HINTS.DISABLE_BREAKOUT_PREASSIGNMENTS),
373
383
 
374
- MeetingUtil.startRecording = (request, locusUrl, locusInfo) => {
375
- const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
384
+ canUserAskForHelp: (displayHints) => !displayHints.includes(DISPLAY_HINTS.DISABLE_ASK_FOR_HELP),
376
385
 
377
- if (MeetingUtil.canUserRecord(displayHints)) {
378
- return request.recordMeeting({locusUrl, recording: true, paused: false});
379
- }
386
+ lockMeeting: (actions, request, locusUrl) => {
387
+ if (actions && actions.canLock) {
388
+ return request.lockMeeting({locusUrl, lock: true});
389
+ }
380
390
 
381
- return Promise.reject(
382
- new PermissionError('Start recording not allowed, due to moderator property.')
383
- );
384
- };
391
+ return Promise.reject(new PermissionError('Lock not allowed, due to joined property.'));
392
+ },
385
393
 
386
- MeetingUtil.pauseRecording = (request, locusUrl, locusInfo) => {
387
- const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
394
+ unlockMeeting: (actions, request, locusUrl) => {
395
+ if (actions && actions.canUnlock) {
396
+ return request.lockMeeting({locusUrl, lock: false});
397
+ }
388
398
 
389
- if (MeetingUtil.canUserPause(displayHints)) {
390
- return request.recordMeeting({locusUrl, recording: true, paused: true});
391
- }
399
+ return Promise.reject(new PermissionError('Unlock not allowed, due to joined property.'));
400
+ },
392
401
 
393
- return Promise.reject(
394
- new PermissionError('Pause recording not allowed, due to moderator property.')
395
- );
396
- };
402
+ handleAudioLogging: (audioTrack?: LocalMicrophoneTrack) => {
403
+ const LOG_HEADER = 'MeetingUtil#handleAudioLogging -->';
397
404
 
398
- MeetingUtil.resumeRecording = (request, locusUrl, locusInfo) => {
399
- const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
405
+ if (audioTrack) {
406
+ const settings = audioTrack.underlyingTrack.getSettings();
407
+ const {deviceId} = settings;
400
408
 
401
- if (MeetingUtil.canUserResume(displayHints)) {
402
- return request.recordMeeting({locusUrl, recording: true, paused: false});
403
- }
409
+ LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
410
+ LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
411
+ }
412
+ },
404
413
 
405
- return Promise.reject(
406
- new PermissionError('Resume recording not allowed, due to moderator property.')
407
- );
408
- };
414
+ handleVideoLogging: (videoTrack?: LocalCameraTrack) => {
415
+ const LOG_HEADER = 'MeetingUtil#handleVideoLogging -->';
409
416
 
410
- MeetingUtil.stopRecording = (request, locusUrl, locusInfo) => {
411
- const displayHints = MeetingUtil.getUserDisplayHintsFromLocusInfo(locusInfo);
417
+ if (videoTrack) {
418
+ const settings = videoTrack.underlyingTrack.getSettings();
419
+ const {deviceId} = settings;
412
420
 
413
- if (MeetingUtil.canUserStop(displayHints)) {
414
- return request.recordMeeting({locusUrl, recording: false, paused: false});
415
- }
421
+ LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
422
+ LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
423
+ }
424
+ },
416
425
 
417
- return Promise.reject(
418
- new PermissionError('Stop recording not allowed, due to moderator property.')
419
- );
420
- };
426
+ handleDeviceLogging: (devices = []) => {
427
+ const LOG_HEADER = 'MeetingUtil#handleDeviceLogging -->';
421
428
 
422
- MeetingUtil.canUserRaiseHand = (displayHints) => displayHints.includes(DISPLAY_HINTS.RAISE_HAND);
429
+ devices.forEach((device) => {
430
+ LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${device.deviceId}`);
431
+ LoggerProxy.logger.log(LOG_HEADER, 'settings', JSON.stringify(device));
432
+ });
433
+ },
423
434
 
424
- MeetingUtil.canUserLowerAllHands = (displayHints) =>
425
- displayHints.includes(DISPLAY_HINTS.LOWER_ALL_HANDS);
435
+ endMeetingForAll: (meeting) => {
436
+ if (meeting.meetingState === FULL_STATE.INACTIVE) {
437
+ return Promise.reject(new MeetingNotActiveError());
438
+ }
426
439
 
427
- MeetingUtil.canUserLowerSomeoneElsesHand = (displayHints) =>
428
- displayHints.includes(DISPLAY_HINTS.LOWER_SOMEONE_ELSES_HAND);
440
+ const endOptions = {
441
+ locusUrl: meeting.locusUrl,
442
+ };
429
443
 
430
- MeetingUtil.bothLeaveAndEndMeetingAvailable = (displayHints) =>
431
- displayHints.includes(DISPLAY_HINTS.LEAVE_TRANSFER_HOST_END_MEETING) ||
432
- displayHints.includes(DISPLAY_HINTS.LEAVE_END_MEETING);
444
+ return meeting.meetingRequest
445
+ .endMeetingForAll(endOptions)
446
+ .then(() => MeetingUtil.cleanUp(meeting))
447
+ .catch((err) => {
448
+ LoggerProxy.logger.error(
449
+ `Meeting:util#endMeetingForAll An error occured while trying to end meeting for all with an id of ${meeting.id}, error: ${err}`
450
+ );
433
451
 
434
- MeetingUtil.lockMeeting = (actions, request, locusUrl) => {
435
- if (actions && actions.canLock) {
436
- return request.lockMeeting({locusUrl, lock: true});
437
- }
452
+ return Promise.reject(err);
453
+ });
454
+ },
438
455
 
439
- return Promise.reject(new PermissionError('Lock not allowed, due to joined property.'));
440
- };
456
+ canEnableClosedCaption: (displayHints) => displayHints.includes(DISPLAY_HINTS.CAPTION_START),
441
457
 
442
- MeetingUtil.unlockMeeting = (actions, request, locusUrl) => {
443
- if (actions && actions.canUnlock) {
444
- return request.lockMeeting({locusUrl, lock: false});
445
- }
458
+ isSaveTranscriptsEnabled: (displayHints) =>
459
+ displayHints.includes(DISPLAY_HINTS.SAVE_TRANSCRIPTS_ENABLED),
446
460
 
447
- return Promise.reject(new PermissionError('Unlock not allowed, due to joined property.'));
448
- };
461
+ canStartTranscribing: (displayHints) =>
462
+ displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_START),
449
463
 
450
- MeetingUtil.handleAudioLogging = (audioTrack) => {
451
- const LOG_HEADER = 'MeetingUtil#handleAudioLogging -->';
464
+ canStopTranscribing: (displayHints) =>
465
+ displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_STOP),
452
466
 
453
- if (audioTrack) {
454
- const settings = audioTrack.getSettings();
455
- const {deviceId} = settings;
467
+ isClosedCaptionActive: (displayHints) =>
468
+ displayHints.includes(DISPLAY_HINTS.CAPTION_STATUS_ACTIVE),
456
469
 
457
- LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
458
- LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
459
- }
460
- };
470
+ isWebexAssistantActive: (displayHints) =>
471
+ displayHints.includes(DISPLAY_HINTS.WEBEX_ASSISTANT_STATUS_ACTIVE),
461
472
 
462
- MeetingUtil.handleVideoLogging = (videoTrack) => {
463
- const LOG_HEADER = 'MeetingUtil#handleVideoLogging -->';
473
+ canViewCaptionPanel: (displayHints) => displayHints.includes(DISPLAY_HINTS.ENABLE_CAPTION_PANEL),
464
474
 
465
- if (videoTrack) {
466
- const settings = videoTrack.getSettings();
467
- const {deviceId} = settings;
475
+ isRealTimeTranslationEnabled: (displayHints) =>
476
+ displayHints.includes(DISPLAY_HINTS.DISPLAY_REAL_TIME_TRANSLATION),
468
477
 
469
- LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${deviceId}`);
470
- LoggerProxy.logger.log(LOG_HEADER, 'settings =', JSON.stringify(settings));
471
- }
472
- };
478
+ canSelectSpokenLanguages: (displayHints) =>
479
+ displayHints.includes(DISPLAY_HINTS.DISPLAY_NON_ENGLISH_ASR),
473
480
 
474
- MeetingUtil.handleDeviceLogging = (devices = []) => {
475
- const LOG_HEADER = 'MeetingUtil#handleDeviceLogging -->';
481
+ waitingForOthersToJoin: (displayHints) => displayHints.includes(DISPLAY_HINTS.WAITING_FOR_OTHERS),
476
482
 
477
- devices.forEach((device) => {
478
- LoggerProxy.logger.log(LOG_HEADER, `deviceId = ${device.deviceId}`);
479
- LoggerProxy.logger.log(LOG_HEADER, 'settings', JSON.stringify(device));
480
- });
481
- };
483
+ canSendReactions: (originalValue, displayHints) => {
484
+ if (displayHints.includes(DISPLAY_HINTS.REACTIONS_ACTIVE)) {
485
+ return true;
486
+ }
487
+ if (displayHints.includes(DISPLAY_HINTS.REACTIONS_INACTIVE)) {
488
+ return false;
489
+ }
482
490
 
483
- MeetingUtil.endMeetingForAll = (meeting) => {
484
- if (meeting.meetingState === FULL_STATE.INACTIVE) {
485
- return Promise.reject(new MeetingNotActiveError());
486
- }
491
+ return originalValue;
492
+ },
493
+ canUserRenameSelfAndObserved: (displayHints) =>
494
+ displayHints.includes(DISPLAY_HINTS.CAN_RENAME_SELF_AND_OBSERVED),
487
495
 
488
- const endOptions = {
489
- locusUrl: meeting.locusUrl,
490
- };
496
+ canUserRenameOthers: (displayHints) => displayHints.includes(DISPLAY_HINTS.CAN_RENAME_OTHERS),
491
497
 
492
- return meeting.meetingRequest
493
- .endMeetingForAll(endOptions)
494
- .then((response) => {
495
- if (response && response.body && response.body.locus) {
496
- meeting.locusInfo.onFullLocus(response.body.locus);
497
- }
498
+ /**
499
+ * Adds the current locus sequence information to a request body
500
+ * @param {Object} meeting The meeting object
501
+ * @param {Object} requestBody The body of a request to locus
502
+ * @returns {void}
503
+ */
504
+ addSequence: (meeting, requestBody) => {
505
+ const sequence = meeting?.locusInfo?.sequence;
498
506
 
499
- return Promise.resolve();
500
- })
501
- .then(() => MeetingUtil.cleanUp(meeting))
502
- .catch((err) => {
503
- LoggerProxy.logger.error(
504
- `Meeting:util#endMeetingForAll An error occured while trying to end meeting for all with an id of ${meeting.id}, error: ${err}`
505
- );
507
+ if (!sequence) {
508
+ return;
509
+ }
506
510
 
507
- return Promise.reject(err);
508
- });
509
- };
511
+ requestBody.sequence = sequence;
512
+ },
513
+
514
+ /**
515
+ * Updates the locus info for the meeting with the delta locus
516
+ * returned from requests that include the sequence information
517
+ * Returns the original response object
518
+ * @param {Object} meeting The meeting object
519
+ * @param {Object} response The response of the http request
520
+ * @returns {Object}
521
+ */
522
+ updateLocusWithDelta: (meeting, response) => {
523
+ if (!meeting) {
524
+ return response;
525
+ }
510
526
 
511
- MeetingUtil.canEnableClosedCaption = (displayHints) =>
512
- displayHints.includes(DISPLAY_HINTS.CAPTION_START);
527
+ const locus = response?.body?.locus;
513
528
 
514
- MeetingUtil.canStartTranscribing = (displayHints) =>
515
- displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_START);
529
+ if (locus) {
530
+ meeting.locusInfo.onDeltaLocus(locus);
531
+ }
516
532
 
517
- MeetingUtil.canStopTranscribing = (displayHints) =>
518
- displayHints.includes(DISPLAY_HINTS.TRANSCRIPTION_CONTROL_STOP);
533
+ return response;
534
+ },
519
535
 
520
- MeetingUtil.isClosedCaptionActive = (displayHints) =>
521
- displayHints.includes(DISPLAY_HINTS.CAPTION_STATUS_ACTIVE);
536
+ generateLocusDeltaRequest: (originalMeeting) => {
537
+ const meetingRef = new WeakRef(originalMeeting);
522
538
 
523
- MeetingUtil.isWebexAssistantActive = (displayHints) =>
524
- displayHints.includes(DISPLAY_HINTS.WEBEX_ASSISTANT_STATUS_ACTIVE);
539
+ const locusDeltaRequest = (originalOptions) => {
540
+ const meeting = meetingRef.deref();
525
541
 
526
- MeetingUtil.canViewCaptionPanel = (displayHints) =>
527
- displayHints.includes(DISPLAY_HINTS.ENABLE_CAPTION_PANEL);
542
+ if (!meeting) {
543
+ return Promise.resolve();
544
+ }
528
545
 
529
- MeetingUtil.isRealTimeTranslationEnabled = (displayHints) =>
530
- displayHints.includes(DISPLAY_HINTS.DISPLAY_REAL_TIME_TRANSLATION);
546
+ const options = cloneDeep(originalOptions);
531
547
 
532
- MeetingUtil.canSelectSpokenLanguages = (displayHints) =>
533
- displayHints.includes(DISPLAY_HINTS.DISPLAY_NON_ENGLISH_ASR);
548
+ if (!options.body) {
549
+ options.body = {};
550
+ }
534
551
 
535
- MeetingUtil.waitingForOthersToJoin = (displayHints) =>
536
- displayHints.includes(DISPLAY_HINTS.WAITING_FOR_OTHERS);
552
+ MeetingUtil.addSequence(meeting, options.body);
537
553
 
538
- MeetingUtil.canEnableReactions = (originalValue, displayHints) => {
539
- if (displayHints.includes(DISPLAY_HINTS.ENABLE_REACTIONS)) {
540
- return true;
541
- }
542
- if (displayHints.includes(DISPLAY_HINTS.DISABLE_REACTIONS)) {
543
- return false;
544
- }
554
+ return meeting
555
+ .request(options)
556
+ .then((response) => MeetingUtil.updateLocusWithDelta(meeting, response));
557
+ };
545
558
 
546
- return originalValue;
547
- };
559
+ return locusDeltaRequest;
560
+ },
548
561
 
549
- MeetingUtil.canSendReactions = (originalValue, displayHints) => {
550
- if (displayHints.includes(DISPLAY_HINTS.REACTIONS_ACTIVE)) {
551
- return true;
552
- }
553
- if (displayHints.includes(DISPLAY_HINTS.REACTIONS_INACTIVE)) {
554
- return false;
555
- }
562
+ selfSupportsFeature: (feature: SELF_POLICY, userPolicies: Record<SELF_POLICY, boolean>) => {
563
+ if (!userPolicies) {
564
+ return true;
565
+ }
556
566
 
557
- return originalValue;
567
+ return userPolicies[feature];
568
+ },
558
569
  };
559
570
 
560
571
  export default MeetingUtil;