@webex/plugin-meetings 3.1.0-next.9 → 3.2.0

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 (181) hide show
  1. package/dist/annotation/annotation.types.d.ts +42 -0
  2. package/dist/annotation/constants.d.ts +31 -0
  3. package/dist/annotation/index.d.ts +117 -0
  4. package/dist/breakouts/breakout.d.ts +8 -0
  5. package/dist/breakouts/breakout.js +1 -1
  6. package/dist/breakouts/collection.d.ts +5 -0
  7. package/dist/breakouts/edit-lock-error.d.ts +15 -0
  8. package/dist/breakouts/events.d.ts +8 -0
  9. package/dist/breakouts/index.d.ts +5 -0
  10. package/dist/breakouts/index.js +1 -1
  11. package/dist/breakouts/request.d.ts +22 -0
  12. package/dist/breakouts/utils.d.ts +15 -0
  13. package/dist/common/browser-detection.d.ts +9 -0
  14. package/dist/common/collection.d.ts +48 -0
  15. package/dist/common/config.d.ts +2 -0
  16. package/dist/common/errors/captcha-error.d.ts +15 -0
  17. package/dist/common/errors/intent-to-join.d.ts +16 -0
  18. package/dist/common/errors/join-meeting.d.ts +17 -0
  19. package/dist/common/errors/media.d.ts +15 -0
  20. package/dist/common/errors/no-meeting-info.d.ts +14 -0
  21. package/dist/common/errors/parameter.d.ts +15 -0
  22. package/dist/common/errors/password-error.d.ts +15 -0
  23. package/dist/common/errors/permission.d.ts +14 -0
  24. package/dist/common/errors/reclaim-host-role-errors.d.ts +60 -0
  25. package/dist/common/errors/reconnection-in-progress.d.ts +9 -0
  26. package/dist/common/errors/reconnection-in-progress.js +34 -0
  27. package/dist/common/errors/reconnection-in-progress.js.map +1 -0
  28. package/dist/common/errors/reconnection.d.ts +15 -0
  29. package/dist/common/errors/stats.d.ts +15 -0
  30. package/dist/common/errors/webex-errors.d.ts +93 -0
  31. package/dist/common/errors/webex-meetings-error.d.ts +20 -0
  32. package/dist/common/events/events-scope.d.ts +17 -0
  33. package/dist/common/events/events.d.ts +12 -0
  34. package/dist/common/events/trigger-proxy.d.ts +2 -0
  35. package/dist/common/events/util.d.ts +2 -0
  36. package/dist/common/logs/logger-config.d.ts +2 -0
  37. package/dist/common/logs/logger-proxy.d.ts +2 -0
  38. package/dist/common/logs/request.d.ts +36 -0
  39. package/dist/common/queue.d.ts +34 -0
  40. package/dist/config.d.ts +73 -0
  41. package/dist/constants.d.ts +1088 -0
  42. package/dist/constants.js +6 -3
  43. package/dist/constants.js.map +1 -1
  44. package/dist/controls-options-manager/constants.d.ts +4 -0
  45. package/dist/controls-options-manager/enums.d.ts +15 -0
  46. package/dist/controls-options-manager/index.d.ts +136 -0
  47. package/dist/controls-options-manager/types.d.ts +43 -0
  48. package/dist/controls-options-manager/util.d.ts +1 -0
  49. package/dist/index.d.ts +7 -0
  50. package/dist/interceptors/index.d.ts +2 -0
  51. package/dist/interceptors/locusRetry.d.ts +27 -0
  52. package/dist/interpretation/collection.d.ts +5 -0
  53. package/dist/interpretation/index.d.ts +5 -0
  54. package/dist/interpretation/index.js +1 -1
  55. package/dist/interpretation/siLanguage.d.ts +5 -0
  56. package/dist/interpretation/siLanguage.js +1 -1
  57. package/dist/locus-info/controlsUtils.d.ts +2 -0
  58. package/dist/locus-info/embeddedAppsUtils.d.ts +2 -0
  59. package/dist/locus-info/fullState.d.ts +2 -0
  60. package/dist/locus-info/hostUtils.d.ts +2 -0
  61. package/dist/locus-info/index.d.ts +322 -0
  62. package/dist/locus-info/infoUtils.d.ts +2 -0
  63. package/dist/locus-info/mediaSharesUtils.d.ts +2 -0
  64. package/dist/locus-info/parser.d.ts +272 -0
  65. package/dist/locus-info/selfUtils.d.ts +2 -0
  66. package/dist/media/MediaConnectionAwaiter.d.ts +61 -0
  67. package/dist/media/index.d.ts +34 -0
  68. package/dist/media/properties.d.ts +93 -0
  69. package/dist/media/util.d.ts +2 -0
  70. package/dist/mediaQualityMetrics/config.d.ts +241 -0
  71. package/dist/mediaQualityMetrics/config.js +10 -10
  72. package/dist/mediaQualityMetrics/config.js.map +1 -1
  73. package/dist/meeting/in-meeting-actions.d.ts +167 -0
  74. package/dist/meeting/index.d.ts +1825 -0
  75. package/dist/meeting/index.js +112 -64
  76. package/dist/meeting/index.js.map +1 -1
  77. package/dist/meeting/locusMediaRequest.d.ts +74 -0
  78. package/dist/meeting/locusMediaRequest.js +27 -0
  79. package/dist/meeting/locusMediaRequest.js.map +1 -1
  80. package/dist/meeting/muteState.d.ts +178 -0
  81. package/dist/meeting/request.d.ts +295 -0
  82. package/dist/meeting/request.type.d.ts +11 -0
  83. package/dist/meeting/state.d.ts +9 -0
  84. package/dist/meeting/util.d.ts +119 -0
  85. package/dist/meeting/util.js +0 -16
  86. package/dist/meeting/util.js.map +1 -1
  87. package/dist/meeting/voicea-meeting.d.ts +16 -0
  88. package/dist/meeting/voicea-meeting.js +37 -49
  89. package/dist/meeting/voicea-meeting.js.map +1 -1
  90. package/dist/meeting-info/collection.d.ts +20 -0
  91. package/dist/meeting-info/index.d.ts +69 -0
  92. package/dist/meeting-info/meeting-info-v2.d.ts +123 -0
  93. package/dist/meeting-info/request.d.ts +22 -0
  94. package/dist/meeting-info/util.d.ts +2 -0
  95. package/dist/meeting-info/utilv2.d.ts +2 -0
  96. package/dist/meetings/collection.d.ts +40 -0
  97. package/dist/meetings/index.d.ts +398 -0
  98. package/dist/meetings/index.js +12 -28
  99. package/dist/meetings/index.js.map +1 -1
  100. package/dist/meetings/meetings.types.d.ts +4 -0
  101. package/dist/meetings/request.d.ts +27 -0
  102. package/dist/meetings/util.d.ts +18 -0
  103. package/dist/member/index.d.ts +160 -0
  104. package/dist/member/types.d.ts +32 -0
  105. package/dist/member/util.d.ts +2 -0
  106. package/dist/members/collection.d.ts +29 -0
  107. package/dist/members/index.d.ts +353 -0
  108. package/dist/members/request.d.ts +114 -0
  109. package/dist/members/types.d.ts +25 -0
  110. package/dist/members/util.d.ts +215 -0
  111. package/dist/metrics/constants.d.ts +70 -0
  112. package/dist/metrics/index.d.ts +45 -0
  113. package/dist/multistream/mediaRequestManager.d.ts +119 -0
  114. package/dist/multistream/receiveSlot.d.ts +68 -0
  115. package/dist/multistream/receiveSlotManager.d.ts +56 -0
  116. package/dist/multistream/remoteMedia.d.ts +72 -0
  117. package/dist/multistream/remoteMediaGroup.d.ts +49 -0
  118. package/dist/multistream/remoteMediaManager.d.ts +300 -0
  119. package/dist/multistream/sendSlotManager.d.ts +69 -0
  120. package/dist/networkQualityMonitor/index.d.ts +70 -0
  121. package/dist/personal-meeting-room/index.d.ts +47 -0
  122. package/dist/personal-meeting-room/request.d.ts +14 -0
  123. package/dist/personal-meeting-room/util.d.ts +2 -0
  124. package/dist/reachability/clusterReachability.d.ts +110 -0
  125. package/dist/reachability/index.d.ts +109 -0
  126. package/dist/reachability/index.js +88 -9
  127. package/dist/reachability/index.js.map +1 -1
  128. package/dist/reachability/request.d.ts +39 -0
  129. package/dist/reachability/util.d.ts +15 -0
  130. package/dist/reactions/constants.d.ts +3 -0
  131. package/dist/reactions/reactions.d.ts +4 -0
  132. package/dist/reactions/reactions.type.d.ts +52 -0
  133. package/dist/reconnection-manager/index.d.ts +136 -0
  134. package/dist/recording-controller/enums.d.ts +7 -0
  135. package/dist/recording-controller/index.d.ts +207 -0
  136. package/dist/recording-controller/util.d.ts +14 -0
  137. package/dist/roap/index.d.ts +86 -0
  138. package/dist/roap/request.d.ts +39 -0
  139. package/dist/roap/request.js +3 -27
  140. package/dist/roap/request.js.map +1 -1
  141. package/dist/roap/turnDiscovery.d.ts +155 -0
  142. package/dist/rtcMetrics/constants.d.ts +4 -0
  143. package/dist/rtcMetrics/index.d.ts +61 -0
  144. package/dist/statsAnalyzer/global.d.ts +36 -0
  145. package/dist/statsAnalyzer/index.d.ts +217 -0
  146. package/dist/statsAnalyzer/index.js +4 -2
  147. package/dist/statsAnalyzer/index.js.map +1 -1
  148. package/dist/statsAnalyzer/mqaUtil.d.ts +48 -0
  149. package/dist/statsAnalyzer/mqaUtil.js +14 -0
  150. package/dist/statsAnalyzer/mqaUtil.js.map +1 -1
  151. package/dist/transcription/index.d.ts +64 -0
  152. package/dist/types/constants.d.ts +3 -1
  153. package/dist/types/mediaQualityMetrics/config.d.ts +8 -2
  154. package/dist/types/meeting/index.d.ts +10 -1
  155. package/dist/types/meeting/locusMediaRequest.d.ts +1 -0
  156. package/dist/types/meeting/voicea-meeting.d.ts +3 -2
  157. package/dist/types/meetings/index.d.ts +1 -16
  158. package/dist/types/reachability/index.d.ts +11 -0
  159. package/dist/webinar/collection.d.ts +16 -0
  160. package/dist/webinar/index.d.ts +5 -0
  161. package/dist/webinar/index.js +1 -1
  162. package/package.json +21 -21
  163. package/src/constants.ts +3 -2
  164. package/src/mediaQualityMetrics/config.ts +13 -7
  165. package/src/meeting/index.ts +73 -30
  166. package/src/meeting/locusMediaRequest.ts +31 -0
  167. package/src/meeting/util.ts +1 -16
  168. package/src/meeting/voicea-meeting.ts +44 -46
  169. package/src/meetings/index.ts +15 -27
  170. package/src/reachability/index.ts +60 -0
  171. package/src/roap/request.ts +1 -24
  172. package/src/statsAnalyzer/index.ts +6 -3
  173. package/src/statsAnalyzer/mqaUtil.ts +18 -0
  174. package/test/unit/spec/meeting/index.js +70 -33
  175. package/test/unit/spec/meeting/locusMediaRequest.ts +49 -0
  176. package/test/unit/spec/meeting/utils.js +0 -10
  177. package/test/unit/spec/meeting/voicea-meeting.ts +5 -14
  178. package/test/unit/spec/meetings/index.js +59 -17
  179. package/test/unit/spec/reachability/index.ts +266 -0
  180. package/test/unit/spec/roap/request.ts +0 -37
  181. package/test/unit/spec/stats-analyzer/index.js +89 -8
@@ -21,7 +21,9 @@ export const emptyAudioReceive = {
21
21
  direction: 'inactive',
22
22
  isMain: true,
23
23
  mariFecEnabled: false,
24
+ mariRtxEnabled: false,
24
25
  mariQosEnabled: false,
26
+ mariLiteEnabled: false,
25
27
  multistreamEnabled: false,
26
28
  },
27
29
  dtlsBitrate: 0,
@@ -75,7 +77,9 @@ export const emptyAudioTransmit = {
75
77
  direction: 'inactive',
76
78
  isMain: true,
77
79
  mariFecEnabled: false,
80
+ mariRtxEnabled: false,
78
81
  mariQosEnabled: false,
82
+ mariLiteEnabled: false,
79
83
  multistreamEnabled: false,
80
84
  },
81
85
  dtlsBitrate: 0,
@@ -86,7 +90,6 @@ export const emptyAudioTransmit = {
86
90
  queueDelay: 0,
87
91
  remoteJitter: 0,
88
92
  remoteLossRate: 0,
89
- remoteReceiveRate: 0,
90
93
  roundTripTime: 0,
91
94
  rtcpBitrate: 0,
92
95
  rtcpPackets: 0,
@@ -119,8 +122,10 @@ export const emptyVideoReceive = {
119
122
  common: {
120
123
  direction: 'inactive',
121
124
  isMain: true, // Not avaliable
122
- mariFecEnabled: true, // Not avaliable
123
- mariQosEnabled: true, // Not avaliable
125
+ mariFecEnabled: false,
126
+ mariRtxEnabled: false,
127
+ mariQosEnabled: false,
128
+ mariLiteEnabled: false,
124
129
  multistreamEnabled: true, // Not avaliable
125
130
  },
126
131
  dtlsBitrate: 0, // Not avaliable
@@ -184,8 +189,10 @@ export const emptyVideoTransmit = {
184
189
  common: {
185
190
  direction: 'inactive',
186
191
  isMain: true,
187
- mariFecEnabled: false, // Not avaliable
188
- mariQosEnabled: false, // Not avaliable
192
+ mariFecEnabled: false,
193
+ mariRtxEnabled: false,
194
+ mariQosEnabled: false,
195
+ mariLiteEnabled: false,
189
196
  multistreamEnabled: false, // Not avaliable
190
197
  },
191
198
  dtlsBitrate: 0, // Not avaliable
@@ -193,10 +200,9 @@ export const emptyVideoTransmit = {
193
200
  fecBitrate: 0, // Not avaliable
194
201
  fecPackets: 0, // TODO: check inbound-rtp// Not avaliable
195
202
  maxBitrate: 0, // Currently hardcoded
196
- queueDelay: 0, // outboundRtp.totalPacketSentDelay // TODO: check if totalInterFrameDelay/ packetSentDelay/ jitterBufferDalay
203
+ queueDelay: 0,
197
204
  remoteJitter: 0, // remoteInboundRtp.jitter
198
205
  remoteLossRate: 0, // comparedResults.lossRate
199
- remoteReceiveRate: 0, // compareResults.packetsLost
200
206
  roundTripTime: 0, // compareResults.roundTripTime
201
207
  rtcpBitrate: 0, // Dont have access to it
202
208
  rtcpPackets: 0, // Dont have access to rtcp
@@ -38,6 +38,7 @@ import {
38
38
  import {
39
39
  EVENT_TRIGGERS as VOICEAEVENTS,
40
40
  TURN_ON_CAPTION_STATUS,
41
+ type MeetingTranscriptPayload,
41
42
  } from '@webex/internal-plugin-voicea';
42
43
  import {processNewCaptions} from './voicea-meeting';
43
44
 
@@ -630,6 +631,7 @@ export default class Meeting extends StatelessWebexPlugin {
630
631
  turnDiscoverySkippedReason: TurnDiscoverySkipReason;
631
632
  turnServerUsed: boolean;
632
633
  areVoiceaEventsSetup = false;
634
+ isMoveToInProgress = false;
633
635
 
634
636
  voiceaListenerCallbacks: object = {
635
637
  [VOICEAEVENTS.VOICEA_ANNOUNCEMENT]: (payload: Transcription['languageOptions']) => {
@@ -654,7 +656,7 @@ export default class Meeting extends StatelessWebexPlugin {
654
656
  this.transcription.isListening = !!data.isListening;
655
657
  this.transcription.commandText = data.text ?? '';
656
658
  },
657
- [VOICEAEVENTS.NEW_CAPTION]: (data) => {
659
+ [VOICEAEVENTS.NEW_CAPTION]: (data: MeetingTranscriptPayload) => {
658
660
  processNewCaptions({data, meeting: this});
659
661
 
660
662
  LoggerProxy.logger.debug(
@@ -1389,11 +1391,11 @@ export default class Meeting extends StatelessWebexPlugin {
1389
1391
  this.remoteMediaManager = null;
1390
1392
 
1391
1393
  this.localAudioStreamMuteStateHandler = () => {
1392
- this.audio.handleLocalStreamMuteStateChange(this);
1394
+ this.audio?.handleLocalStreamMuteStateChange(this);
1393
1395
  };
1394
1396
 
1395
1397
  this.localVideoStreamMuteStateHandler = () => {
1396
- this.video.handleLocalStreamMuteStateChange(this);
1398
+ this.video?.handleLocalStreamMuteStateChange(this);
1397
1399
  };
1398
1400
 
1399
1401
  // The handling of output track changes should be done inside
@@ -3079,6 +3081,7 @@ export default class Meeting extends StatelessWebexPlugin {
3079
3081
  options: {meetingId: this.id},
3080
3082
  });
3081
3083
  }
3084
+ this.updateLLMConnection();
3082
3085
  });
3083
3086
  this.locusInfo.on(LOCUSINFO.EVENTS.SELF_ADMITTED_GUEST, async (payload) => {
3084
3087
  this.stopKeepAlive();
@@ -3942,7 +3945,7 @@ export default class Meeting extends StatelessWebexPlugin {
3942
3945
  // we don't update this.mediaProperties.mediaDirection.sendAudio, because we always keep it as true to avoid extra SDP exchanges
3943
3946
  this.mediaProperties.setLocalAudioStream(localStream);
3944
3947
 
3945
- this.audio.handleLocalStreamChange(this);
3948
+ this.audio?.handleLocalStreamChange(this);
3946
3949
 
3947
3950
  localStream?.on(
3948
3951
  LocalStreamEventNames.UserMuteStateChange,
@@ -3984,7 +3987,7 @@ export default class Meeting extends StatelessWebexPlugin {
3984
3987
  // we don't update this.mediaProperties.mediaDirection.sendVideo, because we always keep it as true to avoid extra SDP exchanges
3985
3988
  this.mediaProperties.setLocalVideoStream(localStream);
3986
3989
 
3987
- this.video.handleLocalStreamChange(this);
3990
+ this.video?.handleLocalStreamChange(this);
3988
3991
 
3989
3992
  localStream?.on(
3990
3993
  LocalStreamEventNames.UserMuteStateChange,
@@ -4694,12 +4697,12 @@ export default class Meeting extends StatelessWebexPlugin {
4694
4697
  * @throws TranscriptionNotSupportedError
4695
4698
  */
4696
4699
  isTranscriptionSupported() {
4697
- if (this.locusInfo.controls.transcribe?.transcribing) {
4700
+ if (this.locusInfo.controls.transcribe?.caption) {
4698
4701
  return true;
4699
4702
  }
4700
4703
 
4701
4704
  LoggerProxy.logger.error(
4702
- 'Meeting:index#isTranscriptionSupported --> Webex Assistant is not enabled/supported'
4705
+ 'Meeting:index#isTranscriptionSupported --> Closed Captions is not enabled/supported'
4703
4706
  );
4704
4707
 
4705
4708
  return false;
@@ -4950,6 +4953,27 @@ export default class Meeting extends StatelessWebexPlugin {
4950
4953
  );
4951
4954
  }
4952
4955
 
4956
+ /**
4957
+ * This is a callback for the LLM event that is triggered when it comes online
4958
+ * This method in turn will trigger an event to the developers that the LLM is connected
4959
+ * @private
4960
+ * @memberof Meeting
4961
+ * @returns {null}
4962
+ */
4963
+ private handleLLMOnline = (): void => {
4964
+ // @ts-ignore
4965
+ this.webex.internal.llm.off('online', this.handleLLMOnline);
4966
+ Trigger.trigger(
4967
+ this,
4968
+ {
4969
+ file: 'meeting/index',
4970
+ function: 'handleLLMOnline',
4971
+ },
4972
+ EVENT_TRIGGERS.MEETING_TRANSCRIPTION_CONNECTED,
4973
+ undefined
4974
+ );
4975
+ };
4976
+
4953
4977
  /**
4954
4978
  * Specify joining via audio (option: pstn), video, screenshare
4955
4979
  * @param {JoinOptions} options A configurable options object for joining a meeting
@@ -5169,6 +5193,8 @@ export default class Meeting extends StatelessWebexPlugin {
5169
5193
  .then((join) => {
5170
5194
  // @ts-ignore - config coming from registerPlugin
5171
5195
  if (this.config.enableAutomaticLLM) {
5196
+ // @ts-ignore
5197
+ this.webex.internal.llm.on('online', this.handleLLMOnline);
5172
5198
  this.updateLLMConnection()
5173
5199
  .catch((error) => {
5174
5200
  LoggerProxy.logger.error(
@@ -5186,15 +5212,6 @@ export default class Meeting extends StatelessWebexPlugin {
5186
5212
  LoggerProxy.logger.info(
5187
5213
  'Meeting:index#join --> Transcription Socket Connection Success'
5188
5214
  );
5189
- Trigger.trigger(
5190
- this,
5191
- {
5192
- file: 'meeting/index',
5193
- function: 'join',
5194
- },
5195
- EVENT_TRIGGERS.MEETING_TRANSCRIPTION_CONNECTED,
5196
- undefined
5197
- );
5198
5215
  });
5199
5216
  }
5200
5217
 
@@ -5426,17 +5443,28 @@ export default class Meeting extends StatelessWebexPlugin {
5426
5443
  },
5427
5444
  };
5428
5445
 
5429
- this.cleanupLocalStreams();
5430
-
5431
5446
  this.mediaProperties.setMediaDirection(mediaSettings.mediaDirection);
5432
5447
  this.mediaProperties.unsetRemoteMedia();
5433
5448
 
5434
- // when a move to is intiated by the client , Locus delets the existing media node from the server as soon the DX answers the meeting
5435
- // once the DX answers we establish connection back the media server with only receiveShare enabled
5436
- // @ts-ignore - reconnectMedia does not accept any argument
5437
- await this.reconnectionManager.reconnectMedia(mediaSettings).then(() => {
5438
- Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_SUCCESS);
5449
+ // when a move to is intiated by the client , Locus delets the existing media node from the server as soon the device answers the meeting
5450
+ // once the device answers we close the old connection and create new media server connection with only share enabled
5451
+ if (this.statsAnalyzer) {
5452
+ await this.statsAnalyzer.stopAnalyzer();
5453
+ }
5454
+ await this.closeRemoteStreams();
5455
+ await this.closePeerConnections();
5456
+ this.cleanupLocalStreams();
5457
+ this.unsetRemoteStreams();
5458
+ this.unsetPeerConnections();
5459
+ this.reconnectionManager.cleanUp();
5460
+
5461
+ await this.addMedia({
5462
+ audioEnabled: false,
5463
+ videoEnabled: false,
5464
+ shareVideoEnabled: true,
5439
5465
  });
5466
+ Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_SUCCESS);
5467
+ this.isMoveToInProgress = false;
5440
5468
  } catch (error) {
5441
5469
  LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
5442
5470
  Metrics.sendBehavioralMetric(BEHAVIORAL_METRICS.MOVE_TO_FAILURE, {
@@ -5445,6 +5473,7 @@ export default class Meeting extends StatelessWebexPlugin {
5445
5473
  reason: error.message,
5446
5474
  stack: error.stack,
5447
5475
  });
5476
+ this.isMoveToInProgress = false;
5448
5477
  }
5449
5478
  });
5450
5479
 
@@ -5453,6 +5482,10 @@ export default class Meeting extends StatelessWebexPlugin {
5453
5482
  resourceId
5454
5483
  );
5455
5484
 
5485
+ // TODO: Check with locus if SELF_OBSERVING event would ever be not emitted
5486
+ // If yes, introduce a timeout mechanism
5487
+ this.isMoveToInProgress = true;
5488
+
5456
5489
  return MeetingUtil.joinMeetingOptions(this, {resourceId, moveToResource: true})
5457
5490
  .then(() => {
5458
5491
  this.meetingFiniteStateMachine.join();
@@ -5466,6 +5499,7 @@ export default class Meeting extends StatelessWebexPlugin {
5466
5499
  stack: error.stack,
5467
5500
  });
5468
5501
  LoggerProxy.logger.error('Meeting:index#moveTo --> Failed to moveTo resourceId', error);
5502
+ this.isMoveToInProgress = false;
5469
5503
 
5470
5504
  return Promise.reject(error);
5471
5505
  });
@@ -6452,11 +6486,14 @@ export default class Meeting extends StatelessWebexPlugin {
6452
6486
  /**
6453
6487
  * Performs TURN discovery as a separate call to the Locus /media API
6454
6488
  *
6455
- * @param {boolean} isRetry
6489
+ * @param {boolean} isReconnecting
6456
6490
  * @param {boolean} isForced
6457
6491
  * @returns {Promise}
6458
6492
  */
6459
- private async doTurnDiscovery(isRetry: boolean, isForced: boolean): Promise<TurnDiscoveryResult> {
6493
+ private async doTurnDiscovery(
6494
+ isReconnecting: boolean,
6495
+ isForced: boolean
6496
+ ): Promise<TurnDiscoveryResult> {
6460
6497
  // @ts-ignore
6461
6498
  const cdl = this.webex.internal.newMetrics.callDiagnosticLatencies;
6462
6499
 
@@ -6465,7 +6502,7 @@ export default class Meeting extends StatelessWebexPlugin {
6465
6502
  name: 'internal.client.add-media.turn-discovery.start',
6466
6503
  });
6467
6504
 
6468
- const turnDiscoveryResult = await this.roap.doTurnDiscovery(this, isRetry, isForced);
6505
+ const turnDiscoveryResult = await this.roap.doTurnDiscovery(this, isReconnecting, isForced);
6469
6506
 
6470
6507
  this.turnDiscoverySkippedReason = turnDiscoveryResult?.turnDiscoverySkippedReason;
6471
6508
  this.turnServerUsed = !this.turnDiscoverySkippedReason;
@@ -6504,11 +6541,16 @@ export default class Meeting extends StatelessWebexPlugin {
6504
6541
  turnServerInfo?: TurnServerInfo
6505
6542
  ): Promise<void> {
6506
6543
  const LOG_HEADER = 'Meeting:index#addMedia():establishMediaConnection -->';
6507
- const isRetry = this.retriedWithTurnServer;
6544
+ const isReconnecting = this.isMoveToInProgress || this.retriedWithTurnServer;
6545
+
6546
+ // We are forcing turn discovery if the case is moveTo and a turn server was used already
6547
+ if (this.isMoveToInProgress && this.turnServerUsed) {
6548
+ isForced = true;
6549
+ }
6508
6550
 
6509
6551
  try {
6510
6552
  if (!turnServerInfo) {
6511
- ({turnServerInfo} = await this.doTurnDiscovery(isRetry, isForced));
6553
+ ({turnServerInfo} = await this.doTurnDiscovery(isReconnecting, isForced));
6512
6554
  }
6513
6555
 
6514
6556
  const mc = await this.createMediaConnection(turnServerInfo, bundlePolicy);
@@ -6705,6 +6747,7 @@ export default class Meeting extends StatelessWebexPlugin {
6705
6747
  this.locusMediaRequest = new LocusMediaRequest(
6706
6748
  {
6707
6749
  correlationId: this.correlationId,
6750
+ meetingId: this.id,
6708
6751
  device: {
6709
6752
  url: this.deviceUrl,
6710
6753
  // @ts-ignore
@@ -7007,7 +7050,7 @@ export default class Meeting extends StatelessWebexPlugin {
7007
7050
  if (audioEnabled !== undefined) {
7008
7051
  this.mediaProperties.mediaDirection.sendAudio = audioEnabled;
7009
7052
  this.mediaProperties.mediaDirection.receiveAudio = audioEnabled;
7010
- this.audio.enable(this, audioEnabled);
7053
+ this.audio?.enable(this, audioEnabled);
7011
7054
  if (this.isMultistream) {
7012
7055
  this.sendSlotManager.setActive(MediaType.AudioMain, audioEnabled);
7013
7056
  }
@@ -7016,7 +7059,7 @@ export default class Meeting extends StatelessWebexPlugin {
7016
7059
  if (videoEnabled !== undefined) {
7017
7060
  this.mediaProperties.mediaDirection.sendVideo = videoEnabled;
7018
7061
  this.mediaProperties.mediaDirection.receiveVideo = videoEnabled;
7019
- this.video.enable(this, videoEnabled);
7062
+ this.video?.enable(this, videoEnabled);
7020
7063
  if (this.isMultistream) {
7021
7064
  this.sendSlotManager.setActive(MediaType.VideoMain, videoEnabled);
7022
7065
  }
@@ -88,6 +88,7 @@ export type Config = {
88
88
  regionCode?: string;
89
89
  };
90
90
  correlationId: string;
91
+ meetingId: string;
91
92
  preferTranscoding: boolean;
92
93
  };
93
94
 
@@ -223,6 +224,14 @@ export class LocusMediaRequest extends WebexPlugin {
223
224
  localMedias.roapMessage = request.roapMessage;
224
225
  localMedias.reachability = request.reachability;
225
226
  body.clientMediaPreferences.joinCookie = request.joinCookie;
227
+
228
+ // @ts-ignore
229
+ this.webex.internal.newMetrics.submitClientEvent({
230
+ name: 'client.locus.media.request',
231
+ options: {
232
+ meetingId: this.config.meetingId,
233
+ },
234
+ });
226
235
  break;
227
236
  }
228
237
 
@@ -256,6 +265,16 @@ export class LocusMediaRequest extends WebexPlugin {
256
265
  this.confluenceState = 'created';
257
266
  }
258
267
 
268
+ if (request.type === 'RoapMessage') {
269
+ // @ts-ignore
270
+ this.webex.internal.newMetrics.submitClientEvent({
271
+ name: 'client.locus.media.response',
272
+ options: {
273
+ meetingId: this.config.meetingId,
274
+ },
275
+ });
276
+ }
277
+
259
278
  return result;
260
279
  })
261
280
  .catch((e) => {
@@ -265,6 +284,18 @@ export class LocusMediaRequest extends WebexPlugin {
265
284
  ) {
266
285
  this.confluenceState = 'not created';
267
286
  }
287
+
288
+ if (request.type === 'RoapMessage') {
289
+ // @ts-ignore
290
+ this.webex.internal.newMetrics.submitClientEvent({
291
+ name: 'client.locus.media.response',
292
+ options: {
293
+ meetingId: this.config.meetingId,
294
+ rawError: e,
295
+ },
296
+ });
297
+ }
298
+
268
299
  throw e;
269
300
  });
270
301
  }
@@ -47,7 +47,6 @@ const MeetingUtil = {
47
47
  },
48
48
 
49
49
  remoteUpdateAudioVideo: (meeting, audioMuted?: boolean, videoMuted?: boolean) => {
50
- const webex = meeting.getWebexObject();
51
50
  if (!meeting) {
52
51
  return Promise.reject(new ParameterError('You need a meeting object.'));
53
52
  }
@@ -60,12 +59,6 @@ const MeetingUtil = {
60
59
  );
61
60
  }
62
61
 
63
- // @ts-ignore
64
- webex.internal.newMetrics.submitClientEvent({
65
- name: 'client.locus.media.request',
66
- options: {meetingId: meeting.id},
67
- });
68
-
69
62
  return meeting.locusMediaRequest
70
63
  .send({
71
64
  type: 'LocalMute',
@@ -77,15 +70,7 @@ const MeetingUtil = {
77
70
  videoMuted,
78
71
  },
79
72
  })
80
- .then((response) => {
81
- // @ts-ignore
82
- webex.internal.newMetrics.submitClientEvent({
83
- name: 'client.locus.media.response',
84
- options: {meetingId: meeting.id},
85
- });
86
-
87
- return response?.body?.locus;
88
- });
73
+ .then((response) => response?.body?.locus);
89
74
  },
90
75
 
91
76
  hasOwner: (info) => info && info.owner,
@@ -1,3 +1,5 @@
1
+ import {type MeetingTranscriptPayload} from '@webex/internal-plugin-voicea';
2
+
1
3
  export const getSpeaker = (members, csis = []) =>
2
4
  Object.values(members).find((member: any) => {
3
5
  const memberCSIs = member.participant.status.csis ?? [];
@@ -31,43 +33,16 @@ export const getSpeakerFromProxyOrStore = ({csisKey, meetingMembers, transcriptD
31
33
  return {speaker, needsCaching};
32
34
  };
33
35
 
34
- export const processNewCaptions = ({data, meeting}) => {
36
+ export const processNewCaptions = ({
37
+ data,
38
+ meeting,
39
+ }: {
40
+ data: MeetingTranscriptPayload;
41
+ meeting: any;
42
+ }) => {
35
43
  const {transcriptId} = data;
36
44
  const transcriptData = meeting.transcription;
37
45
 
38
- if (data.isFinal) {
39
- transcriptData.interimCaptions[transcriptId].forEach((interimId) => {
40
- const interimTranscriptIndex = transcriptData.captions.findIndex(
41
- (transcript) => transcript.id === interimId
42
- );
43
-
44
- if (interimTranscriptIndex !== -1) {
45
- transcriptData.captions.splice(interimTranscriptIndex, 1);
46
- }
47
- });
48
- delete transcriptData.interimCaptions[transcriptId];
49
- const csisKey = data.transcript?.csis[0];
50
-
51
- const {needsCaching, speaker} = getSpeakerFromProxyOrStore({
52
- meetingMembers: meeting.members.membersCollection.members,
53
- transcriptData,
54
- csisKey,
55
- });
56
-
57
- if (needsCaching) {
58
- transcriptData.speakerProxy[csisKey] = speaker;
59
- }
60
- const captionData = {
61
- id: transcriptId,
62
- isFinal: data.isFinal,
63
- translations: data.translations,
64
- text: data.transcript?.text,
65
- currentSpokenLanguage: data.transcript?.transcript_language_code,
66
- timestamp: data.timestamp,
67
- speaker,
68
- };
69
- transcriptData.captions.push(captionData);
70
- }
71
46
  const {transcripts = []} = data;
72
47
  const transcriptsPerCsis = new Map();
73
48
 
@@ -80,8 +55,11 @@ export const processNewCaptions = ({data, meeting}) => {
80
55
 
81
56
  const newCaption = `${transcriptsPerCsis.get(csisMember)?.text ?? ''} ${text}`.trim();
82
57
 
83
- // eslint-disable-next-line camelcase
84
- transcriptsPerCsis.set(csisMember, {text: newCaption, currentSpokenLanguage});
58
+ transcriptsPerCsis.set(csisMember, {
59
+ ...transcript,
60
+ text: newCaption,
61
+ currentSpokenLanguage,
62
+ });
85
63
  }
86
64
  const interimTranscriptionIds = [];
87
65
 
@@ -91,31 +69,51 @@ export const processNewCaptions = ({data, meeting}) => {
91
69
  transcriptData,
92
70
  csisKey: key,
93
71
  });
72
+ const {speakerId} = speaker;
73
+ const interimId = `${transcriptId}_${speakerId}`;
94
74
 
95
75
  if (needsCaching) {
96
76
  transcriptData.speakerProxy[key] = speaker;
97
77
  }
98
- const {speakerId} = speaker;
99
- const interimId = `${transcriptId}_${speakerId}`;
78
+
100
79
  const captionData = {
101
80
  id: interimId,
102
81
  isFinal: data.isFinal,
103
82
  translations: value.translations,
104
83
  text: value.text,
105
- currentCaptionLanguage: value.currentSpokenLanguage,
84
+ currentCaptionLanguage:
85
+ meeting.transcription?.languageOptions?.currentCaptionLanguage ||
86
+ value.currentSpokenLanguage,
87
+ currentSpokenLanguage:
88
+ meeting.transcription?.languageOptions?.currentSpokenLanguage ||
89
+ data.transcripts[0]?.transcript_language_code,
106
90
  timestamp: value?.timestamp,
107
91
  speaker,
108
92
  };
109
93
 
110
- const interimTranscriptIndex = transcriptData.captions.findIndex(
111
- (transcript) => transcript.id === interimId
112
- );
94
+ if (!data.isFinal) {
95
+ const interimTranscriptIndex = transcriptData.captions.findIndex(
96
+ (transcript) => transcript.id === interimId
97
+ );
113
98
 
114
- if (interimTranscriptIndex !== -1) {
115
- transcriptData.captions.splice(interimTranscriptIndex, 1);
116
- }
99
+ if (interimTranscriptIndex !== -1) {
100
+ transcriptData.captions.splice(interimTranscriptIndex, 1);
101
+ }
117
102
 
118
- interimTranscriptionIds.push(interimId);
103
+ interimTranscriptionIds.push(interimId);
104
+ } else {
105
+ transcriptData.interimCaptions[transcriptId].forEach((innerInterimId) => {
106
+ const interimTranscriptIndex = transcriptData.captions.findIndex(
107
+ (transcript) => transcript.id === innerInterimId
108
+ );
109
+
110
+ if (interimTranscriptIndex !== -1) {
111
+ transcriptData.captions.splice(interimTranscriptIndex, 1);
112
+ }
113
+ });
114
+ delete transcriptData.interimCaptions[transcriptId];
115
+ captionData.id = transcriptId;
116
+ }
119
117
  transcriptData.captions.push(captionData);
120
118
  }
121
119
  transcriptData.interimCaptions[transcriptId] = interimTranscriptionIds;
@@ -1,5 +1,5 @@
1
1
  /* eslint no-shadow: ["error", { "allow": ["eventType"] }] */
2
-
2
+ import {union} from 'lodash';
3
3
  import '@webex/internal-plugin-mercury';
4
4
  import '@webex/internal-plugin-conversation';
5
5
  import '@webex/internal-plugin-metrics';
@@ -45,6 +45,8 @@ import {
45
45
  MEETINGNUMBER,
46
46
  _JOINED_,
47
47
  _MOVED_,
48
+ _ON_HOLD_LOBBY_,
49
+ _WAIT_,
48
50
  } from '../constants';
49
51
  import BEHAVIORAL_METRICS from '../metrics/constants';
50
52
  import MeetingInfo from '../meeting-info';
@@ -340,6 +342,9 @@ export default class Meetings extends WebexPlugin {
340
342
  if (newLocus) {
341
343
  const isNewLocusAsBreakout = MeetingsUtil.isBreakoutLocusDTO(newLocus);
342
344
  const isSelfMoved = newLocus?.self?.state === _LEFT_ && newLocus?.self?.reason === _MOVED_;
345
+ const isSelfMovedToLobby =
346
+ newLocus?.self?.devices[0]?.intent?.reason === _ON_HOLD_LOBBY_ &&
347
+ newLocus?.self?.devices[0]?.intent?.type === _WAIT_;
343
348
  if (!meeting) {
344
349
  if (isNewLocusAsBreakout) {
345
350
  LoggerProxy.logger.log(
@@ -352,7 +357,7 @@ export default class Meetings extends WebexPlugin {
352
357
  return this.isNeedHandleMainLocus(meeting, newLocus);
353
358
  }
354
359
  if (!isNewLocusAsBreakout) {
355
- return this.isNeedHandleMainLocus(meeting, newLocus);
360
+ return isSelfMovedToLobby || this.isNeedHandleMainLocus(meeting, newLocus);
356
361
  }
357
362
 
358
363
  return !isSelfMoved;
@@ -996,7 +1001,10 @@ export default class Meetings extends WebexPlugin {
996
1001
  fetchUserPreferredWebexSite() {
997
1002
  return this.request.getMeetingPreferences().then((res) => {
998
1003
  if (res) {
999
- this.preferredWebexSite = MeetingsUtil.parseDefaultSiteFromMeetingPreferences(res);
1004
+ const preferredWebexSite = MeetingsUtil.parseDefaultSiteFromMeetingPreferences(res);
1005
+ this.preferredWebexSite = preferredWebexSite;
1006
+ // @ts-ignore
1007
+ this.webex.internal.services._getCatalog().addAllowedDomains([preferredWebexSite]);
1000
1008
  }
1001
1009
 
1002
1010
  // fall back to getting the preferred site from the user information
@@ -1009,6 +1017,8 @@ export default class Meetings extends WebexPlugin {
1009
1017
  user?.userPreferences?.userPreferencesItems?.preferredWebExSite;
1010
1018
  if (preferredWebexSite) {
1011
1019
  this.preferredWebexSite = preferredWebexSite;
1020
+ // @ts-ignore
1021
+ this.webex.internal.services._getCatalog().addAllowedDomains([preferredWebexSite]);
1012
1022
  } else {
1013
1023
  throw new Error('site not found');
1014
1024
  }
@@ -1383,22 +1393,12 @@ export default class Meetings extends WebexPlugin {
1383
1393
 
1384
1394
  /**
1385
1395
  * Get all meetings.
1386
- * @param {object} options
1387
- * @param {object} options.startDate - get meetings after this start date
1388
- * @param {object} options.endDate - get meetings before this end date
1389
1396
  * @returns {Object} All currently active meetings.
1390
1397
  * @public
1391
1398
  * @memberof Meetings
1392
1399
  */
1393
- public getAllMeetings(
1394
- options: {
1395
- startDate: object;
1396
- endDate: object;
1397
- } = {} as any
1398
- ) {
1399
- // Options may include other parameters to filter this collection
1400
- // of meetings.
1401
- return this.meetingCollection.getAll(options);
1400
+ public getAllMeetings() {
1401
+ return this.meetingCollection.getAll();
1402
1402
  }
1403
1403
 
1404
1404
  /**
@@ -1524,18 +1524,6 @@ export default class Meetings extends WebexPlugin {
1524
1524
  this.breakoutLocusForHandleLater.splice(existIndex, 1);
1525
1525
  }
1526
1526
 
1527
- /**
1528
- * Get all scheduled meetings.
1529
- * @param {object} options
1530
- * @param {object} options.startDate - get meetings after this start date
1531
- * @param {object} options.endDate - get meetings before this end date
1532
- * @returns {Object} All scheduled meetings.
1533
- * @memberof Meetings
1534
- */
1535
- getScheduledMeetings() {
1536
- return this.meetingCollection.getAll({scheduled: true});
1537
- }
1538
-
1539
1527
  /**
1540
1528
  * Get the logger instance for plugin-meetings
1541
1529
  * @returns {Logger}