@webex/plugin-meetings 3.0.0-beta.16 → 3.0.0-beta.161

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