@webex/plugin-meetings 3.8.1 → 3.9.0-webinar5k.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 (296) hide show
  1. package/README.md +26 -13
  2. package/dist/breakouts/breakout.js +1 -1
  3. package/dist/breakouts/index.js +1 -1
  4. package/dist/constants.js +16 -3
  5. package/dist/constants.js.map +1 -1
  6. package/dist/controls-options-manager/enums.js +1 -0
  7. package/dist/controls-options-manager/enums.js.map +1 -1
  8. package/dist/controls-options-manager/types.js.map +1 -1
  9. package/dist/controls-options-manager/util.js +26 -0
  10. package/dist/controls-options-manager/util.js.map +1 -1
  11. package/dist/hashTree/constants.js +23 -0
  12. package/dist/hashTree/constants.js.map +1 -0
  13. package/dist/hashTree/hashTree.js +516 -0
  14. package/dist/hashTree/hashTree.js.map +1 -0
  15. package/dist/hashTree/hashTreeParser.js +521 -0
  16. package/dist/hashTree/hashTreeParser.js.map +1 -0
  17. package/dist/interpretation/index.js +1 -1
  18. package/dist/interpretation/siLanguage.js +1 -1
  19. package/dist/locus-info/controlsUtils.js +11 -3
  20. package/dist/locus-info/controlsUtils.js.map +1 -1
  21. package/dist/locus-info/index.js +331 -59
  22. package/dist/locus-info/index.js.map +1 -1
  23. package/dist/media/index.js +2 -2
  24. package/dist/media/index.js.map +1 -1
  25. package/dist/meeting/brbState.js +17 -14
  26. package/dist/meeting/brbState.js.map +1 -1
  27. package/dist/meeting/in-meeting-actions.js +5 -1
  28. package/dist/meeting/in-meeting-actions.js.map +1 -1
  29. package/dist/meeting/index.js +264 -125
  30. package/dist/meeting/index.js.map +1 -1
  31. package/dist/meeting/muteState.js +2 -5
  32. package/dist/meeting/muteState.js.map +1 -1
  33. package/dist/meeting/request.js +19 -0
  34. package/dist/meeting/request.js.map +1 -1
  35. package/dist/meeting/request.type.js.map +1 -1
  36. package/dist/meeting/util.js +8 -11
  37. package/dist/meeting/util.js.map +1 -1
  38. package/dist/meetings/index.js +6 -2
  39. package/dist/meetings/index.js.map +1 -1
  40. package/dist/member/types.js.map +1 -1
  41. package/dist/members/collection.js +13 -0
  42. package/dist/members/collection.js.map +1 -1
  43. package/dist/members/index.js +44 -23
  44. package/dist/members/index.js.map +1 -1
  45. package/dist/members/request.js +3 -3
  46. package/dist/members/request.js.map +1 -1
  47. package/dist/members/util.js +18 -6
  48. package/dist/members/util.js.map +1 -1
  49. package/dist/metrics/constants.js +1 -0
  50. package/dist/metrics/constants.js.map +1 -1
  51. package/dist/multistream/sendSlotManager.js +32 -2
  52. package/dist/multistream/sendSlotManager.js.map +1 -1
  53. package/dist/reachability/index.js +5 -10
  54. package/dist/reachability/index.js.map +1 -1
  55. package/dist/types/constants.d.ts +12 -0
  56. package/dist/types/controls-options-manager/enums.d.ts +2 -1
  57. package/dist/types/controls-options-manager/types.d.ts +4 -1
  58. package/dist/types/hashTree/constants.d.ts +8 -0
  59. package/dist/types/hashTree/hashTree.d.ts +128 -0
  60. package/dist/types/hashTree/hashTreeParser.d.ts +152 -0
  61. package/dist/types/locus-info/index.d.ts +93 -3
  62. package/dist/types/meeting/brbState.d.ts +0 -1
  63. package/dist/types/meeting/in-meeting-actions.d.ts +4 -0
  64. package/dist/types/meeting/index.d.ts +36 -3
  65. package/dist/types/meeting/request.d.ts +9 -1
  66. package/dist/types/meeting/request.type.d.ts +74 -0
  67. package/dist/types/meeting/util.d.ts +3 -3
  68. package/dist/types/member/types.d.ts +1 -0
  69. package/dist/types/members/collection.d.ts +6 -0
  70. package/dist/types/members/index.d.ts +15 -3
  71. package/dist/types/members/request.d.ts +1 -1
  72. package/dist/types/members/util.d.ts +5 -2
  73. package/dist/types/metrics/constants.d.ts +1 -0
  74. package/dist/types/multistream/sendSlotManager.d.ts +16 -0
  75. package/dist/types/reachability/index.d.ts +2 -2
  76. package/dist/webinar/index.js +1 -1
  77. package/package.json +26 -25
  78. package/src/constants.ts +16 -0
  79. package/src/controls-options-manager/enums.ts +1 -0
  80. package/src/controls-options-manager/types.ts +6 -1
  81. package/src/controls-options-manager/util.ts +31 -0
  82. package/src/hashTree/constants.ts +12 -0
  83. package/src/hashTree/hashTree.ts +460 -0
  84. package/src/hashTree/hashTreeParser.ts +556 -0
  85. package/src/locus-info/controlsUtils.ts +15 -0
  86. package/src/locus-info/index.ts +434 -58
  87. package/src/media/index.ts +2 -2
  88. package/src/meeting/brbState.ts +13 -9
  89. package/src/meeting/in-meeting-actions.ts +8 -0
  90. package/src/meeting/index.ts +193 -39
  91. package/src/meeting/muteState.ts +2 -6
  92. package/src/meeting/request.ts +16 -0
  93. package/src/meeting/request.type.ts +64 -0
  94. package/src/meeting/util.ts +17 -20
  95. package/src/meetings/index.ts +17 -3
  96. package/src/member/types.ts +1 -0
  97. package/src/members/collection.ts +11 -0
  98. package/src/members/index.ts +33 -7
  99. package/src/members/request.ts +2 -2
  100. package/src/members/util.ts +14 -3
  101. package/src/metrics/constants.ts +1 -0
  102. package/src/multistream/sendSlotManager.ts +34 -2
  103. package/src/reachability/index.ts +5 -13
  104. package/test/unit/spec/controls-options-manager/util.js +58 -0
  105. package/test/unit/spec/hashTree/hashTree.ts +394 -0
  106. package/test/unit/spec/hashTree/hashTreeParser.ts +156 -0
  107. package/test/unit/spec/locus-info/controlsUtils.js +52 -0
  108. package/test/unit/spec/locus-info/index.js +547 -54
  109. package/test/unit/spec/media/index.ts +107 -0
  110. package/test/unit/spec/meeting/brbState.ts +23 -4
  111. package/test/unit/spec/meeting/in-meeting-actions.ts +4 -0
  112. package/test/unit/spec/meeting/index.js +647 -46
  113. package/test/unit/spec/meeting/request.js +71 -0
  114. package/test/unit/spec/members/index.js +33 -10
  115. package/test/unit/spec/members/request.js +2 -2
  116. package/test/unit/spec/members/utils.js +27 -7
  117. package/test/unit/spec/multistream/sendSlotManager.ts +59 -0
  118. package/test/unit/spec/reachability/index.ts +2 -6
  119. package/dist/annotation/annotation.types.d.ts +0 -42
  120. package/dist/annotation/constants.d.ts +0 -31
  121. package/dist/annotation/index.d.ts +0 -117
  122. package/dist/breakouts/breakout.d.ts +0 -8
  123. package/dist/breakouts/collection.d.ts +0 -5
  124. package/dist/breakouts/edit-lock-error.d.ts +0 -15
  125. package/dist/breakouts/events.d.ts +0 -8
  126. package/dist/breakouts/index.d.ts +0 -5
  127. package/dist/breakouts/request.d.ts +0 -22
  128. package/dist/breakouts/utils.d.ts +0 -15
  129. package/dist/common/browser-detection.d.ts +0 -9
  130. package/dist/common/collection.d.ts +0 -48
  131. package/dist/common/config.d.ts +0 -2
  132. package/dist/common/errors/captcha-error.d.ts +0 -15
  133. package/dist/common/errors/intent-to-join.d.ts +0 -16
  134. package/dist/common/errors/join-meeting.d.ts +0 -17
  135. package/dist/common/errors/media.d.ts +0 -15
  136. package/dist/common/errors/no-meeting-info.d.ts +0 -14
  137. package/dist/common/errors/parameter.d.ts +0 -15
  138. package/dist/common/errors/password-error.d.ts +0 -15
  139. package/dist/common/errors/permission.d.ts +0 -14
  140. package/dist/common/errors/reclaim-host-role-error.d.ts +0 -60
  141. package/dist/common/errors/reclaim-host-role-error.js +0 -158
  142. package/dist/common/errors/reclaim-host-role-error.js.map +0 -1
  143. package/dist/common/errors/reclaim-host-role-errors.d.ts +0 -60
  144. package/dist/common/errors/reconnection-in-progress.d.ts +0 -9
  145. package/dist/common/errors/reconnection-in-progress.js +0 -35
  146. package/dist/common/errors/reconnection-in-progress.js.map +0 -1
  147. package/dist/common/errors/reconnection.d.ts +0 -15
  148. package/dist/common/errors/stats.d.ts +0 -15
  149. package/dist/common/errors/webex-errors.d.ts +0 -81
  150. package/dist/common/errors/webex-meetings-error.d.ts +0 -20
  151. package/dist/common/events/events-scope.d.ts +0 -17
  152. package/dist/common/events/events.d.ts +0 -12
  153. package/dist/common/events/trigger-proxy.d.ts +0 -2
  154. package/dist/common/events/util.d.ts +0 -2
  155. package/dist/common/logs/logger-config.d.ts +0 -2
  156. package/dist/common/logs/logger-proxy.d.ts +0 -2
  157. package/dist/common/logs/request.d.ts +0 -34
  158. package/dist/common/queue.d.ts +0 -32
  159. package/dist/config.d.ts +0 -73
  160. package/dist/constants.d.ts +0 -952
  161. package/dist/controls-options-manager/constants.d.ts +0 -4
  162. package/dist/controls-options-manager/enums.d.ts +0 -5
  163. package/dist/controls-options-manager/index.d.ts +0 -120
  164. package/dist/controls-options-manager/types.d.ts +0 -43
  165. package/dist/controls-options-manager/util.d.ts +0 -7
  166. package/dist/index.d.ts +0 -4
  167. package/dist/interceptors/index.d.ts +0 -2
  168. package/dist/interceptors/locusRetry.d.ts +0 -27
  169. package/dist/interpretation/collection.d.ts +0 -5
  170. package/dist/interpretation/index.d.ts +0 -5
  171. package/dist/interpretation/siLanguage.d.ts +0 -5
  172. package/dist/locus-info/controlsUtils.d.ts +0 -2
  173. package/dist/locus-info/embeddedAppsUtils.d.ts +0 -2
  174. package/dist/locus-info/fullState.d.ts +0 -2
  175. package/dist/locus-info/hostUtils.d.ts +0 -2
  176. package/dist/locus-info/index.d.ts +0 -269
  177. package/dist/locus-info/infoUtils.d.ts +0 -2
  178. package/dist/locus-info/mediaSharesUtils.d.ts +0 -2
  179. package/dist/locus-info/parser.d.ts +0 -212
  180. package/dist/locus-info/selfUtils.d.ts +0 -2
  181. package/dist/media/index.d.ts +0 -32
  182. package/dist/media/properties.d.ts +0 -108
  183. package/dist/media/util.d.ts +0 -2
  184. package/dist/mediaQualityMetrics/config.d.ts +0 -233
  185. package/dist/mediaQualityMetrics/config.js +0 -513
  186. package/dist/mediaQualityMetrics/config.js.map +0 -1
  187. package/dist/meeting/effectsState.d.ts +0 -42
  188. package/dist/meeting/effectsState.js +0 -260
  189. package/dist/meeting/effectsState.js.map +0 -1
  190. package/dist/meeting/in-meeting-actions.d.ts +0 -79
  191. package/dist/meeting/index.d.ts +0 -1622
  192. package/dist/meeting/locusMediaRequest.d.ts +0 -74
  193. package/dist/meeting/muteState.d.ts +0 -116
  194. package/dist/meeting/request.d.ts +0 -257
  195. package/dist/meeting/request.type.d.ts +0 -11
  196. package/dist/meeting/state.d.ts +0 -9
  197. package/dist/meeting/util.d.ts +0 -2
  198. package/dist/meeting/voicea-meeting.d.ts +0 -16
  199. package/dist/meeting-info/collection.d.ts +0 -20
  200. package/dist/meeting-info/index.d.ts +0 -57
  201. package/dist/meeting-info/meeting-info-v2.d.ts +0 -93
  202. package/dist/meeting-info/request.d.ts +0 -22
  203. package/dist/meeting-info/util.d.ts +0 -2
  204. package/dist/meeting-info/utilv2.d.ts +0 -2
  205. package/dist/meetings/collection.d.ts +0 -23
  206. package/dist/meetings/index.d.ts +0 -296
  207. package/dist/meetings/meetings.types.d.ts +0 -4
  208. package/dist/meetings/request.d.ts +0 -27
  209. package/dist/meetings/util.d.ts +0 -18
  210. package/dist/member/index.d.ts +0 -148
  211. package/dist/member/member.types.d.ts +0 -11
  212. package/dist/member/member.types.js +0 -18
  213. package/dist/member/member.types.js.map +0 -1
  214. package/dist/member/types.d.ts +0 -32
  215. package/dist/member/util.d.ts +0 -2
  216. package/dist/members/collection.d.ts +0 -24
  217. package/dist/members/index.d.ts +0 -308
  218. package/dist/members/request.d.ts +0 -58
  219. package/dist/members/types.d.ts +0 -25
  220. package/dist/members/util.d.ts +0 -2
  221. package/dist/metrics/config.d.ts +0 -169
  222. package/dist/metrics/config.js +0 -289
  223. package/dist/metrics/config.js.map +0 -1
  224. package/dist/metrics/constants.d.ts +0 -59
  225. package/dist/metrics/index.d.ts +0 -152
  226. package/dist/multistream/mediaRequestManager.d.ts +0 -119
  227. package/dist/multistream/receiveSlot.d.ts +0 -68
  228. package/dist/multistream/receiveSlotManager.d.ts +0 -56
  229. package/dist/multistream/remoteMedia.d.ts +0 -72
  230. package/dist/multistream/remoteMediaGroup.d.ts +0 -49
  231. package/dist/multistream/remoteMediaManager.d.ts +0 -300
  232. package/dist/multistream/sendSlotManager.d.ts +0 -69
  233. package/dist/networkQualityMonitor/index.d.ts +0 -70
  234. package/dist/networkQualityMonitor/index.js +0 -226
  235. package/dist/networkQualityMonitor/index.js.map +0 -1
  236. package/dist/peer-connection-manager/index.d.ts +0 -6
  237. package/dist/peer-connection-manager/index.js +0 -671
  238. package/dist/peer-connection-manager/index.js.map +0 -1
  239. package/dist/peer-connection-manager/util.d.ts +0 -6
  240. package/dist/peer-connection-manager/util.js +0 -110
  241. package/dist/peer-connection-manager/util.js.map +0 -1
  242. package/dist/personal-meeting-room/index.d.ts +0 -47
  243. package/dist/personal-meeting-room/request.d.ts +0 -14
  244. package/dist/personal-meeting-room/util.d.ts +0 -2
  245. package/dist/reachability/clusterReachability.d.ts +0 -109
  246. package/dist/reachability/index.d.ts +0 -139
  247. package/dist/reachability/request.d.ts +0 -35
  248. package/dist/reachability/util.d.ts +0 -8
  249. package/dist/reactions/constants.d.ts +0 -3
  250. package/dist/reactions/reactions.d.ts +0 -4
  251. package/dist/reactions/reactions.type.d.ts +0 -32
  252. package/dist/reconnection-manager/index.d.ts +0 -112
  253. package/dist/recording-controller/enums.d.ts +0 -7
  254. package/dist/recording-controller/index.d.ts +0 -193
  255. package/dist/recording-controller/util.d.ts +0 -13
  256. package/dist/roap/collection.d.ts +0 -10
  257. package/dist/roap/collection.js +0 -63
  258. package/dist/roap/collection.js.map +0 -1
  259. package/dist/roap/handler.d.ts +0 -47
  260. package/dist/roap/handler.js +0 -279
  261. package/dist/roap/handler.js.map +0 -1
  262. package/dist/roap/index.d.ts +0 -116
  263. package/dist/roap/request.d.ts +0 -35
  264. package/dist/roap/state.d.ts +0 -9
  265. package/dist/roap/state.js +0 -127
  266. package/dist/roap/state.js.map +0 -1
  267. package/dist/roap/turnDiscovery.d.ts +0 -81
  268. package/dist/roap/util.d.ts +0 -2
  269. package/dist/roap/util.js +0 -76
  270. package/dist/roap/util.js.map +0 -1
  271. package/dist/rtcMetrics/constants.d.ts +0 -4
  272. package/dist/rtcMetrics/constants.js +0 -11
  273. package/dist/rtcMetrics/constants.js.map +0 -1
  274. package/dist/rtcMetrics/index.d.ts +0 -61
  275. package/dist/rtcMetrics/index.js +0 -197
  276. package/dist/rtcMetrics/index.js.map +0 -1
  277. package/dist/statsAnalyzer/global.d.ts +0 -118
  278. package/dist/statsAnalyzer/global.js +0 -127
  279. package/dist/statsAnalyzer/global.js.map +0 -1
  280. package/dist/statsAnalyzer/index.d.ts +0 -193
  281. package/dist/statsAnalyzer/index.js +0 -1019
  282. package/dist/statsAnalyzer/index.js.map +0 -1
  283. package/dist/statsAnalyzer/mqaUtil.d.ts +0 -22
  284. package/dist/statsAnalyzer/mqaUtil.js +0 -181
  285. package/dist/statsAnalyzer/mqaUtil.js.map +0 -1
  286. package/dist/transcription/index.d.ts +0 -64
  287. package/dist/types/common/errors/reconnection-in-progress.d.ts +0 -9
  288. package/dist/types/mediaQualityMetrics/config.d.ts +0 -241
  289. package/dist/types/networkQualityMonitor/index.d.ts +0 -70
  290. package/dist/types/rtcMetrics/constants.d.ts +0 -4
  291. package/dist/types/rtcMetrics/index.d.ts +0 -71
  292. package/dist/types/statsAnalyzer/global.d.ts +0 -36
  293. package/dist/types/statsAnalyzer/index.d.ts +0 -217
  294. package/dist/types/statsAnalyzer/mqaUtil.d.ts +0 -48
  295. package/dist/webinar/collection.d.ts +0 -16
  296. package/dist/webinar/index.d.ts +0 -5
@@ -58,7 +58,13 @@ export class BrbState {
58
58
  public enable(enabled: boolean, sendSlotManager: SendSlotManager) {
59
59
  this.state.client.enabled = enabled;
60
60
 
61
- return this.applyClientStateToServer(sendSlotManager);
61
+ // Don't set the source state override if enabling brb fails
62
+ return this.applyClientStateToServer(sendSlotManager).then(() => {
63
+ sendSlotManager.setSourceStateOverride(
64
+ MediaType.VideoMain,
65
+ this.state.client.enabled ? 'away' : null
66
+ );
67
+ });
62
68
  }
63
69
 
64
70
  /**
@@ -92,7 +98,7 @@ export class BrbState {
92
98
 
93
99
  this.state.syncToServerInProgress = true;
94
100
 
95
- return this.sendLocalBrbStateToServer(sendSlotManager)
101
+ return this.sendLocalBrbStateToServer()
96
102
  .then(() => {
97
103
  this.state.syncToServerInProgress = false;
98
104
 
@@ -109,19 +115,20 @@ export class BrbState {
109
115
  // need to check if a new sync is required, because this.state.client may have changed while we were doing the current sync
110
116
  this.applyClientStateToServer(sendSlotManager);
111
117
  })
112
- .catch((e) => {
118
+ .catch((error) => {
113
119
  this.state.syncToServerInProgress = false;
114
- LoggerProxy.logger.warn(`Meeting:brbState#applyClientStateToServer: error: ${e}`);
120
+ LoggerProxy.logger.warn(`Meeting:brbState#applyClientStateToServer: Error: ${error}`);
121
+
122
+ return Promise.reject(error);
115
123
  });
116
124
  }
117
125
 
118
126
  /**
119
127
  * Send the local brb state to the server
120
128
  *
121
- * @param {SendSlotManager} sendSlotManager
122
129
  * @returns {Promise}
123
130
  */
124
- private async sendLocalBrbStateToServer(sendSlotManager: SendSlotManager) {
131
+ private async sendLocalBrbStateToServer() {
125
132
  const {enabled} = this.state.client;
126
133
 
127
134
  if (!this.meeting.isMultistream) {
@@ -151,9 +158,6 @@ export class BrbState {
151
158
  deviceUrl: this.meeting.deviceUrl,
152
159
  selfId: this.meeting.selfId,
153
160
  })
154
- .then(() => {
155
- sendSlotManager.setSourceStateOverride(MediaType.VideoMain, enabled ? 'away' : null);
156
- })
157
161
  .catch((error) => {
158
162
  LoggerProxy.logger.error('Meeting:brbState#sendLocalBrbStateToServer: Error ', error);
159
163
 
@@ -107,6 +107,8 @@ interface IInMeetingActions {
107
107
  canEnableRemoteDesktopControl?: boolean;
108
108
  canDisableRemoteDesktopControl?: boolean;
109
109
  canMoveToLobby?: boolean;
110
+ canEnablePollingQA?: boolean;
111
+ canDisablePollingQA?: boolean;
110
112
  }
111
113
 
112
114
  /**
@@ -309,6 +311,10 @@ export default class InMeetingActions implements IInMeetingActions {
309
311
 
310
312
  canMoveToLobby = null;
311
313
 
314
+ canEnablePollingQA = null;
315
+
316
+ canDisablePollingQA = null;
317
+
312
318
  /**
313
319
  * Returns all meeting action options
314
320
  * @returns {Object}
@@ -411,6 +417,8 @@ export default class InMeetingActions implements IInMeetingActions {
411
417
  canEnableRemoteDesktopControl: this.canEnableRemoteDesktopControl,
412
418
  canDisableRemoteDesktopControl: this.canDisableRemoteDesktopControl,
413
419
  canMoveToLobby: this.canMoveToLobby,
420
+ canEnablePollingQA: this.canEnablePollingQA,
421
+ canDisablePollingQA: this.canDisablePollingQA,
414
422
  });
415
423
 
416
424
  /**
@@ -66,7 +66,7 @@ import Media, {type BundlePolicy} from '../media';
66
66
  import MediaProperties from '../media/properties';
67
67
  import MeetingStateMachine from './state';
68
68
  import {createMuteState} from './muteState';
69
- import LocusInfo from '../locus-info';
69
+ import LocusInfo, {LocusDTO, LocusLLMEvent} from '../locus-info';
70
70
  import Metrics from '../metrics';
71
71
  import ReconnectionManager from '../reconnection-manager';
72
72
  import ReconnectionNotStartedError from '../common/errors/reconnection-not-started';
@@ -121,6 +121,7 @@ import {
121
121
  WEBINAR_ERROR_REGISTRATION_ID,
122
122
  JOIN_BEFORE_HOST,
123
123
  REGISTRATION_ID_STATUS,
124
+ STAGE_MANAGER_TYPE,
124
125
  } from '../constants';
125
126
  import BEHAVIORAL_METRICS from '../metrics/constants';
126
127
  import ParameterError from '../common/errors/parameter';
@@ -164,6 +165,8 @@ import {BrbState, createBrbState} from './brbState';
164
165
  import MultistreamNotSupportedError from '../common/errors/multistream-not-supported-error';
165
166
  import JoinForbiddenError from '../common/errors/join-forbidden-error';
166
167
  import {ReachabilityMetrics} from '../reachability/reachability.types';
168
+ import {SetStageOptions, SetStageVideoLayout, UnsetStageVideoLayout} from './request.type';
169
+ import {DataSet} from '../hashTree/hashTreeParser';
167
170
 
168
171
  // default callback so we don't call an undefined function, but in practice it should never be used
169
172
  const DEFAULT_ICE_PHASE_CALLBACK = () => 'JOIN_MEETING_FINAL';
@@ -231,6 +234,14 @@ export type AddMediaOptions = {
231
234
  remoteMediaManagerConfig?: RemoteMediaManagerConfiguration; // applies only to multistream meetings
232
235
  bundlePolicy?: BundlePolicy; // applies only to multistream meetings
233
236
  allowMediaInLobby?: boolean; // allows adding media when in the lobby
237
+ additionalMediaOptions?: AdditionalMediaOptions; // allows adding additional options like send/receive audio/video
238
+ };
239
+
240
+ export type AdditionalMediaOptions = {
241
+ sendVideo?: boolean; // if not specified, default value of videoEnabled is used
242
+ receiveVideo?: boolean; // if not specified, default value of videoEnabled is used
243
+ sendAudio?: boolean; // if not specified, default value of audioEnabled true is used
244
+ receiveAudio?: boolean; // if not specified, default value of audioEnabled true is used
234
245
  };
235
246
 
236
247
  export type CallStateForMetrics = {
@@ -263,8 +274,9 @@ type FetchMeetingInfoParams = {
263
274
  };
264
275
 
265
276
  type MediaReachabilityMetrics = ReachabilityMetrics & {
266
- isSubnetReachable: boolean;
267
- selectedCluster: string | null;
277
+ subnet_reachable: boolean;
278
+ selected_cluster: string | null;
279
+ selected_subnet: string | null;
268
280
  };
269
281
 
270
282
  /**
@@ -1344,7 +1356,7 @@ export default class Meeting extends StatelessWebexPlugin {
1344
1356
  captions: [],
1345
1357
  isListening: false,
1346
1358
  commandText: '',
1347
- languageOptions: {},
1359
+ languageOptions: {currentSpokenLanguage: 'en'},
1348
1360
  showCaptionBox: false,
1349
1361
  transcribingRequestStatus: 'INACTIVE',
1350
1362
  isCaptioning: false,
@@ -2753,6 +2765,29 @@ export default class Meeting extends StatelessWebexPlugin {
2753
2765
  }
2754
2766
  );
2755
2767
 
2768
+ this.locusInfo.on(
2769
+ LOCUSINFO.EVENTS.CONTROLS_MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
2770
+ ({spokenLanguage}) => {
2771
+ if (spokenLanguage) {
2772
+ if (this.transcription?.languageOptions) {
2773
+ this.transcription.languageOptions.currentSpokenLanguage = spokenLanguage;
2774
+ }
2775
+ // @ts-ignore
2776
+ this.webex.internal.voicea.onSpokenLanguageUpdate(spokenLanguage, this.id);
2777
+
2778
+ Trigger.trigger(
2779
+ this,
2780
+ {
2781
+ file: 'meeting/index',
2782
+ function: 'setupLocusControlsListener',
2783
+ },
2784
+ EVENT_TRIGGERS.MEETING_TRANSCRIPTION_SPOKEN_LANGUAGE_UPDATED,
2785
+ {spokenLanguage, meetingId: this.id}
2786
+ );
2787
+ }
2788
+ }
2789
+ );
2790
+
2756
2791
  this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_MEETING_MANUAL_CAPTION_UPDATED, ({enable}) => {
2757
2792
  Trigger.trigger(
2758
2793
  this,
@@ -2921,6 +2956,15 @@ export default class Meeting extends StatelessWebexPlugin {
2921
2956
  {state}
2922
2957
  );
2923
2958
  });
2959
+
2960
+ this.locusInfo.on(LOCUSINFO.EVENTS.CONTROLS_POLLING_QA_CHANGED, ({state}) => {
2961
+ Trigger.trigger(
2962
+ this,
2963
+ {file: 'meeting/index', function: 'setupLocusControlsListener'},
2964
+ EVENT_TRIGGERS.MEETING_CONTROLS_POLLING_QA_UPDATED,
2965
+ {state}
2966
+ );
2967
+ });
2924
2968
  }
2925
2969
 
2926
2970
  /**
@@ -3820,15 +3864,16 @@ export default class Meeting extends StatelessWebexPlugin {
3820
3864
  }
3821
3865
 
3822
3866
  /**
3823
- * Cancel an SIP call invitation made during a meeting
3867
+ * Cancel an SIP/phone call invitation made during a meeting
3824
3868
  * @param {Object} invitee
3825
3869
  * @param {String} invitee.memberId
3826
- * @returns {Promise} see #members.cancelSIPInvite
3870
+ * @param {Boolean} [invitee.isInternalNumber] - When cancel phone invitation, if the number is internal
3871
+ * @returns {Promise} see #members.cancelInviteByMemberId
3827
3872
  * @public
3828
3873
  * @memberof Meeting
3829
3874
  */
3830
- public cancelSIPInvite(invitee: {memberId: string}) {
3831
- return this.members.cancelSIPInvite(invitee);
3875
+ public cancelInviteByMemberId(invitee: {memberId: string; isInternalNumber?: boolean}) {
3876
+ return this.members.cancelInviteByMemberId(invitee);
3832
3877
  }
3833
3878
 
3834
3879
  /**
@@ -3886,13 +3931,16 @@ export default class Meeting extends StatelessWebexPlugin {
3886
3931
  return Promise.reject(error);
3887
3932
  }
3888
3933
 
3889
- return this.brbState.enable(enabled, this.sendSlotManager).then(() => {
3890
- if (this.audio && enabled) {
3891
- // locus mutes the participant with brb enabled request,
3892
- // so we need to explicitly update remote mute for correct logic flow
3893
- this.audio.handleServerRemoteMuteUpdate(this, enabled);
3894
- }
3895
- });
3934
+ return this.brbState
3935
+ .enable(enabled, this.sendSlotManager)
3936
+ .then(() => {
3937
+ if (this.audio && enabled) {
3938
+ // locus mutes the participant with brb enabled request,
3939
+ // so we need to explicitly update remote mute for correct logic flow
3940
+ this.audio.handleServerRemoteMuteUpdate(this, enabled);
3941
+ }
3942
+ })
3943
+ .catch((error) => Promise.reject(error));
3896
3944
  }
3897
3945
 
3898
3946
  /**
@@ -4359,6 +4407,14 @@ export default class Meeting extends StatelessWebexPlugin {
4359
4407
  requiredHints: [DISPLAY_HINTS.DISABLE_RDC_MEETING_OPTION],
4360
4408
  displayHints: this.userDisplayHints,
4361
4409
  }),
4410
+ canEnablePollingQA: ControlsOptionsUtil.hasHints({
4411
+ requiredHints: [DISPLAY_HINTS.ENABLE_ATTENDEE_START_POLLING_QA],
4412
+ displayHints: this.userDisplayHints,
4413
+ }),
4414
+ canDisablePollingQA: ControlsOptionsUtil.hasHints({
4415
+ requiredHints: [DISPLAY_HINTS.DISABLE_ATTENDEE_START_POLLING_QA],
4416
+ displayHints: this.userDisplayHints,
4417
+ }),
4362
4418
  }) || changed;
4363
4419
  }
4364
4420
  if (changed) {
@@ -4423,11 +4479,13 @@ export default class Meeting extends StatelessWebexPlugin {
4423
4479
  setLocus(
4424
4480
  locus:
4425
4481
  | {
4482
+ locus: LocusDTO;
4426
4483
  mediaConnections: Array<any>;
4427
4484
  locusUrl: string;
4428
4485
  locusId: string;
4429
4486
  mediaId: string;
4430
4487
  host: object;
4488
+ dataSets: DataSet[];
4431
4489
  }
4432
4490
  | any
4433
4491
  ) {
@@ -4441,7 +4499,7 @@ export default class Meeting extends StatelessWebexPlugin {
4441
4499
  this.selfId = locus.selfId;
4442
4500
  this.mediaId = locus.mediaId;
4443
4501
  this.hostId = mtgLocus.host ? mtgLocus.host.id : this.hostId;
4444
- this.locusInfo.initialSetup(mtgLocus);
4502
+ this.locusInfo.initialSetup(mtgLocus, locus.dataSets);
4445
4503
  }
4446
4504
 
4447
4505
  /**
@@ -4874,11 +4932,6 @@ export default class Meeting extends StatelessWebexPlugin {
4874
4932
 
4875
4933
  // Only send restore event when it was disconnected before and for connected later
4876
4934
  if (!this.hasWebsocketConnected) {
4877
- // @ts-ignore
4878
- this.webex.internal.newMetrics.submitClientEvent({
4879
- name: 'client.mercury.connection.restored',
4880
- options: {meetingId: this.id},
4881
- });
4882
4935
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MERCURY_CONNECTION_RESTORED, {
4883
4936
  correlation_id: this.correlationId,
4884
4937
  });
@@ -4889,11 +4942,6 @@ export default class Meeting extends StatelessWebexPlugin {
4889
4942
  // @ts-ignore
4890
4943
  this.webex.internal.mercury.on(OFFLINE, () => {
4891
4944
  LoggerProxy.logger.error('Meeting:index#setMercuryListener --> Web socket offline');
4892
- // @ts-ignore
4893
- this.webex.internal.newMetrics.submitClientEvent({
4894
- name: 'client.mercury.connection.lost',
4895
- options: {meetingId: this.id},
4896
- });
4897
4945
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MERCURY_CONNECTION_FAILURE, {
4898
4946
  correlation_id: this.correlationId,
4899
4947
  });
@@ -5564,6 +5612,21 @@ export default class Meeting extends StatelessWebexPlugin {
5564
5612
  }
5565
5613
  }
5566
5614
 
5615
+ /** Handles Locus LLM events
5616
+ *
5617
+ * @param {LocusLLMEvent} event - The Locus LLM event to process
5618
+ * @returns {void}
5619
+ */
5620
+ private processLocusLLMEvent = (event: LocusLLMEvent): void => {
5621
+ if (event.data.eventType === 'locus.state_message') {
5622
+ this.locusInfo.parse(this, event.data);
5623
+ } else {
5624
+ LoggerProxy.logger.warn(
5625
+ `Meeting:index#processLocusLLMEvent --> Unknown event type: ${event.data.eventType}`
5626
+ );
5627
+ }
5628
+ };
5629
+
5567
5630
  /**
5568
5631
  * Callback called when a relay event is received from meeting LLM Connection
5569
5632
  * @param {RelayEvent} e Event object coming from LLM Connection
@@ -5984,6 +6047,8 @@ export default class Meeting extends StatelessWebexPlugin {
5984
6047
  );
5985
6048
  // @ts-ignore - Fix type
5986
6049
  this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
6050
+ // @ts-ignore - Fix type
6051
+ this.webex.internal.llm.off('event:locus.state_message', this.processLocusLLMEvent);
5987
6052
  }
5988
6053
 
5989
6054
  if (!isJoined) {
@@ -5998,6 +6063,10 @@ export default class Meeting extends StatelessWebexPlugin {
5998
6063
  this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
5999
6064
  // @ts-ignore - Fix type
6000
6065
  this.webex.internal.llm.on('event:relay.event', this.processRelayEvent);
6066
+ // @ts-ignore - Fix type
6067
+ this.webex.internal.llm.off('event:locus.state_message', this.processLocusLLMEvent);
6068
+ // @ts-ignore - Fix type
6069
+ this.webex.internal.llm.on('event:locus.state_message', this.processLocusLLMEvent);
6001
6070
  LoggerProxy.logger.info(
6002
6071
  'Meeting:index#updateLLMConnection --> enabled to receive relay events!'
6003
6072
  );
@@ -7723,8 +7792,21 @@ export default class Meeting extends StatelessWebexPlugin {
7723
7792
  shareVideoEnabled = true,
7724
7793
  remoteMediaManagerConfig,
7725
7794
  bundlePolicy = 'max-bundle',
7795
+ additionalMediaOptions = {},
7726
7796
  } = options;
7727
7797
 
7798
+ const {
7799
+ sendVideo: rawSendVideo,
7800
+ receiveVideo: rawReceiveVideo,
7801
+ sendAudio: rawSendAudio,
7802
+ receiveAudio: rawReceiveAudio,
7803
+ } = additionalMediaOptions;
7804
+
7805
+ const sendVideo = videoEnabled && (rawSendVideo ?? true);
7806
+ const receiveVideo = videoEnabled && (rawReceiveVideo ?? true);
7807
+ const sendAudio = audioEnabled && (rawSendAudio ?? true);
7808
+ const receiveAudio = audioEnabled && (rawReceiveAudio ?? true);
7809
+
7728
7810
  this.allowMediaInLobby = options?.allowMediaInLobby;
7729
7811
 
7730
7812
  // If the user is unjoined or guest waiting in lobby dont allow the user to addMedia
@@ -7760,11 +7842,11 @@ export default class Meeting extends StatelessWebexPlugin {
7760
7842
  // when audioEnabled/videoEnabled is true, we set sendAudio/sendVideo to true even before any streams are published
7761
7843
  // to avoid doing an extra SDP exchange when they are published for the first time
7762
7844
  this.mediaProperties.setMediaDirection({
7763
- sendAudio: audioEnabled,
7764
- sendVideo: videoEnabled,
7845
+ sendAudio,
7846
+ sendVideo,
7765
7847
  sendShare: false,
7766
- receiveAudio: audioEnabled,
7767
- receiveVideo: videoEnabled,
7848
+ receiveAudio,
7849
+ receiveVideo,
7768
7850
  receiveShare: shareAudioEnabled || shareVideoEnabled,
7769
7851
  });
7770
7852
 
@@ -9156,6 +9238,8 @@ export default class Meeting extends StatelessWebexPlugin {
9156
9238
 
9157
9239
  // @ts-ignore - fix types
9158
9240
  this.webex.internal.llm.off('event:relay.event', this.processRelayEvent);
9241
+ // @ts-ignore - Fix type
9242
+ this.webex.internal.llm.off('event:locus.state_message', this.processLocusLLMEvent);
9159
9243
  };
9160
9244
 
9161
9245
  /**
@@ -9690,21 +9774,91 @@ export default class Meeting extends StatelessWebexPlugin {
9690
9774
  return total;
9691
9775
  }, 0);
9692
9776
 
9777
+ const selectedSubnetFirstOctet = this.mediaServerIp?.split('.')[0];
9778
+
9693
9779
  let isSubnetReachable = null;
9694
- if (totalSuccessCases > 0) {
9695
- // @ts-ignore
9696
- isSubnetReachable = this.webex.meetings.reachability.isSubnetReachable(this.mediaServerIp);
9780
+ if (totalSuccessCases > 0 && selectedSubnetFirstOctet) {
9781
+ isSubnetReachable =
9782
+ // @ts-ignore
9783
+ this.webex.meetings.reachability.isSubnetReachable(selectedSubnetFirstOctet);
9697
9784
  }
9698
9785
 
9699
- let selectedCluster = null;
9700
- if (this.mediaConnections && this.mediaConnections.length > 0) {
9701
- selectedCluster = this.mediaConnections[0].mediaAgentCluster;
9702
- }
9786
+ const selectedCluster = this.mediaConnections?.[0]?.mediaAgentCluster ?? null;
9703
9787
 
9704
9788
  return {
9705
9789
  ...reachabilityMetrics,
9706
- isSubnetReachable,
9707
- selectedCluster,
9790
+ subnet_reachable: isSubnetReachable,
9791
+ selected_cluster: selectedCluster,
9792
+ selected_subnet: selectedSubnetFirstOctet ? `${selectedSubnetFirstOctet}.X.X.X` : null,
9793
+ };
9794
+ }
9795
+
9796
+ /**
9797
+ * Set the stage for the meeting
9798
+ *
9799
+ * @param {SetStageOptions} options Options to use when setting the stage
9800
+ * @returns {Promise} The locus request
9801
+ */
9802
+ setStage({
9803
+ activeSpeakerProportion = 0.5,
9804
+ customBackground,
9805
+ customLogo,
9806
+ customNameLabel,
9807
+ importantParticipants,
9808
+ lockAttendeeViewOnStage = false,
9809
+ showActiveSpeaker = false,
9810
+ }: SetStageOptions = {}) {
9811
+ const videoLayout: SetStageVideoLayout = {
9812
+ overrideDefault: true,
9813
+ lockAttendeeViewOnStageOnly: lockAttendeeViewOnStage,
9814
+ stageParameters: {
9815
+ activeSpeakerProportion,
9816
+ showActiveSpeaker: {show: showActiveSpeaker, order: 0},
9817
+ stageManagerType: 0,
9818
+ },
9708
9819
  };
9820
+
9821
+ if (importantParticipants?.length) {
9822
+ videoLayout.stageParameters.importantParticipants = importantParticipants.map(
9823
+ (importantParticipant, index) => ({...importantParticipant, order: index + 1})
9824
+ );
9825
+ }
9826
+
9827
+ if (customLogo) {
9828
+ if (!videoLayout.customLayouts) {
9829
+ videoLayout.customLayouts = {};
9830
+ }
9831
+ videoLayout.customLayouts.logo = customLogo;
9832
+ // eslint-disable-next-line no-bitwise
9833
+ videoLayout.stageParameters.stageManagerType |= STAGE_MANAGER_TYPE.LOGO;
9834
+ }
9835
+
9836
+ if (customBackground) {
9837
+ if (!videoLayout.customLayouts) {
9838
+ videoLayout.customLayouts = {};
9839
+ }
9840
+ videoLayout.customLayouts.background = customBackground;
9841
+ // eslint-disable-next-line no-bitwise
9842
+ videoLayout.stageParameters.stageManagerType |= STAGE_MANAGER_TYPE.BACKGROUND;
9843
+ }
9844
+
9845
+ if (customNameLabel) {
9846
+ videoLayout.nameLabelStyle = customNameLabel;
9847
+ // eslint-disable-next-line no-bitwise
9848
+ videoLayout.stageParameters.stageManagerType |= STAGE_MANAGER_TYPE.NAME_LABEL;
9849
+ }
9850
+
9851
+ return this.meetingRequest.synchronizeStage(this.locusUrl, videoLayout);
9852
+ }
9853
+
9854
+ /**
9855
+ * Unset the stage for the meeting
9856
+ *
9857
+ * @returns {Promise} The locus request
9858
+ */
9859
+ unsetStage() {
9860
+ const videoLayout: UnsetStageVideoLayout = {overrideDefault: false};
9861
+
9862
+ return this.meetingRequest.synchronizeStage(this.locusUrl, videoLayout);
9709
9863
  }
9710
9864
  }
@@ -291,18 +291,14 @@ export class MuteState {
291
291
  );
292
292
 
293
293
  return MeetingUtil.remoteUpdateAudioVideo(meeting, audioMuted, videoMuted)
294
- .then((locus) => {
294
+ .then((response) => {
295
295
  LoggerProxy.logger.info(
296
296
  `Meeting:muteState#sendLocalMuteRequestToServer --> ${this.type}: local mute (audio=${audioMuted}, video=${videoMuted}) applied to server`
297
297
  );
298
298
 
299
299
  this.state.server.localMute = this.type === AUDIO ? audioMuted : videoMuted;
300
300
 
301
- if (locus) {
302
- meeting.locusInfo.handleLocusDelta(locus, meeting);
303
- }
304
-
305
- return locus;
301
+ return MeetingUtil.updateLocusFromApiResponse(meeting, response);
306
302
  })
307
303
  .catch((remoteUpdateError) => {
308
304
  LoggerProxy.logger.warn(
@@ -32,6 +32,7 @@ import {
32
32
  BrbOptions,
33
33
  ToggleReactionsOptions,
34
34
  PostMeetingDataConsentOptions,
35
+ SynchronizeVideoLayout,
35
36
  } from './request.type';
36
37
  import MeetingUtil from './util';
37
38
  import {AnnotationInfo} from '../annotation/annotation.types';
@@ -969,4 +970,19 @@ export default class MeetingRequest extends StatelessWebexPlugin {
969
970
  },
970
971
  });
971
972
  }
973
+
974
+ /**
975
+ * Synchronize the stage for a meeting
976
+ *
977
+ * @param {LocusUrl} locusUrl The locus URL
978
+ * @param {SetStageVideoLayout} videoLayout The video layout to synchronize
979
+ * @returns {Promise} The locus request
980
+ */
981
+ synchronizeStage(locusUrl: string, videoLayout: SynchronizeVideoLayout) {
982
+ return this.locusDeltaRequest({
983
+ method: HTTP_VERBS.PATCH,
984
+ uri: `${locusUrl}/${CONTROLS}`,
985
+ body: {videoLayout},
986
+ });
987
+ }
972
988
  }
@@ -25,3 +25,67 @@ export type PostMeetingDataConsentOptions = {
25
25
  deviceUrl: string;
26
26
  selfId: string;
27
27
  };
28
+
29
+ export type StageCustomLogoPositions =
30
+ | 'LowerLeft'
31
+ | 'LowerMiddle'
32
+ | 'LowerRight'
33
+ | 'UpperLeft'
34
+ | 'UpperMiddle'
35
+ | 'UpperRight';
36
+
37
+ export type StageNameLabelType = 'Primary' | 'PrimaryInverted' | 'Secondary' | 'SecondaryInverted';
38
+
39
+ export type StageCustomBackground = {
40
+ url: string;
41
+ [others: string]: unknown;
42
+ };
43
+
44
+ export type StageCustomLogo = {
45
+ url: string;
46
+ position: StageCustomLogoPositions;
47
+ [others: string]: unknown;
48
+ };
49
+
50
+ export type StageCustomNameLabel = {
51
+ accentColor: string;
52
+ background: {color: string};
53
+ border: {color: string};
54
+ content: {displayName: {color: string}; subtitle: {color: string}};
55
+ decoration: {color: string};
56
+ fadeOut?: {delay: number};
57
+ type: StageNameLabelType;
58
+ [others: string]: unknown;
59
+ };
60
+
61
+ export type SetStageOptions = {
62
+ activeSpeakerProportion?: number;
63
+ customBackground?: StageCustomBackground;
64
+ customLogo?: StageCustomLogo;
65
+ customNameLabel?: StageCustomNameLabel;
66
+ importantParticipants?: {mainCsi: number; participantId: string}[];
67
+ lockAttendeeViewOnStage?: boolean;
68
+ showActiveSpeaker?: boolean;
69
+ };
70
+
71
+ export type SetStageVideoLayout = {
72
+ overrideDefault: true;
73
+ lockAttendeeViewOnStageOnly: boolean;
74
+ stageParameters: {
75
+ importantParticipants?: {participantId: string; mainCsi: number; order: number}[];
76
+ showActiveSpeaker: {show: boolean; order: number};
77
+ activeSpeakerProportion: number;
78
+ stageManagerType: number;
79
+ };
80
+ customLayouts?: {
81
+ background?: StageCustomBackground;
82
+ logo?: StageCustomLogo;
83
+ };
84
+ nameLabelStyle?: StageCustomNameLabel;
85
+ };
86
+
87
+ export type UnsetStageVideoLayout = {
88
+ overrideDefault: false;
89
+ };
90
+
91
+ export type SynchronizeVideoLayout = SetStageVideoLayout | UnsetStageVideoLayout;
@@ -31,6 +31,7 @@ const MeetingUtil = {
31
31
 
32
32
  // First todo: add check for existance
33
33
  parsed.locus = response.body.locus;
34
+ parsed.dataSets = response.body.dataSets;
34
35
  parsed.mediaConnections = response.body.mediaConnections;
35
36
  parsed.locusUrl = parsed.locus.url;
36
37
  parsed.locusId = parsed.locus.url.split('/').pop();
@@ -59,18 +60,16 @@ const MeetingUtil = {
59
60
  );
60
61
  }
61
62
 
62
- return meeting.locusMediaRequest
63
- .send({
64
- type: 'LocalMute',
65
- selfUrl: meeting.selfUrl,
66
- mediaId: meeting.mediaId,
67
- sequence: meeting.locusInfo.sequence,
68
- muteOptions: {
69
- audioMuted,
70
- videoMuted,
71
- },
72
- })
73
- .then((response) => response?.body?.locus);
63
+ return meeting.locusMediaRequest.send({
64
+ type: 'LocalMute',
65
+ selfUrl: meeting.selfUrl,
66
+ mediaId: meeting.mediaId,
67
+ sequence: meeting.locusInfo.sequence,
68
+ muteOptions: {
69
+ audioMuted,
70
+ videoMuted,
71
+ },
72
+ });
74
73
  },
75
74
 
76
75
  hasOwner: (info) => info && info.owner,
@@ -602,22 +601,20 @@ const MeetingUtil = {
602
601
  },
603
602
 
604
603
  /**
605
- * Updates the locus info for the meeting with the delta locus
606
- * returned from requests that include the sequence information
604
+ * Updates the locus info for the meeting with the locus
605
+ * information returned from API requests made to Locus
607
606
  * Returns the original response object
608
607
  * @param {Object} meeting The meeting object
609
608
  * @param {Object} response The response of the http request
610
609
  * @returns {Object}
611
610
  */
612
- updateLocusWithDelta: (meeting, response) => {
611
+ updateLocusFromApiResponse: (meeting, response) => {
613
612
  if (!meeting) {
614
613
  return response;
615
614
  }
616
615
 
617
- const locus = response?.body?.locus;
618
-
619
- if (locus) {
620
- meeting.locusInfo.handleLocusDelta(locus, meeting);
616
+ if (response?.body?.locus) {
617
+ meeting.locusInfo.handleLocusAPIResponse(meeting, response.body);
621
618
  }
622
619
 
623
620
  return response;
@@ -664,7 +661,7 @@ const MeetingUtil = {
664
661
 
665
662
  return meeting
666
663
  .request(options)
667
- .then((response) => MeetingUtil.updateLocusWithDelta(meeting, response));
664
+ .then((response) => MeetingUtil.updateLocusFromApiResponse(meeting, response));
668
665
  };
669
666
 
670
667
  return locusDeltaRequest;