@webex/plugin-meetings 2.59.8-next.2 → 2.60.0-next.1

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