@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
@@ -0,0 +1,921 @@
1
+ /*!
2
+ * Copyright (c) 2015-2023 Cisco Systems, Inc. See LICENSE file.
3
+ */
4
+ import {WebexPlugin} from '@webex/webex-core';
5
+ import {debounce, forEach} from 'lodash';
6
+ import LoggerProxy from '../common/logs/logger-proxy';
7
+
8
+ import {BREAKOUTS, MEETINGS, HTTP_VERBS, _ID_} from '../constants';
9
+
10
+ import Breakout from './breakout';
11
+ import BreakoutCollection from './collection';
12
+ import BreakoutRequest from './request';
13
+ import breakoutEvent from './events';
14
+ import {boServiceErrorHandler, isSessionTypeChangedFromSessionToMain} from './utils';
15
+
16
+ /**
17
+ * @class Breakouts
18
+ */
19
+ const Breakouts = WebexPlugin.extend({
20
+ namespace: MEETINGS,
21
+ breakoutRequest: BreakoutRequest,
22
+ collections: {
23
+ breakouts: BreakoutCollection,
24
+ },
25
+
26
+ props: {
27
+ allowBackToMain: 'boolean', // only present when in a breakout session
28
+ delayCloseTime: 'number', // appears once breakouts start
29
+ enableBreakoutSession: 'boolean', // appears from the moment you enable breakouts
30
+ hasBreakoutPreAssignments: 'boolean', // appears from the moment you enable breakouts
31
+ groupId: 'string', // appears from the moment you enable breakouts
32
+ name: 'string', // only present when in a breakout session
33
+ sessionId: 'string', // appears from the moment you enable breakouts
34
+ sessionType: 'string', // appears from the moment you enable breakouts
35
+ startTime: 'string', // appears once breakouts start
36
+ status: 'string', // only present when in a breakout session
37
+ url: 'string', // appears from the moment you enable breakouts
38
+ locusUrl: 'string', // the current locus url
39
+ breakoutServiceUrl: 'string', // the current breakout resource url
40
+ mainLocusUrl: 'string', // the locus url of the main session
41
+ groups: 'array', // appears when create breakouts
42
+ manageGroups: 'array', // appears when manage breakouts
43
+ preAssignments: 'array', // appears when getPreAssignments info hasBreakoutPreAssignments = true
44
+ editLock: 'object', // appears when getBreakout info editlock = true
45
+ intervalID: 'number',
46
+ meetingId: 'string',
47
+ canManageBreakouts: 'boolean', // appear the ability to manage breakouts
48
+ },
49
+ children: {
50
+ currentBreakoutSession: Breakout,
51
+ },
52
+
53
+ derived: {
54
+ isInMainSession: {
55
+ cache: false,
56
+ deps: ['sessionType'],
57
+ /**
58
+ * Returns true if the user is in the main session
59
+ * @returns {boolean}
60
+ */
61
+ fn() {
62
+ return this.sessionType === BREAKOUTS.SESSION_TYPES.MAIN;
63
+ },
64
+ },
65
+ isActiveBreakout: {
66
+ cache: false, // fix issue: sometimes the derived will not change even if the deps changed
67
+ deps: ['sessionType', 'status'],
68
+ /**
69
+ * Returns true if the breakout status is active
70
+ * @returns {boolean}
71
+ */
72
+ fn() {
73
+ return (
74
+ this.sessionType === BREAKOUTS.SESSION_TYPES.BREAKOUT &&
75
+ (this.status === BREAKOUTS.STATUS.OPEN || this.status === BREAKOUTS.STATUS.CLOSING)
76
+ );
77
+ },
78
+ },
79
+ breakoutGroupId: {
80
+ cache: false,
81
+ deps: ['manageGroups'],
82
+ /**
83
+ * Returns the active group id
84
+ * @returns {boolean}
85
+ */
86
+ fn() {
87
+ if (this.manageGroups?.length) {
88
+ return this.manageGroups[0].status !== BREAKOUTS.STATUS.CLOSED
89
+ ? this.manageGroups[0].id
90
+ : '';
91
+ }
92
+
93
+ return '';
94
+ },
95
+ },
96
+ breakoutStatus: {
97
+ cache: true,
98
+ deps: ['isInMainSession', 'status', 'groups'],
99
+ /**
100
+ * Returns the breakout status
101
+ * @returns {boolean}
102
+ */
103
+ fn() {
104
+ return this.isInMainSession ? this.groups?.[0]?.status : this.status;
105
+ },
106
+ },
107
+ shouldQueryPreAssignments: {
108
+ cache: false,
109
+ deps: ['canManageBreakouts', 'enableBreakoutSession', 'hasBreakoutPreAssignments'],
110
+ /**
111
+ * Returns should query preAssignments or not
112
+ * @returns {boolean}
113
+ */
114
+ fn() {
115
+ return !!(
116
+ this.canManageBreakouts &&
117
+ this.enableBreakoutSession &&
118
+ this.hasBreakoutPreAssignments
119
+ );
120
+ },
121
+ },
122
+ },
123
+
124
+ /**
125
+ * initialize for the breakouts
126
+ * @returns {void}
127
+ */
128
+ initialize() {
129
+ this.listenTo(this, 'change:breakoutStatus', () => {
130
+ if (this.breakoutStatus === BREAKOUTS.STATUS.CLOSING) {
131
+ this.trigger(BREAKOUTS.EVENTS.BREAKOUTS_CLOSING);
132
+ }
133
+ });
134
+ this.listenTo(this, 'change:shouldQueryPreAssignments', () => {
135
+ if (this.shouldQueryPreAssignments && !this.preAssignments) {
136
+ this.queryPreAssignments();
137
+ }
138
+ });
139
+ this.debouncedQueryRosters = debounce(this.queryRosters, 10, {
140
+ leading: true,
141
+ trailing: false,
142
+ });
143
+ this.listenTo(this.breakouts, 'add', (breakout) => {
144
+ this.debouncedQueryRosters();
145
+ this.triggerReturnToMainEvent(breakout);
146
+ });
147
+ this.listenTo(this.breakouts, 'change:requestedLastModifiedTime', (breakout) => {
148
+ this.triggerReturnToMainEvent(breakout);
149
+ });
150
+ this.listenToCurrentSessionTypeChange();
151
+ this.listenToBroadcastMessages();
152
+ this.listenToBreakoutRosters();
153
+ this.listenToBreakoutHelp();
154
+ // @ts-ignore
155
+ this.breakoutRequest = new BreakoutRequest({webex: this.webex});
156
+ },
157
+
158
+ /**
159
+ * Calls this to clean up listeners
160
+ * @returns {void}
161
+ */
162
+ cleanUp() {
163
+ this.stopListening();
164
+ },
165
+
166
+ /**
167
+ * Update the current locus url of the meeting
168
+ * @param {string} locusUrl // locus url
169
+ * @returns {void}
170
+ */
171
+ locusUrlUpdate(locusUrl) {
172
+ this.set('locusUrl', locusUrl);
173
+ const {isInMainSession, mainLocusUrl} = this;
174
+ if (isInMainSession || !mainLocusUrl) {
175
+ this.set('mainLocusUrl', locusUrl);
176
+ }
177
+ },
178
+
179
+ /**
180
+ * Update whether self is moderator/cohost or not
181
+ * @param {boolean} canManageBreakouts
182
+ * @returns {void}
183
+ */
184
+ updateCanManageBreakouts(canManageBreakouts) {
185
+ this.set('canManageBreakouts', canManageBreakouts);
186
+ },
187
+
188
+ /**
189
+ * Update the current breakout resource url
190
+ * @param {string} breakoutServiceUrl
191
+ * @returns {void}
192
+ */
193
+ breakoutServiceUrlUpdate(breakoutServiceUrl) {
194
+ this.set('breakoutServiceUrl', `${breakoutServiceUrl}/breakout/`);
195
+ },
196
+
197
+ /**
198
+ * The initial roster lists need to be queried because you don't
199
+ * get a breakout.roster event when you join the meeting
200
+ * @returns {void}
201
+ */
202
+ queryRosters() {
203
+ this.webex
204
+ .request({uri: `${this.url}/roster`, qs: {locusUrl: btoa(this.locusUrl)}})
205
+ .then((result) => {
206
+ const {
207
+ body: {rosters},
208
+ } = result;
209
+
210
+ rosters?.forEach(({locus}) => {
211
+ this.handleRosterUpdate(locus);
212
+ });
213
+
214
+ this.trigger(BREAKOUTS.EVENTS.MEMBERS_UPDATE);
215
+ })
216
+ .catch((error) => {
217
+ LoggerProxy.logger.error('Meeting:breakouts#queryRosters failed', error);
218
+ });
219
+ },
220
+
221
+ /**
222
+ *
223
+ * @param {Object} locus // locus object
224
+ * @returns {void}
225
+ */
226
+ handleRosterUpdate(locus) {
227
+ const sessionId = locus.controls?.breakout?.sessionId;
228
+
229
+ const session = this.breakouts.get(sessionId);
230
+
231
+ if (!session) {
232
+ return;
233
+ }
234
+
235
+ session.parseRoster(locus);
236
+ },
237
+ /**
238
+ *Sets up listener for currentBreakoutSession sessionType changed
239
+ * @returns {void}
240
+ */
241
+ listenToCurrentSessionTypeChange(): void {
242
+ this.listenTo(
243
+ this.currentBreakoutSession,
244
+ 'change:sessionType',
245
+ (currentBreakoutSession, sessionType) => {
246
+ if (isSessionTypeChangedFromSessionToMain(currentBreakoutSession, sessionType)) {
247
+ this.trigger(BREAKOUTS.EVENTS.LEAVE_BREAKOUT);
248
+ }
249
+ }
250
+ );
251
+ },
252
+
253
+ /**
254
+ * Sets up listener for broadcast messages sent to the breakout session
255
+ * @returns {void}
256
+ */
257
+ listenToBroadcastMessages() {
258
+ this.listenTo(this.webex.internal.llm, 'event:breakout.message', (event) => {
259
+ const {
260
+ data: {senderUserId, sentTime, message},
261
+ } = event;
262
+
263
+ this.trigger(BREAKOUTS.EVENTS.MESSAGE, {
264
+ senderUserId,
265
+ sentTime,
266
+ message,
267
+ // FIXME: This is only the current sessionId
268
+ // We'd need to check that the dataChannelUrl is still the same
269
+ // to guarantee that this message was sent to this session
270
+ sessionId: this.currentBreakoutSession.sessionId,
271
+ });
272
+ });
273
+ },
274
+
275
+ /**
276
+ * Sets up a listener for roster messags from mecury
277
+ * @returns {void}
278
+ */
279
+ listenToBreakoutRosters() {
280
+ this.listenTo(this.webex.internal.mercury, 'event:breakout.roster', (event) => {
281
+ this.handleRosterUpdate(event.data.locus);
282
+ this.trigger(BREAKOUTS.EVENTS.MEMBERS_UPDATE);
283
+ });
284
+ },
285
+
286
+ /**
287
+ * Sets up a listener for ask help notify from mecury
288
+ * @returns {void}
289
+ */
290
+ listenToBreakoutHelp() {
291
+ this.listenTo(this.webex.internal.mercury, 'event:breakout.help', (event) => {
292
+ const {
293
+ data: {participant, sessionId},
294
+ } = event;
295
+ this.trigger(BREAKOUTS.EVENTS.ASK_FOR_HELP, {participant, sessionId});
296
+ });
297
+ },
298
+
299
+ /**
300
+ * get current breakout is in progress or not
301
+ * @returns {boolean}
302
+ */
303
+ isBreakoutInProgress() {
304
+ const currentStatus = this.groups?.[0]?.status || this.status;
305
+
306
+ return currentStatus === BREAKOUTS.STATUS.OPEN || currentStatus === BREAKOUTS.STATUS.CLOSING;
307
+ },
308
+
309
+ /**
310
+ * get current breakout is in closing or not
311
+ * @returns {boolean}
312
+ */
313
+ isBreakoutIClosing() {
314
+ return (this.groups?.[0]?.status || this.status) === BREAKOUTS.STATUS.CLOSING;
315
+ },
316
+ /**
317
+ * Updates the information about the current breakout
318
+ * @param {Object} params
319
+ * @returns {void}
320
+ */
321
+ updateBreakout(params) {
322
+ this.set(params);
323
+ // These values are set manually so they are unset when they are not included in params
324
+ this.set('groups', params.groups);
325
+ this.set('startTime', params.startTime);
326
+ this.set('status', params.status);
327
+
328
+ this.set('currentBreakoutSession', {
329
+ sessionId: params.sessionId,
330
+ groupId: params.groupId,
331
+ name: params.name,
332
+ current: true,
333
+ sessionType: params.sessionType,
334
+ url: params.url,
335
+ [BREAKOUTS.SESSION_STATES.ACTIVE]: false,
336
+ [BREAKOUTS.SESSION_STATES.ALLOWED]: false,
337
+ [BREAKOUTS.SESSION_STATES.ASSIGNED]: false,
338
+ [BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT]: false,
339
+ [BREAKOUTS.SESSION_STATES.REQUESTED]: false,
340
+ });
341
+
342
+ if (!this.isBreakoutInProgress()) {
343
+ this.clearBreakouts();
344
+ }
345
+
346
+ if (
347
+ this.currentBreakoutSession.previous('sessionId') !== this.currentBreakoutSession.sessionId ||
348
+ this.currentBreakoutSession.previous('groupId') !== this.currentBreakoutSession.groupId
349
+ ) {
350
+ // should report joined session changed
351
+ const meeting = this.webex.meetings.getMeetingByType(_ID_, this.meetingId);
352
+ breakoutEvent.onBreakoutJoinResponse({
353
+ currentSession: this.currentBreakoutSession,
354
+ meeting,
355
+ breakoutMoveId: params.breakoutMoveId,
356
+ });
357
+ }
358
+ },
359
+
360
+ /**
361
+ * Updates the information about available breakouts
362
+ * @param {Object} payload
363
+ * @returns {void}
364
+ */
365
+ updateBreakoutSessions(payload) {
366
+ const breakouts = {};
367
+ if (this.isBreakoutIClosing()) {
368
+ // fix issue: don't clear/update breakouts collection when in closing since locus DTO will send undefined or
369
+ // only the MAIN session info here, if just update it, will miss the breakout roster info during
370
+ // count down to end breakouts
371
+ return;
372
+ }
373
+ if (payload.breakoutSessions) {
374
+ forEach(BREAKOUTS.SESSION_STATES, (state) => {
375
+ forEach(payload.breakoutSessions[state], (breakout) => {
376
+ const {sessionId} = breakout;
377
+
378
+ if (!breakouts[sessionId]) {
379
+ breakouts[sessionId] = breakout;
380
+ breakouts[sessionId][BREAKOUTS.SESSION_STATES.ACTIVE] = false;
381
+ breakouts[sessionId][BREAKOUTS.SESSION_STATES.ASSIGNED] = false;
382
+ breakouts[sessionId][BREAKOUTS.SESSION_STATES.ALLOWED] = false;
383
+ breakouts[sessionId][BREAKOUTS.SESSION_STATES.ASSIGNED_CURRENT] = false;
384
+ breakouts[sessionId][BREAKOUTS.SESSION_STATES.REQUESTED] = false;
385
+ }
386
+
387
+ breakouts[sessionId][state] = true;
388
+
389
+ if (state === BREAKOUTS.SESSION_STATES.REQUESTED) {
390
+ breakouts[sessionId].requestedLastModifiedTime = breakout.modifiedAt;
391
+ }
392
+ });
393
+ });
394
+ }
395
+ forEach(breakouts, (breakout: typeof Breakout) => {
396
+ // eslint-disable-next-line no-param-reassign
397
+ breakout.url = this.url;
398
+ });
399
+
400
+ this.breakouts.set(Object.values(breakouts));
401
+ },
402
+ /**
403
+ * clear breakouts collection
404
+ * @returns {void}
405
+ */
406
+ clearBreakouts() {
407
+ if (this.breakouts.length > 0) {
408
+ this.breakouts.reset();
409
+ }
410
+ },
411
+ /**
412
+ * get main session
413
+ * @returns {Breakout}
414
+ */
415
+ getMainSession() {
416
+ if (this.isInMainSession) {
417
+ return this.currentBreakoutSession;
418
+ }
419
+
420
+ const mainSession = this.breakouts.filter((breakout) => breakout.isMain)[0];
421
+ if (!mainSession) {
422
+ throw new Error('no main session found');
423
+ }
424
+
425
+ return mainSession;
426
+ },
427
+ /**
428
+ * Host/CoHost ask all participants return to main session
429
+ * @returns {Promise}
430
+ */
431
+ askAllToReturn() {
432
+ const mainSession = this.getMainSession();
433
+
434
+ return this.webex.request({
435
+ method: HTTP_VERBS.POST,
436
+ uri: `${this.url}/requestMove`,
437
+ body: {
438
+ groupId: mainSession.groupId,
439
+ sessionId: mainSession.sessionId,
440
+ },
441
+ });
442
+ },
443
+
444
+ /**
445
+ * Broadcast message to all breakout session's participants
446
+ * @param {String} message
447
+ * @param {Object} options
448
+ * @returns {Promise}
449
+ */
450
+ broadcast(message, options) {
451
+ const {breakoutGroupId} = this;
452
+ if (!breakoutGroupId) {
453
+ throw new Error('Cannot broadcast, no breakout session found');
454
+ }
455
+
456
+ return this.breakoutRequest.broadcast({
457
+ url: this.url,
458
+ message,
459
+ options,
460
+ groupId: breakoutGroupId,
461
+ });
462
+ },
463
+ /**
464
+ * Make enable breakout resource
465
+ * @returns {Promise}
466
+ */
467
+ enableBreakouts() {
468
+ if (this.breakoutServiceUrl) {
469
+ // @ts-ignore
470
+ return this.webex
471
+ .request({
472
+ method: HTTP_VERBS.POST,
473
+ uri: this.breakoutServiceUrl,
474
+ body: {
475
+ locusUrl: this.locusUrl,
476
+ },
477
+ })
478
+ .catch((err) => {
479
+ LoggerProxy.logger.error(
480
+ `Meeting:request#touchBreakout --> Error provisioning error ${err}`
481
+ );
482
+ throw err;
483
+ });
484
+ }
485
+
486
+ return Promise.reject(new Error(`enableBreakouts: the breakoutServiceUrl is empty`));
487
+ },
488
+
489
+ /**
490
+ * Make the meeting enable or disable breakout session
491
+ * @param {boolean} enable
492
+ * @returns {Promise}
493
+ */
494
+ async toggleBreakout(enable) {
495
+ if (this.enableBreakoutSession === undefined) {
496
+ const info = await this.enableBreakouts();
497
+ // first time enable, set the initial data
498
+ this.updateBreakout(info?.body);
499
+ if (!enable) {
500
+ await this.doToggleBreakout(enable);
501
+ }
502
+ } else {
503
+ await this.doToggleBreakout(enable);
504
+ }
505
+ },
506
+
507
+ /**
508
+ * do toggle meeting breakout session enable or disable
509
+ * @param {boolean} enable
510
+ * @returns {Promise}
511
+ */
512
+ doToggleBreakout(enable) {
513
+ const body = {
514
+ ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),
515
+ ...{enableBreakoutSession: enable},
516
+ };
517
+
518
+ // @ts-ignore
519
+ return this.webex.request({
520
+ method: HTTP_VERBS.PUT,
521
+ uri: this.url,
522
+ body,
523
+ });
524
+ },
525
+
526
+ /**
527
+ * set groups to manageGroups prop
528
+ * @param {Object} breakoutInfo -- breakout groups
529
+ * @returns {void}
530
+ */
531
+ _setManageGroups(breakoutInfo) {
532
+ if (breakoutInfo?.body?.groups) {
533
+ this.set('manageGroups', breakoutInfo.body.groups);
534
+ }
535
+ },
536
+
537
+ /**
538
+ * Create new breakout sessions
539
+ * @param {object} params -- breakout session group
540
+ * @returns {Promise}
541
+ */
542
+ async create(params) {
543
+ const payload = {...params};
544
+ const body = {
545
+ ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),
546
+ ...{groups: [payload]},
547
+ };
548
+ // @ts-ignore
549
+ const breakoutInfo = await this.webex
550
+ .request({
551
+ method: HTTP_VERBS.PUT,
552
+ uri: this.url,
553
+ body,
554
+ })
555
+ .catch((error) => {
556
+ return Promise.reject(boServiceErrorHandler(error, 'Breakouts#create'));
557
+ });
558
+
559
+ this._setManageGroups(breakoutInfo);
560
+
561
+ // clear edit lock info after save breakout session info
562
+ this._clearEditLockInfo();
563
+
564
+ return breakoutInfo;
565
+ },
566
+
567
+ /**
568
+ * Delete all breakout sessions
569
+ * @returns {Promise}
570
+ */
571
+ async clearSessions() {
572
+ const body = {
573
+ ...(this.editLock && !!this.editLock.token ? {editlock: {token: this.editLock.token}} : {}),
574
+ ...{groups: [{action: BREAKOUTS.ACTION.DELETE}]},
575
+ };
576
+ // @ts-ignore
577
+ const breakoutInfo = await this.webex
578
+ .request({
579
+ method: HTTP_VERBS.PUT,
580
+ uri: this.url,
581
+ body,
582
+ })
583
+ .catch((error) => {
584
+ return Promise.reject(boServiceErrorHandler(error, 'Breakouts#clearSessions'));
585
+ });
586
+
587
+ this._setManageGroups(breakoutInfo);
588
+
589
+ return breakoutInfo;
590
+ },
591
+
592
+ /**
593
+ * Host or cohost starts breakout sessions
594
+ * @param {object} params
595
+ * @returns {Promise}
596
+ */
597
+ async start(params = {}) {
598
+ const action = BREAKOUTS.ACTION.START;
599
+ const payload = {
600
+ id: this.breakoutGroupId,
601
+ action,
602
+ allowBackToMain: false,
603
+ allowToJoinLater: false,
604
+ ...params,
605
+ };
606
+
607
+ const body = {
608
+ ...(this.editLock && !!this.editLock.token
609
+ ? {editlock: {token: this.editLock.token, refresh: true}}
610
+ : {}),
611
+ ...{groups: [payload]},
612
+ };
613
+
614
+ const breakoutInfo = await this.request({
615
+ method: HTTP_VERBS.PUT,
616
+ uri: this.url,
617
+ body,
618
+ }).catch((error) => {
619
+ return Promise.reject(boServiceErrorHandler(error, 'Breakouts#start'));
620
+ });
621
+
622
+ this._setManageGroups(breakoutInfo);
623
+
624
+ return breakoutInfo;
625
+ },
626
+
627
+ /**
628
+ * Host or cohost ends breakout sessions
629
+ * @param {object} params
630
+ * @returns {Promise}
631
+ */
632
+ async end(params = {}) {
633
+ const {delayCloseTime, breakoutGroupId: id} = this;
634
+ const action = BREAKOUTS.ACTION.CLOSE;
635
+ const payload = {
636
+ id,
637
+ action,
638
+ delayCloseTime,
639
+ ...params,
640
+ };
641
+
642
+ const body = {
643
+ ...(this.editLock && !!this.editLock.token
644
+ ? {editlock: {token: this.editLock.token, refresh: true}}
645
+ : {}),
646
+ ...{groups: [payload]},
647
+ };
648
+
649
+ const breakoutInfo = await this.request({
650
+ method: HTTP_VERBS.PUT,
651
+ uri: this.url,
652
+ body,
653
+ }).catch((error) => {
654
+ return Promise.reject(boServiceErrorHandler(error, 'Breakouts#end'));
655
+ });
656
+
657
+ this._setManageGroups(breakoutInfo);
658
+
659
+ return breakoutInfo;
660
+ },
661
+
662
+ /**
663
+ * Host or cohost update breakout sessions
664
+ * @param {Object} params
665
+ * @param {String} params.id
666
+ * @param {Boolean} unlockEdit
667
+ * @returns {Promise}
668
+ */
669
+ async update(params: {id: string}, unlockEdit?: boolean) {
670
+ if (!params.id) {
671
+ return Promise.reject(new Error('Missing breakout group id'));
672
+ }
673
+ const payload = {...params};
674
+
675
+ const body = {
676
+ ...(this.editLock?.token
677
+ ? {editlock: {token: this.editLock.token, refresh: !unlockEdit}}
678
+ : {}),
679
+ ...{groups: [payload]},
680
+ };
681
+
682
+ const breakoutInfo = await this.request({
683
+ method: HTTP_VERBS.PUT,
684
+ uri: this.url,
685
+ body,
686
+ }).catch((error) => {
687
+ return Promise.reject(boServiceErrorHandler(error, 'Breakouts#update'));
688
+ });
689
+
690
+ if (unlockEdit) {
691
+ this._clearEditLockInfo();
692
+ }
693
+
694
+ this._setManageGroups(breakoutInfo);
695
+
696
+ return breakoutInfo;
697
+ },
698
+
699
+ /**
700
+ * get existed breakout sessions
701
+ * @param {boolean} editlock -- lock operations of the breakout sessions
702
+ * @returns {Promise}
703
+ */
704
+ async getBreakout(editlock) {
705
+ const breakout = await this.request({
706
+ method: HTTP_VERBS.GET,
707
+ uri: this.url + (editlock ? `?editlock=${editlock}` : ''),
708
+ });
709
+
710
+ this._setManageGroups(breakout);
711
+ if (editlock && breakout.body?.editlock?.token) {
712
+ this.set('editLock', breakout.body.editlock);
713
+ this.keepEditLockAlive();
714
+ }
715
+
716
+ return breakout;
717
+ },
718
+
719
+ /**
720
+ * enable and edit lock breakout
721
+ * @returns {void}
722
+ */
723
+ async enableAndLockBreakout() {
724
+ if (this.enableBreakoutSession) {
725
+ this.lockBreakout();
726
+ } else {
727
+ const info = await this.enableBreakouts();
728
+
729
+ if (info.body) {
730
+ this.lockBreakout();
731
+ }
732
+ }
733
+ },
734
+
735
+ /**
736
+ * breakout edit locked by yourself or not
737
+ * @returns {boolean}
738
+ */
739
+ hasBreakoutLocked() {
740
+ return (
741
+ this.editLock &&
742
+ this.editLock.token &&
743
+ this.editLock.state === BREAKOUTS.EDIT_LOCK_STATUS.LOCKED
744
+ );
745
+ },
746
+
747
+ /**
748
+ * send breakout edit lock
749
+ * @returns {void}
750
+ */
751
+ async lockBreakout() {
752
+ if (this.editLock && !!this.editLock.token) {
753
+ if (this.editLock.state === BREAKOUTS.EDIT_LOCK_STATUS.LOCKED) {
754
+ throw new Error('Breakout already locked');
755
+ } else {
756
+ this.keepEditLockAlive();
757
+ }
758
+ } else {
759
+ const breakout = await this.getBreakout(true);
760
+ if (breakout.body?.editlock) {
761
+ this.keepEditLockAlive();
762
+ }
763
+ }
764
+ },
765
+
766
+ /**
767
+ * keep edit lock alive
768
+ * @returns {void}
769
+ */
770
+ keepEditLockAlive() {
771
+ if (this.editLock && !!this.editLock.token) {
772
+ const ttl = this.editLock.ttl < 30 ? BREAKOUTS.DEFAULT_TTL : this.editLock.ttl;
773
+ if (this.intervalID) {
774
+ window.clearInterval(this.intervalID);
775
+ }
776
+
777
+ this.intervalID = window.setInterval(() => {
778
+ this.request({
779
+ method: HTTP_VERBS.PUT,
780
+ uri: `${this.url}/editlock/${this.editLock.token}`,
781
+ }).catch((error) => {
782
+ this._clearEditLockInfo();
783
+
784
+ return Promise.reject(boServiceErrorHandler(error, 'Breakouts#keepEditLockAlive'));
785
+ });
786
+ }, (ttl / 2) * 1000);
787
+ }
788
+ },
789
+
790
+ /**
791
+ * unlock edit breakout
792
+ * @returns {void}
793
+ */
794
+ unLockEditBreakout() {
795
+ if (this.editLock && !!this.editLock.token) {
796
+ this.request({
797
+ method: HTTP_VERBS.DELETE,
798
+ uri: `${this.url}/editlock/${this.editLock.token}`,
799
+ })
800
+ .then(() => {
801
+ this._clearEditLockInfo();
802
+ })
803
+ .catch((error) => {
804
+ return Promise.reject(boServiceErrorHandler(error, 'Breakouts#unLockEditBreakout'));
805
+ });
806
+ }
807
+ },
808
+
809
+ /**
810
+ * clear interval and edit lock info
811
+ * @private
812
+ * @returns {void}
813
+ */
814
+ _clearEditLockInfo() {
815
+ if (this.intervalID) {
816
+ clearInterval(this.intervalID);
817
+ }
818
+ this.set('editLock', {});
819
+ },
820
+
821
+ /**
822
+ * assign participants to breakout session
823
+ * @param {Array} sessions
824
+ * @returns {void}
825
+ */
826
+ assign(sessions: any[]) {
827
+ const internalSessions = sessions.map((item) => {
828
+ return {
829
+ id: item.id,
830
+ assigned: item.memberIds,
831
+ assignedEmails: item.emails,
832
+ anyoneCanJoin: !!item.anyone,
833
+ };
834
+ });
835
+
836
+ const body = {
837
+ ...(this.editLock && !!this.editLock.token
838
+ ? {editlock: {token: this.editLock.token, refresh: true}}
839
+ : {}),
840
+ ...{
841
+ groups: [
842
+ {
843
+ id: this.breakoutGroupId,
844
+ sessions: internalSessions,
845
+ },
846
+ ],
847
+ },
848
+ };
849
+
850
+ return this.request({
851
+ method: HTTP_VERBS.PUT,
852
+ uri: this.url,
853
+ body,
854
+ });
855
+ },
856
+
857
+ /**
858
+ * query preAssignments
859
+ * @returns {void}
860
+ */
861
+ queryPreAssignments() {
862
+ this.webex
863
+ .request({uri: `${this.url}/preassignments`, qs: {locusUrl: btoa(this.locusUrl)}})
864
+ .then((result) => {
865
+ if (result.body?.groups) {
866
+ this.set('preAssignments', result.body.groups);
867
+ this.trigger(BREAKOUTS.EVENTS.PRE_ASSIGNMENTS_UPDATE);
868
+ }
869
+ })
870
+ .catch((error) => {
871
+ LoggerProxy.logger.error('Meeting:breakouts#queryPreAssignments failed', error);
872
+ });
873
+ },
874
+ /**
875
+ * assign participants dynamically after breakout sessions started,
876
+ * but currently it only used for admitting participants from lobby into breakout directly
877
+ * @param {Array} sessions
878
+ * @returns {void}
879
+ */
880
+ dynamicAssign(sessions: any[]) {
881
+ const updatedSessions = sessions.map((item) => {
882
+ return {
883
+ id: item.id,
884
+ participants: item.participants,
885
+ targetState: item.targetState,
886
+ };
887
+ });
888
+
889
+ const body = {
890
+ groups: [
891
+ {
892
+ id: this.breakoutGroupId,
893
+ sessions: updatedSessions,
894
+ },
895
+ ],
896
+ editlock: null,
897
+ };
898
+
899
+ if (this.editLock && this.editLock.token) {
900
+ body.editlock = this.editLock;
901
+ }
902
+
903
+ return this.request({
904
+ method: HTTP_VERBS.PUT,
905
+ uri: `${this.url}/dynamicAssign`,
906
+ body,
907
+ });
908
+ },
909
+ /**
910
+ * trigger ASK_RETURN_TO_MAIN event when main session requested
911
+ * @param {Object} breakout
912
+ * @returns {void}
913
+ */
914
+ triggerReturnToMainEvent(breakout) {
915
+ if (breakout.isMain && breakout.requested) {
916
+ this.trigger(BREAKOUTS.EVENTS.ASK_RETURN_TO_MAIN);
917
+ }
918
+ },
919
+ });
920
+
921
+ export default Breakouts;