@atlaskit/collab-provider 8.8.2 → 8.9.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 (70) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/cjs/analytics/analytics-helper.js +21 -12
  3. package/dist/cjs/channel.js +5 -3
  4. package/dist/cjs/document/document-service.js +1 -1
  5. package/dist/cjs/errors/error-code-mapper.js +9 -2
  6. package/dist/cjs/namespace/namespace-service.js +77 -0
  7. package/dist/cjs/participants/participants-helper.js +2 -0
  8. package/dist/cjs/participants/participants-service.js +94 -30
  9. package/dist/cjs/provider/index.js +91 -173
  10. package/dist/cjs/version-wrapper.js +1 -1
  11. package/dist/cjs/version.json +1 -1
  12. package/dist/es2019/analytics/analytics-helper.js +21 -12
  13. package/dist/es2019/channel.js +5 -3
  14. package/dist/es2019/document/document-service.js +1 -1
  15. package/dist/es2019/errors/error-code-mapper.js +9 -2
  16. package/dist/es2019/namespace/namespace-service.js +48 -0
  17. package/dist/es2019/participants/participants-helper.js +2 -0
  18. package/dist/es2019/participants/participants-service.js +88 -30
  19. package/dist/es2019/provider/index.js +82 -145
  20. package/dist/es2019/version-wrapper.js +1 -1
  21. package/dist/es2019/version.json +1 -1
  22. package/dist/esm/analytics/analytics-helper.js +21 -12
  23. package/dist/esm/channel.js +5 -3
  24. package/dist/esm/document/document-service.js +1 -1
  25. package/dist/esm/errors/error-code-mapper.js +9 -2
  26. package/dist/esm/namespace/namespace-service.js +69 -0
  27. package/dist/esm/participants/participants-helper.js +2 -0
  28. package/dist/esm/participants/participants-service.js +94 -30
  29. package/dist/esm/provider/index.js +91 -173
  30. package/dist/esm/version-wrapper.js +1 -1
  31. package/dist/esm/version.json +1 -1
  32. package/dist/types/namespace/namespace-service.d.ts +14 -0
  33. package/dist/types/participants/participants-helper.d.ts +2 -4
  34. package/dist/types/participants/participants-service.d.ts +40 -16
  35. package/dist/types/provider/index.d.ts +20 -36
  36. package/dist/types/types.d.ts +1 -1
  37. package/dist/types-ts4.5/analytics/analytics-helper.d.ts +11 -0
  38. package/dist/types-ts4.5/analytics/performance.d.ts +15 -0
  39. package/dist/types-ts4.5/analytics/ufo.d.ts +3 -0
  40. package/dist/types-ts4.5/channel.d.ts +47 -0
  41. package/dist/types-ts4.5/config.d.ts +5 -0
  42. package/dist/types-ts4.5/connectivity/network.d.ts +17 -0
  43. package/dist/types-ts4.5/connectivity/reconnect-helper.d.ts +8 -0
  44. package/dist/types-ts4.5/connectivity/singleton.d.ts +3 -0
  45. package/dist/types-ts4.5/disconnected-reason-mapper.d.ts +16 -0
  46. package/dist/types-ts4.5/document/catchup.d.ts +9 -0
  47. package/dist/types-ts4.5/document/document-service.d.ts +86 -0
  48. package/dist/types-ts4.5/document/step-queue-state.d.ts +16 -0
  49. package/dist/types-ts4.5/emitter.d.ts +19 -0
  50. package/dist/types-ts4.5/errors/error-code-mapper.d.ts +2 -0
  51. package/dist/types-ts4.5/errors/error-types.d.ts +443 -0
  52. package/dist/types-ts4.5/feature-flags/__test__/index.unit.d.ts +1 -0
  53. package/dist/types-ts4.5/feature-flags/index.d.ts +9 -0
  54. package/dist/types-ts4.5/feature-flags/types.d.ts +13 -0
  55. package/dist/types-ts4.5/helpers/const.d.ts +183 -0
  56. package/dist/types-ts4.5/helpers/utils.d.ts +5 -0
  57. package/dist/types-ts4.5/index.d.ts +4 -0
  58. package/dist/types-ts4.5/metadata/metadata-service.d.ts +25 -0
  59. package/dist/types-ts4.5/namespace/namespace-service.d.ts +14 -0
  60. package/dist/types-ts4.5/participants/participants-helper.d.ts +12 -0
  61. package/dist/types-ts4.5/participants/participants-service.d.ts +94 -0
  62. package/dist/types-ts4.5/participants/participants-state.d.ts +13 -0
  63. package/dist/types-ts4.5/participants/telepointers-helper.d.ts +4 -0
  64. package/dist/types-ts4.5/provider/commit-step.d.ts +25 -0
  65. package/dist/types-ts4.5/provider/index.d.ts +146 -0
  66. package/dist/types-ts4.5/socket-io-provider.d.ts +5 -0
  67. package/dist/types-ts4.5/types.d.ts +265 -0
  68. package/dist/types-ts4.5/version-wrapper.d.ts +3 -0
  69. package/package.json +3 -3
  70. package/report.api.md +4 -2
@@ -35,18 +35,27 @@ var triggerAnalyticsEvent = function triggerAnalyticsEvent(analyticsEvent, analy
35
35
 
36
36
  if (analyticsEvent.eventAction === EVENT_ACTION.ERROR) {
37
37
  payload.nonPrivacySafeAttributes = analyticsEvent.nonPrivacySafeAttributes;
38
- }
39
-
40
- // Let the browser figure out
41
- // when it should send those events
42
- try {
43
- var requestIdleCallbackFunction = window.requestIdleCallback;
44
- var runItLater = typeof requestIdleCallbackFunction === 'function' ? requestIdleCallbackFunction : window.requestAnimationFrame;
45
- runItLater(function () {
46
- analyticsClient.sendOperationalEvent(payload);
47
- });
48
- } catch (error) {
49
- // silently fail for now https://product-fabric.atlassian.net/browse/ESS-3112
38
+ try {
39
+ var requestIdleCallbackFunction = window.requestIdleCallback;
40
+ var runItLater = typeof requestIdleCallbackFunction === 'function' ? requestIdleCallbackFunction : window.requestAnimationFrame;
41
+ runItLater(function () {
42
+ analyticsClient.sendTrackEvent(payload);
43
+ });
44
+ } catch (error) {
45
+ // silently fail for now https://product-fabric.atlassian.net/browse/ESS-3112
46
+ }
47
+ } else {
48
+ // Let the browser figure out
49
+ // when it should send those events
50
+ try {
51
+ var _requestIdleCallbackFunction = window.requestIdleCallback;
52
+ var _runItLater = typeof _requestIdleCallbackFunction === 'function' ? _requestIdleCallbackFunction : window.requestAnimationFrame;
53
+ _runItLater(function () {
54
+ analyticsClient.sendOperationalEvent(payload);
55
+ });
56
+ } catch (error) {
57
+ // silently fail for now https://product-fabric.atlassian.net/browse/ESS-3112
58
+ }
50
59
  }
51
60
  };
52
61
  var AnalyticsHelper = /*#__PURE__*/function () {
@@ -393,7 +393,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
393
393
  if (permissionTokenRefresh) {
394
394
  auth = /*#__PURE__*/function () {
395
395
  var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2(cb) {
396
- var token, _err, _err$data, _err$data$meta, authenticationError;
396
+ var token, _data, _data$meta, authenticationError;
397
397
  return _regeneratorRuntime.wrap(function _callee2$(_context2) {
398
398
  while (1) switch (_context2.prev = _context2.next) {
399
399
  case 0:
@@ -415,6 +415,9 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
415
415
  // save token locally
416
416
  _this2.setToken(token);
417
417
  authData.token = token;
418
+ } else {
419
+ _this2.unsetToken();
420
+ authData.token = undefined;
418
421
  }
419
422
  cb(authData);
420
423
  _context2.next = 17;
@@ -430,8 +433,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
430
433
  code: INTERNAL_ERROR_CODE.TOKEN_PERMISSION_ERROR,
431
434
  meta: {
432
435
  originalError: _context2.t0,
433
- // @ts-expect-error we know the error structure passed in this hack
434
- reason: (_err = err) === null || _err === void 0 ? void 0 : (_err$data = _err.data) === null || _err$data === void 0 ? void 0 : (_err$data$meta = _err$data.meta) === null || _err$data$meta === void 0 ? void 0 : _err$data$meta.reason // Should always be 'RESOURCE_DELETED' Temporary, until Confluence Cloud removes their hack
436
+ reason: _context2.t0 === null || _context2.t0 === void 0 ? void 0 : (_data = _context2.t0.data) === null || _data === void 0 ? void 0 : (_data$meta = _data.meta) === null || _data$meta === void 0 ? void 0 : _data$meta.reason // Should always be 'RESOURCE_DELETED' Temporary, until Confluence Cloud removes their hack
435
437
  // https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/browse/next/packages/native-collab/src/fetchCollabPermissionToken.ts#37
436
438
  }
437
439
  }
@@ -466,7 +466,7 @@ export var DocumentService = /*#__PURE__*/function () {
466
466
  });
467
467
  // If steps can apply to local editor successfully, no need to accumulate the error counter.
468
468
  this.stepRejectCounter = 0;
469
- this.participantsService.emitTelepointersFromSteps(steps, this.providerEmitCallback);
469
+ this.participantsService.emitTelepointersFromSteps(steps);
470
470
 
471
471
  // Resend local steps if none of the received steps originated with us!
472
472
  if (clientIds.indexOf(this.clientId) === -1) {
@@ -5,7 +5,7 @@ import { INTERNAL_ERROR_CODE, PROVIDER_ERROR_CODE } from './error-types';
5
5
  * Maps internal collab provider errors to an emitted error format
6
6
  */
7
7
  export var errorCodeMapper = function errorCodeMapper(error) {
8
- var _error$data, _error$data2, _error$data3;
8
+ var _error$data, _error$data2, _error$data3, _error$data4;
9
9
  switch ((_error$data = error.data) === null || _error$data === void 0 ? void 0 : _error$data.code) {
10
10
  case NCS_ERROR_CODE.HEAD_VERSION_UPDATE_FAILED:
11
11
  case NCS_ERROR_CODE.VERSION_NUMBER_ALREADY_EXISTS:
@@ -88,7 +88,6 @@ export var errorCodeMapper = function errorCodeMapper(error) {
88
88
  case NCS_ERROR_CODE.NAMESPACE_NOT_FOUND:
89
89
  case NCS_ERROR_CODE.ERROR_MAPPING_ERROR:
90
90
  case NCS_ERROR_CODE.EMPTY_BROADCAST:
91
- case INTERNAL_ERROR_CODE.CATCHUP_FAILED:
92
91
  return {
93
92
  code: PROVIDER_ERROR_CODE.INTERNAL_SERVICE_ERROR,
94
93
  message: 'Collab Provider experienced an unrecoverable error',
@@ -96,6 +95,14 @@ export var errorCodeMapper = function errorCodeMapper(error) {
96
95
  reason: (_error$data3 = error.data) === null || _error$data3 === void 0 ? void 0 : _error$data3.code,
97
96
  status: 500
98
97
  };
98
+ case INTERNAL_ERROR_CODE.CATCHUP_FAILED:
99
+ return {
100
+ code: PROVIDER_ERROR_CODE.INTERNAL_SERVICE_ERROR,
101
+ message: 'Collab Provider experienced an unrecoverable error',
102
+ recoverable: true,
103
+ reason: (_error$data4 = error.data) === null || _error$data4 === void 0 ? void 0 : _error$data4.code,
104
+ status: 500
105
+ };
99
106
  default:
100
107
  return;
101
108
  }
@@ -0,0 +1,69 @@
1
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
4
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
6
+ import { createLogger } from '../helpers/utils';
7
+ var logger = createLogger('Provider', 'orange');
8
+
9
+ /**
10
+ * Allows us to keep track of any namespace changes from the server.
11
+ * @param isNamespaceLocked - whether the namespace is locked or not, defaults to false
12
+ */
13
+ export var NamespaceService = /*#__PURE__*/_createClass(function NamespaceService() {
14
+ var _this = this;
15
+ var isNamespaceLocked = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
16
+ _classCallCheck(this, NamespaceService);
17
+ // Primitive values are always copied
18
+ _defineProperty(this, "getIsNamespaceLocked", function () {
19
+ return _this.isNamespaceLocked;
20
+ });
21
+ /**
22
+ * ESS-2916 namespace status event- lock/unlock
23
+ */
24
+ _defineProperty(this, "onNamespaceStatusChanged", /*#__PURE__*/function () {
25
+ var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref) {
26
+ var isLocked, waitTimeInMs, timestamp, start;
27
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
28
+ while (1) switch (_context.prev = _context.next) {
29
+ case 0:
30
+ isLocked = _ref.isLocked, waitTimeInMs = _ref.waitTimeInMs, timestamp = _ref.timestamp;
31
+ start = Date.now();
32
+ logger("Received a namespace status changed event ", {
33
+ isLocked: isLocked,
34
+ waitTimeInMs: waitTimeInMs,
35
+ timestamp: timestamp
36
+ });
37
+ if (!(isLocked && waitTimeInMs)) {
38
+ _context.next = 8;
39
+ break;
40
+ }
41
+ _this.isNamespaceLocked = true;
42
+ logger("Received a namespace status change event ", {
43
+ isLocked: isLocked
44
+ });
45
+
46
+ // To protect the collab editing process from locked out due to BE
47
+ setTimeout(function () {
48
+ logger("The namespace lock has expired", {
49
+ waitTime: Date.now() - start,
50
+ timestamp: timestamp
51
+ });
52
+ _this.isNamespaceLocked = false;
53
+ }, waitTimeInMs);
54
+ return _context.abrupt("return");
55
+ case 8:
56
+ _this.isNamespaceLocked = false;
57
+ logger("The page lock has expired");
58
+ case 10:
59
+ case "end":
60
+ return _context.stop();
61
+ }
62
+ }, _callee);
63
+ }));
64
+ return function (_x) {
65
+ return _ref2.apply(this, arguments);
66
+ };
67
+ }());
68
+ this.isNamespaceLocked = isNamespaceLocked;
69
+ });
@@ -2,6 +2,8 @@ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
2
2
  import _regeneratorRuntime from "@babel/runtime/regenerator";
3
3
  export var PARTICIPANT_UPDATE_INTERVAL = 300 * 1000; // 300 seconds
4
4
 
5
+ // Names are hard
6
+
5
7
  export var createParticipantFromPayload = /*#__PURE__*/function () {
6
8
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(payload, getUser) {
7
9
  var sessionId, timestamp, clientId, userId, user, participant;
@@ -10,20 +10,35 @@ import { EVENT_ACTION, EVENT_STATUS } from '../helpers/const';
10
10
  import { telepointerFromStep } from './telepointers-helper';
11
11
  import { createParticipantFromPayload as enrichParticipant, PARTICIPANT_UPDATE_INTERVAL } from './participants-helper';
12
12
  import { ParticipantsState } from './participants-state';
13
+ import { createLogger } from '../helpers/utils';
14
+ var logger = createLogger('PresenceService', 'pink');
15
+ var SEND_PRESENCE_INTERVAL = 150 * 1000; // 150 seconds
16
+
17
+ /**
18
+ * This service is responsible for handling presence and participant events, as well as sending them on to the editor or NCS.
19
+ * @param analyticsHelper Analytics helper instance
20
+ * @param participantsState Starts with no participants, only add this when testing
21
+ * @param emit Emit from the Provider class (to the editor)
22
+ * @param getUser Callback to get user data from the editor
23
+ * @param channelBroadcast Broadcast from the Channel class (to NCS)
24
+ * @param sendPresenceJoined Callback to Channel class
25
+ */
13
26
  export var ParticipantsService = /*#__PURE__*/function () {
14
27
  function ParticipantsService(analyticsHelper) {
15
28
  var _this = this;
16
29
  var participantsState = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : new ParticipantsState();
30
+ var emit = arguments.length > 2 ? arguments[2] : undefined;
31
+ var getUser = arguments.length > 3 ? arguments[3] : undefined;
32
+ var channelBroadcast = arguments.length > 4 ? arguments[4] : undefined;
33
+ var sendPresenceJoined = arguments.length > 5 ? arguments[5] : undefined;
17
34
  _classCallCheck(this, ParticipantsService);
18
35
  /**
19
36
  * Carries out 3 things: 1) enriches the participant with user data, 2) updates the participantsState, 3) emits the presence event
20
37
  * @param payload Payload from incoming socket event
21
- * @param getUser Function to get user data from confluence
22
- * @param emit Function to execute emit from provider socket
23
38
  * @returns Awaitable Promise, due to getUser
24
39
  */
25
- _defineProperty(this, "updateParticipant", /*#__PURE__*/function () {
26
- var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(payload, getUser, emit) {
40
+ _defineProperty(this, "onParticipantUpdated", /*#__PURE__*/function () {
41
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(payload) {
27
42
  var userId, participant, _this$analyticsHelper, isNewParticipant;
28
43
  return _regeneratorRuntime.wrap(function _callee$(_context) {
29
44
  while (1) switch (_context.prev = _context.next) {
@@ -40,7 +55,7 @@ export var ParticipantsService = /*#__PURE__*/function () {
40
55
  return enrichParticipant( // userId _must_ be defined, this lets the compiler know
41
56
  _objectSpread(_objectSpread({}, payload), {}, {
42
57
  userId: userId
43
- }), getUser);
58
+ }), _this.getUser);
44
59
  case 6:
45
60
  participant = _context.sent;
46
61
  _context.next = 12;
@@ -49,7 +64,7 @@ export var ParticipantsService = /*#__PURE__*/function () {
49
64
  _context.prev = 9;
50
65
  _context.t0 = _context["catch"](3);
51
66
  // We don't want to throw errors for Presence features as they tend to self-restore
52
- (_this$analyticsHelper = _this.analyticsHelper) === null || _this$analyticsHelper === void 0 ? void 0 : _this$analyticsHelper.sendErrorEvent(_context.t0, 'enriching participant');
67
+ (_this$analyticsHelper = _this.analyticsHelper) === null || _this$analyticsHelper === void 0 ? void 0 : _this$analyticsHelper.sendErrorEvent(_context.t0, 'Error while enriching participant');
53
68
  case 12:
54
69
  if (participant) {
55
70
  _context.next = 14;
@@ -67,36 +82,35 @@ export var ParticipantsService = /*#__PURE__*/function () {
67
82
  case 18:
68
83
  _this.emitPresence({
69
84
  joined: [participant]
70
- }, emit, 'handling participant updated event');
85
+ }, 'handling participant updated event');
71
86
  case 19:
72
87
  case "end":
73
88
  return _context.stop();
74
89
  }
75
90
  }, _callee, null, [[3, 9]]);
76
91
  }));
77
- return function (_x, _x2, _x3) {
92
+ return function (_x) {
78
93
  return _ref.apply(this, arguments);
79
94
  };
80
95
  }());
81
96
  /**
82
97
  * Called when a participant leaves the session.
83
- *
84
98
  * We emit the `presence` event to update the active avatars in the editor.
85
99
  */
86
- _defineProperty(this, "participantLeft", function (_ref2, emit) {
100
+ _defineProperty(this, "onParticipantLeft", function (_ref2) {
87
101
  var sessionId = _ref2.sessionId;
88
102
  _this.participantsState.removeBySessionId(sessionId);
89
103
  _this.emitPresence({
90
104
  left: [{
91
105
  sessionId: sessionId
92
106
  }]
93
- }, emit, 'participant leaving');
107
+ }, 'participant leaving');
94
108
  });
95
- _defineProperty(this, "disconnect", function (reason, sessionId, emit) {
109
+ _defineProperty(this, "disconnect", function (reason, sessionId) {
96
110
  var left = _this.participantsState.getParticipants();
97
111
  _this.participantsState.clear();
98
112
  try {
99
- emit('disconnected', {
113
+ _this.emit('disconnected', {
100
114
  reason: disconnectedReasonMapper(reason),
101
115
  sid: sessionId
102
116
  });
@@ -108,7 +122,7 @@ export var ParticipantsService = /*#__PURE__*/function () {
108
122
  if (left.length) {
109
123
  _this.emitPresence({
110
124
  left: left
111
- }, emit, 'emitting presence update on disconnect');
125
+ }, 'emitting presence update on disconnect');
112
126
  }
113
127
  });
114
128
  /**
@@ -123,7 +137,7 @@ export var ParticipantsService = /*#__PURE__*/function () {
123
137
  * Called when we receive a telepointer update from another
124
138
  * participant.
125
139
  */
126
- _defineProperty(this, "participantTelepointer", function (payload, thisSessionId, getUser, emit) {
140
+ _defineProperty(this, "onParticipantTelepointer", function (payload, thisSessionId) {
127
141
  var sessionId = payload.sessionId,
128
142
  selection = payload.selection,
129
143
  timestamp = payload.timestamp;
@@ -141,30 +155,29 @@ export var ParticipantsService = /*#__PURE__*/function () {
141
155
  type: 'telepointer',
142
156
  selection: selection,
143
157
  sessionId: sessionId
144
- }, emit, 'handling participant telepointer event');
158
+ }, 'handling participant telepointer event');
145
159
  });
146
160
  /**
147
161
  * Every 5 minutes (PARTICIPANT_UPDATE_INTERVAL), removes inactive participants and emits the update to other participants.
148
162
  * Needs to be kicked off in the Provider.
149
163
  * @param sessionId SessionId from provider's connection
150
- * @param emit Function to execute emit from provider socket
151
164
  */
152
- _defineProperty(this, "removeInactiveParticipants", function (sessionId, emit) {
165
+ _defineProperty(this, "startInactiveRemover", function (sessionId) {
153
166
  clearTimeout(_this.participantUpdateTimeout);
154
167
  try {
155
- _this.filterInactive(sessionId, emit);
168
+ _this.filterInactive(sessionId);
156
169
  } catch (err) {
157
170
  var _this$analyticsHelper3;
158
171
  (_this$analyticsHelper3 = _this.analyticsHelper) === null || _this$analyticsHelper3 === void 0 ? void 0 : _this$analyticsHelper3.sendErrorEvent(err, 'Failed filtering inactive participants');
159
172
  }
160
173
  _this.participantUpdateTimeout = window.setTimeout(function () {
161
- return _this.removeInactiveParticipants(sessionId, emit);
174
+ return _this.startInactiveRemover(sessionId);
162
175
  }, PARTICIPANT_UPDATE_INTERVAL);
163
176
  });
164
177
  /**
165
178
  * Keep list of participants up to date. Filter out inactive users etc.
166
179
  */
167
- _defineProperty(this, "filterInactive", function (sessionId, emit) {
180
+ _defineProperty(this, "filterInactive", function (sessionId) {
168
181
  var now = Date.now();
169
182
  var left = _this.participantsState.getParticipants().filter(function (p) {
170
183
  return p.sessionId !== sessionId && now - p.lastActive > PARTICIPANT_UPDATE_INTERVAL;
@@ -174,17 +187,17 @@ export var ParticipantsService = /*#__PURE__*/function () {
174
187
  });
175
188
  left.length && _this.emitPresence({
176
189
  left: left
177
- }, emit, 'filtering inactive participants');
190
+ }, 'filtering inactive participants');
178
191
  });
179
192
  /**
180
193
  * Wrapper function to emit with error handling and analytics
181
194
  * @param data Data to emit
182
195
  * @param emit Emit function from Provider
183
196
  */
184
- _defineProperty(this, "emitPresence", function (data, emit, errorMessage) {
197
+ _defineProperty(this, "emitPresence", function (data, errorMessage) {
185
198
  try {
186
199
  var _this$analyticsHelper4;
187
- emit('presence', data);
200
+ _this.emit('presence', data);
188
201
  (_this$analyticsHelper4 = _this.analyticsHelper) === null || _this$analyticsHelper4 === void 0 ? void 0 : _this$analyticsHelper4.sendActionEvent(EVENT_ACTION.UPDATE_PARTICIPANTS, EVENT_STATUS.SUCCESS, {
189
202
  participants: _this.participantsState.size()
190
203
  });
@@ -199,9 +212,9 @@ export var ParticipantsService = /*#__PURE__*/function () {
199
212
  * @param data Data to emit
200
213
  * @param emit Emit function from Provider
201
214
  */
202
- _defineProperty(this, "emitTelepointer", function (data, emit, errorMessage) {
215
+ _defineProperty(this, "emitTelepointer", function (data, errorMessage) {
203
216
  try {
204
- emit('telepointer', data);
217
+ _this.emit('telepointer', data);
205
218
  } catch (error) {
206
219
  var _this$analyticsHelper6;
207
220
  // We don't want to throw errors for Presence features as they tend to self-restore
@@ -214,8 +227,60 @@ export var ParticipantsService = /*#__PURE__*/function () {
214
227
  _defineProperty(this, "clearTimers", function () {
215
228
  clearTimeout(_this.participantUpdateTimeout);
216
229
  });
217
- this.participantsState = participantsState;
230
+ _defineProperty(this, "sendPresence", function (payload) {
231
+ try {
232
+ clearTimeout(_this.presenceUpdateTimeout);
233
+ _this.channelBroadcast('participant:updated', payload);
234
+ _this.presenceUpdateTimeout = window.setTimeout(function () {
235
+ return _this.sendPresence(payload);
236
+ }, SEND_PRESENCE_INTERVAL);
237
+ } catch (error) {
238
+ var _this$analyticsHelper7;
239
+ // We don't want to throw errors for Presence features as they tend to self-restore
240
+ (_this$analyticsHelper7 = _this.analyticsHelper) === null || _this$analyticsHelper7 === void 0 ? void 0 : _this$analyticsHelper7.sendErrorEvent(error, 'Error while sending presence');
241
+ }
242
+ });
243
+ /**
244
+ * Called when a participant joins the session.
245
+ *
246
+ * We keep track of participants internally, and emit the `presence` event to update
247
+ * the active avatars in the editor.
248
+ * This method will be triggered from backend to notify all participants to exchange presence
249
+ */
250
+ _defineProperty(this, "onPresenceJoined", function (payload) {
251
+ try {
252
+ logger('Participant joined with session: ', payload.sessionId);
253
+ // This expose existing users to the newly joined user
254
+ _this.sendPresence(payload);
255
+ } catch (error) {
256
+ var _this$analyticsHelper8;
257
+ // We don't want to throw errors for Presence features as they tend to self-restore
258
+ (_this$analyticsHelper8 = _this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 ? void 0 : _this$analyticsHelper8.sendErrorEvent(error, 'Error while joining presence');
259
+ }
260
+ });
261
+ /**
262
+ * Called when the current user joins the session.
263
+ *
264
+ * This will send both a 'presence' event and a 'participant:updated' event.
265
+ * This updates both the avatars and the participants list.
266
+ */
267
+ _defineProperty(this, "onPresence", function (payload) {
268
+ try {
269
+ logger('onPresence userId: ', payload.userId);
270
+ _this.sendPresence(payload);
271
+ _this.sendPresenceJoined();
272
+ } catch (error) {
273
+ var _this$analyticsHelper9;
274
+ // We don't want to throw errors for Presence features as they tend to self-restore
275
+ (_this$analyticsHelper9 = _this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 ? void 0 : _this$analyticsHelper9.sendErrorEvent(error, 'Error while receiving presence');
276
+ }
277
+ });
218
278
  this.analyticsHelper = analyticsHelper;
279
+ this.participantsState = participantsState;
280
+ this.emit = emit;
281
+ this.getUser = getUser;
282
+ this.channelBroadcast = channelBroadcast;
283
+ this.sendPresenceJoined = sendPresenceJoined;
219
284
  }
220
285
  _createClass(ParticipantsService, [{
221
286
  key: "emitTelepointersFromSteps",
@@ -223,14 +288,13 @@ export var ParticipantsService = /*#__PURE__*/function () {
223
288
  /**
224
289
  * Called on receiving steps, emits each step's telepointer
225
290
  * @param steps Steps to extract telepointers from
226
- * @param emit Provider emit function
227
291
  */
228
- function emitTelepointersFromSteps(steps, emit) {
292
+ function emitTelepointersFromSteps(steps) {
229
293
  var _this2 = this;
230
294
  steps.forEach(function (step) {
231
295
  var event = telepointerFromStep(_this2.participantsState.getParticipants(), step);
232
296
  if (event) {
233
- _this2.emitTelepointer(event, emit, 'emitting telepointers from steps');
297
+ _this2.emitTelepointer(event, 'emitting telepointers from steps');
234
298
  }
235
299
  });
236
300
  }