@atlaskit/collab-provider 7.6.3 → 7.7.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 (36) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/channel.js +17 -0
  3. package/dist/cjs/helpers/const.js +1 -0
  4. package/dist/cjs/provider/index.js +143 -48
  5. package/dist/cjs/version-wrapper.js +1 -1
  6. package/dist/cjs/version.json +1 -1
  7. package/dist/es2019/channel.js +18 -0
  8. package/dist/es2019/helpers/const.js +1 -0
  9. package/dist/es2019/provider/index.js +86 -7
  10. package/dist/es2019/version-wrapper.js +1 -1
  11. package/dist/es2019/version.json +1 -1
  12. package/dist/esm/channel.js +17 -0
  13. package/dist/esm/helpers/const.js +1 -0
  14. package/dist/esm/provider/index.js +146 -48
  15. package/dist/esm/version-wrapper.js +1 -1
  16. package/dist/esm/version.json +1 -1
  17. package/dist/types/helpers/const.d.ts +3 -1
  18. package/dist/types/provider/index.d.ts +6 -0
  19. package/dist/types/types.d.ts +7 -0
  20. package/package.json +2 -10
  21. package/report.api.md +16 -11
  22. package/dist/types-ts4.0/analytics/index.d.ts +0 -5
  23. package/dist/types-ts4.0/analytics/performance.d.ts +0 -14
  24. package/dist/types-ts4.0/channel.d.ts +0 -27
  25. package/dist/types-ts4.0/config.d.ts +0 -5
  26. package/dist/types-ts4.0/disconnected-reason-mapper.d.ts +0 -15
  27. package/dist/types-ts4.0/emitter.d.ts +0 -19
  28. package/dist/types-ts4.0/error-code-mapper.d.ts +0 -32
  29. package/dist/types-ts4.0/helpers/const.d.ts +0 -31
  30. package/dist/types-ts4.0/helpers/utils.d.ts +0 -11
  31. package/dist/types-ts4.0/index.d.ts +0 -2
  32. package/dist/types-ts4.0/provider/catchup.d.ts +0 -9
  33. package/dist/types-ts4.0/provider/index.d.ts +0 -124
  34. package/dist/types-ts4.0/socket-io-provider.d.ts +0 -4
  35. package/dist/types-ts4.0/types.d.ts +0 -170
  36. package/dist/types-ts4.0/version-wrapper.d.ts +0 -3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/collab-provider
2
2
 
3
+ ## 7.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`fa0da169cce`](https://bitbucket.org/atlassian/atlassian-frontend/commits/fa0da169cce) - Introducing namespace status update: lock & unlock events
8
+ - [`eaada7441d0`](https://bitbucket.org/atlassian/atlassian-frontend/commits/eaada7441d0) - ESS-2853 Add metrics for page recovery events
9
+ - [`6319cd08784`](https://bitbucket.org/atlassian/atlassian-frontend/commits/6319cd08784) - add page restoration event handler
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies
14
+
3
15
  ## 7.6.3
4
16
 
5
17
  ### Patch Changes
@@ -117,6 +117,19 @@ var Channel = /*#__PURE__*/function (_Emitter) {
117
117
  userId: userId,
118
118
  metadata: metadata
119
119
  });
120
+ } else {
121
+ // Page is been just restored, need to fix all the participants as well.
122
+ var _doc = data.doc,
123
+ _version = data.version,
124
+ _userId = data.userId,
125
+ _metadata = data.metadata;
126
+
127
+ _this.emit('restore', {
128
+ doc: _doc,
129
+ version: _version,
130
+ userId: _userId,
131
+ metadata: _metadata
132
+ });
120
133
  }
121
134
  } else {
122
135
  _this.emit('steps:added', data);
@@ -215,6 +228,10 @@ var Channel = /*#__PURE__*/function (_Emitter) {
215
228
  });
216
229
  this.socket.on('metadata:changed', function (payload) {
217
230
  _this2.emit('metadata:changed', payload);
231
+ }); // ESS-2916 namespace status event - lock/unlock
232
+
233
+ this.socket.on('status', function (data) {
234
+ _this2.emit('status', data);
218
235
  });
219
236
  this.socket.on('disconnect', /*#__PURE__*/function () {
220
237
  var _ref2 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(reason) {
@@ -25,6 +25,7 @@ exports.EVENT_ACTION = EVENT_ACTION;
25
25
  EVENT_ACTION["CONVERT_PM_TO_ADF"] = "convertPMToADF";
26
26
  EVENT_ACTION["UPDATE_PARTICIPANTS"] = "updateParticipants";
27
27
  EVENT_ACTION["COMMIT_UNCONFIRMED_STEPS"] = "commitUnconfirmedSteps";
28
+ EVENT_ACTION["REINITIALISE_DOCUMENT"] = "reinitialiseDocument";
28
29
  })(EVENT_ACTION || (exports.EVENT_ACTION = EVENT_ACTION = {}));
29
30
 
30
31
  var EVENT_STATUS;
@@ -115,6 +115,7 @@ var Provider = /*#__PURE__*/function (_Emitter) {
115
115
 
116
116
  var _super = _createSuper(Provider);
117
117
 
118
+ // To keep track of the namespace event changes from the server.
118
119
  function Provider(config) {
119
120
  var _this;
120
121
 
@@ -124,6 +125,7 @@ var Provider = /*#__PURE__*/function (_Emitter) {
124
125
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "metadata", {});
125
126
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "stepRejectCounter", 0);
126
127
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "isChannelInitialized", false);
128
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "isNamespaceLocked", false);
127
129
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "initializeChannel", function () {
128
130
  _this.channel.on('connected', function (_ref2) {
129
131
  var sid = _ref2.sid,
@@ -152,7 +154,42 @@ var Provider = /*#__PURE__*/function (_Emitter) {
152
154
  version: version,
153
155
  metadata: metadata
154
156
  });
155
- }).on('steps:added', _this.onStepsAdded.bind((0, _assertThisInitialized2.default)(_this))).on('participant:telepointer', _this.onParticipantTelepointer.bind((0, _assertThisInitialized2.default)(_this))).on('presence:joined', _this.onPresenceJoined.bind((0, _assertThisInitialized2.default)(_this))).on('presence', _this.onPresence.bind((0, _assertThisInitialized2.default)(_this))).on('participant:left', _this.onParticipantLeft.bind((0, _assertThisInitialized2.default)(_this))).on('participant:updated', _this.onParticipantUpdated.bind((0, _assertThisInitialized2.default)(_this))).on('metadata:changed', _this.onMetadataChanged.bind((0, _assertThisInitialized2.default)(_this))).on('disconnect', _this.onDisconnected.bind((0, _assertThisInitialized2.default)(_this))).on('error', _this.onErrorHandled.bind((0, _assertThisInitialized2.default)(_this))).connect();
157
+ }).on('restore', _this.onRestore.bind((0, _assertThisInitialized2.default)(_this))).on('steps:added', _this.onStepsAdded.bind((0, _assertThisInitialized2.default)(_this))).on('participant:telepointer', _this.onParticipantTelepointer.bind((0, _assertThisInitialized2.default)(_this))).on('presence:joined', _this.onPresenceJoined.bind((0, _assertThisInitialized2.default)(_this))).on('presence', _this.onPresence.bind((0, _assertThisInitialized2.default)(_this))).on('participant:left', _this.onParticipantLeft.bind((0, _assertThisInitialized2.default)(_this))).on('participant:updated', _this.onParticipantUpdated.bind((0, _assertThisInitialized2.default)(_this))).on('metadata:changed', _this.onMetadataChanged.bind((0, _assertThisInitialized2.default)(_this))).on('disconnect', _this.onDisconnected.bind((0, _assertThisInitialized2.default)(_this))).on('error', _this.onErrorHandled.bind((0, _assertThisInitialized2.default)(_this))).on('status', _this.onNamespaceStatusChanged.bind((0, _assertThisInitialized2.default)(_this))).connect();
158
+ });
159
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onRestore", function (_ref4) {
160
+ var doc = _ref4.doc,
161
+ version = _ref4.version,
162
+ metadata = _ref4.metadata;
163
+
164
+ // Preseve the unconfirmed steps to prevent data loss.
165
+ var _ref5 = _this.getUnconfirmedSteps() || {
166
+ steps: []
167
+ },
168
+ unconfirmedSteps = _ref5.steps; // Reset the editor,
169
+ // - Repalce the document, keep in sync with the server
170
+ // - Repalce the version number, so editor is in sync with NCS server and can commit new changes.
171
+ // - Repalce the metadata
172
+ // - Reserve the cursore position, in case a cursor jump.
173
+
174
+
175
+ _this.updateDocumentWithMetadata({
176
+ doc: doc,
177
+ version: version,
178
+ metadata: metadata,
179
+ reserveCursor: true
180
+ });
181
+
182
+ (0, _analytics.triggerCollabAnalyticsEvent)({
183
+ eventAction: _const.EVENT_ACTION.REINITIALISE_DOCUMENT,
184
+ attributes: {
185
+ numUnconfirmedSteps: unconfirmedSteps.length,
186
+ documentAri: _this.config.documentAri
187
+ }
188
+ }, _this.analyticsClient); // Re-apply the unconfirmed steps, not 100% of them can be applied, if document is changed significantly.
189
+
190
+ if (unconfirmedSteps.length > 0) {
191
+ _this.applyLocalsteps(unconfirmedSteps);
192
+ }
156
193
  });
157
194
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onStepsAdded", function (data) {
158
195
  logger("Received steps", {
@@ -181,8 +218,8 @@ var Provider = /*#__PURE__*/function (_Emitter) {
181
218
  _this.throttledCatchup();
182
219
  }
183
220
 
184
- _this.updateParticipants([], data.steps.map(function (_ref4) {
185
- var userId = _ref4.userId;
221
+ _this.updateParticipants([], data.steps.map(function (_ref6) {
222
+ var userId = _ref6.userId;
186
223
  return userId;
187
224
  }));
188
225
  });
@@ -195,11 +232,11 @@ var Provider = /*#__PURE__*/function (_Emitter) {
195
232
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "fitlerQueue", function (condition) {
196
233
  _this.queue = _this.queue.filter(condition);
197
234
  });
198
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "updateDocumentWithMetadata", function (_ref5) {
199
- var doc = _ref5.doc,
200
- version = _ref5.version,
201
- metadata = _ref5.metadata,
202
- reserveCursor = _ref5.reserveCursor;
235
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "updateDocumentWithMetadata", function (_ref7) {
236
+ var doc = _ref7.doc,
237
+ version = _ref7.version,
238
+ metadata = _ref7.metadata,
239
+ reserveCursor = _ref7.reserveCursor;
203
240
 
204
241
  _this.emit('init', _objectSpread({
205
242
  doc: doc,
@@ -352,14 +389,14 @@ var Provider = /*#__PURE__*/function (_Emitter) {
352
389
  return _this.sendPresence();
353
390
  }, SEND_PRESENCE_INTERVAL);
354
391
  });
355
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onPresenceJoined", function (_ref7) {
356
- var sessionId = _ref7.sessionId;
392
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onPresenceJoined", function (_ref9) {
393
+ var sessionId = _ref9.sessionId;
357
394
  logger('Participant joined with session: ', sessionId); // This expose existing users to the newly joined user
358
395
 
359
396
  _this.sendPresence();
360
397
  });
361
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onPresence", function (_ref8) {
362
- var userId = _ref8.userId;
398
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onPresence", function (_ref10) {
399
+ var userId = _ref10.userId;
363
400
  logger('onPresence userId: ', userId);
364
401
  _this.userId = userId;
365
402
 
@@ -374,8 +411,8 @@ var Provider = /*#__PURE__*/function (_Emitter) {
374
411
  _this.emit('metadata:changed', metadata);
375
412
  }
376
413
  });
377
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onParticipantLeft", function (_ref9) {
378
- var sessionId = _ref9.sessionId;
414
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onParticipantLeft", function (_ref11) {
415
+ var sessionId = _ref11.sessionId;
379
416
  logger("Participant left");
380
417
 
381
418
  _this.participants.delete(sessionId);
@@ -386,11 +423,11 @@ var Provider = /*#__PURE__*/function (_Emitter) {
386
423
  }]
387
424
  });
388
425
  });
389
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onParticipantUpdated", function (_ref10) {
390
- var sessionId = _ref10.sessionId,
391
- timestamp = _ref10.timestamp,
392
- userId = _ref10.userId,
393
- clientId = _ref10.clientId;
426
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onParticipantUpdated", function (_ref12) {
427
+ var sessionId = _ref12.sessionId,
428
+ timestamp = _ref12.timestamp,
429
+ userId = _ref12.userId,
430
+ clientId = _ref12.clientId;
394
431
 
395
432
  _this.updateParticipant({
396
433
  sessionId: sessionId,
@@ -399,12 +436,12 @@ var Provider = /*#__PURE__*/function (_Emitter) {
399
436
  clientId: clientId
400
437
  });
401
438
  });
402
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onParticipantTelepointer", function (_ref11) {
403
- var sessionId = _ref11.sessionId,
404
- timestamp = _ref11.timestamp,
405
- selection = _ref11.selection,
406
- userId = _ref11.userId,
407
- clientId = _ref11.clientId;
439
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onParticipantTelepointer", function (_ref13) {
440
+ var sessionId = _ref13.sessionId,
441
+ timestamp = _ref13.timestamp,
442
+ selection = _ref13.selection,
443
+ userId = _ref13.userId,
444
+ clientId = _ref13.clientId;
408
445
 
409
446
  if (sessionId === _this.sessionId) {
410
447
  return;
@@ -432,14 +469,14 @@ var Provider = /*#__PURE__*/function (_Emitter) {
432
469
  });
433
470
  });
434
471
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "updateParticipant", /*#__PURE__*/function () {
435
- var _ref13 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(_ref12) {
472
+ var _ref15 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee2(_ref14) {
436
473
  var sessionId, timestamp, userId, clientId, getUser, _yield, _yield$name, name, _yield$email, email, _yield$avatar, avatar, isNewParticipant;
437
474
 
438
475
  return _regenerator.default.wrap(function _callee2$(_context2) {
439
476
  while (1) {
440
477
  switch (_context2.prev = _context2.next) {
441
478
  case 0:
442
- sessionId = _ref12.sessionId, timestamp = _ref12.timestamp, userId = _ref12.userId, clientId = _ref12.clientId;
479
+ sessionId = _ref14.sessionId, timestamp = _ref14.timestamp, userId = _ref14.userId, clientId = _ref14.clientId;
443
480
 
444
481
  if (userId) {
445
482
  _context2.next = 3;
@@ -492,7 +529,7 @@ var Provider = /*#__PURE__*/function (_Emitter) {
492
529
  }));
493
530
 
494
531
  return function (_x) {
495
- return _ref13.apply(this, arguments);
532
+ return _ref15.apply(this, arguments);
496
533
  };
497
534
  }());
498
535
  (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "updateParticipants", function () {
@@ -562,8 +599,8 @@ var Provider = /*#__PURE__*/function (_Emitter) {
562
599
  return _disconnectedReasonMapper.DisconnectReason.UNKNOWN_DISCONNECT;
563
600
  }
564
601
  });
565
- (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onDisconnected", function (_ref14) {
566
- var reason = _ref14.reason;
602
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onDisconnected", function (_ref16) {
603
+ var reason = _ref16.reason;
567
604
  _this.disconnectedAt = Date.now();
568
605
  var left = Array.from(_this.participants.values());
569
606
 
@@ -660,7 +697,9 @@ var Provider = /*#__PURE__*/function (_Emitter) {
660
697
  attributes: {
661
698
  eventStatus: _const.EVENT_STATUS.FAILURE,
662
699
  latency: _measure2 === null || _measure2 === void 0 ? void 0 : _measure2.duration,
663
- documentAri: _this.config.documentAri
700
+ documentAri: _this.config.documentAri,
701
+ // upon failure, emit the number of unconfirmed steps we attempted to sync
702
+ numUnconfirmedSteps: nextUnconfirmedState === null || nextUnconfirmedState === void 0 ? void 0 : nextUnconfirmedState.steps.length
664
703
  }
665
704
  }, _this.analyticsClient);
666
705
  throw new Error("Can't sync up with Collab Service");
@@ -676,7 +715,9 @@ var Provider = /*#__PURE__*/function (_Emitter) {
676
715
  attributes: {
677
716
  eventStatus: _const.EVENT_STATUS.SUCCESS,
678
717
  latency: measure === null || measure === void 0 ? void 0 : measure.duration,
679
- documentAri: _this.config.documentAri
718
+ documentAri: _this.config.documentAri,
719
+ // upon success, emit the total number of unconfirmed steps we synced
720
+ numUnconfirmedSteps: unconfirmedState.steps.length
680
721
  }
681
722
  }, _this.analyticsClient);
682
723
 
@@ -730,6 +771,54 @@ var Provider = /*#__PURE__*/function (_Emitter) {
730
771
  }
731
772
  }, _callee4);
732
773
  })));
774
+ (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "onNamespaceStatusChanged", /*#__PURE__*/function () {
775
+ var _ref18 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee5(data) {
776
+ var isLocked, waitTimeInMs, timestamp, start;
777
+ return _regenerator.default.wrap(function _callee5$(_context5) {
778
+ while (1) {
779
+ switch (_context5.prev = _context5.next) {
780
+ case 0:
781
+ isLocked = data.isLocked, waitTimeInMs = data.waitTimeInMs, timestamp = data.timestamp;
782
+ start = Date.now();
783
+ logger("Received a namespace status changed event ", {
784
+ data: data
785
+ });
786
+
787
+ if (!(isLocked && waitTimeInMs)) {
788
+ _context5.next = 8;
789
+ break;
790
+ }
791
+
792
+ _this.isNamespaceLocked = true;
793
+ logger("Received a namespace status change event ", {
794
+ isLocked: isLocked
795
+ }); // To protect the collab editing process from locked out due to BE
796
+
797
+ setTimeout(function () {
798
+ logger("The namespace lock has expired", {
799
+ waitTime: Date.now() - start,
800
+ timestamp: timestamp
801
+ });
802
+ _this.isNamespaceLocked = false;
803
+ }, waitTimeInMs);
804
+ return _context5.abrupt("return");
805
+
806
+ case 8:
807
+ _this.isNamespaceLocked = false;
808
+ logger("The page lock has expired");
809
+
810
+ case 10:
811
+ case "end":
812
+ return _context5.stop();
813
+ }
814
+ }
815
+ }, _callee5);
816
+ }));
817
+
818
+ return function (_x2) {
819
+ return _ref18.apply(this, arguments);
820
+ };
821
+ }());
733
822
  _this.config = config;
734
823
  _this.channel = new _channel.Channel(config);
735
824
  _this.isChannelInitialized = false;
@@ -755,9 +844,9 @@ var Provider = /*#__PURE__*/function (_Emitter) {
755
844
  }
756
845
  }, {
757
846
  key: "setup",
758
- value: function setup(_ref16) {
759
- var getState = _ref16.getState,
760
- onSyncUpError = _ref16.onSyncUpError;
847
+ value: function setup(_ref19) {
848
+ var getState = _ref19.getState,
849
+ onSyncUpError = _ref19.onSyncUpError;
761
850
  this.getState = getState;
762
851
  this.onSyncUpError = onSyncUpError || noop;
763
852
  this.clientId = getState().plugins.find(function (p) {
@@ -804,6 +893,11 @@ var Provider = /*#__PURE__*/function (_Emitter) {
804
893
  return;
805
894
  }
806
895
 
896
+ if (this.isNamespaceLocked) {
897
+ logger('The document is temporary locked');
898
+ return;
899
+ }
900
+
807
901
  var steps = sendable.steps;
808
902
 
809
903
  if (!steps || !steps.length) {
@@ -821,10 +915,7 @@ var Provider = /*#__PURE__*/function (_Emitter) {
821
915
  steps: steps,
822
916
  version: version
823
917
  });
824
- }
825
- /**
826
- * Called when we receive steps from the service
827
- */
918
+ } // Triggered when page recovery has emitted an 'init' event on a page client is currently connected to.
828
919
 
829
920
  }, {
830
921
  key: "queueSteps",
@@ -868,8 +959,8 @@ var Provider = /*#__PURE__*/function (_Emitter) {
868
959
  logger("Processing data. Version \"".concat(version, "\"."));
869
960
 
870
961
  if (steps && steps.length) {
871
- var clientIds = steps.map(function (_ref17) {
872
- var clientId = _ref17.clientId;
962
+ var clientIds = steps.map(function (_ref20) {
963
+ var clientId = _ref20.clientId;
873
964
  return clientId;
874
965
  });
875
966
  this.emit('data', {
@@ -939,14 +1030,14 @@ var Provider = /*#__PURE__*/function (_Emitter) {
939
1030
  participant = _Array$from$filter2[0];
940
1031
 
941
1032
  if (participant) {
942
- var _ref18 = step,
943
- stepType = _ref18.stepType,
944
- to = _ref18.to,
945
- from = _ref18.from,
946
- _ref18$slice = _ref18.slice,
947
- slice = _ref18$slice === void 0 ? {
1033
+ var _ref21 = step,
1034
+ stepType = _ref21.stepType,
1035
+ to = _ref21.to,
1036
+ from = _ref21.from,
1037
+ _ref21$slice = _ref21.slice,
1038
+ slice = _ref21$slice === void 0 ? {
948
1039
  content: []
949
- } : _ref18$slice;
1040
+ } : _ref21$slice;
950
1041
 
951
1042
  var _slice$content = (0, _slicedToArray2.default)(slice.content, 1),
952
1043
  node = _slice$content[0];
@@ -1018,6 +1109,10 @@ var Provider = /*#__PURE__*/function (_Emitter) {
1018
1109
  this.channel.disconnect();
1019
1110
  return this;
1020
1111
  }
1112
+ /**
1113
+ * ESS-2916 namespace status event- lock/unlock
1114
+ */
1115
+
1021
1116
  }]);
1022
1117
  return Provider;
1023
1118
  }(_emitter.Emitter);
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.version = exports.nextMajorVersion = exports.name = void 0;
7
7
  var name = "@atlaskit/collab-provider";
8
8
  exports.name = name;
9
- var version = "7.6.3";
9
+ var version = "7.7.0";
10
10
  exports.version = version;
11
11
 
12
12
  var nextMajorVersion = function nextMajorVersion() {
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/collab-provider",
3
- "version": "7.6.3",
3
+ "version": "7.7.0",
4
4
  "sideEffects": false
5
5
  }
@@ -71,6 +71,20 @@ export class Channel extends Emitter {
71
71
  userId,
72
72
  metadata
73
73
  });
74
+ } else {
75
+ // Page is been just restored, need to fix all the participants as well.
76
+ const {
77
+ doc,
78
+ version,
79
+ userId,
80
+ metadata
81
+ } = data;
82
+ this.emit('restore', {
83
+ doc,
84
+ version,
85
+ userId,
86
+ metadata
87
+ });
74
88
  }
75
89
  } else {
76
90
  this.emit('steps:added', data);
@@ -169,6 +183,10 @@ export class Channel extends Emitter {
169
183
  });
170
184
  this.socket.on('metadata:changed', payload => {
171
185
  this.emit('metadata:changed', payload);
186
+ }); // ESS-2916 namespace status event - lock/unlock
187
+
188
+ this.socket.on('status', data => {
189
+ this.emit('status', data);
172
190
  });
173
191
  this.socket.on('disconnect', async reason => {
174
192
  this.connected = false;
@@ -16,6 +16,7 @@ export let EVENT_ACTION;
16
16
  EVENT_ACTION["CONVERT_PM_TO_ADF"] = "convertPMToADF";
17
17
  EVENT_ACTION["UPDATE_PARTICIPANTS"] = "updateParticipants";
18
18
  EVENT_ACTION["COMMIT_UNCONFIRMED_STEPS"] = "commitUnconfirmedSteps";
19
+ EVENT_ACTION["REINITIALISE_DOCUMENT"] = "reinitialiseDocument";
19
20
  })(EVENT_ACTION || (EVENT_ACTION = {}));
20
21
 
21
22
  export let EVENT_STATUS;
@@ -50,6 +50,7 @@ const throttledCommitStep = throttle(commitStep, SEND_STEPS_THROTTLE, {
50
50
  trailing: true
51
51
  });
52
52
  export class Provider extends Emitter {
53
+ // To keep track of the namespace event changes from the server.
53
54
  constructor(config) {
54
55
  super();
55
56
 
@@ -61,6 +62,8 @@ export class Provider extends Emitter {
61
62
 
62
63
  _defineProperty(this, "isChannelInitialized", false);
63
64
 
65
+ _defineProperty(this, "isNamespaceLocked", false);
66
+
64
67
  _defineProperty(this, "initializeChannel", () => {
65
68
  this.channel.on('connected', ({
66
69
  sid,
@@ -88,7 +91,42 @@ export class Provider extends Emitter {
88
91
  version,
89
92
  metadata
90
93
  });
91
- }).on('steps:added', this.onStepsAdded.bind(this)).on('participant:telepointer', this.onParticipantTelepointer.bind(this)).on('presence:joined', this.onPresenceJoined.bind(this)).on('presence', this.onPresence.bind(this)).on('participant:left', this.onParticipantLeft.bind(this)).on('participant:updated', this.onParticipantUpdated.bind(this)).on('metadata:changed', this.onMetadataChanged.bind(this)).on('disconnect', this.onDisconnected.bind(this)).on('error', this.onErrorHandled.bind(this)).connect();
94
+ }).on('restore', this.onRestore.bind(this)).on('steps:added', this.onStepsAdded.bind(this)).on('participant:telepointer', this.onParticipantTelepointer.bind(this)).on('presence:joined', this.onPresenceJoined.bind(this)).on('presence', this.onPresence.bind(this)).on('participant:left', this.onParticipantLeft.bind(this)).on('participant:updated', this.onParticipantUpdated.bind(this)).on('metadata:changed', this.onMetadataChanged.bind(this)).on('disconnect', this.onDisconnected.bind(this)).on('error', this.onErrorHandled.bind(this)).on('status', this.onNamespaceStatusChanged.bind(this)).connect();
95
+ });
96
+
97
+ _defineProperty(this, "onRestore", ({
98
+ doc,
99
+ version,
100
+ metadata
101
+ }) => {
102
+ // Preseve the unconfirmed steps to prevent data loss.
103
+ const {
104
+ steps: unconfirmedSteps
105
+ } = this.getUnconfirmedSteps() || {
106
+ steps: []
107
+ }; // Reset the editor,
108
+ // - Repalce the document, keep in sync with the server
109
+ // - Repalce the version number, so editor is in sync with NCS server and can commit new changes.
110
+ // - Repalce the metadata
111
+ // - Reserve the cursore position, in case a cursor jump.
112
+
113
+ this.updateDocumentWithMetadata({
114
+ doc,
115
+ version,
116
+ metadata,
117
+ reserveCursor: true
118
+ });
119
+ triggerCollabAnalyticsEvent({
120
+ eventAction: EVENT_ACTION.REINITIALISE_DOCUMENT,
121
+ attributes: {
122
+ numUnconfirmedSteps: unconfirmedSteps.length,
123
+ documentAri: this.config.documentAri
124
+ }
125
+ }, this.analyticsClient); // Re-apply the unconfirmed steps, not 100% of them can be applied, if document is changed significantly.
126
+
127
+ if (unconfirmedSteps.length > 0) {
128
+ this.applyLocalsteps(unconfirmedSteps);
129
+ }
92
130
  });
93
131
 
94
132
  _defineProperty(this, "onStepsAdded", data => {
@@ -509,7 +547,9 @@ export class Provider extends Emitter {
509
547
  attributes: {
510
548
  eventStatus: EVENT_STATUS.FAILURE,
511
549
  latency: measure === null || measure === void 0 ? void 0 : measure.duration,
512
- documentAri: this.config.documentAri
550
+ documentAri: this.config.documentAri,
551
+ // upon failure, emit the number of unconfirmed steps we attempted to sync
552
+ numUnconfirmedSteps: nextUnconfirmedState === null || nextUnconfirmedState === void 0 ? void 0 : nextUnconfirmedState.steps.length
513
553
  }
514
554
  }, this.analyticsClient);
515
555
  throw new Error("Can't sync up with Collab Service");
@@ -522,7 +562,9 @@ export class Provider extends Emitter {
522
562
  attributes: {
523
563
  eventStatus: EVENT_STATUS.SUCCESS,
524
564
  latency: measure === null || measure === void 0 ? void 0 : measure.duration,
525
- documentAri: this.config.documentAri
565
+ documentAri: this.config.documentAri,
566
+ // upon success, emit the total number of unconfirmed steps we synced
567
+ numUnconfirmedSteps: unconfirmedState.steps.length
526
568
  }
527
569
  }, this.analyticsClient);
528
570
  }
@@ -564,6 +606,37 @@ export class Provider extends Emitter {
564
606
  };
565
607
  });
566
608
 
609
+ _defineProperty(this, "onNamespaceStatusChanged", async data => {
610
+ const {
611
+ isLocked,
612
+ waitTimeInMs,
613
+ timestamp
614
+ } = data;
615
+ const start = Date.now();
616
+ logger(`Received a namespace status changed event `, {
617
+ data
618
+ });
619
+
620
+ if (isLocked && waitTimeInMs) {
621
+ this.isNamespaceLocked = true;
622
+ logger(`Received a namespace status change event `, {
623
+ isLocked
624
+ }); // To protect the collab editing process from locked out due to BE
625
+
626
+ setTimeout(() => {
627
+ logger(`The namespace lock has expired`, {
628
+ waitTime: Date.now() - start,
629
+ timestamp
630
+ });
631
+ this.isNamespaceLocked = false;
632
+ }, waitTimeInMs);
633
+ return;
634
+ }
635
+
636
+ this.isNamespaceLocked = false;
637
+ logger(`The page lock has expired`);
638
+ });
639
+
567
640
  this.config = config;
568
641
  this.channel = new Channel(config);
569
642
  this.isChannelInitialized = false;
@@ -629,6 +702,11 @@ export class Provider extends Emitter {
629
702
  return;
630
703
  }
631
704
 
705
+ if (this.isNamespaceLocked) {
706
+ logger('The document is temporary locked');
707
+ return;
708
+ }
709
+
632
710
  const {
633
711
  steps
634
712
  } = sendable;
@@ -648,10 +726,7 @@ export class Provider extends Emitter {
648
726
  steps,
649
727
  version
650
728
  });
651
- }
652
- /**
653
- * Called when we receive steps from the service
654
- */
729
+ } // Triggered when page recovery has emitted an 'init' event on a page client is currently connected to.
655
730
 
656
731
 
657
732
  queueSteps(data) {
@@ -826,5 +901,9 @@ export class Provider extends Emitter {
826
901
  this.channel.disconnect();
827
902
  return this;
828
903
  }
904
+ /**
905
+ * ESS-2916 namespace status event- lock/unlock
906
+ */
907
+
829
908
 
830
909
  }
@@ -1,5 +1,5 @@
1
1
  export const name = "@atlaskit/collab-provider";
2
- export const version = "7.6.3";
2
+ export const version = "7.7.0";
3
3
  export const nextMajorVersion = () => {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/collab-provider",
3
- "version": "7.6.3",
3
+ "version": "7.7.0",
4
4
  "sideEffects": false
5
5
  }
@@ -102,6 +102,19 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
102
102
  userId: userId,
103
103
  metadata: metadata
104
104
  });
105
+ } else {
106
+ // Page is been just restored, need to fix all the participants as well.
107
+ var _doc = data.doc,
108
+ _version = data.version,
109
+ _userId = data.userId,
110
+ _metadata = data.metadata;
111
+
112
+ _this.emit('restore', {
113
+ doc: _doc,
114
+ version: _version,
115
+ userId: _userId,
116
+ metadata: _metadata
117
+ });
105
118
  }
106
119
  } else {
107
120
  _this.emit('steps:added', data);
@@ -201,6 +214,10 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
201
214
  });
202
215
  this.socket.on('metadata:changed', function (payload) {
203
216
  _this2.emit('metadata:changed', payload);
217
+ }); // ESS-2916 namespace status event - lock/unlock
218
+
219
+ this.socket.on('status', function (data) {
220
+ _this2.emit('status', data);
204
221
  });
205
222
  this.socket.on('disconnect', /*#__PURE__*/function () {
206
223
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(reason) {
@@ -16,6 +16,7 @@ export var EVENT_ACTION;
16
16
  EVENT_ACTION["CONVERT_PM_TO_ADF"] = "convertPMToADF";
17
17
  EVENT_ACTION["UPDATE_PARTICIPANTS"] = "updateParticipants";
18
18
  EVENT_ACTION["COMMIT_UNCONFIRMED_STEPS"] = "commitUnconfirmedSteps";
19
+ EVENT_ACTION["REINITIALISE_DOCUMENT"] = "reinitialiseDocument";
19
20
  })(EVENT_ACTION || (EVENT_ACTION = {}));
20
21
 
21
22
  export var EVENT_STATUS;