@webex/plugin-meetings 3.11.0 → 3.12.0-next.2

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 (170) hide show
  1. package/dist/aiEnableRequest/index.js +184 -0
  2. package/dist/aiEnableRequest/index.js.map +1 -0
  3. package/dist/aiEnableRequest/utils.js +36 -0
  4. package/dist/aiEnableRequest/utils.js.map +1 -0
  5. package/dist/annotation/index.js +14 -5
  6. package/dist/annotation/index.js.map +1 -1
  7. package/dist/breakouts/breakout.js +1 -1
  8. package/dist/breakouts/index.js +1 -1
  9. package/dist/config.js +7 -2
  10. package/dist/config.js.map +1 -1
  11. package/dist/constants.js +28 -6
  12. package/dist/constants.js.map +1 -1
  13. package/dist/hashTree/constants.js +3 -1
  14. package/dist/hashTree/constants.js.map +1 -1
  15. package/dist/hashTree/hashTree.js +18 -0
  16. package/dist/hashTree/hashTree.js.map +1 -1
  17. package/dist/hashTree/hashTreeParser.js +850 -410
  18. package/dist/hashTree/hashTreeParser.js.map +1 -1
  19. package/dist/hashTree/types.js +4 -2
  20. package/dist/hashTree/types.js.map +1 -1
  21. package/dist/hashTree/utils.js +10 -0
  22. package/dist/hashTree/utils.js.map +1 -1
  23. package/dist/index.js +11 -2
  24. package/dist/index.js.map +1 -1
  25. package/dist/interceptors/constant.js +12 -0
  26. package/dist/interceptors/constant.js.map +1 -0
  27. package/dist/interceptors/dataChannelAuthToken.js +290 -0
  28. package/dist/interceptors/dataChannelAuthToken.js.map +1 -0
  29. package/dist/interceptors/index.js +7 -0
  30. package/dist/interceptors/index.js.map +1 -1
  31. package/dist/interceptors/utils.js +27 -0
  32. package/dist/interceptors/utils.js.map +1 -0
  33. package/dist/interpretation/index.js +2 -2
  34. package/dist/interpretation/index.js.map +1 -1
  35. package/dist/interpretation/siLanguage.js +1 -1
  36. package/dist/locus-info/controlsUtils.js +5 -3
  37. package/dist/locus-info/controlsUtils.js.map +1 -1
  38. package/dist/locus-info/index.js +522 -131
  39. package/dist/locus-info/index.js.map +1 -1
  40. package/dist/locus-info/selfUtils.js +1 -0
  41. package/dist/locus-info/selfUtils.js.map +1 -1
  42. package/dist/locus-info/types.js.map +1 -1
  43. package/dist/media/MediaConnectionAwaiter.js +57 -1
  44. package/dist/media/MediaConnectionAwaiter.js.map +1 -1
  45. package/dist/media/properties.js +4 -2
  46. package/dist/media/properties.js.map +1 -1
  47. package/dist/meeting/in-meeting-actions.js +7 -1
  48. package/dist/meeting/in-meeting-actions.js.map +1 -1
  49. package/dist/meeting/index.js +1173 -877
  50. package/dist/meeting/index.js.map +1 -1
  51. package/dist/meeting/request.js +50 -0
  52. package/dist/meeting/request.js.map +1 -1
  53. package/dist/meeting/request.type.js.map +1 -1
  54. package/dist/meeting/util.js +133 -3
  55. package/dist/meeting/util.js.map +1 -1
  56. package/dist/meetings/index.js +117 -48
  57. package/dist/meetings/index.js.map +1 -1
  58. package/dist/member/index.js +10 -0
  59. package/dist/member/index.js.map +1 -1
  60. package/dist/member/util.js +10 -0
  61. package/dist/member/util.js.map +1 -1
  62. package/dist/metrics/constants.js +2 -1
  63. package/dist/metrics/constants.js.map +1 -1
  64. package/dist/multistream/mediaRequestManager.js +9 -60
  65. package/dist/multistream/mediaRequestManager.js.map +1 -1
  66. package/dist/multistream/remoteMediaManager.js +11 -0
  67. package/dist/multistream/remoteMediaManager.js.map +1 -1
  68. package/dist/reachability/index.js +18 -10
  69. package/dist/reachability/index.js.map +1 -1
  70. package/dist/reactions/reactions.type.js.map +1 -1
  71. package/dist/reconnection-manager/index.js +0 -1
  72. package/dist/reconnection-manager/index.js.map +1 -1
  73. package/dist/types/aiEnableRequest/index.d.ts +5 -0
  74. package/dist/types/aiEnableRequest/utils.d.ts +2 -0
  75. package/dist/types/config.d.ts +4 -0
  76. package/dist/types/constants.d.ts +23 -1
  77. package/dist/types/hashTree/constants.d.ts +1 -0
  78. package/dist/types/hashTree/hashTree.d.ts +7 -0
  79. package/dist/types/hashTree/hashTreeParser.d.ts +122 -14
  80. package/dist/types/hashTree/types.d.ts +3 -0
  81. package/dist/types/hashTree/utils.d.ts +6 -0
  82. package/dist/types/index.d.ts +1 -0
  83. package/dist/types/interceptors/constant.d.ts +5 -0
  84. package/dist/types/interceptors/dataChannelAuthToken.d.ts +43 -0
  85. package/dist/types/interceptors/index.d.ts +2 -1
  86. package/dist/types/interceptors/utils.d.ts +1 -0
  87. package/dist/types/locus-info/index.d.ts +60 -8
  88. package/dist/types/locus-info/types.d.ts +7 -0
  89. package/dist/types/media/MediaConnectionAwaiter.d.ts +10 -1
  90. package/dist/types/media/properties.d.ts +2 -1
  91. package/dist/types/meeting/in-meeting-actions.d.ts +6 -0
  92. package/dist/types/meeting/index.d.ts +61 -7
  93. package/dist/types/meeting/request.d.ts +16 -1
  94. package/dist/types/meeting/request.type.d.ts +5 -0
  95. package/dist/types/meeting/util.d.ts +31 -0
  96. package/dist/types/meetings/index.d.ts +4 -2
  97. package/dist/types/member/index.d.ts +1 -0
  98. package/dist/types/member/util.d.ts +5 -0
  99. package/dist/types/metrics/constants.d.ts +1 -0
  100. package/dist/types/multistream/mediaRequestManager.d.ts +0 -23
  101. package/dist/types/reactions/reactions.type.d.ts +1 -0
  102. package/dist/types/webinar/utils.d.ts +6 -0
  103. package/dist/webinar/index.js +291 -91
  104. package/dist/webinar/index.js.map +1 -1
  105. package/dist/webinar/utils.js +25 -0
  106. package/dist/webinar/utils.js.map +1 -0
  107. package/package.json +24 -23
  108. package/src/aiEnableRequest/README.md +84 -0
  109. package/src/aiEnableRequest/index.ts +170 -0
  110. package/src/aiEnableRequest/utils.ts +25 -0
  111. package/src/annotation/index.ts +27 -7
  112. package/src/config.ts +4 -0
  113. package/src/constants.ts +29 -1
  114. package/src/hashTree/constants.ts +1 -0
  115. package/src/hashTree/hashTree.ts +17 -0
  116. package/src/hashTree/hashTreeParser.ts +745 -252
  117. package/src/hashTree/types.ts +4 -0
  118. package/src/hashTree/utils.ts +9 -0
  119. package/src/index.ts +8 -1
  120. package/src/interceptors/constant.ts +6 -0
  121. package/src/interceptors/dataChannelAuthToken.ts +170 -0
  122. package/src/interceptors/index.ts +2 -1
  123. package/src/interceptors/utils.ts +16 -0
  124. package/src/interpretation/index.ts +2 -2
  125. package/src/locus-info/controlsUtils.ts +11 -0
  126. package/src/locus-info/index.ts +579 -113
  127. package/src/locus-info/selfUtils.ts +1 -0
  128. package/src/locus-info/types.ts +8 -0
  129. package/src/media/MediaConnectionAwaiter.ts +41 -1
  130. package/src/media/properties.ts +3 -1
  131. package/src/meeting/in-meeting-actions.ts +12 -0
  132. package/src/meeting/index.ts +291 -76
  133. package/src/meeting/request.ts +42 -0
  134. package/src/meeting/request.type.ts +6 -0
  135. package/src/meeting/util.ts +160 -2
  136. package/src/meetings/index.ts +157 -44
  137. package/src/member/index.ts +10 -0
  138. package/src/member/util.ts +12 -0
  139. package/src/metrics/constants.ts +1 -0
  140. package/src/multistream/mediaRequestManager.ts +4 -54
  141. package/src/multistream/remoteMediaManager.ts +13 -0
  142. package/src/reachability/index.ts +9 -0
  143. package/src/reactions/reactions.type.ts +1 -0
  144. package/src/reconnection-manager/index.ts +0 -1
  145. package/src/webinar/index.ts +191 -6
  146. package/src/webinar/utils.ts +16 -0
  147. package/test/unit/spec/aiEnableRequest/index.ts +981 -0
  148. package/test/unit/spec/aiEnableRequest/utils.ts +130 -0
  149. package/test/unit/spec/annotation/index.ts +69 -7
  150. package/test/unit/spec/hashTree/hashTree.ts +66 -0
  151. package/test/unit/spec/hashTree/hashTreeParser.ts +2225 -189
  152. package/test/unit/spec/interceptors/dataChannelAuthToken.ts +210 -0
  153. package/test/unit/spec/interceptors/utils.ts +75 -0
  154. package/test/unit/spec/locus-info/controlsUtils.js +29 -0
  155. package/test/unit/spec/locus-info/index.js +1134 -55
  156. package/test/unit/spec/media/MediaConnectionAwaiter.ts +41 -1
  157. package/test/unit/spec/media/properties.ts +12 -3
  158. package/test/unit/spec/meeting/in-meeting-actions.ts +8 -2
  159. package/test/unit/spec/meeting/index.js +829 -115
  160. package/test/unit/spec/meeting/request.js +70 -0
  161. package/test/unit/spec/meeting/utils.js +438 -26
  162. package/test/unit/spec/meetings/index.js +653 -32
  163. package/test/unit/spec/member/index.js +28 -4
  164. package/test/unit/spec/member/util.js +65 -27
  165. package/test/unit/spec/multistream/mediaRequestManager.ts +2 -85
  166. package/test/unit/spec/multistream/remoteMediaManager.ts +30 -0
  167. package/test/unit/spec/reachability/index.ts +23 -0
  168. package/test/unit/spec/reconnection-manager/index.js +4 -8
  169. package/test/unit/spec/webinar/index.ts +474 -37
  170. package/test/unit/spec/webinar/utils.ts +39 -0
@@ -48,7 +48,7 @@ var _constants = require("../constants");
48
48
  var _constants2 = _interopRequireDefault(require("../metrics/constants"));
49
49
  var _meetingInfo = _interopRequireDefault(require("../meeting-info"));
50
50
  var _meetingInfoV = _interopRequireDefault(require("../meeting-info/meeting-info-v2"));
51
- var _meeting = _interopRequireDefault(require("../meeting"));
51
+ var _meeting = _interopRequireWildcard(require("../meeting"));
52
52
  var _personalMeetingRoom = _interopRequireDefault(require("../personal-meeting-room"));
53
53
  var _reachability = _interopRequireDefault(require("../reachability"));
54
54
  var _request2 = _interopRequireDefault(require("./request"));
@@ -63,6 +63,7 @@ var _webexErrors = require("../common/errors/webex-errors");
63
63
  var _noMeetingInfo = _interopRequireDefault(require("../common/errors/no-meeting-info"));
64
64
  var _joinForbiddenError = _interopRequireDefault(require("../common/errors/join-forbidden-error"));
65
65
  var _utils = require("../hashTree/utils");
66
+ var _locusInfo = require("../locus-info");
66
67
  function _interopRequireWildcard(e, t) { if ("function" == typeof _WeakMap) var r = new _WeakMap(), n = new _WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t3 in e) "default" !== _t3 && {}.hasOwnProperty.call(e, _t3) && ((i = (o = _Object$defineProperty) && _Object$getOwnPropertyDescriptor(e, _t3)) && (i.get || i.set) ? o(f, _t3, i) : f[_t3] = e[_t3]); return f; })(e, t); }
67
68
  function ownKeys(e, r) { var t = _Object$keys2(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
68
69
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
@@ -194,6 +195,8 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
194
195
  (0, _defineProperty2.default)(_this, "preferredWebexSite", void 0);
195
196
  (0, _defineProperty2.default)(_this, "reachability", void 0);
196
197
  (0, _defineProperty2.default)(_this, "registered", void 0);
198
+ (0, _defineProperty2.default)(_this, "registrationPromise", void 0);
199
+ (0, _defineProperty2.default)(_this, "unregistrationPromise", void 0);
197
200
  (0, _defineProperty2.default)(_this, "request", void 0);
198
201
  (0, _defineProperty2.default)(_this, "geoHintInfo", void 0);
199
202
  (0, _defineProperty2.default)(_this, "meetingInfo", void 0);
@@ -446,6 +449,15 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
446
449
  if (existingMeeting) {
447
450
  return existingMeeting;
448
451
  }
452
+ if (data.eventType === _constants.LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
453
+ // need to check if maybe this event indicates a move to/from breakout
454
+ var meetingForHashTreeMessage = (0, _locusInfo.findMeetingForHashTreeMessage)(data.stateElementsMessage, this.meetingCollection,
455
+ // @ts-ignore
456
+ this.webex.internal.device.url);
457
+ if (meetingForHashTreeMessage) {
458
+ return meetingForHashTreeMessage;
459
+ }
460
+ }
449
461
 
450
462
  // if that didn't work, fallback to other fields like correlationId, sipUri, etc
451
463
 
@@ -482,6 +494,11 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
482
494
  var useRandomDelayForInfo = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
483
495
  var meeting = this.getCorrespondingMeetingByLocus(data);
484
496
 
497
+ // @ts-ignore
498
+ if (this.config.experimental.storeLocusHashTreeEventsForDebugging) {
499
+ (0, _meeting.storeEventForDebugging)('mercury', data);
500
+ }
501
+
485
502
  // Special case when locus has got replaced, This only happend once if a replace locus exists
486
503
  // https://sqbu-github.cisco.com/WebExSquared/locus/wiki/Locus-changing-mid-call
487
504
 
@@ -492,7 +509,7 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
492
509
  meeting = this.meetingCollection.getByKey(_meetings.MEETING_KEY.LOCUS_URL, data.locus.replaces[data.locus.replaces.length - 1].locusUrl);
493
510
  }
494
511
  if (meeting && !_util2.default.isBreakoutLocusDTO(data.locus)) {
495
- meeting.locusInfo.updateMainSessionLocusCache(data.locus);
512
+ meeting.locusInfo.updateMainSessionLocusCache(data.locus); // here data.locus will never be a complete locus
496
513
  }
497
514
  if (!this.isNeedHandleLocusDTO(meeting, data.locus)) {
498
515
  _loggerProxy.default.logger.log("Meetings:index#handleLocusEvent --> doesn't need to process locus event");
@@ -519,25 +536,29 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
519
536
  // };
520
537
  // rather then locus object change to locus url
521
538
 
522
- if (data.eventType !== _constants.LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
523
- if (data.locus && data.locus.fullState && data.locus.fullState.state === _constants.LOCUS.STATE.INACTIVE) {
524
- // just ignore the event as its already ended and not active
525
- _loggerProxy.default.logger.warn('Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.');
526
- return;
527
- }
539
+ if (data.eventType === _constants.LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
540
+ // We're about to create a new meeting object from this hash tree message.
541
+ // There is some existing (pre-hash trees) SDK logic here that requires a locus object
542
+ // (at the very minimum we need locus.url to be set)
543
+ // so we try to create locus from the received hash tree message
544
+ // it will not be complete, in most cases it will only have the self part, but that's still better than nothing
545
+ var _createLocusFromHashT = (0, _locusInfo.createLocusFromHashTreeMessage)(data.stateElementsMessage),
546
+ locus = _createLocusFromHashT.locus;
547
+ data.locus = locus;
548
+ }
549
+ if (data.locus && data.locus.fullState && data.locus.fullState.state === _constants.LOCUS.STATE.INACTIVE) {
550
+ // just ignore the event as its already ended and not active
551
+ _loggerProxy.default.logger.warn('Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.');
552
+ return;
553
+ }
528
554
 
529
- // When its wireless share or guest and user leaves the meeting we dont have to keep the meeting object
530
- // Any future events will be neglected
555
+ // When its wireless share or guest and user leaves the meeting we dont have to keep the meeting object
556
+ // Any future events will be neglected
531
557
 
532
- if (data.locus && data.locus.self && data.locus.self.state === _constants._LEFT_ && data.locus.self.removed === true) {
533
- // just ignore the event as its already ended and not active
534
- _loggerProxy.default.logger.warn('Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.');
535
- return;
536
- }
537
- }
538
- if (data.eventType === _constants.LOCUSEVENT.HASH_TREE_DATA_UPDATED) {
539
- // in hash tree messages we don't ge the locus object, but the meeting constructor needs at least locus.url
540
- (0, _lodash.set)(data, 'locus.url', data.stateElementsMessage.locusUrl);
558
+ if (data.locus && data.locus.self && data.locus.self.state === _constants._LEFT_ && data.locus.self.removed === true) {
559
+ // just ignore the event as its already ended and not active
560
+ _loggerProxy.default.logger.warn('Meetings:index#handleLocusEvent --> Locus event received for meeting, after it was ended.');
561
+ return;
541
562
  }
542
563
  this.create(data.locus, _constants.DESTINATION_TYPE.LOCUS_ID, useRandomDelayForInfo).then(/*#__PURE__*/function () {
543
564
  var _ref3 = (0, _asyncToGenerator2.default)(/*#__PURE__*/_regenerator.default.mark(function _callee3(newMeeting) {
@@ -608,7 +629,7 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
608
629
  }
609
630
 
610
631
  /**
611
- * handles locus events through mercury that are not roap
632
+ * handles locus events through mercury that are not roap or approval request events
612
633
  * @param {Object} envelope
613
634
  * @param {Object} envelope.data
614
635
  * @param {String} envelope.data.eventType
@@ -622,7 +643,7 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
622
643
  var data = envelope.data;
623
644
  // eslint-disable-next-line @typescript-eslint/no-shadow
624
645
  var eventType = data.eventType;
625
- if (eventType && eventType !== _constants.LOCUSEVENT.MESSAGE_ROAP) {
646
+ if (eventType && eventType !== _constants.LOCUSEVENT.MESSAGE_ROAP && eventType !== _constants.LOCUSEVENT.APPROVAL_REQUEST) {
626
647
  this.handleLocusEvent(data, true);
627
648
  }
628
649
  }
@@ -943,7 +964,11 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
943
964
  value: function executeRegistrationStep(step, stepName) {
944
965
  var _this5 = this;
945
966
  return step().then(function () {
967
+ _loggerProxy.default.logger.info("Meetings:index#executeRegistrationStep --> INFO, ".concat(stepName, " completed"));
946
968
  _this5.registrationStatus[stepName] = true;
969
+ }).catch(function (error) {
970
+ _loggerProxy.default.logger.error("Meetings:index#executeRegistrationStep --> ERROR, ".concat(stepName, " failed: ").concat(error.message));
971
+ return _promise.default.reject(error);
947
972
  });
948
973
  }
949
974
 
@@ -960,7 +985,20 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
960
985
  key: "register",
961
986
  value: function register(deviceRegistrationOptions) {
962
987
  var _this6 = this;
963
- this.registrationStatus = (0, _lodash.clone)(_constants.INITIAL_REGISTRATION_STATUS);
988
+ if (this.unregistrationPromise) {
989
+ _loggerProxy.default.logger.info('Meetings:index#register --> INFO, Meetings plugin unregistration in progress, waiting to register');
990
+ this.registrationPromise = this.unregistrationPromise.catch(function () {}) // It doesn't matter what happened during unregistration
991
+ .finally(function () {
992
+ _loggerProxy.default.logger.info('Meetings:index#register --> INFO, Meetings plugin unregistration completed, proceeding to register');
993
+ _this6.registrationPromise = null;
994
+ return _this6.register(deviceRegistrationOptions);
995
+ });
996
+ return this.registrationPromise;
997
+ }
998
+ if (this.registrationPromise) {
999
+ _loggerProxy.default.logger.info('Meetings:index#register --> INFO, Meetings plugin registration in progress, returning existing promise');
1000
+ return this.registrationPromise;
1001
+ }
964
1002
 
965
1003
  // @ts-ignore
966
1004
  if (!this.webex.canAuthorize) {
@@ -971,7 +1009,9 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
971
1009
  _loggerProxy.default.logger.info('Meetings:index#register --> INFO, Meetings plugin already registered');
972
1010
  return _promise.default.resolve();
973
1011
  }
974
- return _promise.default.all([this.executeRegistrationStep(function () {
1012
+ _loggerProxy.default.logger.info('Meetings:index#register --> INFO, Registering Meetings plugin');
1013
+ this.registrationStatus = (0, _lodash.clone)(_constants.INITIAL_REGISTRATION_STATUS);
1014
+ this.registrationPromise = _promise.default.all([this.executeRegistrationStep(function () {
975
1015
  return _this6.fetchUserPreferredWebexSite();
976
1016
  }, 'fetchWebexSite'), this.executeRegistrationStep(function () {
977
1017
  return _this6.getGeoHint();
@@ -1012,7 +1052,10 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
1012
1052
  stack: error.stack
1013
1053
  });
1014
1054
  return _promise.default.reject(error);
1055
+ }).finally(function () {
1056
+ _this6.registrationPromise = null;
1015
1057
  });
1058
+ return this.registrationPromise;
1016
1059
  }
1017
1060
 
1018
1061
  /**
@@ -1027,35 +1070,61 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
1027
1070
  key: "unregister",
1028
1071
  value: function unregister() {
1029
1072
  var _this7 = this;
1073
+ if (this.unregistrationPromise) {
1074
+ _loggerProxy.default.logger.info('Meetings:index#unregister --> INFO, Meetings plugin unregistration in progress, returning existing promise');
1075
+ return this.unregistrationPromise;
1076
+ }
1077
+ if (this.registrationPromise) {
1078
+ _loggerProxy.default.logger.info('Meetings:index#unregister --> INFO, Meetings plugin registration in progress, waiting to unregister');
1079
+
1080
+ // Wait for registration to complete (success or failure), then call unregister again
1081
+ this.unregistrationPromise = this.registrationPromise.catch(function () {}) // It doesn't matter what happened during registration
1082
+ .finally(function () {
1083
+ _loggerProxy.default.logger.info('Meetings:index#unregister --> INFO, Meetings plugin registration completed, proceeding to unregister');
1084
+ _this7.unregistrationPromise = null;
1085
+ return _this7.unregister();
1086
+ });
1087
+ return this.unregistrationPromise;
1088
+ }
1030
1089
  if (!this.registered) {
1031
1090
  _loggerProxy.default.logger.info('Meetings:index#unregister --> INFO, Meetings plugin already unregistered');
1032
1091
  return _promise.default.resolve();
1033
1092
  }
1034
1093
  this.stopListeningForEvents();
1035
- return (
1036
- // @ts-ignore
1037
- this.webex.internal.mercury.disconnect()
1038
- // @ts-ignore
1039
- .then(function () {
1040
- return _this7.webex.internal.device.unregister();
1041
- }).catch(function (error) {
1042
- // If error status code is 404, continue the chain
1043
- if (error.statusCode === 404) {
1044
- _loggerProxy.default.logger.info('Meetings:index#unregister --> 404 error during device unregister, proceeding normally');
1045
- return; // returning undefined allows the chain to continue
1046
- }
1047
- // For any other status code, break the chain by rethrowing
1048
- _loggerProxy.default.logger.error("Meetings:index#unregister --> Failed to unregister device: ".concat(error.message));
1049
- throw error; // rethrow to break the promise chain
1050
- }).then(function () {
1051
- _triggerProxy.default.trigger(_this7, {
1052
- file: 'meetings',
1053
- function: 'unregister'
1054
- }, _constants.EVENT_TRIGGERS.MEETINGS_UNREGISTERED);
1055
- _this7.registered = false;
1056
- _this7.registrationStatus = (0, _lodash.clone)(_constants.INITIAL_REGISTRATION_STATUS);
1057
- })
1058
- );
1094
+ this.unregistrationPromise =
1095
+ // @ts-ignore
1096
+ this.webex.internal.mercury
1097
+ // Use code 3050 with a non-reconnecting reason to prevent Mercury auto-reconnect
1098
+ // during unregister. Without this, disconnect() defaults to code 1000/"Done" which
1099
+ // force-closes as "Done (forced)" - a normalReconnectReason that triggers auto-reconnect,
1100
+ // causing a race condition with device.unregister().
1101
+ .disconnect({
1102
+ code: 3050,
1103
+ reason: 'meetings unregister'
1104
+ })
1105
+ // @ts-ignore
1106
+ .then(function () {
1107
+ return _this7.webex.internal.device.unregister();
1108
+ }).catch(function (error) {
1109
+ // If error status code is 404, continue the chain
1110
+ if (error.statusCode === 404) {
1111
+ _loggerProxy.default.logger.info('Meetings:index#unregister --> 404 error during device unregister, proceeding normally');
1112
+ return; // returning undefined allows the chain to continue
1113
+ }
1114
+ // For any other status code, break the chain by rethrowing
1115
+ _loggerProxy.default.logger.error("Meetings:index#unregister --> Failed to unregister device: ".concat(error.message));
1116
+ throw error; // rethrow to break the promise chain
1117
+ }).then(function () {
1118
+ _triggerProxy.default.trigger(_this7, {
1119
+ file: 'meetings',
1120
+ function: 'unregister'
1121
+ }, _constants.EVENT_TRIGGERS.MEETINGS_UNREGISTERED);
1122
+ _this7.registered = false;
1123
+ _this7.registrationStatus = (0, _lodash.clone)(_constants.INITIAL_REGISTRATION_STATUS);
1124
+ }).finally(function () {
1125
+ _this7.unregistrationPromise = null;
1126
+ });
1127
+ return this.unregistrationPromise;
1059
1128
  }
1060
1129
  }, {
1061
1130
  key: "uploadLogs",
@@ -1783,7 +1852,7 @@ var Meetings = exports.default = /*#__PURE__*/function (_WebexPlugin) {
1783
1852
  }
1784
1853
  var associateBreakoutLocus = this.breakoutLocusForHandleLater[existIndex];
1785
1854
  this.handleLocusEvent({
1786
- eventType: _constants.LOCUSEVENT.SDK_NO_EVENT,
1855
+ eventType: _constants.LOCUSEVENT.SDK_LOCUS_FROM_SYNC_MEETINGS,
1787
1856
  locus: associateBreakoutLocus,
1788
1857
  locusUrl: associateBreakoutLocus.url
1789
1858
  });