@webex/plugin-meetings 3.0.0-beta.31 → 3.0.0-beta.310

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 (378) 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 +94 -15
  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 +709 -35
  15. package/dist/breakouts/index.js.map +1 -1
  16. package/dist/breakouts/utils.js +45 -1
  17. package/dist/breakouts/utils.js.map +1 -1
  18. package/dist/common/errors/no-meeting-info.js +51 -0
  19. package/dist/common/errors/no-meeting-info.js.map +1 -0
  20. package/dist/common/errors/reclaim-host-role-errors.js +158 -0
  21. package/dist/common/errors/reclaim-host-role-errors.js.map +1 -0
  22. package/dist/common/errors/webex-errors.js +48 -7
  23. package/dist/common/errors/webex-errors.js.map +1 -1
  24. package/dist/common/logs/logger-proxy.js +1 -1
  25. package/dist/common/logs/logger-proxy.js.map +1 -1
  26. package/dist/common/logs/request.js +5 -1
  27. package/dist/common/logs/request.js.map +1 -1
  28. package/dist/common/queue.js +24 -9
  29. package/dist/common/queue.js.map +1 -1
  30. package/dist/config.js +5 -11
  31. package/dist/config.js.map +1 -1
  32. package/dist/constants.js +233 -29
  33. package/dist/constants.js.map +1 -1
  34. package/dist/controls-options-manager/enums.js +14 -2
  35. package/dist/controls-options-manager/enums.js.map +1 -1
  36. package/dist/controls-options-manager/index.js +109 -15
  37. package/dist/controls-options-manager/index.js.map +1 -1
  38. package/dist/controls-options-manager/types.js +7 -0
  39. package/dist/controls-options-manager/types.js.map +1 -0
  40. package/dist/controls-options-manager/util.js +309 -18
  41. package/dist/controls-options-manager/util.js.map +1 -1
  42. package/dist/index.js +112 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/interpretation/collection.js +23 -0
  45. package/dist/interpretation/collection.js.map +1 -0
  46. package/dist/interpretation/index.js +366 -0
  47. package/dist/interpretation/index.js.map +1 -0
  48. package/dist/interpretation/siLanguage.js +25 -0
  49. package/dist/interpretation/siLanguage.js.map +1 -0
  50. package/dist/locus-info/controlsUtils.js +91 -2
  51. package/dist/locus-info/controlsUtils.js.map +1 -1
  52. package/dist/locus-info/index.js +383 -62
  53. package/dist/locus-info/index.js.map +1 -1
  54. package/dist/locus-info/infoUtils.js +7 -1
  55. package/dist/locus-info/infoUtils.js.map +1 -1
  56. package/dist/locus-info/mediaSharesUtils.js +57 -1
  57. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  58. package/dist/locus-info/parser.js +249 -72
  59. package/dist/locus-info/parser.js.map +1 -1
  60. package/dist/locus-info/selfUtils.js +89 -14
  61. package/dist/locus-info/selfUtils.js.map +1 -1
  62. package/dist/media/index.js +61 -116
  63. package/dist/media/index.js.map +1 -1
  64. package/dist/media/properties.js +73 -124
  65. package/dist/media/properties.js.map +1 -1
  66. package/dist/meeting/in-meeting-actions.js +82 -2
  67. package/dist/meeting/in-meeting-actions.js.map +1 -1
  68. package/dist/meeting/index.js +3777 -2929
  69. package/dist/meeting/index.js.map +1 -1
  70. package/dist/meeting/locusMediaRequest.js +292 -0
  71. package/dist/meeting/locusMediaRequest.js.map +1 -0
  72. package/dist/meeting/muteState.js +230 -124
  73. package/dist/meeting/muteState.js.map +1 -1
  74. package/dist/meeting/request.js +260 -196
  75. package/dist/meeting/request.js.map +1 -1
  76. package/dist/meeting/util.js +601 -417
  77. package/dist/meeting/util.js.map +1 -1
  78. package/dist/meeting-info/index.js +73 -7
  79. package/dist/meeting-info/index.js.map +1 -1
  80. package/dist/meeting-info/meeting-info-v2.js +192 -51
  81. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  82. package/dist/meeting-info/util.js +1 -1
  83. package/dist/meeting-info/util.js.map +1 -1
  84. package/dist/meeting-info/utilv2.js +36 -36
  85. package/dist/meeting-info/utilv2.js.map +1 -1
  86. package/dist/meetings/collection.js +39 -0
  87. package/dist/meetings/collection.js.map +1 -1
  88. package/dist/meetings/index.js +415 -115
  89. package/dist/meetings/index.js.map +1 -1
  90. package/dist/meetings/meetings.types.js +7 -0
  91. package/dist/meetings/meetings.types.js.map +1 -0
  92. package/dist/meetings/request.js +2 -0
  93. package/dist/meetings/request.js.map +1 -1
  94. package/dist/meetings/util.js +72 -6
  95. package/dist/meetings/util.js.map +1 -1
  96. package/dist/member/index.js +58 -0
  97. package/dist/member/index.js.map +1 -1
  98. package/dist/member/types.js +25 -0
  99. package/dist/member/types.js.map +1 -0
  100. package/dist/member/util.js +132 -25
  101. package/dist/member/util.js.map +1 -1
  102. package/dist/members/collection.js +10 -0
  103. package/dist/members/collection.js.map +1 -1
  104. package/dist/members/index.js +102 -6
  105. package/dist/members/index.js.map +1 -1
  106. package/dist/members/request.js +106 -38
  107. package/dist/members/request.js.map +1 -1
  108. package/dist/members/types.js +15 -0
  109. package/dist/members/types.js.map +1 -0
  110. package/dist/members/util.js +326 -232
  111. package/dist/members/util.js.map +1 -1
  112. package/dist/metrics/constants.js +13 -5
  113. package/dist/metrics/constants.js.map +1 -1
  114. package/dist/metrics/index.js +1 -468
  115. package/dist/metrics/index.js.map +1 -1
  116. package/dist/multistream/mediaRequestManager.js +238 -49
  117. package/dist/multistream/mediaRequestManager.js.map +1 -1
  118. package/dist/multistream/receiveSlot.js +29 -16
  119. package/dist/multistream/receiveSlot.js.map +1 -1
  120. package/dist/multistream/receiveSlotManager.js +39 -36
  121. package/dist/multistream/receiveSlotManager.js.map +1 -1
  122. package/dist/multistream/remoteMedia.js +44 -18
  123. package/dist/multistream/remoteMedia.js.map +1 -1
  124. package/dist/multistream/remoteMediaGroup.js +60 -3
  125. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  126. package/dist/multistream/remoteMediaManager.js +209 -59
  127. package/dist/multistream/remoteMediaManager.js.map +1 -1
  128. package/dist/multistream/sendSlotManager.js +233 -0
  129. package/dist/multistream/sendSlotManager.js.map +1 -0
  130. package/dist/reachability/index.js +225 -59
  131. package/dist/reachability/index.js.map +1 -1
  132. package/dist/reachability/request.js +17 -8
  133. package/dist/reachability/request.js.map +1 -1
  134. package/dist/reconnection-manager/index.js +201 -156
  135. package/dist/reconnection-manager/index.js.map +1 -1
  136. package/dist/recording-controller/index.js +21 -2
  137. package/dist/recording-controller/index.js.map +1 -1
  138. package/dist/recording-controller/util.js +9 -8
  139. package/dist/recording-controller/util.js.map +1 -1
  140. package/dist/roap/index.js +62 -32
  141. package/dist/roap/index.js.map +1 -1
  142. package/dist/roap/request.js +112 -97
  143. package/dist/roap/request.js.map +1 -1
  144. package/dist/roap/turnDiscovery.js +95 -36
  145. package/dist/roap/turnDiscovery.js.map +1 -1
  146. package/dist/rtcMetrics/constants.js +12 -0
  147. package/dist/rtcMetrics/constants.js.map +1 -0
  148. package/dist/rtcMetrics/index.js +117 -0
  149. package/dist/rtcMetrics/index.js.map +1 -0
  150. package/dist/statsAnalyzer/index.js +86 -78
  151. package/dist/statsAnalyzer/index.js.map +1 -1
  152. package/dist/statsAnalyzer/mqaUtil.js +11 -10
  153. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  154. package/dist/types/annotation/annotation.types.d.ts +42 -0
  155. package/dist/types/annotation/constants.d.ts +31 -0
  156. package/dist/types/annotation/index.d.ts +117 -0
  157. package/dist/types/breakouts/edit-lock-error.d.ts +15 -0
  158. package/dist/types/breakouts/events.d.ts +8 -0
  159. package/dist/types/breakouts/utils.d.ts +14 -0
  160. package/dist/types/common/errors/no-meeting-info.d.ts +14 -0
  161. package/dist/types/common/errors/reclaim-host-role-errors.d.ts +60 -0
  162. package/dist/types/common/errors/webex-errors.d.ts +25 -1
  163. package/dist/types/common/logs/request.d.ts +2 -0
  164. package/dist/types/common/queue.d.ts +9 -7
  165. package/dist/types/config.d.ts +1 -7
  166. package/dist/types/constants.d.ts +194 -24
  167. package/dist/types/controls-options-manager/enums.d.ts +11 -1
  168. package/dist/types/controls-options-manager/index.d.ts +17 -1
  169. package/dist/types/controls-options-manager/types.d.ts +43 -0
  170. package/dist/types/controls-options-manager/util.d.ts +1 -7
  171. package/dist/types/index.d.ts +6 -4
  172. package/dist/types/interpretation/collection.d.ts +5 -0
  173. package/dist/types/interpretation/index.d.ts +5 -0
  174. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  175. package/dist/types/locus-info/index.d.ts +57 -4
  176. package/dist/types/locus-info/parser.d.ts +67 -6
  177. package/dist/types/media/index.d.ts +2 -0
  178. package/dist/types/media/properties.d.ts +34 -48
  179. package/dist/types/meeting/in-meeting-actions.d.ts +82 -2
  180. package/dist/types/meeting/index.d.ts +463 -510
  181. package/dist/types/meeting/locusMediaRequest.d.ts +74 -0
  182. package/dist/types/meeting/muteState.d.ts +99 -23
  183. package/dist/types/meeting/request.d.ts +72 -43
  184. package/dist/types/meeting/util.d.ts +101 -1
  185. package/dist/types/meeting-info/index.d.ts +13 -1
  186. package/dist/types/meeting-info/meeting-info-v2.d.ts +31 -1
  187. package/dist/types/meetings/collection.d.ts +17 -0
  188. package/dist/types/meetings/index.d.ts +98 -20
  189. package/dist/types/meetings/meetings.types.d.ts +4 -0
  190. package/dist/types/member/index.d.ts +14 -0
  191. package/dist/types/member/types.d.ts +32 -0
  192. package/dist/types/members/collection.d.ts +5 -0
  193. package/dist/types/members/index.d.ts +35 -2
  194. package/dist/types/members/request.d.ts +73 -9
  195. package/dist/types/members/types.d.ts +25 -0
  196. package/dist/types/members/util.d.ts +214 -1
  197. package/dist/types/metrics/constants.d.ts +12 -4
  198. package/dist/types/metrics/index.d.ts +4 -119
  199. package/dist/types/multistream/mediaRequestManager.d.ts +73 -5
  200. package/dist/types/multistream/receiveSlot.d.ts +13 -11
  201. package/dist/types/multistream/receiveSlotManager.d.ts +14 -4
  202. package/dist/types/multistream/remoteMedia.d.ts +8 -29
  203. package/dist/types/multistream/remoteMediaGroup.d.ts +0 -9
  204. package/dist/types/multistream/remoteMediaManager.d.ts +46 -2
  205. package/dist/types/multistream/sendSlotManager.d.ts +61 -0
  206. package/dist/types/reachability/index.d.ts +61 -7
  207. package/dist/types/reachability/request.d.ts +7 -3
  208. package/dist/types/reconnection-manager/index.d.ts +9 -0
  209. package/dist/types/recording-controller/index.d.ts +15 -1
  210. package/dist/types/recording-controller/util.d.ts +5 -4
  211. package/dist/types/roap/index.d.ts +2 -1
  212. package/dist/types/roap/request.d.ts +15 -11
  213. package/dist/types/roap/turnDiscovery.d.ts +21 -3
  214. package/dist/types/rtcMetrics/constants.d.ts +4 -0
  215. package/dist/types/rtcMetrics/index.d.ts +47 -0
  216. package/dist/types/statsAnalyzer/index.d.ts +7 -1
  217. package/dist/types/webinar/collection.d.ts +16 -0
  218. package/dist/types/webinar/index.d.ts +5 -0
  219. package/dist/webinar/collection.js +44 -0
  220. package/dist/webinar/collection.js.map +1 -0
  221. package/dist/webinar/index.js +69 -0
  222. package/dist/webinar/index.js.map +1 -0
  223. package/package.json +23 -20
  224. package/src/annotation/annotation.types.ts +50 -0
  225. package/src/annotation/constants.ts +36 -0
  226. package/src/annotation/index.ts +328 -0
  227. package/src/breakouts/README.md +42 -12
  228. package/src/breakouts/breakout.ts +67 -9
  229. package/src/breakouts/edit-lock-error.ts +25 -0
  230. package/src/breakouts/events.ts +56 -0
  231. package/src/breakouts/index.ts +592 -20
  232. package/src/breakouts/utils.ts +42 -0
  233. package/src/common/errors/no-meeting-info.ts +24 -0
  234. package/src/common/errors/reclaim-host-role-errors.ts +134 -0
  235. package/src/common/errors/webex-errors.ts +44 -2
  236. package/src/common/logs/logger-proxy.ts +1 -1
  237. package/src/common/logs/request.ts +5 -1
  238. package/src/common/queue.ts +22 -8
  239. package/src/config.ts +4 -10
  240. package/src/constants.ts +221 -19
  241. package/src/controls-options-manager/enums.ts +12 -0
  242. package/src/controls-options-manager/index.ts +116 -21
  243. package/src/controls-options-manager/types.ts +59 -0
  244. package/src/controls-options-manager/util.ts +294 -14
  245. package/src/index.ts +40 -0
  246. package/src/interpretation/README.md +60 -0
  247. package/src/interpretation/collection.ts +19 -0
  248. package/src/interpretation/index.ts +332 -0
  249. package/src/interpretation/siLanguage.ts +18 -0
  250. package/src/locus-info/controlsUtils.ts +108 -0
  251. package/src/locus-info/index.ts +413 -59
  252. package/src/locus-info/infoUtils.ts +10 -2
  253. package/src/locus-info/mediaSharesUtils.ts +64 -0
  254. package/src/locus-info/parser.ts +258 -47
  255. package/src/locus-info/selfUtils.ts +81 -5
  256. package/src/media/index.ts +102 -122
  257. package/src/media/properties.ts +87 -110
  258. package/src/meeting/in-meeting-actions.ts +163 -3
  259. package/src/meeting/index.ts +3132 -2541
  260. package/src/meeting/locusMediaRequest.ts +313 -0
  261. package/src/meeting/muteState.ts +229 -131
  262. package/src/meeting/request.ts +177 -121
  263. package/src/meeting/util.ts +588 -394
  264. package/src/meeting-info/index.ts +81 -8
  265. package/src/meeting-info/meeting-info-v2.ts +170 -14
  266. package/src/meeting-info/util.ts +1 -1
  267. package/src/meeting-info/utilv2.ts +23 -23
  268. package/src/meetings/collection.ts +33 -0
  269. package/src/meetings/index.ts +445 -123
  270. package/src/meetings/meetings.types.ts +12 -0
  271. package/src/meetings/request.ts +2 -0
  272. package/src/meetings/util.ts +80 -11
  273. package/src/member/index.ts +58 -0
  274. package/src/member/types.ts +38 -0
  275. package/src/member/util.ts +141 -25
  276. package/src/members/collection.ts +8 -0
  277. package/src/members/index.ts +134 -8
  278. package/src/members/request.ts +97 -17
  279. package/src/members/types.ts +29 -0
  280. package/src/members/util.ts +333 -240
  281. package/src/metrics/constants.ts +12 -4
  282. package/src/metrics/index.ts +1 -490
  283. package/src/multistream/mediaRequestManager.ts +289 -79
  284. package/src/multistream/receiveSlot.ts +31 -17
  285. package/src/multistream/receiveSlotManager.ts +34 -24
  286. package/src/multistream/remoteMedia.ts +27 -2
  287. package/src/multistream/remoteMediaGroup.ts +59 -0
  288. package/src/multistream/remoteMediaManager.ts +148 -30
  289. package/src/multistream/sendSlotManager.ts +170 -0
  290. package/src/reachability/index.ts +228 -37
  291. package/src/reachability/request.ts +17 -8
  292. package/src/reconnection-manager/index.ts +83 -56
  293. package/src/recording-controller/index.ts +20 -3
  294. package/src/recording-controller/util.ts +26 -9
  295. package/src/roap/index.ts +63 -32
  296. package/src/roap/request.ts +100 -104
  297. package/src/roap/turnDiscovery.ts +48 -26
  298. package/src/rtcMetrics/constants.ts +3 -0
  299. package/src/rtcMetrics/index.ts +100 -0
  300. package/src/statsAnalyzer/index.ts +105 -91
  301. package/src/statsAnalyzer/mqaUtil.ts +13 -14
  302. package/src/webinar/collection.ts +31 -0
  303. package/src/webinar/index.ts +62 -0
  304. package/test/integration/spec/converged-space-meetings.js +60 -3
  305. package/test/integration/spec/journey.js +320 -261
  306. package/test/integration/spec/space-meeting.js +76 -3
  307. package/test/unit/spec/annotation/index.ts +418 -0
  308. package/test/unit/spec/breakouts/breakout.ts +118 -28
  309. package/test/unit/spec/breakouts/edit-lock-error.ts +30 -0
  310. package/test/unit/spec/breakouts/events.ts +89 -0
  311. package/test/unit/spec/breakouts/index.ts +1395 -69
  312. package/test/unit/spec/breakouts/utils.js +52 -1
  313. package/test/unit/spec/common/queue.js +31 -2
  314. package/test/unit/spec/controls-options-manager/index.js +163 -0
  315. package/test/unit/spec/controls-options-manager/util.js +576 -60
  316. package/test/unit/spec/fixture/locus.js +1 -0
  317. package/test/unit/spec/interpretation/collection.ts +15 -0
  318. package/test/unit/spec/interpretation/index.ts +589 -0
  319. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  320. package/test/unit/spec/locus-info/controlsUtils.js +316 -43
  321. package/test/unit/spec/locus-info/index.js +1304 -33
  322. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  323. package/test/unit/spec/locus-info/lib/SeqCmp.json +16 -0
  324. package/test/unit/spec/locus-info/mediaSharesUtils.ts +32 -0
  325. package/test/unit/spec/locus-info/parser.js +116 -35
  326. package/test/unit/spec/locus-info/selfConstant.js +27 -4
  327. package/test/unit/spec/locus-info/selfUtils.js +208 -17
  328. package/test/unit/spec/media/index.ts +104 -37
  329. package/test/unit/spec/media/properties.ts +2 -2
  330. package/test/unit/spec/meeting/in-meeting-actions.ts +81 -3
  331. package/test/unit/spec/meeting/index.js +5216 -1956
  332. package/test/unit/spec/meeting/locusMediaRequest.ts +442 -0
  333. package/test/unit/spec/meeting/muteState.js +408 -208
  334. package/test/unit/spec/meeting/request.js +483 -49
  335. package/test/unit/spec/meeting/utils.js +679 -64
  336. package/test/unit/spec/meeting-info/index.js +300 -0
  337. package/test/unit/spec/meeting-info/meetinginfov2.js +526 -5
  338. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  339. package/test/unit/spec/meetings/collection.js +26 -0
  340. package/test/unit/spec/meetings/index.js +1011 -205
  341. package/test/unit/spec/meetings/utils.js +202 -2
  342. package/test/unit/spec/member/index.js +61 -6
  343. package/test/unit/spec/member/util.js +510 -34
  344. package/test/unit/spec/members/index.js +432 -1
  345. package/test/unit/spec/members/request.js +206 -27
  346. package/test/unit/spec/members/utils.js +210 -0
  347. package/test/unit/spec/metrics/index.js +1 -50
  348. package/test/unit/spec/multistream/mediaRequestManager.ts +803 -162
  349. package/test/unit/spec/multistream/receiveSlot.ts +28 -20
  350. package/test/unit/spec/multistream/receiveSlotManager.ts +32 -30
  351. package/test/unit/spec/multistream/remoteMedia.ts +30 -0
  352. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  353. package/test/unit/spec/multistream/remoteMediaManager.ts +326 -0
  354. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  355. package/test/unit/spec/reachability/index.ts +549 -9
  356. package/test/unit/spec/reachability/request.js +68 -0
  357. package/test/unit/spec/reconnection-manager/index.js +85 -9
  358. package/test/unit/spec/recording-controller/index.js +294 -218
  359. package/test/unit/spec/recording-controller/util.js +223 -96
  360. package/test/unit/spec/roap/index.ts +178 -64
  361. package/test/unit/spec/roap/request.ts +203 -85
  362. package/test/unit/spec/roap/turnDiscovery.ts +82 -36
  363. package/test/unit/spec/rtcMetrics/index.ts +73 -0
  364. package/test/unit/spec/stats-analyzer/index.js +136 -2
  365. package/test/unit/spec/webinar/collection.ts +13 -0
  366. package/test/unit/spec/webinar/index.ts +60 -0
  367. package/test/utils/integrationTestUtils.js +46 -0
  368. package/test/utils/testUtils.js +0 -52
  369. package/dist/meeting/effectsState.js +0 -262
  370. package/dist/meeting/effectsState.js.map +0 -1
  371. package/dist/metrics/config.js +0 -299
  372. package/dist/metrics/config.js.map +0 -1
  373. package/dist/types/meeting/effectsState.d.ts +0 -42
  374. package/dist/types/metrics/config.d.ts +0 -178
  375. package/src/index.js +0 -16
  376. package/src/meeting/effectsState.ts +0 -211
  377. package/src/metrics/config.ts +0 -495
  378. package/test/unit/spec/meeting/effectsState.js +0 -285
@@ -1,4 +1,4 @@
1
- import {isEqual} from 'lodash';
1
+ import {isEqual, assignWith, cloneDeep, isEmpty} from 'lodash';
2
2
 
3
3
  import LoggerProxy from '../common/logs/logger-proxy';
4
4
  import EventsScope from '../common/events/events-scope';
@@ -17,8 +17,6 @@ import {
17
17
  CALL_REMOVED_REASON,
18
18
  RECORDING_STATE,
19
19
  } from '../constants';
20
- import Metrics from '../metrics';
21
- import {eventType} from '../metrics/config';
22
20
  import InfoUtils from './infoUtils';
23
21
  import FullState from './fullState';
24
22
  import SelfUtils from './selfUtils';
@@ -27,6 +25,8 @@ import ControlsUtils from './controlsUtils';
27
25
  import EmbeddedAppsUtils from './embeddedAppsUtils';
28
26
  import MediaSharesUtils from './mediaSharesUtils';
29
27
  import LocusDeltaParser from './parser';
28
+ import Metrics from '../metrics';
29
+ import BEHAVIORAL_METRICS from '../metrics/constants';
30
30
 
31
31
  /**
32
32
  * @description LocusInfo extends ChildEmitter to convert locusInfo info a private emitter to parent object
@@ -59,11 +59,19 @@ export default class LocusInfo extends EventsScope {
59
59
  fullState: any;
60
60
  host: any;
61
61
  info: any;
62
+ roles: any;
62
63
  mediaShares: any;
63
64
  replace: any;
64
65
  url: any;
65
66
  services: any;
66
-
67
+ mainSessionLocusCache: any;
68
+ /**
69
+ * Constructor
70
+ * @param {function} updateMeeting callback to update the meeting object from an object
71
+ * @param {object} webex
72
+ * @param {string} meetingId
73
+ * @returns {undefined}
74
+ */
67
75
  constructor(updateMeeting, webex, meetingId) {
68
76
  super();
69
77
  this.parsedLocus = {
@@ -77,6 +85,82 @@ export default class LocusInfo extends EventsScope {
77
85
  this.locusParser = new LocusDeltaParser();
78
86
  }
79
87
 
88
+ /**
89
+ * Does a Locus sync. It tries to get the latest delta DTO or if it can't, it falls back to getting the full Locus DTO.
90
+ *
91
+ * @param {Meeting} meeting
92
+ * @returns {undefined}
93
+ */
94
+ private doLocusSync(meeting: any) {
95
+ let isDelta;
96
+ let url;
97
+
98
+ if (this.locusParser.workingCopy.syncUrl) {
99
+ url = this.locusParser.workingCopy.syncUrl;
100
+ isDelta = true;
101
+ } else {
102
+ url = meeting.locusUrl;
103
+ isDelta = false;
104
+ }
105
+
106
+ LoggerProxy.logger.info(
107
+ `Locus-info:index#doLocusSync --> doing Locus sync (getting ${
108
+ isDelta ? 'delta' : 'full'
109
+ } DTO)`
110
+ );
111
+
112
+ // return value ignored on purpose
113
+ meeting.meetingRequest
114
+ .getLocusDTO({url})
115
+ .catch((e) => {
116
+ if (isDelta) {
117
+ LoggerProxy.logger.info(
118
+ 'Locus-info:index#doLocusSync --> delta sync failed, falling back to full sync'
119
+ );
120
+
121
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.LOCUS_DELTA_SYNC_FAILED, {
122
+ correlationId: meeting.correlationId,
123
+ url,
124
+ reason: e.message,
125
+ errorName: e.name,
126
+ stack: e.stack,
127
+ code: e.code,
128
+ });
129
+
130
+ isDelta = false;
131
+
132
+ return meeting.meetingRequest.getLocusDTO({url: meeting.locusUrl}).catch((err) => {
133
+ LoggerProxy.logger.info(
134
+ 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
135
+ );
136
+ this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
137
+ throw err;
138
+ });
139
+ }
140
+ LoggerProxy.logger.info(
141
+ 'Locus-info:index#doLocusSync --> fallback full sync failed, destroying the meeting'
142
+ );
143
+ this.webex.meetings.destroy(meeting, MEETING_REMOVED_REASON.LOCUS_DTO_SYNC_FAILED);
144
+ throw e;
145
+ })
146
+ .then((res) => {
147
+ if (isDelta) {
148
+ if (!isEmpty(res.body)) {
149
+ meeting.locusInfo.handleLocusDelta(res.body, meeting);
150
+ } else {
151
+ LoggerProxy.logger.info(
152
+ 'Locus-info:index#doLocusSync --> received empty body from syncUrl, so we already have latest Locus DTO'
153
+ );
154
+ }
155
+ } else {
156
+ meeting.locusInfo.onFullLocus(res.body);
157
+ }
158
+ // Notify parser to resume processing delta events.
159
+ // Any deltas in the queue that have now been superseded by this sync will simply be ignored
160
+ this.locusParser.resume();
161
+ });
162
+ }
163
+
80
164
  /**
81
165
  * Apply locus delta data to meeting
82
166
  * @param {string} action Locus delta action
@@ -85,28 +169,19 @@ export default class LocusInfo extends EventsScope {
85
169
  * @returns {undefined}
86
170
  */
87
171
  applyLocusDeltaData(action: string, locus: any, meeting: any) {
88
- const {DESYNC, USE_CURRENT, USE_INCOMING} = LocusDeltaParser.loci;
172
+ const {DESYNC, USE_CURRENT, USE_INCOMING, WAIT, LOCUS_URL_CHANGED} = LocusDeltaParser.loci;
89
173
 
90
174
  switch (action) {
91
175
  case USE_INCOMING:
92
176
  meeting.locusInfo.onDeltaLocus(locus);
93
177
  break;
94
178
  case USE_CURRENT:
95
- meeting.locusDesync = false;
96
- meeting.needToGetFullLocus = false;
179
+ case WAIT:
180
+ // do nothing
97
181
  break;
98
182
  case DESYNC:
99
- meeting.meetingRequest
100
- .getFullLocus({
101
- desync: true,
102
- locusUrl: meeting.locusUrl,
103
- })
104
- .then((res) => {
105
- meeting.locusInfo.onFullLocus(res.body);
106
- // Notify parser to resume processing delta events
107
- // now that we have full locus from DESYNC.
108
- this.locusParser.resume();
109
- });
183
+ case LOCUS_URL_CHANGED:
184
+ this.doLocusSync(meeting);
110
185
  break;
111
186
  default:
112
187
  LoggerProxy.logger.info(
@@ -172,12 +247,13 @@ export default class LocusInfo extends EventsScope {
172
247
  */
173
248
  this.deltaParticipants = [];
174
249
 
250
+ this.updateLocusCache(locus);
175
251
  // above section only updates the locusInfo object
176
252
  // The below section makes sure it updates the locusInfo as well as updates the meeting object
177
253
  this.updateParticipants(locus.participants);
178
254
  // For 1:1 space meeting the conversation Url does not exist in locus.conversation
179
255
  this.updateConversationUrl(locus.conversationUrl, locus.info);
180
- this.updateControls(locus.controls);
256
+ this.updateControls(locus.controls, locus.self);
181
257
  this.updateLocusUrl(locus.url);
182
258
  this.updateFullState(locus.fullState);
183
259
  this.updateMeetingInfo(locus.info);
@@ -195,6 +271,7 @@ export default class LocusInfo extends EventsScope {
195
271
  * @memberof LocusInfo
196
272
  */
197
273
  initialSetup(locus: object) {
274
+ this.updateLocusCache(locus);
198
275
  this.onFullLocus(locus);
199
276
 
200
277
  // Change it to true after it receives it first locus object
@@ -210,7 +287,7 @@ export default class LocusInfo extends EventsScope {
210
287
  parse(meeting: any, data: any) {
211
288
  // eslint-disable-next-line @typescript-eslint/no-shadow
212
289
  const {eventType} = data;
213
-
290
+ const locus = this.getTheLocusToUpdate(data.locus);
214
291
  LoggerProxy.logger.info(`Locus-info:index#parse --> received locus data: ${eventType}`);
215
292
 
216
293
  switch (eventType) {
@@ -228,16 +305,16 @@ export default class LocusInfo extends EventsScope {
228
305
  case LOCUSEVENT.PARTICIPANT_DECLINED:
229
306
  case LOCUSEVENT.FLOOR_GRANTED:
230
307
  case LOCUSEVENT.FLOOR_RELEASED:
231
- this.onFullLocus(data.locus, eventType);
308
+ this.onFullLocus(locus, eventType);
232
309
  break;
233
310
  case LOCUSEVENT.DIFFERENCE:
234
- this.handleLocusDelta(data.locus, meeting);
311
+ this.handleLocusDelta(locus, meeting);
235
312
  break;
236
313
 
237
314
  default:
238
315
  // Why will there be a event with no eventType ????
239
316
  // we may not need this, we can get full locus
240
- this.handleLocusDelta(data.locus, meeting);
317
+ this.handleLocusDelta(locus, meeting);
241
318
  }
242
319
  }
243
320
 
@@ -259,18 +336,27 @@ export default class LocusInfo extends EventsScope {
259
336
  * @returns {object} null
260
337
  * @memberof LocusInfo
261
338
  */
262
- // eslint-disable-next-line @typescript-eslint/no-shadow
263
339
  onFullLocus(locus: any, eventType?: string) {
264
340
  if (!locus) {
265
341
  LoggerProxy.logger.error(
266
342
  'Locus-info:index#onFullLocus --> object passed as argument was invalid, continuing.'
267
343
  );
268
344
  }
345
+
346
+ if (!this.locusParser.isNewFullLocus(locus)) {
347
+ LoggerProxy.logger.info(
348
+ `Locus-info:index#onFullLocus --> ignoring old full locus DTO, eventType=${eventType}`
349
+ );
350
+
351
+ return;
352
+ }
353
+
269
354
  this.updateParticipantDeltas(locus.participants);
270
355
  this.scheduledMeeting = locus.meeting || null;
271
356
  this.participants = locus.participants;
357
+ const isReplaceMembers = ControlsUtils.isNeedReplaceMembers(this.controls, locus.controls);
272
358
  this.updateLocusInfo(locus);
273
- this.updateParticipants(locus.participants);
359
+ this.updateParticipants(locus.participants, isReplaceMembers);
274
360
  this.isMeetingActive();
275
361
  this.handleOneOnOneEvent(eventType);
276
362
  this.updateEmbeddedApps(locus.embeddedApps);
@@ -329,8 +415,9 @@ export default class LocusInfo extends EventsScope {
329
415
  * @memberof LocusInfo
330
416
  */
331
417
  onDeltaLocus(locus: any) {
418
+ const isReplaceMembers = ControlsUtils.isNeedReplaceMembers(this.controls, locus.controls);
332
419
  this.updateLocusInfo(locus);
333
- this.updateParticipants(locus.participants);
420
+ this.updateParticipants(locus.participants, isReplaceMembers);
334
421
  this.isMeetingActive();
335
422
  }
336
423
 
@@ -347,7 +434,7 @@ export default class LocusInfo extends EventsScope {
347
434
  return;
348
435
  }
349
436
 
350
- this.updateControls(locus.controls);
437
+ this.updateControls(locus.controls, locus.self);
351
438
  this.updateConversationUrl(locus.conversationUrl, locus.info);
352
439
  this.updateCreated(locus.created);
353
440
  this.updateFullState(locus.fullState);
@@ -418,10 +505,15 @@ export default class LocusInfo extends EventsScope {
418
505
  LoggerProxy.logger.warn(
419
506
  'Locus-info:index#isMeetingActive --> Call Ended, locus state is inactive.'
420
507
  );
421
- Metrics.postEvent({
422
- event: eventType.REMOTE_ENDED,
423
- meetingId: this.meetingId,
508
+
509
+ // @ts-ignore
510
+ this.webex.internal.newMetrics.submitClientEvent({
511
+ name: 'client.call.remote-ended',
512
+ options: {
513
+ meetingId: this.meetingId,
514
+ },
424
515
  });
516
+
425
517
  this.emitScoped(
426
518
  {
427
519
  file: 'locus-info',
@@ -440,9 +532,12 @@ export default class LocusInfo extends EventsScope {
440
532
  this.parsedLocus.self.state === MEETING_STATE.STATES.NOTIFIED ||
441
533
  this.parsedLocus.self.state === MEETING_STATE.STATES.JOINED)
442
534
  ) {
443
- Metrics.postEvent({
444
- event: eventType.REMOTE_ENDED,
445
- meetingId: this.meetingId,
535
+ // @ts-ignore
536
+ this.webex.internal.newMetrics.submitClientEvent({
537
+ name: 'client.call.remote-ended',
538
+ options: {
539
+ meetingId: this.meetingId,
540
+ },
446
541
  });
447
542
  this.emitScoped(
448
543
  {
@@ -464,10 +559,14 @@ export default class LocusInfo extends EventsScope {
464
559
  partner.state === MEETING_STATE.STATES.NOTIFIED ||
465
560
  partner.state === MEETING_STATE.STATES.IDLE) // Happens when user just joins and adds no Media
466
561
  ) {
467
- Metrics.postEvent({
468
- event: eventType.REMOTE_ENDED,
469
- meetingId: this.meetingId,
562
+ // @ts-ignore
563
+ this.webex.internal.newMetrics.submitClientEvent({
564
+ name: 'client.call.remote-ended',
565
+ options: {
566
+ meetingId: this.meetingId,
567
+ },
470
568
  });
569
+
471
570
  this.emitScoped(
472
571
  {
473
572
  file: 'locus-info',
@@ -490,9 +589,13 @@ export default class LocusInfo extends EventsScope {
490
589
  LoggerProxy.logger.warn(
491
590
  'Locus-info:index#isMeetingActive --> Meeting is ending due to inactive or terminating'
492
591
  );
493
- Metrics.postEvent({
494
- event: eventType.REMOTE_ENDED,
495
- meetingId: this.meetingId,
592
+
593
+ // @ts-ignore
594
+ this.webex.internal.newMetrics.submitClientEvent({
595
+ name: 'client.call.remote-ended',
596
+ options: {
597
+ meetingId: this.meetingId,
598
+ },
496
599
  });
497
600
  this.emitScoped(
498
601
  {
@@ -507,9 +610,13 @@ export default class LocusInfo extends EventsScope {
507
610
  );
508
611
  } else if (this.fullState && this.fullState.removed) {
509
612
  // user has been dropped from a meeting
510
- Metrics.postEvent({
511
- event: eventType.REMOTE_ENDED,
512
- meetingId: this.meetingId,
613
+
614
+ // @ts-ignore
615
+ this.webex.internal.newMetrics.submitClientEvent({
616
+ name: 'client.call.remote-ended',
617
+ options: {
618
+ meetingId: this.meetingId,
619
+ },
513
620
  });
514
621
  this.emitScoped(
515
622
  {
@@ -646,13 +753,13 @@ export default class LocusInfo extends EventsScope {
646
753
  }
647
754
 
648
755
  /**
649
- *
756
+ * update meeting's members
650
757
  * @param {Object} participants new participants object
651
- * @param {boolen} deltaParticpantFlag delta event
758
+ * @param {Boolean} isReplace is replace the whole members
652
759
  * @returns {Array} updatedParticipants
653
760
  * @memberof LocusInfo
654
761
  */
655
- updateParticipants(participants: object) {
762
+ updateParticipants(participants: object, isReplace?: boolean) {
656
763
  this.emitScoped(
657
764
  {
658
765
  file: 'locus-info',
@@ -665,16 +772,18 @@ export default class LocusInfo extends EventsScope {
665
772
  selfIdentity: this.parsedLocus.self && this.parsedLocus.self.selfIdentity,
666
773
  selfId: this.parsedLocus.self && this.parsedLocus.self.selfId,
667
774
  hostId: this.parsedLocus.host && this.parsedLocus.host.hostId,
775
+ isReplace,
668
776
  }
669
777
  );
670
778
  }
671
779
 
672
780
  /**
673
781
  * @param {Object} controls
782
+ * @param {Object} self
674
783
  * @returns {undefined}
675
784
  * @memberof LocusInfo
676
785
  */
677
- updateControls(controls: object) {
786
+ updateControls(controls: object, self: object) {
678
787
  if (controls && !isEqual(this.controls, controls)) {
679
788
  this.parsedLocus.controls = ControlsUtils.parse(controls);
680
789
  const {
@@ -685,10 +794,76 @@ export default class LocusInfo extends EventsScope {
685
794
  hasTranscribeChanged,
686
795
  hasEntryExitToneChanged,
687
796
  hasBreakoutChanged,
797
+ hasVideoEnabledChanged,
798
+ hasMuteOnEntryChanged,
799
+ hasShareControlChanged,
800
+ hasDisallowUnmuteChanged,
801
+ hasReactionsChanged,
802
+ hasReactionDisplayNamesChanged,
803
+ hasViewTheParticipantListChanged,
804
+ hasRaiseHandChanged,
805
+ hasVideoChanged,
806
+ hasInterpretationChanged,
688
807
  },
689
808
  current,
690
809
  } = ControlsUtils.getControls(this.controls, controls);
691
810
 
811
+ if (hasMuteOnEntryChanged) {
812
+ this.emitScoped(
813
+ {file: 'locus-info', function: 'updateControls'},
814
+ LOCUSINFO.EVENTS.CONTROLS_MUTE_ON_ENTRY_CHANGED,
815
+ {state: current.muteOnEntry}
816
+ );
817
+ }
818
+
819
+ if (hasShareControlChanged) {
820
+ this.emitScoped(
821
+ {file: 'locus-info', function: 'updateControls'},
822
+ LOCUSINFO.EVENTS.CONTROLS_SHARE_CONTROL_CHANGED,
823
+ {state: current.shareControl}
824
+ );
825
+ }
826
+
827
+ if (hasDisallowUnmuteChanged) {
828
+ this.emitScoped(
829
+ {file: 'locus-info', function: 'updateControls'},
830
+ LOCUSINFO.EVENTS.CONTROLS_DISALLOW_UNMUTE_CHANGED,
831
+ {state: current.disallowUnmute}
832
+ );
833
+ }
834
+
835
+ if (hasReactionsChanged || hasReactionDisplayNamesChanged) {
836
+ this.emitScoped(
837
+ {file: 'locus-info', function: 'updateControls'},
838
+ LOCUSINFO.EVENTS.CONTROLS_REACTIONS_CHANGED,
839
+ {state: current.reactions}
840
+ );
841
+ }
842
+
843
+ if (hasViewTheParticipantListChanged) {
844
+ this.emitScoped(
845
+ {file: 'locus-info', function: 'updateControls'},
846
+ LOCUSINFO.EVENTS.CONTROLS_VIEW_THE_PARTICIPANTS_LIST_CHANGED,
847
+ {state: current.viewTheParticipantList}
848
+ );
849
+ }
850
+
851
+ if (hasRaiseHandChanged) {
852
+ this.emitScoped(
853
+ {file: 'locus-info', function: 'updateControls'},
854
+ LOCUSINFO.EVENTS.CONTROLS_RAISE_HAND_CHANGED,
855
+ {state: current.raiseHand}
856
+ );
857
+ }
858
+
859
+ if (hasVideoChanged) {
860
+ this.emitScoped(
861
+ {file: 'locus-info', function: 'updateControls'},
862
+ LOCUSINFO.EVENTS.CONTROLS_VIDEO_CHANGED,
863
+ {state: current.video}
864
+ );
865
+ }
866
+
692
867
  if (hasRecordingChanged || hasRecordingPausedChanged) {
693
868
  let state = null;
694
869
 
@@ -750,7 +925,10 @@ export default class LocusInfo extends EventsScope {
750
925
 
751
926
  if (hasBreakoutChanged) {
752
927
  const {breakout} = current;
753
-
928
+ breakout.breakoutMoveId = SelfUtils.getReplacedBreakoutMoveId(
929
+ self,
930
+ this.webex.internal.device.url
931
+ );
754
932
  this.emitScoped(
755
933
  {
756
934
  file: 'locus-info',
@@ -763,9 +941,25 @@ export default class LocusInfo extends EventsScope {
763
941
  );
764
942
  }
765
943
 
944
+ if (hasInterpretationChanged) {
945
+ const {interpretation} = current;
946
+ this.emitScoped(
947
+ {
948
+ file: 'locus-info',
949
+ function: 'updateControls',
950
+ },
951
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_INTERPRETATION_UPDATED,
952
+ {
953
+ interpretation,
954
+ }
955
+ );
956
+ }
957
+
766
958
  if (hasEntryExitToneChanged) {
767
959
  const {entryExitTone} = current;
768
960
 
961
+ this.updateMeeting({entryExitTone});
962
+
769
963
  this.emitScoped(
770
964
  {
771
965
  file: 'locus-info',
@@ -776,8 +970,26 @@ export default class LocusInfo extends EventsScope {
776
970
  entryExitTone,
777
971
  }
778
972
  );
973
+ }
779
974
 
780
- this.updateMeeting({entryExitTone});
975
+ // videoEnabled is handled differently than other controls,
976
+ // to fit with audio mute status logic
977
+ if (hasVideoEnabledChanged) {
978
+ const {videoEnabled} = current;
979
+
980
+ this.updateMeeting({unmuteVideoAllowed: videoEnabled});
981
+
982
+ this.emitScoped(
983
+ {
984
+ file: 'locus-info',
985
+ function: 'updateControls',
986
+ },
987
+ LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
988
+ {
989
+ // muted: not part of locus.controls
990
+ unmuteAllowed: videoEnabled,
991
+ }
992
+ );
781
993
  }
782
994
 
783
995
  this.controls = controls;
@@ -918,20 +1130,14 @@ export default class LocusInfo extends EventsScope {
918
1130
  * @memberof LocusInfo
919
1131
  */
920
1132
  updateMeetingInfo(info: object, self?: object) {
921
- if (info && !isEqual(this.info, info)) {
922
- const roles = self ? SelfUtils.getRoles(self) : this.parsedLocus.self?.roles || [];
1133
+ const roles = self ? SelfUtils.getRoles(self) : this.parsedLocus.self?.roles || [];
1134
+ if (
1135
+ (info && !isEqual(this.info, info)) ||
1136
+ (roles.length && !isEqual(this.roles, roles) && info)
1137
+ ) {
923
1138
  const isJoined = SelfUtils.isJoined(self || this.parsedLocus.self);
924
1139
  const parsedInfo = InfoUtils.getInfos(this.parsedLocus.info, info, roles, isJoined);
925
1140
 
926
- this.emitScoped(
927
- {
928
- file: 'locus-info',
929
- function: 'updateMeetingInfo',
930
- },
931
- LOCUSINFO.EVENTS.MEETING_INFO_UPDATED,
932
- {info: parsedInfo.current, self}
933
- );
934
-
935
1141
  if (parsedInfo.updates.isLocked) {
936
1142
  this.emitScoped(
937
1143
  {
@@ -957,7 +1163,16 @@ export default class LocusInfo extends EventsScope {
957
1163
  this.parsedLocus.info = parsedInfo.current;
958
1164
  // Parses the info and adds necessary values
959
1165
  this.updateMeeting(parsedInfo.current);
1166
+
1167
+ this.emitScoped(
1168
+ {
1169
+ file: 'locus-info',
1170
+ function: 'updateMeetingInfo',
1171
+ },
1172
+ LOCUSINFO.EVENTS.MEETING_INFO_UPDATED
1173
+ );
960
1174
  }
1175
+ this.roles = roles;
961
1176
  }
962
1177
 
963
1178
  /**
@@ -1099,6 +1314,20 @@ export default class LocusInfo extends EventsScope {
1099
1314
  );
1100
1315
  }
1101
1316
 
1317
+ if (parsedSelves.updates.interpretationChanged) {
1318
+ this.emitScoped(
1319
+ {
1320
+ file: 'locus-info',
1321
+ function: 'updateSelf',
1322
+ },
1323
+ LOCUSINFO.EVENTS.SELF_MEETING_INTERPRETATION_CHANGED,
1324
+ {
1325
+ interpretation: parsedSelves.current.interpretation,
1326
+ selfParticipantId: parsedSelves.current.selfId,
1327
+ }
1328
+ );
1329
+ }
1330
+
1102
1331
  if (parsedSelves.updates.isMediaInactiveOrReleased) {
1103
1332
  this.emitScoped(
1104
1333
  {
@@ -1120,6 +1349,31 @@ export default class LocusInfo extends EventsScope {
1120
1349
  self
1121
1350
  );
1122
1351
  }
1352
+
1353
+ if (parsedSelves.updates.isRolesChanged) {
1354
+ this.emitScoped(
1355
+ {
1356
+ file: 'locus-info',
1357
+ function: 'updateSelf',
1358
+ },
1359
+ LOCUSINFO.EVENTS.SELF_ROLES_CHANGED,
1360
+ {oldRoles: parsedSelves.previous?.roles, newRoles: parsedSelves.current?.roles}
1361
+ );
1362
+ }
1363
+
1364
+ if (parsedSelves.updates.isVideoMutedByOthersChanged) {
1365
+ this.emitScoped(
1366
+ {
1367
+ file: 'locus-info',
1368
+ function: 'updateSelf',
1369
+ },
1370
+ LOCUSINFO.EVENTS.SELF_REMOTE_VIDEO_MUTE_STATUS_UPDATED,
1371
+ {
1372
+ muted: parsedSelves.current.remoteVideoMuted,
1373
+ // unmuteAllowed: not part of .self
1374
+ }
1375
+ );
1376
+ }
1123
1377
  if (parsedSelves.updates.localAudioUnmuteRequiredByServer) {
1124
1378
  this.emitScoped(
1125
1379
  {
@@ -1334,4 +1588,104 @@ export default class LocusInfo extends EventsScope {
1334
1588
  this.identities = identities;
1335
1589
  }
1336
1590
  }
1591
+
1592
+ /**
1593
+ * check the locus is main session's one or not, if is main session's, update main session cache
1594
+ * @param {Object} locus
1595
+ * @returns {undefined}
1596
+ * @memberof LocusInfo
1597
+ */
1598
+ updateLocusCache(locus: any) {
1599
+ const isMainSessionDTO = ControlsUtils.isMainSessionDTO(locus);
1600
+ if (isMainSessionDTO) {
1601
+ this.updateMainSessionLocusCache(locus);
1602
+ }
1603
+ }
1604
+
1605
+ /**
1606
+ * if return from breakout to main session, need to use cached main session DTO since locus won't send the full locus (participants)
1607
+ * if join breakout from main session, need to query main locus url (if response with 403 means no privilege, need to clear the cache)
1608
+ * @param {Object} newLocus
1609
+ * @returns {Object}
1610
+ * @memberof LocusInfo
1611
+ */
1612
+ getTheLocusToUpdate(newLocus: any) {
1613
+ const switchStatus = ControlsUtils.getSessionSwitchStatus(this.controls, newLocus?.controls);
1614
+ if (switchStatus.isReturnToMain && this.mainSessionLocusCache) {
1615
+ return cloneDeep(this.mainSessionLocusCache);
1616
+ }
1617
+ if (switchStatus.isJoinToBreakout) {
1618
+ this.emitScoped(
1619
+ {
1620
+ file: 'locus-info',
1621
+ function: 'updateControls',
1622
+ },
1623
+ LOCUSINFO.EVENTS.CONTROLS_JOIN_BREAKOUT_FROM_MAIN,
1624
+ {
1625
+ mainLocusUrl: this.url,
1626
+ }
1627
+ );
1628
+ }
1629
+
1630
+ return newLocus;
1631
+ }
1632
+
1633
+ /**
1634
+ * merge participants by participant id
1635
+ * @param {Array} participants
1636
+ * @param {Array} sourceParticipants
1637
+ * @returns {Array} merged participants
1638
+ * @memberof LocusInfo
1639
+ */
1640
+ // eslint-disable-next-line class-methods-use-this
1641
+ mergeParticipants(participants, sourceParticipants) {
1642
+ if (!sourceParticipants || !sourceParticipants.length) return participants;
1643
+ if (!participants || !participants.length) {
1644
+ return sourceParticipants;
1645
+ }
1646
+ sourceParticipants.forEach((participant) => {
1647
+ const existIndex = participants.findIndex((p) => p.id === participant.id);
1648
+ if (existIndex > -1) {
1649
+ participants.splice(existIndex, 1, participant);
1650
+ } else {
1651
+ participants.push(participant);
1652
+ }
1653
+ });
1654
+
1655
+ return participants;
1656
+ }
1657
+
1658
+ /**
1659
+ * need cache main sessions' participants since locus will not send the full list when cohost/host leave breakout
1660
+ * @param {Object} mainLocus
1661
+ * @returns {undefined}
1662
+ * @memberof LocusInfo
1663
+ */
1664
+ updateMainSessionLocusCache(mainLocus: any) {
1665
+ if (!mainLocus) {
1666
+ return;
1667
+ }
1668
+ const locusClone = cloneDeep(mainLocus);
1669
+ if (this.mainSessionLocusCache) {
1670
+ // shallow merge and do special merge for participants
1671
+ assignWith(this.mainSessionLocusCache, locusClone, (objValue, srcValue, key) => {
1672
+ if (key === 'participants') {
1673
+ return this.mergeParticipants(objValue, srcValue);
1674
+ }
1675
+
1676
+ return srcValue || objValue;
1677
+ });
1678
+ } else {
1679
+ this.mainSessionLocusCache = locusClone;
1680
+ }
1681
+ }
1682
+
1683
+ /**
1684
+ * clear main session cache
1685
+ * @returns {undefined}
1686
+ * @memberof LocusInfo
1687
+ */
1688
+ clearMainSessionLocusCache() {
1689
+ this.mainSessionLocusCache = null;
1690
+ }
1337
1691
  }