@webex/plugin-meetings 3.0.0-beta.26 → 3.0.0-beta.261

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 (361) 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 +49 -0
  5. package/dist/annotation/constants.js.map +1 -0
  6. package/dist/annotation/index.js +342 -0
  7. package/dist/annotation/index.js.map +1 -0
  8. package/dist/breakouts/breakout.js +114 -14
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/edit-lock-error.js +52 -0
  11. package/dist/breakouts/edit-lock-error.js.map +1 -0
  12. package/dist/breakouts/events.js +45 -0
  13. package/dist/breakouts/events.js.map +1 -0
  14. package/dist/breakouts/index.js +841 -19
  15. package/dist/breakouts/index.js.map +1 -1
  16. package/dist/breakouts/request.js +78 -0
  17. package/dist/breakouts/request.js.map +1 -0
  18. package/dist/breakouts/utils.js +67 -0
  19. package/dist/breakouts/utils.js.map +1 -0
  20. package/dist/common/errors/webex-errors.js +28 -7
  21. package/dist/common/errors/webex-errors.js.map +1 -1
  22. package/dist/common/logs/logger-proxy.js +1 -1
  23. package/dist/common/logs/logger-proxy.js.map +1 -1
  24. package/dist/common/queue.js +24 -9
  25. package/dist/common/queue.js.map +1 -1
  26. package/dist/config.js +5 -10
  27. package/dist/config.js.map +1 -1
  28. package/dist/constants.js +196 -28
  29. package/dist/constants.js.map +1 -1
  30. package/dist/controls-options-manager/enums.js +14 -2
  31. package/dist/controls-options-manager/enums.js.map +1 -1
  32. package/dist/controls-options-manager/index.js +109 -15
  33. package/dist/controls-options-manager/index.js.map +1 -1
  34. package/dist/controls-options-manager/types.js +7 -0
  35. package/dist/controls-options-manager/types.js.map +1 -0
  36. package/dist/controls-options-manager/util.js +309 -18
  37. package/dist/controls-options-manager/util.js.map +1 -1
  38. package/dist/index.js +112 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/interpretation/collection.js +23 -0
  41. package/dist/interpretation/collection.js.map +1 -0
  42. package/dist/interpretation/index.js +366 -0
  43. package/dist/interpretation/index.js.map +1 -0
  44. package/dist/interpretation/siLanguage.js +25 -0
  45. package/dist/interpretation/siLanguage.js.map +1 -0
  46. package/dist/locus-info/controlsUtils.js +91 -2
  47. package/dist/locus-info/controlsUtils.js.map +1 -1
  48. package/dist/locus-info/index.js +381 -62
  49. package/dist/locus-info/index.js.map +1 -1
  50. package/dist/locus-info/infoUtils.js +7 -1
  51. package/dist/locus-info/infoUtils.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 +224 -63
  55. package/dist/locus-info/parser.js.map +1 -1
  56. package/dist/locus-info/selfUtils.js +89 -14
  57. package/dist/locus-info/selfUtils.js.map +1 -1
  58. package/dist/media/index.js +58 -116
  59. package/dist/media/index.js.map +1 -1
  60. package/dist/media/properties.js +60 -121
  61. package/dist/media/properties.js.map +1 -1
  62. package/dist/meeting/in-meeting-actions.js +82 -2
  63. package/dist/meeting/in-meeting-actions.js.map +1 -1
  64. package/dist/meeting/index.js +3022 -2795
  65. package/dist/meeting/index.js.map +1 -1
  66. package/dist/meeting/locusMediaRequest.js +292 -0
  67. package/dist/meeting/locusMediaRequest.js.map +1 -0
  68. package/dist/meeting/muteState.js +230 -124
  69. package/dist/meeting/muteState.js.map +1 -1
  70. package/dist/meeting/request.js +256 -196
  71. package/dist/meeting/request.js.map +1 -1
  72. package/dist/meeting/util.js +601 -417
  73. package/dist/meeting/util.js.map +1 -1
  74. package/dist/meeting-info/index.js +70 -7
  75. package/dist/meeting-info/index.js.map +1 -1
  76. package/dist/meeting-info/meeting-info-v2.js +189 -51
  77. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  78. package/dist/meeting-info/util.js +1 -1
  79. package/dist/meeting-info/util.js.map +1 -1
  80. package/dist/meeting-info/utilv2.js +36 -36
  81. package/dist/meeting-info/utilv2.js.map +1 -1
  82. package/dist/meetings/collection.js +22 -0
  83. package/dist/meetings/collection.js.map +1 -1
  84. package/dist/meetings/index.js +372 -90
  85. package/dist/meetings/index.js.map +1 -1
  86. package/dist/meetings/meetings.types.js +7 -0
  87. package/dist/meetings/meetings.types.js.map +1 -0
  88. package/dist/meetings/request.js +2 -0
  89. package/dist/meetings/request.js.map +1 -1
  90. package/dist/meetings/util.js +88 -1
  91. package/dist/meetings/util.js.map +1 -1
  92. package/dist/member/index.js +49 -0
  93. package/dist/member/index.js.map +1 -1
  94. package/dist/member/types.js +25 -0
  95. package/dist/member/types.js.map +1 -0
  96. package/dist/member/util.js +121 -25
  97. package/dist/member/util.js.map +1 -1
  98. package/dist/members/collection.js +10 -0
  99. package/dist/members/collection.js.map +1 -1
  100. package/dist/members/index.js +86 -5
  101. package/dist/members/index.js.map +1 -1
  102. package/dist/members/request.js +106 -38
  103. package/dist/members/request.js.map +1 -1
  104. package/dist/members/types.js +15 -0
  105. package/dist/members/types.js.map +1 -0
  106. package/dist/members/util.js +316 -233
  107. package/dist/members/util.js.map +1 -1
  108. package/dist/metrics/constants.js +10 -5
  109. package/dist/metrics/constants.js.map +1 -1
  110. package/dist/metrics/index.js +1 -468
  111. package/dist/metrics/index.js.map +1 -1
  112. package/dist/multistream/mediaRequestManager.js +238 -49
  113. package/dist/multistream/mediaRequestManager.js.map +1 -1
  114. package/dist/multistream/receiveSlot.js +49 -16
  115. package/dist/multistream/receiveSlot.js.map +1 -1
  116. package/dist/multistream/receiveSlotManager.js +52 -34
  117. package/dist/multistream/receiveSlotManager.js.map +1 -1
  118. package/dist/multistream/remoteMedia.js +44 -18
  119. package/dist/multistream/remoteMedia.js.map +1 -1
  120. package/dist/multistream/remoteMediaGroup.js +60 -3
  121. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  122. package/dist/multistream/remoteMediaManager.js +209 -59
  123. package/dist/multistream/remoteMediaManager.js.map +1 -1
  124. package/dist/multistream/sendSlotManager.js +233 -0
  125. package/dist/multistream/sendSlotManager.js.map +1 -0
  126. package/dist/reachability/index.js +161 -57
  127. package/dist/reachability/index.js.map +1 -1
  128. package/dist/reachability/request.js +17 -8
  129. package/dist/reachability/request.js.map +1 -1
  130. package/dist/reconnection-manager/index.js +199 -154
  131. package/dist/reconnection-manager/index.js.map +1 -1
  132. package/dist/recording-controller/index.js +21 -2
  133. package/dist/recording-controller/index.js.map +1 -1
  134. package/dist/recording-controller/util.js +9 -8
  135. package/dist/recording-controller/util.js.map +1 -1
  136. package/dist/roap/index.js +23 -29
  137. package/dist/roap/index.js.map +1 -1
  138. package/dist/roap/request.js +112 -97
  139. package/dist/roap/request.js.map +1 -1
  140. package/dist/roap/turnDiscovery.js +96 -36
  141. package/dist/roap/turnDiscovery.js.map +1 -1
  142. package/dist/rtcMetrics/constants.js +12 -0
  143. package/dist/rtcMetrics/constants.js.map +1 -0
  144. package/dist/rtcMetrics/index.js +117 -0
  145. package/dist/rtcMetrics/index.js.map +1 -0
  146. package/dist/statsAnalyzer/index.js +51 -34
  147. package/dist/statsAnalyzer/index.js.map +1 -1
  148. package/dist/statsAnalyzer/mqaUtil.js +6 -6
  149. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  150. package/dist/types/annotation/annotation.types.d.ts +42 -0
  151. package/dist/types/annotation/constants.d.ts +31 -0
  152. package/dist/types/annotation/index.d.ts +117 -0
  153. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  154. package/dist/types/breakouts/events.d.ts +8 -0
  155. package/dist/types/breakouts/request.d.ts +22 -0
  156. package/dist/types/breakouts/utils.d.ts +15 -0
  157. package/dist/types/common/errors/webex-errors.d.ts +13 -1
  158. package/dist/types/common/queue.d.ts +9 -7
  159. package/dist/types/config.d.ts +1 -6
  160. package/dist/types/constants.d.ts +155 -21
  161. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  162. package/dist/types/controls-options-manager/index.d.ts +17 -1
  163. package/dist/types/controls-options-manager/types.d.ts +43 -0
  164. package/dist/types/controls-options-manager/util.d.ts +1 -7
  165. package/dist/types/index.d.ts +6 -4
  166. package/dist/types/interpretation/collection.d.ts +5 -0
  167. package/dist/types/interpretation/index.d.ts +5 -0
  168. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  169. package/dist/types/locus-info/index.d.ts +57 -4
  170. package/dist/types/locus-info/parser.d.ts +65 -6
  171. package/dist/types/media/index.d.ts +2 -0
  172. package/dist/types/media/properties.d.ts +34 -48
  173. package/dist/types/meeting/in-meeting-actions.d.ts +82 -2
  174. package/dist/types/meeting/index.d.ts +344 -506
  175. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  176. package/dist/types/meeting/muteState.d.ts +99 -23
  177. package/dist/types/meeting/request.d.ts +72 -43
  178. package/dist/types/meeting/util.d.ts +101 -1
  179. package/dist/types/meeting-info/index.d.ts +13 -1
  180. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  181. package/dist/types/meetings/collection.d.ts +8 -0
  182. package/dist/types/meetings/index.d.ts +86 -12
  183. package/dist/types/meetings/meetings.types.d.ts +4 -0
  184. package/dist/types/member/index.d.ts +13 -0
  185. package/dist/types/member/types.d.ts +32 -0
  186. package/dist/types/members/collection.d.ts +5 -0
  187. package/dist/types/members/index.d.ts +35 -2
  188. package/dist/types/members/request.d.ts +73 -9
  189. package/dist/types/members/types.d.ts +24 -0
  190. package/dist/types/members/util.d.ts +209 -1
  191. package/dist/types/metrics/constants.d.ts +9 -4
  192. package/dist/types/metrics/index.d.ts +4 -119
  193. package/dist/types/multistream/mediaRequestManager.d.ts +73 -5
  194. package/dist/types/multistream/receiveSlot.d.ts +16 -12
  195. package/dist/types/multistream/receiveSlotManager.d.ts +19 -4
  196. package/dist/types/multistream/remoteMedia.d.ts +8 -29
  197. package/dist/types/multistream/remoteMediaGroup.d.ts +0 -9
  198. package/dist/types/multistream/remoteMediaManager.d.ts +46 -2
  199. package/dist/types/multistream/sendSlotManager.d.ts +61 -0
  200. package/dist/types/reachability/index.d.ts +44 -7
  201. package/dist/types/reachability/request.d.ts +7 -3
  202. package/dist/types/reconnection-manager/index.d.ts +9 -0
  203. package/dist/types/recording-controller/index.d.ts +15 -1
  204. package/dist/types/recording-controller/util.d.ts +5 -4
  205. package/dist/types/roap/request.d.ts +15 -11
  206. package/dist/types/roap/turnDiscovery.d.ts +18 -1
  207. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  208. package/dist/types/rtcMetrics/index.d.ts +47 -0
  209. package/dist/types/statsAnalyzer/index.d.ts +6 -1
  210. package/package.json +23 -20
  211. package/src/annotation/annotation.types.ts +50 -0
  212. package/src/annotation/constants.ts +36 -0
  213. package/src/annotation/index.ts +328 -0
  214. package/src/breakouts/README.md +44 -14
  215. package/src/breakouts/breakout.ts +87 -9
  216. package/src/breakouts/edit-lock-error.ts +25 -0
  217. package/src/breakouts/events.ts +56 -0
  218. package/src/breakouts/index.ts +710 -10
  219. package/src/breakouts/request.ts +55 -0
  220. package/src/breakouts/utils.ts +57 -0
  221. package/src/common/errors/webex-errors.ts +27 -2
  222. package/src/common/logs/logger-proxy.ts +1 -1
  223. package/src/common/queue.ts +22 -8
  224. package/src/config.ts +4 -9
  225. package/src/constants.ts +178 -18
  226. package/src/controls-options-manager/enums.ts +12 -0
  227. package/src/controls-options-manager/index.ts +116 -21
  228. package/src/controls-options-manager/types.ts +59 -0
  229. package/src/controls-options-manager/util.ts +294 -14
  230. package/src/index.ts +40 -0
  231. package/src/interpretation/README.md +60 -0
  232. package/src/interpretation/collection.ts +19 -0
  233. package/src/interpretation/index.ts +332 -0
  234. package/src/interpretation/siLanguage.ts +18 -0
  235. package/src/locus-info/controlsUtils.ts +108 -0
  236. package/src/locus-info/index.ts +412 -59
  237. package/src/locus-info/infoUtils.ts +10 -2
  238. package/src/locus-info/mediaSharesUtils.ts +48 -0
  239. package/src/locus-info/parser.ts +231 -39
  240. package/src/locus-info/selfUtils.ts +81 -5
  241. package/src/media/index.ts +100 -122
  242. package/src/media/properties.ts +70 -108
  243. package/src/meeting/in-meeting-actions.ts +163 -3
  244. package/src/meeting/index.ts +2471 -2306
  245. package/src/meeting/locusMediaRequest.ts +313 -0
  246. package/src/meeting/muteState.ts +229 -131
  247. package/src/meeting/request.ts +172 -121
  248. package/src/meeting/util.ts +588 -394
  249. package/src/meeting-info/index.ts +79 -8
  250. package/src/meeting-info/meeting-info-v2.ts +168 -14
  251. package/src/meeting-info/util.ts +1 -1
  252. package/src/meeting-info/utilv2.ts +23 -23
  253. package/src/meetings/collection.ts +20 -0
  254. package/src/meetings/index.ts +414 -108
  255. package/src/meetings/meetings.types.ts +12 -0
  256. package/src/meetings/request.ts +2 -0
  257. package/src/meetings/util.ts +103 -4
  258. package/src/member/index.ts +49 -0
  259. package/src/member/types.ts +38 -0
  260. package/src/member/util.ts +127 -25
  261. package/src/members/collection.ts +8 -0
  262. package/src/members/index.ts +107 -6
  263. package/src/members/request.ts +97 -17
  264. package/src/members/types.ts +28 -0
  265. package/src/members/util.ts +319 -240
  266. package/src/metrics/constants.ts +9 -4
  267. package/src/metrics/index.ts +1 -490
  268. package/src/multistream/mediaRequestManager.ts +289 -79
  269. package/src/multistream/receiveSlot.ts +55 -18
  270. package/src/multistream/receiveSlotManager.ts +46 -24
  271. package/src/multistream/remoteMedia.ts +27 -2
  272. package/src/multistream/remoteMediaGroup.ts +59 -0
  273. package/src/multistream/remoteMediaManager.ts +148 -30
  274. package/src/multistream/sendSlotManager.ts +170 -0
  275. package/src/reachability/index.ts +165 -37
  276. package/src/reachability/request.ts +17 -8
  277. package/src/reconnection-manager/index.ts +81 -54
  278. package/src/recording-controller/index.ts +20 -3
  279. package/src/recording-controller/util.ts +26 -9
  280. package/src/roap/index.ts +23 -30
  281. package/src/roap/request.ts +100 -104
  282. package/src/roap/turnDiscovery.ts +51 -25
  283. package/src/rtcMetrics/constants.ts +3 -0
  284. package/src/rtcMetrics/index.ts +100 -0
  285. package/src/statsAnalyzer/index.ts +73 -35
  286. package/src/statsAnalyzer/mqaUtil.ts +8 -10
  287. package/test/integration/spec/converged-space-meetings.js +233 -0
  288. package/test/integration/spec/journey.js +320 -261
  289. package/test/integration/spec/space-meeting.js +76 -3
  290. package/test/unit/spec/annotation/index.ts +418 -0
  291. package/test/unit/spec/breakouts/breakout.ts +142 -24
  292. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  293. package/test/unit/spec/breakouts/events.ts +89 -0
  294. package/test/unit/spec/breakouts/index.ts +1545 -48
  295. package/test/unit/spec/breakouts/request.ts +104 -0
  296. package/test/unit/spec/breakouts/utils.js +72 -0
  297. package/test/unit/spec/common/queue.js +31 -2
  298. package/test/unit/spec/controls-options-manager/index.js +163 -0
  299. package/test/unit/spec/controls-options-manager/util.js +576 -60
  300. package/test/unit/spec/fixture/locus.js +1 -0
  301. package/test/unit/spec/interpretation/collection.ts +15 -0
  302. package/test/unit/spec/interpretation/index.ts +589 -0
  303. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  304. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  305. package/test/unit/spec/locus-info/index.js +1283 -33
  306. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  307. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  308. package/test/unit/spec/locus-info/parser.js +62 -22
  309. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  310. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  311. package/test/unit/spec/media/index.ts +104 -37
  312. package/test/unit/spec/meeting/in-meeting-actions.ts +81 -3
  313. package/test/unit/spec/meeting/index.js +4095 -1913
  314. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  315. package/test/unit/spec/meeting/muteState.js +408 -208
  316. package/test/unit/spec/meeting/request.js +440 -45
  317. package/test/unit/spec/meeting/utils.js +679 -64
  318. package/test/unit/spec/meeting-info/index.js +293 -0
  319. package/test/unit/spec/meeting-info/meetinginfov2.js +517 -5
  320. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  321. package/test/unit/spec/meetings/collection.js +14 -0
  322. package/test/unit/spec/meetings/index.js +941 -151
  323. package/test/unit/spec/meetings/utils.js +206 -2
  324. package/test/unit/spec/member/index.js +58 -4
  325. package/test/unit/spec/member/util.js +479 -35
  326. package/test/unit/spec/members/index.js +319 -1
  327. package/test/unit/spec/members/request.js +206 -27
  328. package/test/unit/spec/members/utils.js +184 -0
  329. package/test/unit/spec/metrics/index.js +1 -50
  330. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  331. package/test/unit/spec/multistream/receiveSlot.ts +72 -13
  332. package/test/unit/spec/multistream/receiveSlotManager.ts +58 -28
  333. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  334. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  335. package/test/unit/spec/multistream/remoteMediaManager.ts +326 -0
  336. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  337. package/test/unit/spec/reachability/index.ts +343 -9
  338. package/test/unit/spec/reachability/request.js +68 -0
  339. package/test/unit/spec/reconnection-manager/index.js +84 -9
  340. package/test/unit/spec/recording-controller/index.js +294 -218
  341. package/test/unit/spec/recording-controller/util.js +223 -96
  342. package/test/unit/spec/roap/index.ts +31 -51
  343. package/test/unit/spec/roap/request.ts +203 -85
  344. package/test/unit/spec/roap/turnDiscovery.ts +48 -13
  345. package/test/unit/spec/rtcMetrics/index.ts +68 -0
  346. package/test/unit/spec/stats-analyzer/index.js +29 -2
  347. package/test/utils/constants.js +9 -0
  348. package/test/utils/integrationTestUtils.js +46 -0
  349. package/test/utils/testUtils.js +0 -45
  350. package/test/utils/webex-config.js +4 -0
  351. package/test/utils/webex-test-users.js +6 -3
  352. package/dist/meeting/effectsState.js +0 -262
  353. package/dist/meeting/effectsState.js.map +0 -1
  354. package/dist/metrics/config.js +0 -299
  355. package/dist/metrics/config.js.map +0 -1
  356. package/dist/types/meeting/effectsState.d.ts +0 -42
  357. package/dist/types/metrics/config.d.ts +0 -178
  358. package/src/index.js +0 -16
  359. package/src/meeting/effectsState.ts +0 -211
  360. package/src/metrics/config.ts +0 -495
  361. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -2,14 +2,16 @@
2
2
 
3
3
  import '@webex/internal-plugin-mercury';
4
4
  import '@webex/internal-plugin-conversation';
5
+ import '@webex/internal-plugin-metrics';
5
6
  // @ts-ignore
6
7
  import {WebexPlugin} from '@webex/webex-core';
7
8
  import {setLogger} from '@webex/internal-media-core';
8
9
 
10
+ import * as mediaHelpersModule from '@webex/media-helpers';
11
+
9
12
  import 'webrtc-adapter';
10
13
 
11
14
  import Metrics from '../metrics';
12
- import {trigger, eventType} from '../metrics/config';
13
15
  import LoggerConfig from '../common/logs/logger-config';
14
16
  import StaticConfig from '../common/config';
15
17
  import LoggerProxy from '../common/logs/logger-proxy';
@@ -40,6 +42,9 @@ import {
40
42
  MEETING_REMOVED_REASON,
41
43
  _CONVERSATION_URL_,
42
44
  CONVERSATION_URL,
45
+ MEETINGNUMBER,
46
+ _JOINED_,
47
+ _MOVED_,
43
48
  } from '../constants';
44
49
  import BEHAVIORAL_METRICS from '../metrics/constants';
45
50
  import MeetingInfo from '../meeting-info';
@@ -53,6 +58,9 @@ import CaptchaError from '../common/errors/captcha-error';
53
58
 
54
59
  import MeetingCollection from './collection';
55
60
  import MeetingsUtil from './util';
61
+ import PermissionError from '../common/errors/permission';
62
+ import {INoiseReductionEffect, IVirtualBackgroundEffect} from './meetings.types';
63
+ import {SpaceIDDeprecatedError} from '../common/errors/webex-errors';
56
64
 
57
65
  let mediaLogger;
58
66
 
@@ -139,12 +147,13 @@ export default class Meetings extends WebexPlugin {
139
147
  meetingCollection: any;
140
148
  personalMeetingRoom: any;
141
149
  preferredWebexSite: any;
142
- reachability: any;
150
+ reachability: Reachability;
143
151
  registered: any;
144
152
  request: any;
145
153
  geoHintInfo: any;
146
154
  meetingInfo: any;
147
-
155
+ mediaHelpers: any;
156
+ breakoutLocusForHandleLater: any;
148
157
  namespace = MEETINGS;
149
158
 
150
159
  /**
@@ -156,6 +165,17 @@ export default class Meetings extends WebexPlugin {
156
165
  constructor(...args) {
157
166
  super(...args);
158
167
 
168
+ /**
169
+ * The webrtc-core media helpers. This is a temporary solution required for the SDK sample app
170
+ * to be able to call media helper functions.
171
+ *
172
+ * @instance
173
+ * @type {Object}
174
+ * @private
175
+ * @memberof Meetings
176
+ */
177
+ this.mediaHelpers = mediaHelpersModule;
178
+
159
179
  /**
160
180
  * The Meetings request to interact with server
161
181
  * @instance
@@ -183,15 +203,17 @@ export default class Meetings extends WebexPlugin {
183
203
  * @memberof Meetings
184
204
  */
185
205
  this.personalMeetingRoom = null;
206
+
186
207
  /**
187
- * The Reachability object to interact with server, starts as null until {@link Meeting#setReachability} is called
208
+ * The Reachability object to interact with server
188
209
  * starts as null
189
210
  * @instance
190
211
  * @type {Object}
191
212
  * @private
192
213
  * @memberof Meetings
193
214
  */
194
- this.reachability = null;
215
+ // @ts-ignore
216
+ this.reachability = new Reachability(this.webex);
195
217
 
196
218
  /**
197
219
  * If the meetings plugin has been registered and listening via {@link Meetings#register}
@@ -221,30 +243,137 @@ export default class Meetings extends WebexPlugin {
221
243
  */
222
244
  this.media = {
223
245
  getUserMedia: Media.getUserMedia,
224
- getSupportedDevice: Media.getSupportedDevice,
225
246
  };
226
247
 
227
248
  this.onReady();
228
249
  }
229
250
 
230
251
  /**
231
- * handle locus events and takes meeting actions with them as they come in
252
+ * check whether you need to handle this main session's locus data or not
253
+ * @param {Object} meeting current meeting data
254
+ * @param {Object} newLocus new locus data
255
+ * @returns {boolean}
256
+ * @private
257
+ * @memberof Meetings
258
+ */
259
+ private isNeedHandleMainLocus(meeting: any, newLocus: any) {
260
+ const breakoutUrl = newLocus.controls?.breakout?.url;
261
+ const breakoutLocus = this.meetingCollection.getActiveBreakoutLocus(breakoutUrl);
262
+
263
+ const isSelfJoined = newLocus?.self?.state === _JOINED_;
264
+ const isSelfMoved = newLocus?.self?.state === _LEFT_ && newLocus?.self?.reason === _MOVED_;
265
+ // @ts-ignore
266
+ const deviceFromNewLocus = MeetingsUtil.getThisDevice(newLocus, this.webex.internal.device.url);
267
+ const isResourceMovedOnThisDevice =
268
+ deviceFromNewLocus?.state === _LEFT_ && deviceFromNewLocus?.reason === _MOVED_;
269
+
270
+ const isNewLocusJoinThisDevice = MeetingsUtil.joinedOnThisDevice(
271
+ meeting,
272
+ newLocus,
273
+ // @ts-ignore
274
+ this.webex.internal.device.url
275
+ );
276
+ const isBreakoutLocusJoinThisDevice =
277
+ breakoutLocus?.joinedWith?.correlationId &&
278
+ breakoutLocus.joinedWith.correlationId === meeting?.correlationId;
279
+
280
+ if (isSelfJoined && isNewLocusJoinThisDevice) {
281
+ LoggerProxy.logger.log(
282
+ 'Meetings:index#isNeedHandleMainLocus --> self this device shown as JOINED in the main session'
283
+ );
284
+ if (breakoutLocus?.joinedWith && deviceFromNewLocus) {
285
+ const breakoutReplaceAt =
286
+ breakoutLocus.joinedWith.replaces?.length > 0
287
+ ? breakoutLocus.joinedWith.replaces[0].replaceAt
288
+ : '';
289
+ const newLocusReplaceAt =
290
+ deviceFromNewLocus.replaces?.length > 0 ? deviceFromNewLocus.replaces[0].replaceAt : '';
291
+ if (breakoutReplaceAt && newLocusReplaceAt && breakoutReplaceAt > newLocusReplaceAt) {
292
+ LoggerProxy.logger.log(
293
+ `Meetings:index#isNeedHandleMainLocus --> this is expired main joined status locus_dto replacedAt ${newLocusReplaceAt} bo replacedAt ${breakoutReplaceAt}`
294
+ );
295
+
296
+ return false;
297
+ }
298
+ }
299
+
300
+ return true;
301
+ }
302
+ if (isBreakoutLocusJoinThisDevice) {
303
+ LoggerProxy.logger.log(
304
+ `Meetings:index#isNeedHandleMainLocus --> there is active breakout session and joined on this device, and don't need to handle main session: ${breakoutUrl}`
305
+ );
306
+
307
+ return false;
308
+ }
309
+ if (isSelfMoved && (newLocus?.self?.removed || isResourceMovedOnThisDevice)) {
310
+ LoggerProxy.logger.log(
311
+ 'Meetings:index#isNeedHandleMainLocus --> self moved main locus with self removed status or with device resource moved, not need to handle'
312
+ );
313
+
314
+ return false;
315
+ }
316
+ if (isSelfJoined && isResourceMovedOnThisDevice) {
317
+ LoggerProxy.logger.log(
318
+ 'Meetings:index#isNeedHandleMainLocus --> self device left&moved in main locus with self joined status, not need to handle'
319
+ );
320
+
321
+ return false;
322
+ }
323
+ LoggerProxy.logger.log(
324
+ 'Meetings:index#isNeedHandleMainLocus --> this is a normal main session locusDTO update case'
325
+ );
326
+
327
+ return true;
328
+ }
329
+
330
+ /**
331
+ * check whether you need to handle this locus data or not
332
+ * @param {Object} meeting old locus data
333
+ * @param {Object} newLocus new locus data
334
+ * @returns {boolean}
335
+ * @private
336
+ * @memberof Meetings
337
+ */
338
+ private isNeedHandleLocusDTO(meeting: any, newLocus: any) {
339
+ if (newLocus) {
340
+ const isNewLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(newLocus);
341
+ const isSelfMoved = newLocus?.self?.state === _LEFT_ && newLocus?.self?.reason === _MOVED_;
342
+ if (!meeting) {
343
+ if (isNewLocusAsBreakout) {
344
+ LoggerProxy.logger.log(
345
+ `Meetings:index#isNeedHandleLocusDTO --> the first breakout session locusDTO active status: ${newLocus.fullState?.active}`
346
+ );
347
+
348
+ return newLocus.self?.state === _JOINED_;
349
+ }
350
+
351
+ return this.isNeedHandleMainLocus(meeting, newLocus);
352
+ }
353
+ if (!isNewLocusAsBreakout) {
354
+ return this.isNeedHandleMainLocus(meeting, newLocus);
355
+ }
356
+
357
+ return !isSelfMoved;
358
+ }
359
+
360
+ return true;
361
+ }
362
+
363
+ /**
364
+ * get corresponding meeting object by locus data
232
365
  * @param {Object} data a locus event
233
366
  * @param {String} data.locusUrl
234
367
  * @param {Object} data.locus
235
- * @param {Boolean} useRandomDelayForInfo whether a random delay should be added to fetching meeting info
236
- * @param {String} data.eventType
237
- * @returns {undefined}
368
+ * @returns {Object}
238
369
  * @private
239
370
  * @memberof Meetings
240
371
  */
241
- private handleLocusEvent(data: {locusUrl: string; locus: any}, useRandomDelayForInfo = false) {
242
- let meeting = null;
243
-
372
+ getCorrespondingMeetingByLocus(data) {
244
373
  // getting meeting by correlationId. This will happen for the new event
245
374
  // Either the locus
246
375
  // TODO : Add check for the callBack Address
247
- meeting =
376
+ return (
248
377
  this.meetingCollection.getByKey(LOCUS_URL, data.locusUrl) ||
249
378
  // @ts-ignore
250
379
  this.meetingCollection.getByKey(
@@ -260,7 +389,24 @@ export default class Meetings extends WebexPlugin {
260
389
  ) ||
261
390
  (data.locus.info?.isUnifiedSpaceMeeting
262
391
  ? undefined
263
- : this.meetingCollection.getByKey(CONVERSATION_URL, data.locus.conversationUrl));
392
+ : this.meetingCollection.getByKey(CONVERSATION_URL, data.locus.conversationUrl)) ||
393
+ this.meetingCollection.getByKey(MEETINGNUMBER, data.locus?.info?.webExMeetingId)
394
+ );
395
+ }
396
+
397
+ /**
398
+ * handle locus events and takes meeting actions with them as they come in
399
+ * @param {Object} data a locus event
400
+ * @param {String} data.locusUrl
401
+ * @param {Object} data.locus
402
+ * @param {Boolean} useRandomDelayForInfo whether a random delay should be added to fetching meeting info
403
+ * @param {String} data.eventType
404
+ * @returns {undefined}
405
+ * @private
406
+ * @memberof Meetings
407
+ */
408
+ private handleLocusEvent(data: {locusUrl: string; locus: any}, useRandomDelayForInfo = false) {
409
+ let meeting = this.getCorrespondingMeetingByLocus(data);
264
410
 
265
411
  // Special case when locus has got replaced, This only happend once if a replace locus exists
266
412
  // https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-changing-mid-call
@@ -273,6 +419,16 @@ export default class Meetings extends WebexPlugin {
273
419
  );
274
420
  }
275
421
 
422
+ if (meeting && !MeetingsUtil.isBreakoutLocusDTO(data.locus)) {
423
+ meeting.locusInfo.updateMainSessionLocusCache(data.locus);
424
+ }
425
+ if (!this.isNeedHandleLocusDTO(meeting, data.locus)) {
426
+ LoggerProxy.logger.log(
427
+ `Meetings:index#handleLocusEvent --> doesn't need to process locus event`
428
+ );
429
+
430
+ return;
431
+ }
276
432
  if (!meeting) {
277
433
  // TODO: create meeting when we get a meeting object
278
434
  // const checkForEnded = (locus) => {
@@ -329,6 +485,7 @@ export default class Meetings extends WebexPlugin {
329
485
 
330
486
  // It's a new meeting so initialize the locus data
331
487
  meeting.locusInfo.initialSetup(data.locus);
488
+ this.checkHandleBreakoutLocus(data.locus);
332
489
  })
333
490
  .catch((e) => {
334
491
  LoggerProxy.logger.error(e);
@@ -338,10 +495,15 @@ export default class Meetings extends WebexPlugin {
338
495
  // because the other user left so before sending 'added' event make sure it exists in the collection
339
496
 
340
497
  if (this.getMeetingByType(_ID_, meeting.id)) {
341
- Metrics.postEvent({
342
- event: eventType.REMOTE_STARTED,
343
- meeting,
344
- data: {trigger: trigger.MERCURY_EVENT},
498
+ // @ts-ignore
499
+ this.webex.internal.newMetrics.submitClientEvent({
500
+ name: 'client.call.remote-started',
501
+ payload: {
502
+ trigger: 'mercury-event',
503
+ },
504
+ options: {
505
+ meetingId: meeting.id,
506
+ },
345
507
  });
346
508
  Trigger.trigger(
347
509
  this,
@@ -494,7 +656,7 @@ export default class Meetings extends WebexPlugin {
494
656
 
495
657
  MeetingsUtil.checkH264Support({disableNotifications: true});
496
658
  // @ts-ignore
497
- Metrics.initialSetup(this.meetingCollection, this.webex);
659
+ Metrics.initialSetup(this.webex);
498
660
  });
499
661
  }
500
662
 
@@ -663,6 +825,36 @@ export default class Meetings extends WebexPlugin {
663
825
  );
664
826
  }
665
827
 
828
+ /**
829
+ * Creates a noise reduction effect
830
+ *
831
+ * @param {INoiseReductionEffect} options optional custom effect options
832
+ * @returns {Promise<effect>} noise reduction effect.
833
+ * @public
834
+ * @memberof Meetings
835
+ */
836
+ createNoiseReductionEffect = async (options?: INoiseReductionEffect) => {
837
+ // @ts-ignore
838
+ const authToken = this.webex.credentials.supertoken.access_token;
839
+
840
+ return new mediaHelpersModule.NoiseReductionEffect({authToken, ...options});
841
+ };
842
+
843
+ /**
844
+ * Creates a virtual background effect
845
+ *
846
+ * @param {IVirtualBackgroundEffect} options optional custom effect options
847
+ * @returns {Promise<effect>} virtual background effect.
848
+ * @public
849
+ * @memberof Meetings
850
+ */
851
+ createVirtualBackgroundEffect = async (options?: IVirtualBackgroundEffect) => {
852
+ // @ts-ignore
853
+ const authToken = this.webex.credentials.supertoken.access_token;
854
+
855
+ return new mediaHelpersModule.VirtualBackgroundEffect({authToken, ...options});
856
+ };
857
+
666
858
  /**
667
859
  * Uploads logs to the webex services for tracking
668
860
  * @param {Object} [options={}]
@@ -695,6 +887,7 @@ export default class Meetings extends WebexPlugin {
695
887
  'Meetings:index#uploadLogs --> Upload logs for meeting completed.',
696
888
  uploadResult
697
889
  );
890
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPLOAD_LOGS_SUCCESS, options);
698
891
  Trigger.trigger(
699
892
  this,
700
893
  {
@@ -729,8 +922,7 @@ export default class Meetings extends WebexPlugin {
729
922
  );
730
923
 
731
924
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.UPLOAD_LOGS_FAILURE, {
732
- // @ts-ignore - seems like typo
733
- meetingId: options.meetingsId,
925
+ ...options,
734
926
  reason: uploadError.message,
735
927
  stack: uploadError.stack,
736
928
  code: uploadError.code,
@@ -738,17 +930,6 @@ export default class Meetings extends WebexPlugin {
738
930
  });
739
931
  }
740
932
 
741
- /**
742
- * initializes the reachability instance for Meetings
743
- * @returns {undefined}
744
- * @public
745
- * @memberof Meetings
746
- */
747
- setReachability() {
748
- // @ts-ignore
749
- this.reachability = new Reachability(this.webex);
750
- }
751
-
752
933
  /**
753
934
  * gets the reachability instance for Meetings
754
935
  * @returns {Reachability}
@@ -766,10 +947,6 @@ export default class Meetings extends WebexPlugin {
766
947
  * @memberof Meetings
767
948
  */
768
949
  startReachability() {
769
- if (!this.reachability) {
770
- this.setReachability();
771
- }
772
-
773
950
  return this.getReachability().gatherReachability();
774
951
  }
775
952
 
@@ -797,6 +974,29 @@ export default class Meetings extends WebexPlugin {
797
974
  if (res) {
798
975
  this.preferredWebexSite = MeetingsUtil.parseDefaultSiteFromMeetingPreferences(res);
799
976
  }
977
+
978
+ // fall back to getting the preferred site from the user information
979
+ if (!this.preferredWebexSite) {
980
+ // @ts-ignore
981
+ return this.webex.internal.user
982
+ .get()
983
+ .then((user) => {
984
+ const preferredWebexSite =
985
+ user?.userPreferences?.userPreferencesItems?.preferredWebExSite;
986
+ if (preferredWebexSite) {
987
+ this.preferredWebexSite = preferredWebexSite;
988
+ } else {
989
+ throw new Error('site not found');
990
+ }
991
+ })
992
+ .catch(() => {
993
+ LoggerProxy.logger.error(
994
+ 'Failed to fetch preferred site from user - no site will be set'
995
+ );
996
+ });
997
+ }
998
+
999
+ return Promise.resolve();
800
1000
  });
801
1001
  }
802
1002
 
@@ -838,14 +1038,22 @@ export default class Meetings extends WebexPlugin {
838
1038
 
839
1039
  /**
840
1040
  * Create a meeting.
841
- * @param {string} destination - sipURL, spaceId, phonenumber, or locus object}
1041
+ * @param {string} destination - sipURL, phonenumber, or locus object}
842
1042
  * @param {string} [type] - the optional specified type, such as locusId
843
1043
  * @param {Boolean} useRandomDelayForInfo - whether a random delay should be added to fetching meeting info
1044
+ * @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
1045
+ * @param {string} correlationId - the optional specified correlationId
844
1046
  * @returns {Promise<Meeting>} A new Meeting.
845
1047
  * @public
846
1048
  * @memberof Meetings
847
1049
  */
848
- public create(destination: string, type: string = null, useRandomDelayForInfo = false) {
1050
+ public create(
1051
+ destination: string,
1052
+ type: string = null,
1053
+ useRandomDelayForInfo = false,
1054
+ infoExtraParams = {},
1055
+ correlationId: string = undefined
1056
+ ) {
849
1057
  // TODO: type should be from a dictionary
850
1058
 
851
1059
  // Validate meeting information based on the provided destination and
@@ -857,9 +1065,12 @@ export default class Meetings extends WebexPlugin {
857
1065
  .fetchInfoOptions(destination, type)
858
1066
  // Catch a failure to fetch info options.
859
1067
  .catch((error) => {
860
- LoggerProxy.logger.info(
861
- `Meetings:index#create --> INFO, unable to determine info options: ${error.message}`
1068
+ LoggerProxy.logger.error(
1069
+ `Meetings:index#create --> ERROR, unable to determine info options: ${error.message}`
862
1070
  );
1071
+ if (error instanceof SpaceIDDeprecatedError) {
1072
+ throw new SpaceIDDeprecatedError();
1073
+ }
863
1074
  })
864
1075
  .then((options: any = {}) => {
865
1076
  // Normalize the destination.
@@ -890,48 +1101,52 @@ export default class Meetings extends WebexPlugin {
890
1101
  // Validate if a meeting was found.
891
1102
  if (!meeting) {
892
1103
  // Create a meeting based on the normalized destination and type.
893
- return this.createMeeting(targetDest, type, useRandomDelayForInfo).then(
894
- (createdMeeting: any) => {
895
- // If the meeting was successfully created.
896
- if (createdMeeting && createdMeeting.on) {
897
- // Create a destruction event for the meeting.
898
- createdMeeting.on(EVENTS.DESTROY_MEETING, (payload) => {
899
- // @ts-ignore
900
- if (this.config.autoUploadLogs) {
901
- this.uploadLogs({
902
- callStart: createdMeeting.locusInfo?.fullState?.lastActive,
903
- correlationId: createdMeeting.correlationId,
904
- feedbackId: createdMeeting.correlationId,
905
- locusId: createdMeeting.locusId,
906
- meetingId: createdMeeting.locusInfo?.info?.webExMeetingId,
907
- }).then(() => this.destroy(createdMeeting, payload.reason));
908
- } else {
909
- this.destroy(createdMeeting, payload.reason);
910
- }
911
- });
912
-
913
- createdMeeting.on(EVENTS.REQUEST_UPLOAD_LOGS, (meetingInstance) => {
914
- // @ts-ignore
915
- if (this.config.autoUploadLogs) {
916
- this.uploadLogs({
917
- callStart: meetingInstance?.locusInfo?.fullState?.lastActive,
918
- correlationId: meetingInstance.correlationId,
919
- feedbackId: meetingInstance.correlationId,
920
- locusId: meetingInstance.locusId,
921
- meetingId: meetingInstance.locusInfo?.info?.webExMeetingId,
922
- });
923
- }
924
- });
925
- } else {
926
- LoggerProxy.logger.error(
927
- `Meetings:index#create --> ERROR, meeting does not have on method, will not be destroyed, meeting cleanup impossible for meeting: ${meeting}`
928
- );
929
- }
930
-
931
- // Return the newly created meeting.
932
- return Promise.resolve(createdMeeting);
1104
+ return this.createMeeting(
1105
+ targetDest,
1106
+ type,
1107
+ useRandomDelayForInfo,
1108
+ infoExtraParams,
1109
+ correlationId
1110
+ ).then((createdMeeting: any) => {
1111
+ // If the meeting was successfully created.
1112
+ if (createdMeeting && createdMeeting.on) {
1113
+ // Create a destruction event for the meeting.
1114
+ createdMeeting.on(EVENTS.DESTROY_MEETING, (payload) => {
1115
+ // @ts-ignore
1116
+ if (this.config.autoUploadLogs) {
1117
+ this.uploadLogs({
1118
+ callStart: createdMeeting.locusInfo?.fullState?.lastActive,
1119
+ correlationId: createdMeeting.correlationId,
1120
+ feedbackId: createdMeeting.correlationId,
1121
+ locusId: createdMeeting.locusId,
1122
+ meetingId: createdMeeting.locusInfo?.info?.webExMeetingId,
1123
+ }).then(() => this.destroy(createdMeeting, payload.reason));
1124
+ } else {
1125
+ this.destroy(createdMeeting, payload.reason);
1126
+ }
1127
+ });
1128
+
1129
+ createdMeeting.on(EVENTS.REQUEST_UPLOAD_LOGS, (meetingInstance) => {
1130
+ // @ts-ignore
1131
+ if (this.config.autoUploadLogs) {
1132
+ this.uploadLogs({
1133
+ callStart: meetingInstance?.locusInfo?.fullState?.lastActive,
1134
+ correlationId: meetingInstance.correlationId,
1135
+ feedbackId: meetingInstance.correlationId,
1136
+ locusId: meetingInstance.locusId,
1137
+ meetingId: meetingInstance.locusInfo?.info?.webExMeetingId,
1138
+ });
1139
+ }
1140
+ });
1141
+ } else {
1142
+ LoggerProxy.logger.error(
1143
+ `Meetings:index#create --> ERROR, meeting does not have on method, will not be destroyed, meeting cleanup impossible for meeting: ${meeting}`
1144
+ );
933
1145
  }
934
- );
1146
+
1147
+ // Return the newly created meeting.
1148
+ return Promise.resolve(createdMeeting);
1149
+ });
935
1150
  }
936
1151
 
937
1152
  // Return the existing meeting.
@@ -944,6 +1159,8 @@ export default class Meetings extends WebexPlugin {
944
1159
  * @param {String} destination see create()
945
1160
  * @param {String} type see create()
946
1161
  * @param {Boolean} useRandomDelayForInfo whether a random delay should be added to fetching meeting info
1162
+ * @param {Object} infoExtraParams extra parameters to be provided when fetching meeting info
1163
+ * @param {String} correlationId the optional specified correlationId
947
1164
  * @returns {Promise} a new meeting instance complete with meeting info and destination
948
1165
  * @private
949
1166
  * @memberof Meetings
@@ -951,7 +1168,9 @@ export default class Meetings extends WebexPlugin {
951
1168
  private async createMeeting(
952
1169
  destination: any,
953
1170
  type: string = null,
954
- useRandomDelayForInfo = false
1171
+ useRandomDelayForInfo = false,
1172
+ infoExtraParams = {},
1173
+ correlationId: string = undefined
955
1174
  ) {
956
1175
  const meeting = new Meeting(
957
1176
  {
@@ -965,6 +1184,7 @@ export default class Meetings extends WebexPlugin {
965
1184
  meetingInfoProvider: this.meetingInfo,
966
1185
  destination,
967
1186
  destinationType: type,
1187
+ correlationId,
968
1188
  },
969
1189
  {
970
1190
  // @ts-ignore
@@ -999,15 +1219,26 @@ export default class Meetings extends WebexPlugin {
999
1219
 
1000
1220
  if (enableUnifiedMeetings && !isMeetingActive && useRandomDelayForInfo && waitingTime > 0) {
1001
1221
  meeting.fetchMeetingInfoTimeoutId = setTimeout(
1002
- () => meeting.fetchMeetingInfo({}),
1222
+ () =>
1223
+ meeting.fetchMeetingInfo({
1224
+ extraParams: infoExtraParams,
1225
+ sendCAevents: !!correlationId, // if client sends correlation id as argument of public create(), then it means that this meeting creation is part of a pre-join intent from user
1226
+ }),
1003
1227
  waitingTime
1004
1228
  );
1005
1229
  meeting.parseMeetingInfo(undefined, destination);
1006
1230
  } else {
1007
- await meeting.fetchMeetingInfo({});
1231
+ await meeting.fetchMeetingInfo({
1232
+ extraParams: infoExtraParams,
1233
+ sendCAevents: !!correlationId, // if client sends correlation id as argument of public create(), then it means that this meeting creation is part of a pre-join intent from user
1234
+ });
1008
1235
  }
1009
1236
  } catch (err) {
1010
- if (!(err instanceof CaptchaError) && !(err instanceof PasswordError)) {
1237
+ if (
1238
+ !(err instanceof CaptchaError) &&
1239
+ !(err instanceof PasswordError) &&
1240
+ !(err instanceof PermissionError)
1241
+ ) {
1011
1242
  // if there is no meeting info we assume its a 1:1 call or wireless share
1012
1243
  LoggerProxy.logger.info(
1013
1244
  `Meetings:index#createMeeting --> Info Unable to fetch meeting info for ${destination}.`
@@ -1064,7 +1295,7 @@ export default class Meetings extends WebexPlugin {
1064
1295
  //
1065
1296
  // Our job is to determine the appropriate one
1066
1297
  // and its corresponding service so that developers
1067
- // need only sipURL or spaceID to get a meeting
1298
+ // need only sipURL to get a meeting
1068
1299
  // and its ID, but have the option to use createWithType()
1069
1300
  // and specify those types to get meetingInfo
1070
1301
  }
@@ -1108,33 +1339,108 @@ export default class Meetings extends WebexPlugin {
1108
1339
  * @memberof Meetings
1109
1340
  */
1110
1341
  public syncMeetings() {
1111
- return this.request.getActiveMeetings().then((locusArray) => {
1112
- const activeLocusUrl = [];
1113
-
1114
- if (locusArray?.loci && locusArray.loci.length > 0) {
1115
- locusArray.loci.forEach((locus) => {
1116
- activeLocusUrl.push(locus.url);
1117
- this.handleLocusEvent({
1118
- locus,
1119
- locusUrl: locus.url,
1342
+ return this.request
1343
+ .getActiveMeetings()
1344
+ .then((locusArray) => {
1345
+ const activeLocusUrl = [];
1346
+
1347
+ if (locusArray?.loci && locusArray.loci.length > 0) {
1348
+ const lociToUpdate = this.sortLocusArrayToUpdate(locusArray.loci);
1349
+ lociToUpdate.forEach((locus) => {
1350
+ activeLocusUrl.push(locus.url);
1351
+ this.handleLocusEvent({
1352
+ locus,
1353
+ locusUrl: locus.url,
1354
+ });
1120
1355
  });
1121
- });
1122
- }
1123
- const meetingsCollection = this.meetingCollection.getAll();
1124
-
1125
- if (Object.keys(meetingsCollection).length > 0) {
1126
- // Some time the mercury event is missed after mercury reconnect
1127
- // if sync returns no locus then clear all the meetings
1128
- for (const meeting of Object.values(meetingsCollection)) {
1129
- // @ts-ignore
1130
- if (!activeLocusUrl.includes(meeting.locusUrl)) {
1131
- // destroy function also uploads logs
1356
+ }
1357
+ const meetingsCollection = this.meetingCollection.getAll();
1358
+
1359
+ if (Object.keys(meetingsCollection).length > 0) {
1360
+ // Some time the mercury event is missed after mercury reconnect
1361
+ // if sync returns no locus then clear all the meetings
1362
+ for (const meeting of Object.values(meetingsCollection)) {
1132
1363
  // @ts-ignore
1133
- this.destroy(meeting, MEETING_REMOVED_REASON.NO_MEETINGS_TO_SYNC);
1364
+ if (!activeLocusUrl.includes(meeting.locusUrl)) {
1365
+ // destroy function also uploads logs
1366
+ // @ts-ignore
1367
+ this.destroy(meeting, MEETING_REMOVED_REASON.NO_MEETINGS_TO_SYNC);
1368
+ }
1134
1369
  }
1135
1370
  }
1371
+ })
1372
+ .catch((error) => {
1373
+ LoggerProxy.logger.error(
1374
+ `Meetings:index#syncMeetings --> failed to sync meetings, ${error}`
1375
+ );
1376
+ throw new Error(error);
1377
+ });
1378
+ }
1379
+
1380
+ /**
1381
+ * sort out locus array for initial creating
1382
+ * @param {Array} loci original locus array
1383
+ * @returns {undefined}
1384
+ * @public
1385
+ * @memberof Meetings
1386
+ */
1387
+ sortLocusArrayToUpdate(loci: any[]) {
1388
+ const mainLoci = loci.filter((locus) => !MeetingsUtil.isBreakoutLocusDTO(locus));
1389
+ const breakoutLoci = loci.filter((locus) => MeetingsUtil.isValidBreakoutLocus(locus));
1390
+ this.breakoutLocusForHandleLater = [];
1391
+ const lociToUpdate = [...mainLoci];
1392
+ breakoutLoci.forEach((breakoutLocus) => {
1393
+ const associateMainLocus = mainLoci.find(
1394
+ (mainLocus) => mainLocus.controls?.breakout?.url === breakoutLocus.controls?.breakout?.url
1395
+ );
1396
+ const existCorrespondingMeeting = this.getCorrespondingMeetingByLocus({
1397
+ locus: breakoutLocus,
1398
+ locusUrl: breakoutLocus.url,
1399
+ });
1400
+
1401
+ if (associateMainLocus && !existCorrespondingMeeting) {
1402
+ // if exists both main session and breakout session locus of the same non-exist meeting, handle main locus first,
1403
+ // after meeting create with main locus, then handle the associate breakout locus.
1404
+ // if only handle breakout locus, will miss some date
1405
+ this.breakoutLocusForHandleLater.push(breakoutLocus);
1406
+ } else {
1407
+ lociToUpdate.push(breakoutLocus);
1136
1408
  }
1137
1409
  });
1410
+
1411
+ return lociToUpdate;
1412
+ }
1413
+
1414
+ /**
1415
+ * check breakout locus which waiting for main locus's meeting to be created, then handle the breakout locus
1416
+ * @param {Object} newCreatedLocus the locus which just create meeting object of it
1417
+ * @returns {undefined}
1418
+ * @public
1419
+ * @memberof Meetings
1420
+ */
1421
+ checkHandleBreakoutLocus(newCreatedLocus) {
1422
+ if (
1423
+ !newCreatedLocus ||
1424
+ !this.breakoutLocusForHandleLater ||
1425
+ !this.breakoutLocusForHandleLater.length
1426
+ ) {
1427
+ return;
1428
+ }
1429
+ if (MeetingsUtil.isBreakoutLocusDTO(newCreatedLocus)) {
1430
+ return;
1431
+ }
1432
+ const existIndex = this.breakoutLocusForHandleLater.findIndex(
1433
+ (breakoutLocus) =>
1434
+ breakoutLocus.controls?.breakout?.url === newCreatedLocus.controls?.breakout?.url
1435
+ );
1436
+
1437
+ if (existIndex < 0) {
1438
+ return;
1439
+ }
1440
+
1441
+ const associateBreakoutLocus = this.breakoutLocusForHandleLater[existIndex];
1442
+ this.handleLocusEvent({locus: associateBreakoutLocus, locusUrl: associateBreakoutLocus.url});
1443
+ this.breakoutLocusForHandleLater.splice(existIndex, 1);
1138
1444
  }
1139
1445
 
1140
1446
  /**