@atlaskit/collab-provider 10.7.2 → 10.8.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,30 @@
1
1
  # @atlaskit/collab-provider
2
2
 
3
+ ## 10.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#117768](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/117768)
8
+ [`d55a8d95dd68a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/d55a8d95dd68a) -
9
+ Add support for presenceActivity changes within collab provider. Remove unused code from original
10
+ presence experiment.
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+
16
+ ## 10.7.3
17
+
18
+ ### Patch Changes
19
+
20
+ - [#117438](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/117438)
21
+ [`0de6100bab361`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0de6100bab361) -
22
+ CEPS-219: The collab provider waits for an ACK from NCS before committing the enxt batch of steps,
23
+ but there is a timeout of 5s in case this ACK is lost. Since we are now intentionally increasing
24
+ this ack for single player sessions, this causes unwanted behvaiour if the ack is 5s or more, as
25
+ the provider will re-send even though an ack is in flight. We increase the window to 20s so that
26
+ we have a bigger window of ack delay values we can experiment with.
27
+
3
28
  ## 10.7.2
4
29
 
5
30
  ### Patch Changes
@@ -556,14 +556,6 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
556
556
  timestamp: timestamp
557
557
  }, data));
558
558
  });
559
- this.socket.on('participant:activity-ack', function (_ref7) {
560
- var data = _ref7.data;
561
- _this2.emit('participant:activity-ack', data);
562
- });
563
- this.socket.on('participant:activity-join', function (_ref8) {
564
- var data = _ref8.data;
565
- _this2.emit('participant:activity-join', data);
566
- });
567
559
  this.socket.on('presence:joined', function (data) {
568
560
  _this2.emit('presence:joined', data);
569
561
  });
@@ -573,11 +565,11 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
573
565
  this.socket.on('participant:left', function (data) {
574
566
  _this2.emit('participant:left', data);
575
567
  });
576
- this.socket.on('participant:updated', function (_ref9) {
577
- var sessionId = _ref9.sessionId,
578
- timestamp = _ref9.timestamp,
579
- data = _ref9.data,
580
- clientId = _ref9.clientId;
568
+ this.socket.on('participant:updated', function (_ref7) {
569
+ var sessionId = _ref7.sessionId,
570
+ timestamp = _ref7.timestamp,
571
+ data = _ref7.data,
572
+ clientId = _ref7.clientId;
581
573
  _this2.emit('participant:updated', _objectSpread({
582
574
  sessionId: sessionId,
583
575
  timestamp: timestamp,
@@ -595,7 +587,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
595
587
  // Ignored via go/ees005
596
588
  // eslint-disable-next-line require-await
597
589
  this.socket.on('disconnect', /*#__PURE__*/function () {
598
- var _ref10 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6(reason) {
590
+ var _ref8 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee6(reason) {
599
591
  var _this2$analyticsHelpe, reconnectionError;
600
592
  return _regenerator.default.wrap(function _callee6$(_context6) {
601
593
  while (1) switch (_context6.prev = _context6.next) {
@@ -628,7 +620,7 @@ var Channel = exports.Channel = /*#__PURE__*/function (_Emitter) {
628
620
  }, _callee6);
629
621
  }));
630
622
  return function (_x9) {
631
- return _ref10.apply(this, arguments);
623
+ return _ref8.apply(this, arguments);
632
624
  };
633
625
  }());
634
626
 
@@ -42,6 +42,9 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
42
42
  var setUserId = arguments.length > 7 ? arguments[7] : undefined;
43
43
  var getAIProviderActiveIds = arguments.length > 8 ? arguments[8] : undefined;
44
44
  (0, _classCallCheck2.default)(this, ParticipantsService);
45
+ (0, _defineProperty2.default)(this, "sendPresenceActivityChanged", function () {
46
+ _this.sendPresence();
47
+ });
45
48
  (0, _defineProperty2.default)(this, "sendAIProviderChanged", function (payload) {
46
49
  if (payload.providerId) {
47
50
  for (var propKey in payload.permit) {
@@ -87,6 +90,9 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
87
90
  });
88
91
  }
89
92
  });
93
+ (0, _defineProperty2.default)(this, "hasPresenceActivityChanged", function (previous, current) {
94
+ return previous.presenceActivity !== current.presenceActivity;
95
+ });
90
96
  /**
91
97
  * Carries out 3 things: 1) enriches the participant with user data, 2) updates the participantsState, 3) emits the presence event
92
98
  * @param payload Payload from incoming socket event
@@ -94,7 +100,7 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
94
100
  */
95
101
  (0, _defineProperty2.default)(this, "onParticipantUpdated", /*#__PURE__*/function () {
96
102
  var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(payload) {
97
- var userId, participant, _this$analyticsHelper, isNewParticipant;
103
+ var userId, participant, _this$analyticsHelper, previousParticipant;
98
104
  return _regenerator.default.wrap(function _callee$(_context) {
99
105
  while (1) switch (_context.prev = _context.next) {
100
106
  case 0:
@@ -127,18 +133,25 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
127
133
  }
128
134
  return _context.abrupt("return");
129
135
  case 14:
130
- isNewParticipant = _this.participantsState.doesntHave(participant.sessionId);
136
+ previousParticipant = _this.participantsState.getBySessionId(participant.sessionId);
131
137
  _this.participantsState.setBySessionId(participant.sessionId, participant);
132
- if (isNewParticipant) {
133
- _context.next = 18;
138
+ if (!previousParticipant) {
139
+ _context.next = 19;
134
140
  break;
135
141
  }
142
+ if (_this.hasPresenceActivityChanged(previousParticipant, participant)) {
143
+ _this.emitPresenceActivityChange({
144
+ type: 'participant:activity',
145
+ activity: participant.presenceActivity
146
+ }, 'handling participant activity changed event');
147
+ }
136
148
  return _context.abrupt("return");
137
- case 18:
149
+ case 19:
150
+ // Only emit the joined presence event if this is a new participant
138
151
  _this.emitPresence({
139
152
  joined: [participant]
140
153
  }, 'handling participant updated event');
141
- case 19:
154
+ case 20:
142
155
  case "end":
143
156
  return _context.stop();
144
157
  }
@@ -322,32 +335,6 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
322
335
  (_this$analyticsHelper7 = _this.analyticsHelper) === null || _this$analyticsHelper7 === void 0 || _this$analyticsHelper7.sendErrorEvent(error, 'Error while sending presence');
323
336
  }
324
337
  });
325
- /**
326
- * sending new joiner's activity to existing participants
327
- */
328
- (0, _defineProperty2.default)(this, "onParticipantActivityJoin", function (payload) {
329
- try {
330
- logger('New participant joined: ', payload.activity);
331
- _this.emit('activity:join', payload);
332
- } catch (error) {
333
- var _this$analyticsHelper8;
334
- // We don't want to throw errors for Presence features as they tend to self-restore
335
- (_this$analyticsHelper8 = _this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 || _this$analyticsHelper8.sendErrorEvent(error, "Error while sending 'activity:join'");
336
- }
337
- });
338
- /**
339
- * respond to new joiner with existing participant's activity
340
- */
341
- (0, _defineProperty2.default)(this, "onParticipantActivityAck", function (payload) {
342
- try {
343
- logger('Existing participants ack: ', payload.activity);
344
- _this.emit('activity:ack', payload);
345
- } catch (error) {
346
- var _this$analyticsHelper9;
347
- // We don't want to throw errors for Presence features as they tend to self-restore
348
- (_this$analyticsHelper9 = _this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 || _this$analyticsHelper9.sendErrorEvent(error, "Error while sending 'activity:ack'");
349
- }
350
- });
351
338
  /**
352
339
  * Called when a participant joins the session.
353
340
  *
@@ -361,9 +348,9 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
361
348
  // This expose existing users to the newly joined user
362
349
  _this.sendPresence();
363
350
  } catch (error) {
364
- var _this$analyticsHelper10;
351
+ var _this$analyticsHelper8;
365
352
  // We don't want to throw errors for Presence features as they tend to self-restore
366
- (_this$analyticsHelper10 = _this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 || _this$analyticsHelper10.sendErrorEvent(error, 'Error while joining presence');
353
+ (_this$analyticsHelper8 = _this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 || _this$analyticsHelper8.sendErrorEvent(error, 'Error while joining presence');
367
354
  }
368
355
  });
369
356
  /**
@@ -381,9 +368,9 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
381
368
  _this.sendPresence();
382
369
  _this.sendPresenceJoined();
383
370
  } catch (error) {
384
- var _this$analyticsHelper11;
371
+ var _this$analyticsHelper9;
385
372
  // We don't want to throw errors for Presence features as they tend to self-restore
386
- (_this$analyticsHelper11 = _this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 || _this$analyticsHelper11.sendErrorEvent(error, 'Error while receiving presence');
373
+ (_this$analyticsHelper9 = _this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 || _this$analyticsHelper9.sendErrorEvent(error, 'Error while receiving presence');
387
374
  }
388
375
  });
389
376
  /**
@@ -424,5 +411,22 @@ var ParticipantsService = exports.ParticipantsService = /*#__PURE__*/function ()
424
411
  }
425
412
  });
426
413
  }
414
+ }, {
415
+ key: "emitPresenceActivityChange",
416
+ value:
417
+ /**
418
+ * Wrapper function to emit with error handling and analytics
419
+ * @param data Data to emit
420
+ * @param errorMessage Error message for analytics
421
+ */
422
+ function emitPresenceActivityChange(data, errorMessage) {
423
+ try {
424
+ this.emit('presence:changed', data);
425
+ } catch (error) {
426
+ var _this$analyticsHelper10;
427
+ // We don't want to throw errors for Presence features as they tend to self-restore
428
+ (_this$analyticsHelper10 = this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 || _this$analyticsHelper10.sendErrorEvent(error, "Error while ".concat(errorMessage));
429
+ }
430
+ }
427
431
  }]);
428
432
  }();
@@ -16,7 +16,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
16
16
  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; }
17
17
  var logger = (0, _utils.createLogger)('commit-step', 'black');
18
18
  var readyToCommit = exports.readyToCommit = true;
19
- var RESET_READYTOCOMMIT_INTERVAL_MS = exports.RESET_READYTOCOMMIT_INTERVAL_MS = 5000;
19
+ var RESET_READYTOCOMMIT_INTERVAL_MS = exports.RESET_READYTOCOMMIT_INTERVAL_MS = 20000;
20
20
  var commitStepQueue = exports.commitStepQueue = function commitStepQueue(_ref) {
21
21
  var broadcast = _ref.broadcast,
22
22
  steps = _ref.steps,
@@ -163,7 +163,7 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
163
163
  _this.emit('permission', permit);
164
164
  }).on('steps:added', _this.documentService.onStepsAdded).on('metadata:changed', _this.metadataService.onMetadataChanged).on('participant:telepointer', function (payload) {
165
165
  return _this.participantsService.onParticipantTelepointer(payload, _this.sessionId);
166
- }).on('participant:activity-join', _this.participantsService.onParticipantActivityJoin).on('participant:activity-ack', _this.participantsService.onParticipantActivityAck).on('presence:joined', _this.participantsService.onPresenceJoined).on('presence', _this.participantsService.onPresence).on('participant:left', _this.participantsService.onParticipantLeft).on('participant:updated', _this.participantsService.onParticipantUpdated).on('disconnect', _this.onDisconnected.bind(_this)).on('error', _this.onErrorHandled).on('status', /*#__PURE__*/function () {
166
+ }).on('presence:joined', _this.participantsService.onPresenceJoined).on('presence', _this.participantsService.onPresence).on('participant:left', _this.participantsService.onParticipantLeft).on('participant:updated', _this.participantsService.onParticipantUpdated).on('disconnect', _this.onDisconnected.bind(_this)).on('error', _this.onErrorHandled).on('status', /*#__PURE__*/function () {
167
167
  var _ref4 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(status) {
168
168
  var isLocked;
169
169
  return _regenerator.default.wrap(function _callee$(_context) {
@@ -206,6 +206,9 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
206
206
  presenceActivity: _this.presenceActivity
207
207
  };
208
208
  });
209
+ (0, _defineProperty2.default)(_this, "setPresenceActivity", function (activity) {
210
+ _this.presenceActivity = activity;
211
+ });
209
212
  /**
210
213
  * @param {InternalError} error The error to handle
211
214
  */
@@ -555,12 +558,11 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
555
558
  this.channel.broadcast('participant:telepointer', _objectSpread(_objectSpread({}, basePayload), {}, {
556
559
  selection: data.selection
557
560
  }), (0, _performance.shouldTelepointerBeSampled)() ? (0, _telepointersHelper.telepointerCallback)(this.config.documentAri) : undefined);
558
- } else if ((data === null || data === void 0 ? void 0 : data.type) === 'activity:join' || (data === null || data === void 0 ? void 0 : data.type) === 'activity:ack') {
559
- this.channel.broadcast((data === null || data === void 0 ? void 0 : data.type) === 'activity:join' ? 'participant:activity-join' : 'participant:activity-ack', _objectSpread(_objectSpread({}, basePayload), {}, {
560
- activity: data.activity
561
- }), activityCallback());
562
561
  } else if ((data === null || data === void 0 ? void 0 : data.type) === 'ai-provider:change') {
563
562
  this.participantsService.sendAIProviderChanged(_objectSpread(_objectSpread({}, basePayload), data));
563
+ } else if ((data === null || data === void 0 ? void 0 : data.type) === 'participant:activity') {
564
+ this.setPresenceActivity(data.activity);
565
+ this.participantsService.sendPresenceActivityChanged();
564
566
  }
565
567
  } catch (error) {
566
568
  var _this$analyticsHelper12;
@@ -696,20 +698,4 @@ var Provider = exports.Provider = /*#__PURE__*/function (_Emitter) {
696
698
  return this.namespaceService.getIsNamespaceLocked();
697
699
  }
698
700
  }]);
699
- }(_emitter.Emitter);
700
- /**
701
- * Callback for handling the broadcast response of participant activity.
702
- * This example assumes a simple logging mechanism. It could be expanded to handle errors or other responses.
703
- *
704
- * @param activity The activity that was broadcast.
705
- * @returns A function that handles the response from the broadcast operation.
706
- */
707
- function activityCallback() {
708
- return function (error) {
709
- if (error) {
710
- // Log or handle the error. This could involve retrying the broadcast or notifying the user.
711
- logger('Error broadcasting participant activity:', error);
712
- return;
713
- }
714
- };
715
- }
701
+ }(_emitter.Emitter);
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.version = exports.nextMajorVersion = exports.name = void 0;
7
7
  var name = exports.name = "@atlaskit/collab-provider";
8
- var version = exports.version = "10.7.2";
8
+ var version = exports.version = "10.8.0";
9
9
  var nextMajorVersion = exports.nextMajorVersion = function nextMajorVersion() {
10
10
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
11
11
  };
@@ -401,16 +401,6 @@ export class Channel extends Emitter {
401
401
  ...data
402
402
  });
403
403
  });
404
- this.socket.on('participant:activity-ack', ({
405
- data
406
- }) => {
407
- this.emit('participant:activity-ack', data);
408
- });
409
- this.socket.on('participant:activity-join', ({
410
- data
411
- }) => {
412
- this.emit('participant:activity-join', data);
413
- });
414
404
  this.socket.on('presence:joined', data => {
415
405
  this.emit('presence:joined', data);
416
406
  });
@@ -19,6 +19,9 @@ const SEND_PRESENCE_INTERVAL = 150 * 1000; // 150 seconds
19
19
  */
20
20
  export class ParticipantsService {
21
21
  constructor(analyticsHelper, participantsState = new ParticipantsState(), emit, getUser, channelBroadcast, sendPresenceJoined, getPresenceData, setUserId, getAIProviderActiveIds) {
22
+ _defineProperty(this, "sendPresenceActivityChanged", () => {
23
+ this.sendPresence();
24
+ });
22
25
  _defineProperty(this, "sendAIProviderChanged", payload => {
23
26
  if (payload.providerId) {
24
27
  for (const propKey in payload.permit) {
@@ -64,6 +67,9 @@ export class ParticipantsService {
64
67
  });
65
68
  }
66
69
  });
70
+ _defineProperty(this, "hasPresenceActivityChanged", (previous, current) => {
71
+ return previous.presenceActivity !== current.presenceActivity;
72
+ });
67
73
  /**
68
74
  * Carries out 3 things: 1) enriches the participant with user data, 2) updates the participantsState, 3) emits the presence event
69
75
  * @param payload Payload from incoming socket event
@@ -95,11 +101,19 @@ export class ParticipantsService {
95
101
  if (!participant) {
96
102
  return;
97
103
  }
98
- const isNewParticipant = this.participantsState.doesntHave(participant.sessionId);
104
+ const previousParticipant = this.participantsState.getBySessionId(participant.sessionId);
99
105
  this.participantsState.setBySessionId(participant.sessionId, participant);
100
- if (!isNewParticipant) {
106
+ if (previousParticipant) {
107
+ if (this.hasPresenceActivityChanged(previousParticipant, participant)) {
108
+ this.emitPresenceActivityChange({
109
+ type: 'participant:activity',
110
+ activity: participant.presenceActivity
111
+ }, 'handling participant activity changed event');
112
+ }
101
113
  return;
102
114
  }
115
+
116
+ // Only emit the joined presence event if this is a new participant
103
117
  this.emitPresence({
104
118
  joined: [participant]
105
119
  }, 'handling participant updated event');
@@ -267,32 +281,6 @@ export class ParticipantsService {
267
281
  (_this$analyticsHelper7 = this.analyticsHelper) === null || _this$analyticsHelper7 === void 0 ? void 0 : _this$analyticsHelper7.sendErrorEvent(error, 'Error while sending presence');
268
282
  }
269
283
  });
270
- /**
271
- * sending new joiner's activity to existing participants
272
- */
273
- _defineProperty(this, "onParticipantActivityJoin", payload => {
274
- try {
275
- logger('New participant joined: ', payload.activity);
276
- this.emit('activity:join', payload);
277
- } catch (error) {
278
- var _this$analyticsHelper8;
279
- // We don't want to throw errors for Presence features as they tend to self-restore
280
- (_this$analyticsHelper8 = this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 ? void 0 : _this$analyticsHelper8.sendErrorEvent(error, `Error while sending 'activity:join'`);
281
- }
282
- });
283
- /**
284
- * respond to new joiner with existing participant's activity
285
- */
286
- _defineProperty(this, "onParticipantActivityAck", payload => {
287
- try {
288
- logger('Existing participants ack: ', payload.activity);
289
- this.emit('activity:ack', payload);
290
- } catch (error) {
291
- var _this$analyticsHelper9;
292
- // We don't want to throw errors for Presence features as they tend to self-restore
293
- (_this$analyticsHelper9 = this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 ? void 0 : _this$analyticsHelper9.sendErrorEvent(error, `Error while sending 'activity:ack'`);
294
- }
295
- });
296
284
  /**
297
285
  * Called when a participant joins the session.
298
286
  *
@@ -306,9 +294,9 @@ export class ParticipantsService {
306
294
  // This expose existing users to the newly joined user
307
295
  this.sendPresence();
308
296
  } catch (error) {
309
- var _this$analyticsHelper10;
297
+ var _this$analyticsHelper8;
310
298
  // We don't want to throw errors for Presence features as they tend to self-restore
311
- (_this$analyticsHelper10 = this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 ? void 0 : _this$analyticsHelper10.sendErrorEvent(error, 'Error while joining presence');
299
+ (_this$analyticsHelper8 = this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 ? void 0 : _this$analyticsHelper8.sendErrorEvent(error, 'Error while joining presence');
312
300
  }
313
301
  });
314
302
  /**
@@ -326,9 +314,9 @@ export class ParticipantsService {
326
314
  this.sendPresence();
327
315
  this.sendPresenceJoined();
328
316
  } catch (error) {
329
- var _this$analyticsHelper11;
317
+ var _this$analyticsHelper9;
330
318
  // We don't want to throw errors for Presence features as they tend to self-restore
331
- (_this$analyticsHelper11 = this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 ? void 0 : _this$analyticsHelper11.sendErrorEvent(error, 'Error while receiving presence');
319
+ (_this$analyticsHelper9 = this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 ? void 0 : _this$analyticsHelper9.sendErrorEvent(error, 'Error while receiving presence');
332
320
  }
333
321
  });
334
322
  /**
@@ -365,4 +353,18 @@ export class ParticipantsService {
365
353
  }
366
354
  });
367
355
  }
356
+ /**
357
+ * Wrapper function to emit with error handling and analytics
358
+ * @param data Data to emit
359
+ * @param errorMessage Error message for analytics
360
+ */
361
+ emitPresenceActivityChange(data, errorMessage) {
362
+ try {
363
+ this.emit('presence:changed', data);
364
+ } catch (error) {
365
+ var _this$analyticsHelper10;
366
+ // We don't want to throw errors for Presence features as they tend to self-restore
367
+ (_this$analyticsHelper10 = this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 ? void 0 : _this$analyticsHelper10.sendErrorEvent(error, `Error while ${errorMessage}`);
368
+ }
369
+ }
368
370
  }
@@ -6,7 +6,7 @@ import { NCS_ERROR_CODE } from '../errors/ncs-errors';
6
6
  import { createLogger } from '../helpers/utils';
7
7
  const logger = createLogger('commit-step', 'black');
8
8
  export let readyToCommit = true;
9
- export const RESET_READYTOCOMMIT_INTERVAL_MS = 5000;
9
+ export const RESET_READYTOCOMMIT_INTERVAL_MS = 20000;
10
10
  export const commitStepQueue = ({
11
11
  broadcast,
12
12
  steps,
@@ -141,7 +141,7 @@ export class Provider extends Emitter {
141
141
  }).on('restore', this.documentService.onRestore).on('permission', permit => {
142
142
  this.permit = Object.assign(this.permit, permit);
143
143
  this.emit('permission', permit);
144
- }).on('steps:added', this.documentService.onStepsAdded).on('metadata:changed', this.metadataService.onMetadataChanged).on('participant:telepointer', payload => this.participantsService.onParticipantTelepointer(payload, this.sessionId)).on('participant:activity-join', this.participantsService.onParticipantActivityJoin).on('participant:activity-ack', this.participantsService.onParticipantActivityAck).on('presence:joined', this.participantsService.onPresenceJoined).on('presence', this.participantsService.onPresence).on('participant:left', this.participantsService.onParticipantLeft).on('participant:updated', this.participantsService.onParticipantUpdated).on('disconnect', this.onDisconnected.bind(this)).on('error', this.onErrorHandled).on('status', async status => {
144
+ }).on('steps:added', this.documentService.onStepsAdded).on('metadata:changed', this.metadataService.onMetadataChanged).on('participant:telepointer', payload => this.participantsService.onParticipantTelepointer(payload, this.sessionId)).on('presence:joined', this.participantsService.onPresenceJoined).on('presence', this.participantsService.onPresence).on('participant:left', this.participantsService.onParticipantLeft).on('participant:updated', this.participantsService.onParticipantUpdated).on('disconnect', this.onDisconnected.bind(this)).on('error', this.onErrorHandled).on('status', async status => {
145
145
  await this.namespaceService.onNamespaceStatusChanged(status);
146
146
  const isLocked = this.namespaceService.getIsNamespaceLocked();
147
147
  this.emit('namespace-lock:check', {
@@ -168,6 +168,9 @@ export class Provider extends Emitter {
168
168
  presenceActivity: this.presenceActivity
169
169
  };
170
170
  });
171
+ _defineProperty(this, "setPresenceActivity", activity => {
172
+ this.presenceActivity = activity;
173
+ });
171
174
  /**
172
175
  * @param {InternalError} error The error to handle
173
176
  */
@@ -479,16 +482,14 @@ export class Provider extends Emitter {
479
482
  ...basePayload,
480
483
  selection: data.selection
481
484
  }, shouldTelepointerBeSampled() ? telepointerCallback(this.config.documentAri) : undefined);
482
- } else if ((data === null || data === void 0 ? void 0 : data.type) === 'activity:join' || (data === null || data === void 0 ? void 0 : data.type) === 'activity:ack') {
483
- this.channel.broadcast((data === null || data === void 0 ? void 0 : data.type) === 'activity:join' ? 'participant:activity-join' : 'participant:activity-ack', {
484
- ...basePayload,
485
- activity: data.activity
486
- }, activityCallback());
487
485
  } else if ((data === null || data === void 0 ? void 0 : data.type) === 'ai-provider:change') {
488
486
  this.participantsService.sendAIProviderChanged({
489
487
  ...basePayload,
490
488
  ...data
491
489
  });
490
+ } else if ((data === null || data === void 0 ? void 0 : data.type) === 'participant:activity') {
491
+ this.setPresenceActivity(data.activity);
492
+ this.participantsService.sendPresenceActivityChanged();
492
493
  }
493
494
  } catch (error) {
494
495
  var _this$analyticsHelper14;
@@ -604,21 +605,4 @@ export class Provider extends Emitter {
604
605
  getIsNamespaceLocked() {
605
606
  return this.namespaceService.getIsNamespaceLocked();
606
607
  }
607
- }
608
-
609
- /**
610
- * Callback for handling the broadcast response of participant activity.
611
- * This example assumes a simple logging mechanism. It could be expanded to handle errors or other responses.
612
- *
613
- * @param activity The activity that was broadcast.
614
- * @returns A function that handles the response from the broadcast operation.
615
- */
616
- function activityCallback() {
617
- return error => {
618
- if (error) {
619
- // Log or handle the error. This could involve retrying the broadcast or notifying the user.
620
- logger('Error broadcasting participant activity:', error);
621
- return;
622
- }
623
- };
624
608
  }
@@ -1,5 +1,5 @@
1
1
  export const name = "@atlaskit/collab-provider";
2
- export const version = "10.7.2";
2
+ export const version = "10.8.0";
3
3
  export const nextMajorVersion = () => {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -549,14 +549,6 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
549
549
  timestamp: timestamp
550
550
  }, data));
551
551
  });
552
- this.socket.on('participant:activity-ack', function (_ref7) {
553
- var data = _ref7.data;
554
- _this2.emit('participant:activity-ack', data);
555
- });
556
- this.socket.on('participant:activity-join', function (_ref8) {
557
- var data = _ref8.data;
558
- _this2.emit('participant:activity-join', data);
559
- });
560
552
  this.socket.on('presence:joined', function (data) {
561
553
  _this2.emit('presence:joined', data);
562
554
  });
@@ -566,11 +558,11 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
566
558
  this.socket.on('participant:left', function (data) {
567
559
  _this2.emit('participant:left', data);
568
560
  });
569
- this.socket.on('participant:updated', function (_ref9) {
570
- var sessionId = _ref9.sessionId,
571
- timestamp = _ref9.timestamp,
572
- data = _ref9.data,
573
- clientId = _ref9.clientId;
561
+ this.socket.on('participant:updated', function (_ref7) {
562
+ var sessionId = _ref7.sessionId,
563
+ timestamp = _ref7.timestamp,
564
+ data = _ref7.data,
565
+ clientId = _ref7.clientId;
574
566
  _this2.emit('participant:updated', _objectSpread({
575
567
  sessionId: sessionId,
576
568
  timestamp: timestamp,
@@ -588,7 +580,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
588
580
  // Ignored via go/ees005
589
581
  // eslint-disable-next-line require-await
590
582
  this.socket.on('disconnect', /*#__PURE__*/function () {
591
- var _ref10 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(reason) {
583
+ var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee6(reason) {
592
584
  var _this2$analyticsHelpe, reconnectionError;
593
585
  return _regeneratorRuntime.wrap(function _callee6$(_context6) {
594
586
  while (1) switch (_context6.prev = _context6.next) {
@@ -621,7 +613,7 @@ export var Channel = /*#__PURE__*/function (_Emitter) {
621
613
  }, _callee6);
622
614
  }));
623
615
  return function (_x9) {
624
- return _ref10.apply(this, arguments);
616
+ return _ref8.apply(this, arguments);
625
617
  };
626
618
  }());
627
619
 
@@ -35,6 +35,9 @@ export var ParticipantsService = /*#__PURE__*/function () {
35
35
  var setUserId = arguments.length > 7 ? arguments[7] : undefined;
36
36
  var getAIProviderActiveIds = arguments.length > 8 ? arguments[8] : undefined;
37
37
  _classCallCheck(this, ParticipantsService);
38
+ _defineProperty(this, "sendPresenceActivityChanged", function () {
39
+ _this.sendPresence();
40
+ });
38
41
  _defineProperty(this, "sendAIProviderChanged", function (payload) {
39
42
  if (payload.providerId) {
40
43
  for (var propKey in payload.permit) {
@@ -80,6 +83,9 @@ export var ParticipantsService = /*#__PURE__*/function () {
80
83
  });
81
84
  }
82
85
  });
86
+ _defineProperty(this, "hasPresenceActivityChanged", function (previous, current) {
87
+ return previous.presenceActivity !== current.presenceActivity;
88
+ });
83
89
  /**
84
90
  * Carries out 3 things: 1) enriches the participant with user data, 2) updates the participantsState, 3) emits the presence event
85
91
  * @param payload Payload from incoming socket event
@@ -87,7 +93,7 @@ export var ParticipantsService = /*#__PURE__*/function () {
87
93
  */
88
94
  _defineProperty(this, "onParticipantUpdated", /*#__PURE__*/function () {
89
95
  var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(payload) {
90
- var userId, participant, _this$analyticsHelper, isNewParticipant;
96
+ var userId, participant, _this$analyticsHelper, previousParticipant;
91
97
  return _regeneratorRuntime.wrap(function _callee$(_context) {
92
98
  while (1) switch (_context.prev = _context.next) {
93
99
  case 0:
@@ -120,18 +126,25 @@ export var ParticipantsService = /*#__PURE__*/function () {
120
126
  }
121
127
  return _context.abrupt("return");
122
128
  case 14:
123
- isNewParticipant = _this.participantsState.doesntHave(participant.sessionId);
129
+ previousParticipant = _this.participantsState.getBySessionId(participant.sessionId);
124
130
  _this.participantsState.setBySessionId(participant.sessionId, participant);
125
- if (isNewParticipant) {
126
- _context.next = 18;
131
+ if (!previousParticipant) {
132
+ _context.next = 19;
127
133
  break;
128
134
  }
135
+ if (_this.hasPresenceActivityChanged(previousParticipant, participant)) {
136
+ _this.emitPresenceActivityChange({
137
+ type: 'participant:activity',
138
+ activity: participant.presenceActivity
139
+ }, 'handling participant activity changed event');
140
+ }
129
141
  return _context.abrupt("return");
130
- case 18:
142
+ case 19:
143
+ // Only emit the joined presence event if this is a new participant
131
144
  _this.emitPresence({
132
145
  joined: [participant]
133
146
  }, 'handling participant updated event');
134
- case 19:
147
+ case 20:
135
148
  case "end":
136
149
  return _context.stop();
137
150
  }
@@ -315,32 +328,6 @@ export var ParticipantsService = /*#__PURE__*/function () {
315
328
  (_this$analyticsHelper7 = _this.analyticsHelper) === null || _this$analyticsHelper7 === void 0 || _this$analyticsHelper7.sendErrorEvent(error, 'Error while sending presence');
316
329
  }
317
330
  });
318
- /**
319
- * sending new joiner's activity to existing participants
320
- */
321
- _defineProperty(this, "onParticipantActivityJoin", function (payload) {
322
- try {
323
- logger('New participant joined: ', payload.activity);
324
- _this.emit('activity:join', payload);
325
- } catch (error) {
326
- var _this$analyticsHelper8;
327
- // We don't want to throw errors for Presence features as they tend to self-restore
328
- (_this$analyticsHelper8 = _this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 || _this$analyticsHelper8.sendErrorEvent(error, "Error while sending 'activity:join'");
329
- }
330
- });
331
- /**
332
- * respond to new joiner with existing participant's activity
333
- */
334
- _defineProperty(this, "onParticipantActivityAck", function (payload) {
335
- try {
336
- logger('Existing participants ack: ', payload.activity);
337
- _this.emit('activity:ack', payload);
338
- } catch (error) {
339
- var _this$analyticsHelper9;
340
- // We don't want to throw errors for Presence features as they tend to self-restore
341
- (_this$analyticsHelper9 = _this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 || _this$analyticsHelper9.sendErrorEvent(error, "Error while sending 'activity:ack'");
342
- }
343
- });
344
331
  /**
345
332
  * Called when a participant joins the session.
346
333
  *
@@ -354,9 +341,9 @@ export var ParticipantsService = /*#__PURE__*/function () {
354
341
  // This expose existing users to the newly joined user
355
342
  _this.sendPresence();
356
343
  } catch (error) {
357
- var _this$analyticsHelper10;
344
+ var _this$analyticsHelper8;
358
345
  // We don't want to throw errors for Presence features as they tend to self-restore
359
- (_this$analyticsHelper10 = _this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 || _this$analyticsHelper10.sendErrorEvent(error, 'Error while joining presence');
346
+ (_this$analyticsHelper8 = _this.analyticsHelper) === null || _this$analyticsHelper8 === void 0 || _this$analyticsHelper8.sendErrorEvent(error, 'Error while joining presence');
360
347
  }
361
348
  });
362
349
  /**
@@ -374,9 +361,9 @@ export var ParticipantsService = /*#__PURE__*/function () {
374
361
  _this.sendPresence();
375
362
  _this.sendPresenceJoined();
376
363
  } catch (error) {
377
- var _this$analyticsHelper11;
364
+ var _this$analyticsHelper9;
378
365
  // We don't want to throw errors for Presence features as they tend to self-restore
379
- (_this$analyticsHelper11 = _this.analyticsHelper) === null || _this$analyticsHelper11 === void 0 || _this$analyticsHelper11.sendErrorEvent(error, 'Error while receiving presence');
366
+ (_this$analyticsHelper9 = _this.analyticsHelper) === null || _this$analyticsHelper9 === void 0 || _this$analyticsHelper9.sendErrorEvent(error, 'Error while receiving presence');
380
367
  }
381
368
  });
382
369
  /**
@@ -417,5 +404,22 @@ export var ParticipantsService = /*#__PURE__*/function () {
417
404
  }
418
405
  });
419
406
  }
407
+ }, {
408
+ key: "emitPresenceActivityChange",
409
+ value:
410
+ /**
411
+ * Wrapper function to emit with error handling and analytics
412
+ * @param data Data to emit
413
+ * @param errorMessage Error message for analytics
414
+ */
415
+ function emitPresenceActivityChange(data, errorMessage) {
416
+ try {
417
+ this.emit('presence:changed', data);
418
+ } catch (error) {
419
+ var _this$analyticsHelper10;
420
+ // We don't want to throw errors for Presence features as they tend to self-restore
421
+ (_this$analyticsHelper10 = this.analyticsHelper) === null || _this$analyticsHelper10 === void 0 || _this$analyticsHelper10.sendErrorEvent(error, "Error while ".concat(errorMessage));
422
+ }
423
+ }
420
424
  }]);
421
425
  }();
@@ -9,7 +9,7 @@ import { NCS_ERROR_CODE } from '../errors/ncs-errors';
9
9
  import { createLogger } from '../helpers/utils';
10
10
  var logger = createLogger('commit-step', 'black');
11
11
  export var readyToCommit = true;
12
- export var RESET_READYTOCOMMIT_INTERVAL_MS = 5000;
12
+ export var RESET_READYTOCOMMIT_INTERVAL_MS = 20000;
13
13
  export var commitStepQueue = function commitStepQueue(_ref) {
14
14
  var broadcast = _ref.broadcast,
15
15
  steps = _ref.steps,
@@ -156,7 +156,7 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
156
156
  _this.emit('permission', permit);
157
157
  }).on('steps:added', _this.documentService.onStepsAdded).on('metadata:changed', _this.metadataService.onMetadataChanged).on('participant:telepointer', function (payload) {
158
158
  return _this.participantsService.onParticipantTelepointer(payload, _this.sessionId);
159
- }).on('participant:activity-join', _this.participantsService.onParticipantActivityJoin).on('participant:activity-ack', _this.participantsService.onParticipantActivityAck).on('presence:joined', _this.participantsService.onPresenceJoined).on('presence', _this.participantsService.onPresence).on('participant:left', _this.participantsService.onParticipantLeft).on('participant:updated', _this.participantsService.onParticipantUpdated).on('disconnect', _this.onDisconnected.bind(_this)).on('error', _this.onErrorHandled).on('status', /*#__PURE__*/function () {
159
+ }).on('presence:joined', _this.participantsService.onPresenceJoined).on('presence', _this.participantsService.onPresence).on('participant:left', _this.participantsService.onParticipantLeft).on('participant:updated', _this.participantsService.onParticipantUpdated).on('disconnect', _this.onDisconnected.bind(_this)).on('error', _this.onErrorHandled).on('status', /*#__PURE__*/function () {
160
160
  var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(status) {
161
161
  var isLocked;
162
162
  return _regeneratorRuntime.wrap(function _callee$(_context) {
@@ -199,6 +199,9 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
199
199
  presenceActivity: _this.presenceActivity
200
200
  };
201
201
  });
202
+ _defineProperty(_this, "setPresenceActivity", function (activity) {
203
+ _this.presenceActivity = activity;
204
+ });
202
205
  /**
203
206
  * @param {InternalError} error The error to handle
204
207
  */
@@ -548,12 +551,11 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
548
551
  this.channel.broadcast('participant:telepointer', _objectSpread(_objectSpread({}, basePayload), {}, {
549
552
  selection: data.selection
550
553
  }), shouldTelepointerBeSampled() ? telepointerCallback(this.config.documentAri) : undefined);
551
- } else if ((data === null || data === void 0 ? void 0 : data.type) === 'activity:join' || (data === null || data === void 0 ? void 0 : data.type) === 'activity:ack') {
552
- this.channel.broadcast((data === null || data === void 0 ? void 0 : data.type) === 'activity:join' ? 'participant:activity-join' : 'participant:activity-ack', _objectSpread(_objectSpread({}, basePayload), {}, {
553
- activity: data.activity
554
- }), activityCallback());
555
554
  } else if ((data === null || data === void 0 ? void 0 : data.type) === 'ai-provider:change') {
556
555
  this.participantsService.sendAIProviderChanged(_objectSpread(_objectSpread({}, basePayload), data));
556
+ } else if ((data === null || data === void 0 ? void 0 : data.type) === 'participant:activity') {
557
+ this.setPresenceActivity(data.activity);
558
+ this.participantsService.sendPresenceActivityChanged();
557
559
  }
558
560
  } catch (error) {
559
561
  var _this$analyticsHelper12;
@@ -689,21 +691,4 @@ export var Provider = /*#__PURE__*/function (_Emitter) {
689
691
  return this.namespaceService.getIsNamespaceLocked();
690
692
  }
691
693
  }]);
692
- }(Emitter);
693
-
694
- /**
695
- * Callback for handling the broadcast response of participant activity.
696
- * This example assumes a simple logging mechanism. It could be expanded to handle errors or other responses.
697
- *
698
- * @param activity The activity that was broadcast.
699
- * @returns A function that handles the response from the broadcast operation.
700
- */
701
- function activityCallback() {
702
- return function (error) {
703
- if (error) {
704
- // Log or handle the error. This could involve retrying the broadcast or notifying the user.
705
- logger('Error broadcasting participant activity:', error);
706
- return;
707
- }
708
- };
709
- }
694
+ }(Emitter);
@@ -1,5 +1,5 @@
1
1
  export var name = "@atlaskit/collab-provider";
2
- export var version = "10.7.2";
2
+ export var version = "10.8.0";
3
3
  export var nextMajorVersion = function nextMajorVersion() {
4
4
  return [Number(version.split('.')[0]) + 1, 0, 0].join('.');
5
5
  };
@@ -1,4 +1,4 @@
1
1
  export { Provider } from './provider';
2
2
  export type { CollabEventDisconnectedData, Socket } from './types';
3
- export type { NewCollabSyncUpErrorAttributes, ResolvedEditorState, CollabMetadataPayload, CollabEventInitData, CollabInitPayload, CollabEventConnectionData, CollabConnectedPayload, CollabDisconnectedPayload, CollabDataPayload, CollabActivityData, CollabTelepointerPayload, CollabPresencePayload, CollabLocalStepsPayload, CollabPermissionEventPayload, CollabEventRemoteData, CollabEventPresenceData, CollabActivityJoinPayload, CollabActivityAckPayload, CollabEventConnectingData, CollabEventTelepointerData, CollabSendableSelection, CollabParticipant, CollabEvents, SyncUpErrorFunction, CollabEditProvider, ProviderError, ProviderParticipant, CollabEventLocalStepData, UserPermitType, CollabNamespaceLockCheckPayload, } from '@atlaskit/editor-common/collab';
3
+ export type { NewCollabSyncUpErrorAttributes, ResolvedEditorState, CollabMetadataPayload, CollabEventInitData, CollabInitPayload, CollabEventConnectionData, CollabConnectedPayload, CollabDisconnectedPayload, CollabDataPayload, CollabTelepointerPayload, CollabPresencePayload, CollabPresenceActivityChangePayload, CollabLocalStepsPayload, CollabPermissionEventPayload, CollabEventRemoteData, CollabEventPresenceData, CollabEventConnectingData, CollabEventTelepointerData, CollabSendableSelection, CollabParticipant, CollabEvents, SyncUpErrorFunction, CollabEditProvider, ProviderError, ProviderParticipant, CollabEventLocalStepData, UserPermitType, CollabNamespaceLockCheckPayload, } from '@atlaskit/editor-common/collab';
4
4
  export { PROVIDER_ERROR_CODE } from '@atlaskit/editor-common/collab';
@@ -1,6 +1,6 @@
1
1
  import type AnalyticsHelper from '../analytics/analytics-helper';
2
- import type { CollabEventDisconnectedData, ChannelEvent, PresenceData, PresencePayload, TelepointerPayload, ActivityPayload } from '../types';
3
- import type { CollabActivityData, CollabEventPresenceData, CollabTelepointerPayload, ProviderParticipant, StepJson, UserPermitType } from '@atlaskit/editor-common/collab';
2
+ import type { CollabEventDisconnectedData, ChannelEvent, PresenceData, PresencePayload, TelepointerPayload } from '../types';
3
+ import type { CollabEventPresenceData, CollabTelepointerPayload, CollabPresenceActivityChangePayload, ProviderParticipant, StepJson, UserPermitType } from '@atlaskit/editor-common/collab';
4
4
  import type { GetUserType } from './participants-helper';
5
5
  import { ParticipantsState } from './participants-state';
6
6
  /**
@@ -24,7 +24,8 @@ export declare class ParticipantsService {
24
24
  private getAIProviderActiveIds?;
25
25
  private participantUpdateTimeout;
26
26
  private presenceUpdateTimeout;
27
- constructor(analyticsHelper: AnalyticsHelper | undefined, participantsState: ParticipantsState, emit: (evt: 'presence' | 'telepointer' | 'disconnected' | 'activity:join' | 'activity:ack', data: CollabEventPresenceData | CollabTelepointerPayload | CollabEventDisconnectedData | CollabActivityData) => void, getUser: GetUserType, channelBroadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, sendPresenceJoined: () => void, getPresenceData: () => PresenceData, setUserId: (id: string) => void, getAIProviderActiveIds?: (() => string[]) | undefined);
27
+ constructor(analyticsHelper: AnalyticsHelper | undefined, participantsState: ParticipantsState, emit: (evt: 'presence' | 'telepointer' | 'disconnected' | 'presence:changed', data: CollabEventPresenceData | CollabTelepointerPayload | CollabEventDisconnectedData | CollabPresenceActivityChangePayload) => void, getUser: GetUserType, channelBroadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, sendPresenceJoined: () => void, getPresenceData: () => PresenceData, setUserId: (id: string) => void, getAIProviderActiveIds?: (() => string[]) | undefined);
28
+ sendPresenceActivityChanged: () => void;
28
29
  sendAIProviderChanged: (payload: {
29
30
  userId: string;
30
31
  sessionId: string;
@@ -37,6 +38,7 @@ export declare class ParticipantsService {
37
38
  private sendAIProviderParticipantUpdated;
38
39
  private sendAIProviderParticipantLeft;
39
40
  private sendAIProvidersPresence;
41
+ private hasPresenceActivityChanged;
40
42
  /**
41
43
  * Carries out 3 things: 1) enriches the participant with user data, 2) updates the participantsState, 3) emits the presence event
42
44
  * @param payload Payload from incoming socket event
@@ -86,19 +88,17 @@ export declare class ParticipantsService {
86
88
  * @param emit Emit function from Provider
87
89
  */
88
90
  private emitTelepointer;
91
+ /**
92
+ * Wrapper function to emit with error handling and analytics
93
+ * @param data Data to emit
94
+ * @param errorMessage Error message for analytics
95
+ */
96
+ private emitPresenceActivityChange;
89
97
  /**
90
98
  * Used when the provider is disconnected or destroyed to prevent perpetual timers from continuously running
91
99
  */
92
100
  clearTimers: () => void;
93
101
  private sendPresence;
94
- /**
95
- * sending new joiner's activity to existing participants
96
- */
97
- onParticipantActivityJoin: (payload: ActivityPayload) => void;
98
- /**
99
- * respond to new joiner with existing participant's activity
100
- */
101
- onParticipantActivityAck: (payload: ActivityPayload) => void;
102
102
  /**
103
103
  * Called when a participant joins the session.
104
104
  *
@@ -4,7 +4,7 @@ import type { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/trans
4
4
  import type AnalyticsHelper from '../analytics/analytics-helper';
5
5
  import type { InternalError } from '../errors/internal-errors';
6
6
  export declare let readyToCommit: boolean;
7
- export declare const RESET_READYTOCOMMIT_INTERVAL_MS = 5000;
7
+ export declare const RESET_READYTOCOMMIT_INTERVAL_MS = 20000;
8
8
  export declare const commitStepQueue: ({ broadcast, steps, version, userId, clientId, onStepsAdded, onErrorHandled, analyticsHelper, emit, __livePage, hasRecovered, collabMode, forcePublish, }: {
9
9
  broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void;
10
10
  steps: readonly ProseMirrorStep[];
@@ -2,7 +2,7 @@ import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/stat
2
2
  import type { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
3
3
  import { Emitter } from '../emitter';
4
4
  import type { Config } from '../types';
5
- import type { CollabEditProvider, CollabEvents, CollabTelepointerPayload, ResolvedEditorState, Metadata, SyncUpErrorFunction, CollabActivityJoinPayload, CollabActivityAckPayload, CollabActivityAIProviderChangedPayload, PresenceActivity } from '@atlaskit/editor-common/collab';
5
+ import type { CollabEditProvider, CollabEvents, CollabTelepointerPayload, ResolvedEditorState, Metadata, SyncUpErrorFunction, CollabPresenceActivityChangePayload, CollabActivityAIProviderChangedPayload, PresenceActivity } from '@atlaskit/editor-common/collab';
6
6
  import { Api } from '../api/api';
7
7
  import { NullApi } from '../api/null-api';
8
8
  export declare const MAX_STEP_REJECTED_ERROR = 15;
@@ -49,6 +49,7 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
49
49
  private initializeChannel;
50
50
  private setUserId;
51
51
  private getPresenceData;
52
+ private setPresenceActivity;
52
53
  /**
53
54
  * Initialisation logic, called by Jira with a dummy getState function, deprecated in favour of the setup method which allows more configuration
54
55
  * @param {Function} getState Function that returns the editor state, used to retrieve collab-edit properties and to interact with prosemirror-collab
@@ -95,7 +96,7 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
95
96
  * @param {CollabSendableSelection} data.selection Object representing the selected element
96
97
  * @param {string} data.sessionId Identifier identifying the session
97
98
  */
98
- sendMessage(data: CollabTelepointerPayload | CollabActivityJoinPayload | CollabActivityAckPayload | CollabActivityAIProviderChangedPayload): void;
99
+ sendMessage(data: CollabTelepointerPayload | CollabActivityAIProviderChangedPayload | CollabPresenceActivityChangePayload): void;
99
100
  setAIProviderActiveIds(ids?: string[]): void;
100
101
  private getAIProviderActiveIds;
101
102
  private onDisconnected;
@@ -4,7 +4,7 @@ import type { InternalError } from './errors/internal-errors';
4
4
  import type { JSONDocNode } from '@atlaskit/editor-json-transformer';
5
5
  import type { GetUserType } from './participants/participants-helper';
6
6
  import type AnalyticsHelper from './analytics/analytics-helper';
7
- import type { StepJson, CollabSendableSelection, Metadata, UserPermitType, Activity, PresenceActivity } from '@atlaskit/editor-common/collab';
7
+ import type { StepJson, CollabSendableSelection, Metadata, UserPermitType, PresenceActivity } from '@atlaskit/editor-common/collab';
8
8
  import { type CatchupEventReason } from './helpers/const';
9
9
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
10
10
  export interface CollabEventDisconnectedData {
@@ -123,7 +123,7 @@ export type InitPayload = {
123
123
  export type BroadcastIncomingPayload = {
124
124
  sessionId?: string;
125
125
  timestamp?: number;
126
- data: PresencePayload | TelepointerPayload | StepsPayload | ActivityPayload | any;
126
+ data: PresencePayload | TelepointerPayload | StepsPayload | any;
127
127
  };
128
128
  export type PresenceData = {
129
129
  sessionId: string;
@@ -137,11 +137,6 @@ export type PresencePayload = PresenceData & {
137
137
  timestamp: number;
138
138
  data?: Record<string, any>;
139
139
  };
140
- export type ActivityPayload = {
141
- userId: string | undefined;
142
- activity: Activity;
143
- sessionId: string;
144
- };
145
140
  export type TelepointerPayload = PresencePayload & {
146
141
  selection: CollabSendableSelection;
147
142
  };
@@ -182,8 +177,6 @@ export type ChannelEvent = {
182
177
  'presence:joined': PresencePayload;
183
178
  presence: PresencePayload;
184
179
  'participant:left': PresencePayload;
185
- 'participant:activity-join': ActivityPayload;
186
- 'participant:activity-ack': ActivityPayload;
187
180
  'participant:telepointer': TelepointerPayload;
188
181
  'participant:updated': PresencePayload;
189
182
  'steps:commit': StepsPayload & {
@@ -1,4 +1,4 @@
1
1
  export { Provider } from './provider';
2
2
  export type { CollabEventDisconnectedData, Socket } from './types';
3
- export type { NewCollabSyncUpErrorAttributes, ResolvedEditorState, CollabMetadataPayload, CollabEventInitData, CollabInitPayload, CollabEventConnectionData, CollabConnectedPayload, CollabDisconnectedPayload, CollabDataPayload, CollabActivityData, CollabTelepointerPayload, CollabPresencePayload, CollabLocalStepsPayload, CollabPermissionEventPayload, CollabEventRemoteData, CollabEventPresenceData, CollabActivityJoinPayload, CollabActivityAckPayload, CollabEventConnectingData, CollabEventTelepointerData, CollabSendableSelection, CollabParticipant, CollabEvents, SyncUpErrorFunction, CollabEditProvider, ProviderError, ProviderParticipant, CollabEventLocalStepData, UserPermitType, CollabNamespaceLockCheckPayload, } from '@atlaskit/editor-common/collab';
3
+ export type { NewCollabSyncUpErrorAttributes, ResolvedEditorState, CollabMetadataPayload, CollabEventInitData, CollabInitPayload, CollabEventConnectionData, CollabConnectedPayload, CollabDisconnectedPayload, CollabDataPayload, CollabTelepointerPayload, CollabPresencePayload, CollabPresenceActivityChangePayload, CollabLocalStepsPayload, CollabPermissionEventPayload, CollabEventRemoteData, CollabEventPresenceData, CollabEventConnectingData, CollabEventTelepointerData, CollabSendableSelection, CollabParticipant, CollabEvents, SyncUpErrorFunction, CollabEditProvider, ProviderError, ProviderParticipant, CollabEventLocalStepData, UserPermitType, CollabNamespaceLockCheckPayload, } from '@atlaskit/editor-common/collab';
4
4
  export { PROVIDER_ERROR_CODE } from '@atlaskit/editor-common/collab';
@@ -1,6 +1,6 @@
1
1
  import type AnalyticsHelper from '../analytics/analytics-helper';
2
- import type { CollabEventDisconnectedData, ChannelEvent, PresenceData, PresencePayload, TelepointerPayload, ActivityPayload } from '../types';
3
- import type { CollabActivityData, CollabEventPresenceData, CollabTelepointerPayload, ProviderParticipant, StepJson, UserPermitType } from '@atlaskit/editor-common/collab';
2
+ import type { CollabEventDisconnectedData, ChannelEvent, PresenceData, PresencePayload, TelepointerPayload } from '../types';
3
+ import type { CollabEventPresenceData, CollabTelepointerPayload, CollabPresenceActivityChangePayload, ProviderParticipant, StepJson, UserPermitType } from '@atlaskit/editor-common/collab';
4
4
  import type { GetUserType } from './participants-helper';
5
5
  import { ParticipantsState } from './participants-state';
6
6
  /**
@@ -24,7 +24,8 @@ export declare class ParticipantsService {
24
24
  private getAIProviderActiveIds?;
25
25
  private participantUpdateTimeout;
26
26
  private presenceUpdateTimeout;
27
- constructor(analyticsHelper: AnalyticsHelper | undefined, participantsState: ParticipantsState, emit: (evt: 'presence' | 'telepointer' | 'disconnected' | 'activity:join' | 'activity:ack', data: CollabEventPresenceData | CollabTelepointerPayload | CollabEventDisconnectedData | CollabActivityData) => void, getUser: GetUserType, channelBroadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, sendPresenceJoined: () => void, getPresenceData: () => PresenceData, setUserId: (id: string) => void, getAIProviderActiveIds?: (() => string[]) | undefined);
27
+ constructor(analyticsHelper: AnalyticsHelper | undefined, participantsState: ParticipantsState, emit: (evt: 'presence' | 'telepointer' | 'disconnected' | 'presence:changed', data: CollabEventPresenceData | CollabTelepointerPayload | CollabEventDisconnectedData | CollabPresenceActivityChangePayload) => void, getUser: GetUserType, channelBroadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void, sendPresenceJoined: () => void, getPresenceData: () => PresenceData, setUserId: (id: string) => void, getAIProviderActiveIds?: (() => string[]) | undefined);
28
+ sendPresenceActivityChanged: () => void;
28
29
  sendAIProviderChanged: (payload: {
29
30
  userId: string;
30
31
  sessionId: string;
@@ -37,6 +38,7 @@ export declare class ParticipantsService {
37
38
  private sendAIProviderParticipantUpdated;
38
39
  private sendAIProviderParticipantLeft;
39
40
  private sendAIProvidersPresence;
41
+ private hasPresenceActivityChanged;
40
42
  /**
41
43
  * Carries out 3 things: 1) enriches the participant with user data, 2) updates the participantsState, 3) emits the presence event
42
44
  * @param payload Payload from incoming socket event
@@ -86,19 +88,17 @@ export declare class ParticipantsService {
86
88
  * @param emit Emit function from Provider
87
89
  */
88
90
  private emitTelepointer;
91
+ /**
92
+ * Wrapper function to emit with error handling and analytics
93
+ * @param data Data to emit
94
+ * @param errorMessage Error message for analytics
95
+ */
96
+ private emitPresenceActivityChange;
89
97
  /**
90
98
  * Used when the provider is disconnected or destroyed to prevent perpetual timers from continuously running
91
99
  */
92
100
  clearTimers: () => void;
93
101
  private sendPresence;
94
- /**
95
- * sending new joiner's activity to existing participants
96
- */
97
- onParticipantActivityJoin: (payload: ActivityPayload) => void;
98
- /**
99
- * respond to new joiner with existing participant's activity
100
- */
101
- onParticipantActivityAck: (payload: ActivityPayload) => void;
102
102
  /**
103
103
  * Called when a participant joins the session.
104
104
  *
@@ -4,7 +4,7 @@ import type { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/trans
4
4
  import type AnalyticsHelper from '../analytics/analytics-helper';
5
5
  import type { InternalError } from '../errors/internal-errors';
6
6
  export declare let readyToCommit: boolean;
7
- export declare const RESET_READYTOCOMMIT_INTERVAL_MS = 5000;
7
+ export declare const RESET_READYTOCOMMIT_INTERVAL_MS = 20000;
8
8
  export declare const commitStepQueue: ({ broadcast, steps, version, userId, clientId, onStepsAdded, onErrorHandled, analyticsHelper, emit, __livePage, hasRecovered, collabMode, forcePublish, }: {
9
9
  broadcast: <K extends keyof ChannelEvent>(type: K, data: Omit<ChannelEvent[K], 'timestamp'>, callback?: Function) => void;
10
10
  steps: readonly ProseMirrorStep[];
@@ -2,7 +2,7 @@ import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/stat
2
2
  import type { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
3
3
  import { Emitter } from '../emitter';
4
4
  import type { Config } from '../types';
5
- import type { CollabEditProvider, CollabEvents, CollabTelepointerPayload, ResolvedEditorState, Metadata, SyncUpErrorFunction, CollabActivityJoinPayload, CollabActivityAckPayload, CollabActivityAIProviderChangedPayload, PresenceActivity } from '@atlaskit/editor-common/collab';
5
+ import type { CollabEditProvider, CollabEvents, CollabTelepointerPayload, ResolvedEditorState, Metadata, SyncUpErrorFunction, CollabPresenceActivityChangePayload, CollabActivityAIProviderChangedPayload, PresenceActivity } from '@atlaskit/editor-common/collab';
6
6
  import { Api } from '../api/api';
7
7
  import { NullApi } from '../api/null-api';
8
8
  export declare const MAX_STEP_REJECTED_ERROR = 15;
@@ -49,6 +49,7 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
49
49
  private initializeChannel;
50
50
  private setUserId;
51
51
  private getPresenceData;
52
+ private setPresenceActivity;
52
53
  /**
53
54
  * Initialisation logic, called by Jira with a dummy getState function, deprecated in favour of the setup method which allows more configuration
54
55
  * @param {Function} getState Function that returns the editor state, used to retrieve collab-edit properties and to interact with prosemirror-collab
@@ -95,7 +96,7 @@ export declare class Provider extends Emitter<CollabEvents> implements BaseEvent
95
96
  * @param {CollabSendableSelection} data.selection Object representing the selected element
96
97
  * @param {string} data.sessionId Identifier identifying the session
97
98
  */
98
- sendMessage(data: CollabTelepointerPayload | CollabActivityJoinPayload | CollabActivityAckPayload | CollabActivityAIProviderChangedPayload): void;
99
+ sendMessage(data: CollabTelepointerPayload | CollabActivityAIProviderChangedPayload | CollabPresenceActivityChangePayload): void;
99
100
  setAIProviderActiveIds(ids?: string[]): void;
100
101
  private getAIProviderActiveIds;
101
102
  private onDisconnected;
@@ -4,7 +4,7 @@ import type { InternalError } from './errors/internal-errors';
4
4
  import type { JSONDocNode } from '@atlaskit/editor-json-transformer';
5
5
  import type { GetUserType } from './participants/participants-helper';
6
6
  import type AnalyticsHelper from './analytics/analytics-helper';
7
- import type { StepJson, CollabSendableSelection, Metadata, UserPermitType, Activity, PresenceActivity } from '@atlaskit/editor-common/collab';
7
+ import type { StepJson, CollabSendableSelection, Metadata, UserPermitType, PresenceActivity } from '@atlaskit/editor-common/collab';
8
8
  import { type CatchupEventReason } from './helpers/const';
9
9
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
10
10
  export interface CollabEventDisconnectedData {
@@ -123,7 +123,7 @@ export type InitPayload = {
123
123
  export type BroadcastIncomingPayload = {
124
124
  sessionId?: string;
125
125
  timestamp?: number;
126
- data: PresencePayload | TelepointerPayload | StepsPayload | ActivityPayload | any;
126
+ data: PresencePayload | TelepointerPayload | StepsPayload | any;
127
127
  };
128
128
  export type PresenceData = {
129
129
  sessionId: string;
@@ -137,11 +137,6 @@ export type PresencePayload = PresenceData & {
137
137
  timestamp: number;
138
138
  data?: Record<string, any>;
139
139
  };
140
- export type ActivityPayload = {
141
- userId: string | undefined;
142
- activity: Activity;
143
- sessionId: string;
144
- };
145
140
  export type TelepointerPayload = PresencePayload & {
146
141
  selection: CollabSendableSelection;
147
142
  };
@@ -182,8 +177,6 @@ export type ChannelEvent = {
182
177
  'presence:joined': PresencePayload;
183
178
  presence: PresencePayload;
184
179
  'participant:left': PresencePayload;
185
- 'participant:activity-join': ActivityPayload;
186
- 'participant:activity-ack': ActivityPayload;
187
180
  'participant:telepointer': TelepointerPayload;
188
181
  'participant:updated': PresencePayload;
189
182
  'steps:commit': StepsPayload & {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/collab-provider",
3
- "version": "10.7.2",
3
+ "version": "10.8.0",
4
4
  "description": "A provider for collaborative editing.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/"
@@ -35,13 +35,13 @@
35
35
  "@atlaskit/adf-utils": "^19.18.0",
36
36
  "@atlaskit/analytics-gas-types": "^5.1.0",
37
37
  "@atlaskit/analytics-listeners": "^9.0.0",
38
- "@atlaskit/editor-common": "^100.0.0",
38
+ "@atlaskit/editor-common": "^100.4.0",
39
39
  "@atlaskit/editor-json-transformer": "^8.23.0",
40
40
  "@atlaskit/editor-prosemirror": "7.0.0",
41
- "@atlaskit/feature-gate-js-client": "^4.25.0",
41
+ "@atlaskit/feature-gate-js-client": "^4.26.0",
42
42
  "@atlaskit/platform-feature-flags": "^1.1.0",
43
43
  "@atlaskit/prosemirror-collab": "^0.14.0",
44
- "@atlaskit/react-ufo": "^3.0.0",
44
+ "@atlaskit/react-ufo": "^3.1.0",
45
45
  "@atlaskit/ufo": "^0.4.0",
46
46
  "@atlaskit/util-service-support": "^6.2.0",
47
47
  "@babel/runtime": "^7.0.0",