@webex/plugin-meetings 3.0.0-bnr.4 → 3.0.0-stream-classes.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) 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 +70 -32
  9. package/dist/breakouts/breakout.js.map +1 -1
  10. package/dist/breakouts/events.js +45 -0
  11. package/dist/breakouts/events.js.map +1 -0
  12. package/dist/breakouts/index.js +422 -217
  13. package/dist/breakouts/index.js.map +1 -1
  14. package/dist/breakouts/utils.js +12 -1
  15. package/dist/breakouts/utils.js.map +1 -1
  16. package/dist/common/errors/webex-errors.js +3 -2
  17. package/dist/common/errors/webex-errors.js.map +1 -1
  18. package/dist/common/logs/logger-proxy.js +1 -1
  19. package/dist/common/logs/logger-proxy.js.map +1 -1
  20. package/dist/common/logs/request.d.ts +1 -1
  21. package/dist/common/queue.js +24 -9
  22. package/dist/common/queue.js.map +1 -1
  23. package/dist/config.js +1 -7
  24. package/dist/config.js.map +1 -1
  25. package/dist/constants.js +118 -24
  26. package/dist/constants.js.map +1 -1
  27. package/dist/controls-options-manager/enums.js +2 -0
  28. package/dist/controls-options-manager/enums.js.map +1 -1
  29. package/dist/controls-options-manager/index.js +19 -14
  30. package/dist/controls-options-manager/index.js.map +1 -1
  31. package/dist/controls-options-manager/types.js.map +1 -1
  32. package/dist/controls-options-manager/util.js +80 -11
  33. package/dist/controls-options-manager/util.js.map +1 -1
  34. package/dist/index.js +62 -20
  35. package/dist/index.js.map +1 -1
  36. package/dist/interpretation/collection.js +23 -0
  37. package/dist/interpretation/collection.js.map +1 -0
  38. package/dist/interpretation/index.js +366 -0
  39. package/dist/interpretation/index.js.map +1 -0
  40. package/dist/interpretation/siLanguage.js +25 -0
  41. package/dist/interpretation/siLanguage.js.map +1 -0
  42. package/dist/locus-info/controlsUtils.js +71 -1
  43. package/dist/locus-info/controlsUtils.js.map +1 -1
  44. package/dist/locus-info/index.js +305 -57
  45. package/dist/locus-info/index.js.map +1 -1
  46. package/dist/locus-info/infoUtils.js +7 -1
  47. package/dist/locus-info/infoUtils.js.map +1 -1
  48. package/dist/locus-info/mediaSharesUtils.js +43 -1
  49. package/dist/locus-info/mediaSharesUtils.js.map +1 -1
  50. package/dist/locus-info/parser.js +219 -63
  51. package/dist/locus-info/parser.js.map +1 -1
  52. package/dist/locus-info/selfUtils.js +44 -22
  53. package/dist/locus-info/selfUtils.js.map +1 -1
  54. package/dist/media/index.js +57 -104
  55. package/dist/media/index.js.map +1 -1
  56. package/dist/media/properties.js +60 -121
  57. package/dist/media/properties.js.map +1 -1
  58. package/dist/meeting/in-meeting-actions.js +61 -3
  59. package/dist/meeting/in-meeting-actions.js.map +1 -1
  60. package/dist/meeting/index.js +2530 -2534
  61. package/dist/meeting/index.js.map +1 -1
  62. package/dist/meeting/locusMediaRequest.js +292 -0
  63. package/dist/meeting/locusMediaRequest.js.map +1 -0
  64. package/dist/meeting/muteState.js +125 -205
  65. package/dist/meeting/muteState.js.map +1 -1
  66. package/dist/meeting/request.js +150 -150
  67. package/dist/meeting/request.js.map +1 -1
  68. package/dist/meeting/util.js +568 -438
  69. package/dist/meeting/util.js.map +1 -1
  70. package/dist/meeting-info/index.js +48 -7
  71. package/dist/meeting-info/index.js.map +1 -1
  72. package/dist/meeting-info/meeting-info-v2.js +94 -38
  73. package/dist/meeting-info/meeting-info-v2.js.map +1 -1
  74. package/dist/meeting-info/utilv2.js +4 -2
  75. package/dist/meeting-info/utilv2.js.map +1 -1
  76. package/dist/meetings/index.d.ts +0 -2
  77. package/dist/meetings/index.js +260 -85
  78. package/dist/meetings/index.js.map +1 -1
  79. package/dist/meetings/meetings.types.js +7 -0
  80. package/dist/meetings/meetings.types.js.map +1 -0
  81. package/dist/meetings/util.js +42 -7
  82. package/dist/meetings/util.js.map +1 -1
  83. package/dist/member/index.d.ts +2 -0
  84. package/dist/member/index.js +26 -0
  85. package/dist/member/index.js.map +1 -1
  86. package/dist/member/member.types.d.ts +11 -0
  87. package/dist/member/member.types.js +18 -0
  88. package/dist/member/member.types.js.map +1 -0
  89. package/dist/member/types.js +11 -1
  90. package/dist/member/types.js.map +1 -1
  91. package/dist/member/util.js +60 -23
  92. package/dist/member/util.js.map +1 -1
  93. package/dist/members/index.js +4 -1
  94. package/dist/members/index.js.map +1 -1
  95. package/dist/members/request.js +75 -45
  96. package/dist/members/request.js.map +1 -1
  97. package/dist/members/util.js +308 -317
  98. package/dist/members/util.js.map +1 -1
  99. package/dist/metrics/config.js +1 -3
  100. package/dist/metrics/config.js.map +1 -1
  101. package/dist/metrics/constants.js +1 -0
  102. package/dist/metrics/constants.js.map +1 -1
  103. package/dist/metrics/index.d.ts +1 -1
  104. package/dist/metrics/index.js +1 -451
  105. package/dist/metrics/index.js.map +1 -1
  106. package/dist/multistream/mediaRequestManager.js +136 -40
  107. package/dist/multistream/mediaRequestManager.js.map +1 -1
  108. package/dist/multistream/receiveSlot.js.map +1 -1
  109. package/dist/multistream/receiveSlotManager.js +4 -4
  110. package/dist/multistream/receiveSlotManager.js.map +1 -1
  111. package/dist/multistream/remoteMedia.js.map +1 -1
  112. package/dist/multistream/remoteMediaGroup.js +60 -3
  113. package/dist/multistream/remoteMediaGroup.js.map +1 -1
  114. package/dist/multistream/remoteMediaManager.js +36 -0
  115. package/dist/multistream/remoteMediaManager.js.map +1 -1
  116. package/dist/multistream/sendSlotManager.js +233 -0
  117. package/dist/multistream/sendSlotManager.js.map +1 -0
  118. package/dist/reachability/index.js +18 -3
  119. package/dist/reachability/index.js.map +1 -1
  120. package/dist/reachability/request.js +5 -3
  121. package/dist/reachability/request.js.map +1 -1
  122. package/dist/reconnection-manager/index.js +181 -153
  123. package/dist/reconnection-manager/index.js.map +1 -1
  124. package/dist/recording-controller/index.js +21 -2
  125. package/dist/recording-controller/index.js.map +1 -1
  126. package/dist/recording-controller/util.js +9 -8
  127. package/dist/recording-controller/util.js.map +1 -1
  128. package/dist/roap/index.js +25 -32
  129. package/dist/roap/index.js.map +1 -1
  130. package/dist/roap/request.js +42 -51
  131. package/dist/roap/request.js.map +1 -1
  132. package/dist/roap/turnDiscovery.js +97 -38
  133. package/dist/roap/turnDiscovery.js.map +1 -1
  134. package/dist/rtcMetrics/constants.js +12 -0
  135. package/dist/rtcMetrics/constants.js.map +1 -0
  136. package/dist/rtcMetrics/index.js +117 -0
  137. package/dist/rtcMetrics/index.js.map +1 -0
  138. package/dist/statsAnalyzer/index.js +0 -1
  139. package/dist/statsAnalyzer/index.js.map +1 -1
  140. package/dist/types/annotation/annotation.types.d.ts +43 -0
  141. package/dist/types/annotation/constants.d.ts +31 -0
  142. package/dist/types/annotation/index.d.ts +124 -0
  143. package/dist/types/breakouts/events.d.ts +2 -0
  144. package/dist/types/breakouts/utils.d.ts +7 -0
  145. package/dist/types/common/errors/webex-errors.d.ts +1 -1
  146. package/dist/types/config.d.ts +0 -6
  147. package/dist/types/constants.d.ts +51 -21
  148. package/dist/types/controls-options-manager/enums.d.ts +2 -0
  149. package/dist/types/controls-options-manager/index.d.ts +1 -1
  150. package/dist/types/controls-options-manager/types.d.ts +7 -1
  151. package/dist/types/index.d.ts +1 -1
  152. package/dist/types/interpretation/collection.d.ts +5 -0
  153. package/dist/types/interpretation/index.d.ts +5 -0
  154. package/dist/types/interpretation/siLanguage.d.ts +5 -0
  155. package/dist/types/locus-info/index.d.ts +39 -1
  156. package/dist/types/media/index.d.ts +2 -0
  157. package/dist/types/media/properties.d.ts +16 -38
  158. package/dist/types/meeting/in-meeting-actions.d.ts +46 -2
  159. package/dist/types/meeting/index.d.ts +179 -379
  160. package/dist/types/meeting/locusMediaRequest.d.ts +70 -0
  161. package/dist/types/meeting/muteState.d.ts +39 -40
  162. package/dist/types/meeting/request.d.ts +25 -26
  163. package/dist/types/meeting/util.d.ts +74 -1
  164. package/dist/types/meeting-info/meeting-info-v2.d.ts +14 -3
  165. package/dist/types/meetings/index.d.ts +49 -1
  166. package/dist/types/meetings/meetings.types.d.ts +4 -0
  167. package/dist/types/member/index.d.ts +2 -0
  168. package/dist/types/members/request.d.ts +56 -11
  169. package/dist/types/members/util.d.ts +209 -1
  170. package/dist/types/metrics/config.d.ts +26 -2
  171. package/dist/types/metrics/constants.d.ts +1 -0
  172. package/dist/types/metrics/index.d.ts +17 -0
  173. package/dist/types/multistream/mediaRequestManager.d.ts +27 -10
  174. package/dist/types/multistream/receiveSlot.d.ts +3 -3
  175. package/dist/types/multistream/remoteMedia.d.ts +2 -2
  176. package/dist/types/multistream/remoteMediaManager.d.ts +14 -0
  177. package/dist/types/roap/request.d.ts +6 -8
  178. package/dist/types/roap/turnDiscovery.d.ts +18 -1
  179. package/package.json +3 -2
  180. package/src/annotation/annotation.types.ts +50 -0
  181. package/src/annotation/constants.ts +36 -0
  182. package/src/annotation/index.ts +328 -0
  183. package/src/breakouts/README.md +3 -2
  184. package/src/breakouts/breakout.ts +62 -27
  185. package/src/breakouts/events.ts +56 -0
  186. package/src/breakouts/index.ts +244 -64
  187. package/src/breakouts/utils.ts +13 -0
  188. package/src/common/errors/webex-errors.ts +6 -2
  189. package/src/common/logs/logger-proxy.ts +1 -1
  190. package/src/common/queue.ts +22 -8
  191. package/src/config.ts +0 -6
  192. package/src/constants.ts +111 -19
  193. package/src/controls-options-manager/enums.ts +2 -0
  194. package/src/controls-options-manager/index.ts +13 -10
  195. package/src/controls-options-manager/types.ts +10 -0
  196. package/src/controls-options-manager/util.ts +82 -11
  197. package/src/index.ts +18 -11
  198. package/src/interpretation/README.md +60 -0
  199. package/src/interpretation/collection.ts +19 -0
  200. package/src/interpretation/index.ts +332 -0
  201. package/src/interpretation/siLanguage.ts +18 -0
  202. package/src/locus-info/controlsUtils.ts +81 -0
  203. package/src/locus-info/index.ts +318 -57
  204. package/src/locus-info/infoUtils.ts +10 -2
  205. package/src/locus-info/mediaSharesUtils.ts +48 -0
  206. package/src/locus-info/parser.ts +224 -39
  207. package/src/locus-info/selfUtils.ts +32 -20
  208. package/src/media/index.ts +94 -108
  209. package/src/media/properties.ts +69 -109
  210. package/src/meeting/in-meeting-actions.ts +120 -4
  211. package/src/meeting/index.ts +1967 -2120
  212. package/src/meeting/locusMediaRequest.ts +314 -0
  213. package/src/meeting/muteState.ts +119 -194
  214. package/src/meeting/request.ts +122 -115
  215. package/src/meeting/util.ts +549 -413
  216. package/src/meeting-info/index.ts +54 -8
  217. package/src/meeting-info/meeting-info-v2.ts +89 -24
  218. package/src/meeting-info/utilv2.ts +6 -2
  219. package/src/meetings/index.ts +247 -87
  220. package/src/meetings/meetings.types.ts +12 -0
  221. package/src/meetings/util.ts +47 -12
  222. package/src/member/index.ts +28 -1
  223. package/src/member/types.ts +14 -0
  224. package/src/member/util.ts +75 -26
  225. package/src/members/index.ts +7 -1
  226. package/src/members/request.ts +61 -21
  227. package/src/members/util.ts +316 -326
  228. package/src/metrics/constants.ts +1 -0
  229. package/src/metrics/index.ts +1 -474
  230. package/src/multistream/mediaRequestManager.ts +183 -67
  231. package/src/multistream/receiveSlot.ts +4 -4
  232. package/src/multistream/receiveSlotManager.ts +4 -4
  233. package/src/multistream/remoteMedia.ts +2 -2
  234. package/src/multistream/remoteMediaGroup.ts +59 -0
  235. package/src/multistream/remoteMediaManager.ts +33 -0
  236. package/src/multistream/sendSlotManager.ts +170 -0
  237. package/src/reachability/index.ts +15 -4
  238. package/src/reachability/request.ts +7 -3
  239. package/src/reconnection-manager/index.ts +36 -29
  240. package/src/recording-controller/index.ts +20 -3
  241. package/src/recording-controller/util.ts +26 -9
  242. package/src/roap/index.ts +25 -30
  243. package/src/roap/request.ts +44 -51
  244. package/src/roap/turnDiscovery.ts +51 -25
  245. package/src/rtcMetrics/constants.ts +3 -0
  246. package/src/rtcMetrics/index.ts +100 -0
  247. package/src/statsAnalyzer/index.ts +0 -1
  248. package/test/integration/spec/converged-space-meetings.js +60 -3
  249. package/test/integration/spec/journey.js +336 -259
  250. package/test/integration/spec/space-meeting.js +76 -3
  251. package/test/unit/spec/annotation/index.ts +418 -0
  252. package/test/unit/spec/breakouts/breakout.ts +85 -26
  253. package/test/unit/spec/breakouts/events.ts +89 -0
  254. package/test/unit/spec/breakouts/index.ts +636 -98
  255. package/test/unit/spec/breakouts/utils.js +19 -1
  256. package/test/unit/spec/common/queue.js +31 -2
  257. package/test/unit/spec/controls-options-manager/index.js +8 -1
  258. package/test/unit/spec/controls-options-manager/util.js +576 -397
  259. package/test/unit/spec/fixture/locus.js +1 -0
  260. package/test/unit/spec/interpretation/collection.ts +15 -0
  261. package/test/unit/spec/interpretation/index.ts +589 -0
  262. package/test/unit/spec/interpretation/siLanguage.ts +28 -0
  263. package/test/unit/spec/locus-info/controlsUtils.js +195 -1
  264. package/test/unit/spec/locus-info/index.js +950 -45
  265. package/test/unit/spec/locus-info/infoUtils.js +37 -15
  266. package/test/unit/spec/locus-info/mediaSharesUtils.ts +22 -0
  267. package/test/unit/spec/locus-info/parser.js +62 -22
  268. package/test/unit/spec/locus-info/selfConstant.js +19 -0
  269. package/test/unit/spec/locus-info/selfUtils.js +131 -26
  270. package/test/unit/spec/media/index.ts +82 -79
  271. package/test/unit/spec/meeting/in-meeting-actions.ts +60 -2
  272. package/test/unit/spec/meeting/index.js +3208 -1734
  273. package/test/unit/spec/meeting/locusMediaRequest.ts +443 -0
  274. package/test/unit/spec/meeting/muteState.js +328 -417
  275. package/test/unit/spec/meeting/request.js +393 -48
  276. package/test/unit/spec/meeting/utils.js +552 -76
  277. package/test/unit/spec/meeting-info/index.js +181 -0
  278. package/test/unit/spec/meeting-info/meetinginfov2.js +258 -20
  279. package/test/unit/spec/meeting-info/utilv2.js +21 -0
  280. package/test/unit/spec/meetings/index.js +631 -145
  281. package/test/unit/spec/meetings/utils.js +164 -9
  282. package/test/unit/spec/member/index.js +44 -14
  283. package/test/unit/spec/member/util.js +296 -155
  284. package/test/unit/spec/members/index.js +23 -3
  285. package/test/unit/spec/members/request.js +167 -35
  286. package/test/unit/spec/metrics/index.js +1 -50
  287. package/test/unit/spec/multistream/mediaRequestManager.ts +366 -8
  288. package/test/unit/spec/multistream/receiveSlot.ts +1 -1
  289. package/test/unit/spec/multistream/remoteMediaGroup.ts +266 -0
  290. package/test/unit/spec/multistream/remoteMediaManager.ts +123 -0
  291. package/test/unit/spec/multistream/sendSlotManager.ts +242 -0
  292. package/test/unit/spec/reachability/index.ts +66 -5
  293. package/test/unit/spec/reachability/request.js +3 -1
  294. package/test/unit/spec/reconnection-manager/index.js +55 -5
  295. package/test/unit/spec/recording-controller/index.js +294 -218
  296. package/test/unit/spec/recording-controller/util.js +223 -96
  297. package/test/unit/spec/roap/index.ts +21 -48
  298. package/test/unit/spec/roap/request.ts +74 -60
  299. package/test/unit/spec/roap/turnDiscovery.ts +30 -6
  300. package/test/unit/spec/rtcMetrics/index.ts +68 -0
  301. package/test/utils/integrationTestUtils.js +46 -0
  302. package/test/utils/testUtils.js +0 -60
  303. package/src/metrics/config.ts +0 -487
@@ -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';
@@ -64,10 +62,10 @@ export default class LocusInfo extends EventsScope {
64
62
  replace: any;
65
63
  url: any;
66
64
  services: any;
67
-
65
+ mainSessionLocusCache: any;
68
66
  /**
69
67
  * Constructor
70
- * @param {boolean} updateMeeting true if the meeting should be updated
68
+ * @param {function} updateMeeting callback to update the meeting object from an object
71
69
  * @param {object} webex
72
70
  * @param {string} meetingId
73
71
  * @returns {undefined}
@@ -85,6 +83,53 @@ export default class LocusInfo extends EventsScope {
85
83
  this.locusParser = new LocusDeltaParser();
86
84
  }
87
85
 
86
+ /**
87
+ * 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.
88
+ *
89
+ * @param {Meeting} meeting
90
+ * @returns {undefined}
91
+ */
92
+ private doLocusSync(meeting: any) {
93
+ let isDelta;
94
+ let url;
95
+
96
+ if (this.locusParser.workingCopy.syncUrl) {
97
+ url = this.locusParser.workingCopy.syncUrl;
98
+ isDelta = true;
99
+ } else {
100
+ url = meeting.locusUrl;
101
+ isDelta = false;
102
+ }
103
+
104
+ LoggerProxy.logger.info(
105
+ `Locus-info:index#doLocusSync --> doing Locus sync (getting ${
106
+ isDelta ? 'delta' : 'full'
107
+ } DTO)`
108
+ );
109
+
110
+ // return value ignored on purpose
111
+ meeting.meetingRequest
112
+ .getLocusDTO({url})
113
+ .then((res) => {
114
+ if (isDelta) {
115
+ if (!isEmpty(res.body)) {
116
+ meeting.locusInfo.handleLocusDelta(res.body, meeting);
117
+ } else {
118
+ LoggerProxy.logger.info(
119
+ 'Locus-info:index#doLocusSync --> received empty body from syncUrl, so we already have latest Locus DTO'
120
+ );
121
+ }
122
+ } else {
123
+ meeting.locusInfo.onFullLocus(res.body);
124
+ }
125
+ })
126
+ .finally(() => {
127
+ // Notify parser to resume processing delta events.
128
+ // Any deltas in the queue that have now been superseded by this sync will simply be ignored
129
+ this.locusParser.resume();
130
+ });
131
+ }
132
+
88
133
  /**
89
134
  * Apply locus delta data to meeting
90
135
  * @param {string} action Locus delta action
@@ -93,28 +138,18 @@ export default class LocusInfo extends EventsScope {
93
138
  * @returns {undefined}
94
139
  */
95
140
  applyLocusDeltaData(action: string, locus: any, meeting: any) {
96
- const {DESYNC, USE_CURRENT, USE_INCOMING} = LocusDeltaParser.loci;
141
+ const {DESYNC, USE_CURRENT, USE_INCOMING, WAIT} = LocusDeltaParser.loci;
97
142
 
98
143
  switch (action) {
99
144
  case USE_INCOMING:
100
145
  meeting.locusInfo.onDeltaLocus(locus);
101
146
  break;
102
147
  case USE_CURRENT:
103
- meeting.locusDesync = false;
104
- meeting.needToGetFullLocus = false;
148
+ case WAIT:
149
+ // do nothing
105
150
  break;
106
151
  case DESYNC:
107
- meeting.meetingRequest
108
- .getFullLocus({
109
- desync: true,
110
- locusUrl: meeting.locusUrl,
111
- })
112
- .then((res) => {
113
- meeting.locusInfo.onFullLocus(res.body);
114
- // Notify parser to resume processing delta events
115
- // now that we have full locus from DESYNC.
116
- this.locusParser.resume();
117
- });
152
+ this.doLocusSync(meeting);
118
153
  break;
119
154
  default:
120
155
  LoggerProxy.logger.info(
@@ -180,12 +215,13 @@ export default class LocusInfo extends EventsScope {
180
215
  */
181
216
  this.deltaParticipants = [];
182
217
 
218
+ this.updateLocusCache(locus);
183
219
  // above section only updates the locusInfo object
184
220
  // The below section makes sure it updates the locusInfo as well as updates the meeting object
185
221
  this.updateParticipants(locus.participants);
186
222
  // For 1:1 space meeting the conversation Url does not exist in locus.conversation
187
223
  this.updateConversationUrl(locus.conversationUrl, locus.info);
188
- this.updateControls(locus.controls);
224
+ this.updateControls(locus.controls, locus.self);
189
225
  this.updateLocusUrl(locus.url);
190
226
  this.updateFullState(locus.fullState);
191
227
  this.updateMeetingInfo(locus.info);
@@ -203,6 +239,7 @@ export default class LocusInfo extends EventsScope {
203
239
  * @memberof LocusInfo
204
240
  */
205
241
  initialSetup(locus: object) {
242
+ this.updateLocusCache(locus);
206
243
  this.onFullLocus(locus);
207
244
 
208
245
  // Change it to true after it receives it first locus object
@@ -218,7 +255,7 @@ export default class LocusInfo extends EventsScope {
218
255
  parse(meeting: any, data: any) {
219
256
  // eslint-disable-next-line @typescript-eslint/no-shadow
220
257
  const {eventType} = data;
221
-
258
+ const locus = this.getTheLocusToUpdate(data.locus);
222
259
  LoggerProxy.logger.info(`Locus-info:index#parse --> received locus data: ${eventType}`);
223
260
 
224
261
  switch (eventType) {
@@ -236,16 +273,16 @@ export default class LocusInfo extends EventsScope {
236
273
  case LOCUSEVENT.PARTICIPANT_DECLINED:
237
274
  case LOCUSEVENT.FLOOR_GRANTED:
238
275
  case LOCUSEVENT.FLOOR_RELEASED:
239
- this.onFullLocus(data.locus, eventType);
276
+ this.onFullLocus(locus, eventType);
240
277
  break;
241
278
  case LOCUSEVENT.DIFFERENCE:
242
- this.handleLocusDelta(data.locus, meeting);
279
+ this.handleLocusDelta(locus, meeting);
243
280
  break;
244
281
 
245
282
  default:
246
283
  // Why will there be a event with no eventType ????
247
284
  // we may not need this, we can get full locus
248
- this.handleLocusDelta(data.locus, meeting);
285
+ this.handleLocusDelta(locus, meeting);
249
286
  }
250
287
  }
251
288
 
@@ -267,13 +304,21 @@ export default class LocusInfo extends EventsScope {
267
304
  * @returns {object} null
268
305
  * @memberof LocusInfo
269
306
  */
270
- // eslint-disable-next-line @typescript-eslint/no-shadow
271
307
  onFullLocus(locus: any, eventType?: string) {
272
308
  if (!locus) {
273
309
  LoggerProxy.logger.error(
274
310
  'Locus-info:index#onFullLocus --> object passed as argument was invalid, continuing.'
275
311
  );
276
312
  }
313
+
314
+ if (!this.locusParser.isNewFullLocus(locus)) {
315
+ LoggerProxy.logger.info(
316
+ `Locus-info:index#onFullLocus --> ignoring old full locus DTO, eventType=${eventType}`
317
+ );
318
+
319
+ return;
320
+ }
321
+
277
322
  this.updateParticipantDeltas(locus.participants);
278
323
  this.scheduledMeeting = locus.meeting || null;
279
324
  this.participants = locus.participants;
@@ -357,7 +402,7 @@ export default class LocusInfo extends EventsScope {
357
402
  return;
358
403
  }
359
404
 
360
- this.updateControls(locus.controls);
405
+ this.updateControls(locus.controls, locus.self);
361
406
  this.updateConversationUrl(locus.conversationUrl, locus.info);
362
407
  this.updateCreated(locus.created);
363
408
  this.updateFullState(locus.fullState);
@@ -428,10 +473,15 @@ export default class LocusInfo extends EventsScope {
428
473
  LoggerProxy.logger.warn(
429
474
  'Locus-info:index#isMeetingActive --> Call Ended, locus state is inactive.'
430
475
  );
431
- Metrics.postEvent({
432
- event: eventType.REMOTE_ENDED,
433
- meetingId: this.meetingId,
476
+
477
+ // @ts-ignore
478
+ this.webex.internal.newMetrics.submitClientEvent({
479
+ name: 'client.call.remote-ended',
480
+ options: {
481
+ meetingId: this.meetingId,
482
+ },
434
483
  });
484
+
435
485
  this.emitScoped(
436
486
  {
437
487
  file: 'locus-info',
@@ -450,9 +500,12 @@ export default class LocusInfo extends EventsScope {
450
500
  this.parsedLocus.self.state === MEETING_STATE.STATES.NOTIFIED ||
451
501
  this.parsedLocus.self.state === MEETING_STATE.STATES.JOINED)
452
502
  ) {
453
- Metrics.postEvent({
454
- event: eventType.REMOTE_ENDED,
455
- meetingId: this.meetingId,
503
+ // @ts-ignore
504
+ this.webex.internal.newMetrics.submitClientEvent({
505
+ name: 'client.call.remote-ended',
506
+ options: {
507
+ meetingId: this.meetingId,
508
+ },
456
509
  });
457
510
  this.emitScoped(
458
511
  {
@@ -474,10 +527,14 @@ export default class LocusInfo extends EventsScope {
474
527
  partner.state === MEETING_STATE.STATES.NOTIFIED ||
475
528
  partner.state === MEETING_STATE.STATES.IDLE) // Happens when user just joins and adds no Media
476
529
  ) {
477
- Metrics.postEvent({
478
- event: eventType.REMOTE_ENDED,
479
- meetingId: this.meetingId,
530
+ // @ts-ignore
531
+ this.webex.internal.newMetrics.submitClientEvent({
532
+ name: 'client.call.remote-ended',
533
+ options: {
534
+ meetingId: this.meetingId,
535
+ },
480
536
  });
537
+
481
538
  this.emitScoped(
482
539
  {
483
540
  file: 'locus-info',
@@ -500,9 +557,13 @@ export default class LocusInfo extends EventsScope {
500
557
  LoggerProxy.logger.warn(
501
558
  'Locus-info:index#isMeetingActive --> Meeting is ending due to inactive or terminating'
502
559
  );
503
- Metrics.postEvent({
504
- event: eventType.REMOTE_ENDED,
505
- meetingId: this.meetingId,
560
+
561
+ // @ts-ignore
562
+ this.webex.internal.newMetrics.submitClientEvent({
563
+ name: 'client.call.remote-ended',
564
+ options: {
565
+ meetingId: this.meetingId,
566
+ },
506
567
  });
507
568
  this.emitScoped(
508
569
  {
@@ -517,9 +578,13 @@ export default class LocusInfo extends EventsScope {
517
578
  );
518
579
  } else if (this.fullState && this.fullState.removed) {
519
580
  // user has been dropped from a meeting
520
- Metrics.postEvent({
521
- event: eventType.REMOTE_ENDED,
522
- meetingId: this.meetingId,
581
+
582
+ // @ts-ignore
583
+ this.webex.internal.newMetrics.submitClientEvent({
584
+ name: 'client.call.remote-ended',
585
+ options: {
586
+ meetingId: this.meetingId,
587
+ },
523
588
  });
524
589
  this.emitScoped(
525
590
  {
@@ -682,10 +747,11 @@ export default class LocusInfo extends EventsScope {
682
747
 
683
748
  /**
684
749
  * @param {Object} controls
750
+ * @param {Object} self
685
751
  * @returns {undefined}
686
752
  * @memberof LocusInfo
687
753
  */
688
- updateControls(controls: object) {
754
+ updateControls(controls: object, self: object) {
689
755
  if (controls && !isEqual(this.controls, controls)) {
690
756
  this.parsedLocus.controls = ControlsUtils.parse(controls);
691
757
  const {
@@ -697,10 +763,75 @@ export default class LocusInfo extends EventsScope {
697
763
  hasEntryExitToneChanged,
698
764
  hasBreakoutChanged,
699
765
  hasVideoEnabledChanged,
766
+ hasMuteOnEntryChanged,
767
+ hasShareControlChanged,
768
+ hasDisallowUnmuteChanged,
769
+ hasReactionsChanged,
770
+ hasReactionDisplayNamesChanged,
771
+ hasViewTheParticipantListChanged,
772
+ hasRaiseHandChanged,
773
+ hasVideoChanged,
774
+ hasInterpretationChanged,
700
775
  },
701
776
  current,
702
777
  } = ControlsUtils.getControls(this.controls, controls);
703
778
 
779
+ if (hasMuteOnEntryChanged) {
780
+ this.emitScoped(
781
+ {file: 'locus-info', function: 'updateControls'},
782
+ LOCUSINFO.EVENTS.CONTROLS_MUTE_ON_ENTRY_CHANGED,
783
+ {state: current.muteOnEntry}
784
+ );
785
+ }
786
+
787
+ if (hasShareControlChanged) {
788
+ this.emitScoped(
789
+ {file: 'locus-info', function: 'updateControls'},
790
+ LOCUSINFO.EVENTS.CONTROLS_SHARE_CONTROL_CHANGED,
791
+ {state: current.shareControl}
792
+ );
793
+ }
794
+
795
+ if (hasDisallowUnmuteChanged) {
796
+ this.emitScoped(
797
+ {file: 'locus-info', function: 'updateControls'},
798
+ LOCUSINFO.EVENTS.CONTROLS_DISALLOW_UNMUTE_CHANGED,
799
+ {state: current.disallowUnmute}
800
+ );
801
+ }
802
+
803
+ if (hasReactionsChanged || hasReactionDisplayNamesChanged) {
804
+ this.emitScoped(
805
+ {file: 'locus-info', function: 'updateControls'},
806
+ LOCUSINFO.EVENTS.CONTROLS_REACTIONS_CHANGED,
807
+ {state: current.reactions}
808
+ );
809
+ }
810
+
811
+ if (hasViewTheParticipantListChanged) {
812
+ this.emitScoped(
813
+ {file: 'locus-info', function: 'updateControls'},
814
+ LOCUSINFO.EVENTS.CONTROLS_VIEW_THE_PARTICIPANTS_LIST_CHANGED,
815
+ {state: current.viewTheParticipantList}
816
+ );
817
+ }
818
+
819
+ if (hasRaiseHandChanged) {
820
+ this.emitScoped(
821
+ {file: 'locus-info', function: 'updateControls'},
822
+ LOCUSINFO.EVENTS.CONTROLS_RAISE_HAND_CHANGED,
823
+ {state: current.raiseHand}
824
+ );
825
+ }
826
+
827
+ if (hasVideoChanged) {
828
+ this.emitScoped(
829
+ {file: 'locus-info', function: 'updateControls'},
830
+ LOCUSINFO.EVENTS.CONTROLS_VIDEO_CHANGED,
831
+ {state: current.video}
832
+ );
833
+ }
834
+
704
835
  if (hasRecordingChanged || hasRecordingPausedChanged) {
705
836
  let state = null;
706
837
 
@@ -762,7 +893,10 @@ export default class LocusInfo extends EventsScope {
762
893
 
763
894
  if (hasBreakoutChanged) {
764
895
  const {breakout} = current;
765
-
896
+ breakout.breakoutMoveId = SelfUtils.getReplacedBreakoutMoveId(
897
+ self,
898
+ this.webex.internal.device.url
899
+ );
766
900
  this.emitScoped(
767
901
  {
768
902
  file: 'locus-info',
@@ -775,6 +909,20 @@ export default class LocusInfo extends EventsScope {
775
909
  );
776
910
  }
777
911
 
912
+ if (hasInterpretationChanged) {
913
+ const {interpretation} = current;
914
+ this.emitScoped(
915
+ {
916
+ file: 'locus-info',
917
+ function: 'updateControls',
918
+ },
919
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_INTERPRETATION_UPDATED,
920
+ {
921
+ interpretation,
922
+ }
923
+ );
924
+ }
925
+
778
926
  if (hasEntryExitToneChanged) {
779
927
  const {entryExitTone} = current;
780
928
 
@@ -958,15 +1106,6 @@ export default class LocusInfo extends EventsScope {
958
1106
  const isJoined = SelfUtils.isJoined(self || this.parsedLocus.self);
959
1107
  const parsedInfo = InfoUtils.getInfos(this.parsedLocus.info, info, roles, isJoined);
960
1108
 
961
- this.emitScoped(
962
- {
963
- file: 'locus-info',
964
- function: 'updateMeetingInfo',
965
- },
966
- LOCUSINFO.EVENTS.MEETING_INFO_UPDATED,
967
- {info: parsedInfo.current, self}
968
- );
969
-
970
1109
  if (parsedInfo.updates.isLocked) {
971
1110
  this.emitScoped(
972
1111
  {
@@ -992,6 +1131,14 @@ export default class LocusInfo extends EventsScope {
992
1131
  this.parsedLocus.info = parsedInfo.current;
993
1132
  // Parses the info and adds necessary values
994
1133
  this.updateMeeting(parsedInfo.current);
1134
+
1135
+ this.emitScoped(
1136
+ {
1137
+ file: 'locus-info',
1138
+ function: 'updateMeetingInfo',
1139
+ },
1140
+ LOCUSINFO.EVENTS.MEETING_INFO_UPDATED
1141
+ );
995
1142
  }
996
1143
  this.roles = roles;
997
1144
  }
@@ -1135,6 +1282,20 @@ export default class LocusInfo extends EventsScope {
1135
1282
  );
1136
1283
  }
1137
1284
 
1285
+ if (parsedSelves.updates.interpretationChanged) {
1286
+ this.emitScoped(
1287
+ {
1288
+ file: 'locus-info',
1289
+ function: 'updateSelf',
1290
+ },
1291
+ LOCUSINFO.EVENTS.SELF_MEETING_INTERPRETATION_CHANGED,
1292
+ {
1293
+ interpretation: parsedSelves.current.interpretation,
1294
+ selfParticipantId: parsedSelves.current.selfId,
1295
+ }
1296
+ );
1297
+ }
1298
+
1138
1299
  if (parsedSelves.updates.isMediaInactiveOrReleased) {
1139
1300
  this.emitScoped(
1140
1301
  {
@@ -1156,18 +1317,18 @@ export default class LocusInfo extends EventsScope {
1156
1317
  self
1157
1318
  );
1158
1319
  }
1159
- // When the user upgrades to moderator or cohost
1160
- if (parsedSelves.updates.isUpgradeToModeratorOrCohost) {
1320
+
1321
+ if (parsedSelves.updates.isRolesChanged) {
1161
1322
  this.emitScoped(
1162
1323
  {
1163
1324
  file: 'locus-info',
1164
1325
  function: 'updateSelf',
1165
1326
  },
1166
- LOCUSINFO.EVENTS.SELF_MODERATOR_OR_COHOST_UPGRADE,
1167
- self
1327
+ LOCUSINFO.EVENTS.SELF_ROLES_CHANGED,
1328
+ {oldRoles: parsedSelves.previous?.roles, newRoles: parsedSelves.current?.roles}
1168
1329
  );
1169
1330
  }
1170
- //
1331
+
1171
1332
  if (parsedSelves.updates.isVideoMutedByOthersChanged) {
1172
1333
  this.emitScoped(
1173
1334
  {
@@ -1395,4 +1556,104 @@ export default class LocusInfo extends EventsScope {
1395
1556
  this.identities = identities;
1396
1557
  }
1397
1558
  }
1559
+
1560
+ /**
1561
+ * check the locus is main session's one or not, if is main session's, update main session cache
1562
+ * @param {Object} locus
1563
+ * @returns {undefined}
1564
+ * @memberof LocusInfo
1565
+ */
1566
+ updateLocusCache(locus: any) {
1567
+ const isMainSessionDTO = ControlsUtils.isMainSessionDTO(locus);
1568
+ if (isMainSessionDTO) {
1569
+ this.updateMainSessionLocusCache(locus);
1570
+ }
1571
+ }
1572
+
1573
+ /**
1574
+ * if return from breakout to main session, need to use cached main session DTO since locus won't send the full locus (participants)
1575
+ * if join breakout from main session, need to query main locus url (if response with 403 means no privilege, need to clear the cache)
1576
+ * @param {Object} newLocus
1577
+ * @returns {Object}
1578
+ * @memberof LocusInfo
1579
+ */
1580
+ getTheLocusToUpdate(newLocus: any) {
1581
+ const switchStatus = ControlsUtils.getSessionSwitchStatus(this.controls, newLocus?.controls);
1582
+ if (switchStatus.isReturnToMain && this.mainSessionLocusCache) {
1583
+ return cloneDeep(this.mainSessionLocusCache);
1584
+ }
1585
+ if (switchStatus.isJoinToBreakout) {
1586
+ this.emitScoped(
1587
+ {
1588
+ file: 'locus-info',
1589
+ function: 'updateControls',
1590
+ },
1591
+ LOCUSINFO.EVENTS.CONTROLS_JOIN_BREAKOUT_FROM_MAIN,
1592
+ {
1593
+ mainLocusUrl: this.url,
1594
+ }
1595
+ );
1596
+ }
1597
+
1598
+ return newLocus;
1599
+ }
1600
+
1601
+ /**
1602
+ * merge participants by participant id
1603
+ * @param {Array} participants
1604
+ * @param {Array} sourceParticipants
1605
+ * @returns {Array} merged participants
1606
+ * @memberof LocusInfo
1607
+ */
1608
+ // eslint-disable-next-line class-methods-use-this
1609
+ mergeParticipants(participants, sourceParticipants) {
1610
+ if (!sourceParticipants || !sourceParticipants.length) return participants;
1611
+ if (!participants || !participants.length) {
1612
+ return sourceParticipants;
1613
+ }
1614
+ sourceParticipants.forEach((participant) => {
1615
+ const existIndex = participants.findIndex((p) => p.id === participant.id);
1616
+ if (existIndex > -1) {
1617
+ participants.splice(existIndex, 1, participant);
1618
+ } else {
1619
+ participants.push(participant);
1620
+ }
1621
+ });
1622
+
1623
+ return participants;
1624
+ }
1625
+
1626
+ /**
1627
+ * need cache main sessions' participants since locus will not send the full list when cohost/host leave breakout
1628
+ * @param {Object} mainLocus
1629
+ * @returns {undefined}
1630
+ * @memberof LocusInfo
1631
+ */
1632
+ updateMainSessionLocusCache(mainLocus: any) {
1633
+ if (!mainLocus) {
1634
+ return;
1635
+ }
1636
+ const locusClone = cloneDeep(mainLocus);
1637
+ if (this.mainSessionLocusCache) {
1638
+ // shallow merge and do special merge for participants
1639
+ assignWith(this.mainSessionLocusCache, locusClone, (objValue, srcValue, key) => {
1640
+ if (key === 'participants') {
1641
+ return this.mergeParticipants(objValue, srcValue);
1642
+ }
1643
+
1644
+ return srcValue || objValue;
1645
+ });
1646
+ } else {
1647
+ this.mainSessionLocusCache = locusClone;
1648
+ }
1649
+ }
1650
+
1651
+ /**
1652
+ * clear main session cache
1653
+ * @returns {undefined}
1654
+ * @memberof LocusInfo
1655
+ */
1656
+ clearMainSessionLocusCache() {
1657
+ this.mainSessionLocusCache = null;
1658
+ }
1398
1659
  }
@@ -1,4 +1,4 @@
1
- import {SELF_ROLES, DISPLAY_HINTS} from '../constants';
1
+ import {SELF_ROLES, DISPLAY_HINTS, INTERSTITIAL_DISPLAY_HINTS} from '../constants';
2
2
 
3
3
  const InfoUtils: any = {};
4
4
 
@@ -9,7 +9,15 @@ InfoUtils.parse = (info, roles, isJoined = true) => {
9
9
  coHost: InfoUtils.parseCoHost(info),
10
10
  };
11
11
 
12
- let userDisplayHints = isJoined ? {...parsed.policy} : {};
12
+ let userDisplayHints = isJoined
13
+ ? {...parsed.policy}
14
+ : {
15
+ ...Object.fromEntries(
16
+ Object.entries(parsed.policy).filter(([hint]) =>
17
+ INTERSTITIAL_DISPLAY_HINTS.includes(hint)
18
+ )
19
+ ),
20
+ };
13
21
 
14
22
  if (roles.includes(SELF_ROLES.COHOST)) {
15
23
  userDisplayHints = {...userDisplayHints, ...parsed.coHost};
@@ -13,6 +13,9 @@ MediaSharesUtils.parse = (mediaShares: object) => {
13
13
  content: {
14
14
  beneficiaryId: MediaSharesUtils.getContentBeneficiaryId(mediaShares),
15
15
  disposition: MediaSharesUtils.getContentDisposition(mediaShares),
16
+ annotation: MediaSharesUtils.getContentAnnotation(mediaShares),
17
+ url: MediaSharesUtils.getContentUrl(mediaShares),
18
+ shareInstanceId: MediaSharesUtils.getShareInstanceId(mediaShares),
16
19
  },
17
20
  whiteboard: {
18
21
  beneficiaryId: MediaSharesUtils.getWhiteboardBeneficiaryId(mediaShares),
@@ -140,6 +143,51 @@ MediaSharesUtils.getContentBeneficiaryId = (mediaShares: object) => {
140
143
  return contentFloor.beneficiary.id;
141
144
  };
142
145
 
146
+ /**
147
+ * get live annotation is sharing from media shares (content)
148
+ * @param {Object} mediaShares
149
+ * @returns {Object}
150
+ */
151
+ MediaSharesUtils.getContentAnnotation = (mediaShares: object) => {
152
+ const extractContent = MediaSharesUtils.extractContent(mediaShares);
153
+
154
+ if (!extractContent || !extractContent.annotation) {
155
+ return undefined;
156
+ }
157
+
158
+ return extractContent.annotation;
159
+ };
160
+
161
+ /**
162
+ * get url is sharing from media shares (content)
163
+ * @param {Object} mediaShares
164
+ * @returns {Object}
165
+ */
166
+ MediaSharesUtils.getContentUrl = (mediaShares: object) => {
167
+ const extractContent = MediaSharesUtils.extractContent(mediaShares);
168
+
169
+ if (!extractContent || !extractContent.url) {
170
+ return undefined;
171
+ }
172
+
173
+ return extractContent.url;
174
+ };
175
+
176
+ /**
177
+ * get shareInstanceId is sharing from media shares (content)
178
+ * @param {Object} mediaShares
179
+ * @returns {Object}
180
+ */
181
+ MediaSharesUtils.getShareInstanceId = (mediaShares: object) => {
182
+ const extractContent = MediaSharesUtils.extractContent(mediaShares);
183
+
184
+ if (!extractContent || !extractContent.floor || !extractContent.floor.shareInstanceId) {
185
+ return undefined;
186
+ }
187
+
188
+ return extractContent.floor.shareInstanceId;
189
+ };
190
+
143
191
  /**
144
192
  * get who is sharing from media shares (whiteboard)
145
193
  * @param {Object} mediaShares