@atlaskit/editor-synced-block-provider 8.5.7 → 8.6.1

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,29 @@
1
1
  # @atlaskit/editor-synced-block-provider
2
2
 
3
+ ## 8.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`f543995529d9d`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/f543995529d9d) -
8
+ [ux] Synced blocks now recover automatically from realtime connection drops that happen while a
9
+ tab is hidden or the network is offline. Instead of showing a fetch error when reconnection
10
+ attempts are exhausted in the background, the block silently re-arms and reconnects when the tab
11
+ becomes visible again or the network comes back online.
12
+ - Updated dependencies
13
+
14
+ ## 8.6.0
15
+
16
+ ### Minor Changes
17
+
18
+ - [`c0b0b98789f7a`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/c0b0b98789f7a) -
19
+ Add analytics for synced block source creation: record the creation input method and whether the
20
+ block was created empty, and emit a one-off event the first time an empty source block gains
21
+ content.
22
+
23
+ ### Patch Changes
24
+
25
+ - Updated dependencies
26
+
3
27
  ## 8.5.7
4
28
 
5
29
  ### Patch Changes
@@ -1020,7 +1020,7 @@ var ReferenceSyncBlockStoreManager = exports.ReferenceSyncBlockStoreManager = /*
1020
1020
  _context4.next = 1;
1021
1021
  break;
1022
1022
  }
1023
- return _context4.abrupt("return", (0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_2'));
1023
+ return _context4.abrupt("return", true);
1024
1024
  case 1:
1025
1025
  if (this.isCacheDirty) {
1026
1026
  _context4.next = 2;
@@ -59,6 +59,20 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
59
59
  * multiple blocks are created concurrently. See EDITOR-7112.
60
60
  */
61
61
  (0, _defineProperty2.default)(this, "creationsTimedOutDuringFlush", new Set());
62
+ /**
63
+ * Creation-type signals captured at `createBodiedSyncBlockNode` time and read
64
+ * back in `commitPendingCreation` to enrich the `syncedBlockCreate` event.
65
+ * Kept out of the flushed cache record so it never leaks into Block Service /
66
+ * ADF; removed once consumed.
67
+ */
68
+ (0, _defineProperty2.default)(this, "creationEnrichment", new Map());
69
+ /**
70
+ * Resource IDs of blocks created empty this session that have not yet fired
71
+ * the first-content-added event. Added on empty creation, removed when the
72
+ * block first gains content (the event fires once). Blocks created with
73
+ * content or not created this session are never tracked.
74
+ */
75
+ (0, _defineProperty2.default)(this, "awaitingFirstContent", new Set());
62
76
  /**
63
77
  * resourceId -> timestamp (ms) of the last `syncedBlockDelete` emission, used
64
78
  * to suppress duplicates within {@link DELETE_DEDUPE_WINDOW_MS}. Only consulted
@@ -411,17 +425,48 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
411
425
  var _this$fireAnalyticsEv4;
412
426
  var sourceProduct = (0, _utils.getSourceProductFromResourceIdSafe)(resourceId);
413
427
  (_this$fireAnalyticsEv4 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv4 === void 0 || _this$fireAnalyticsEv4.call(this, (0, _errorHandling.createSuccessPayload)(resourceId || '', sourceProduct));
414
- // Operational create-success event with the join key.
428
+ // Operational create-success event with the join key + creation-type
429
+ // signals (inputMethod / createdEmpty) captured at the command layer.
415
430
  if ((0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_4')) {
416
431
  var _this$fireAnalyticsEv5, _this$syncBlockCache$;
417
- (_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 || _this$fireAnalyticsEv5.call(this, (0, _errorHandling.createSuccessOperationalPayload)(resourceId || '', (_this$syncBlockCache$ = this.syncBlockCache.get(resourceId)) === null || _this$syncBlockCache$ === void 0 ? void 0 : _this$syncBlockCache$.blockInstanceId, sourceProduct));
432
+ (_this$fireAnalyticsEv5 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv5 === void 0 || _this$fireAnalyticsEv5.call(this, (0, _errorHandling.createSuccessOperationalPayload)(resourceId || '', (_this$syncBlockCache$ = this.syncBlockCache.get(resourceId)) === null || _this$syncBlockCache$ === void 0 ? void 0 : _this$syncBlockCache$.blockInstanceId, sourceProduct, this.creationEnrichment.get(resourceId)));
418
433
  }
419
434
  } else {
420
435
  var _this$fireAnalyticsEv6;
421
436
  // Delete the node from cache if fail to create so it's not flushed to BE
422
437
  this.syncBlockCache.delete(resourceId || '');
438
+ // Creation failed, so there is no block to add content to — drop the
439
+ // first-content tracking entry so a later unrelated edit cannot fire it.
440
+ this.awaitingFirstContent.delete(resourceId || '');
423
441
  (_this$fireAnalyticsEv6 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv6 === void 0 || _this$fireAnalyticsEv6.call(this, (0, _errorHandling.createErrorPayload)('Fail to create bodied sync block', resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
424
442
  }
443
+ // Enrichment is single-use — drop it once the create has resolved either way.
444
+ this.creationEnrichment.delete(resourceId || '');
445
+ }
446
+
447
+ /**
448
+ * Fire the first-content-added event once when a block created empty this
449
+ * session first gains content. The caller detects the in-block edit; this owns
450
+ * dedupe + emission (fires at most once per block, only for empty→content).
451
+ * Gated behind `platform_editor_blocks_patch_4`.
452
+ */
453
+ }, {
454
+ key: "maybeEmitFirstContentAdded",
455
+ value: function maybeEmitFirstContentAdded(resourceId, blockInstanceId) {
456
+ var _this$fireAnalyticsEv7;
457
+ if (this.viewMode === 'view') {
458
+ return;
459
+ }
460
+ if (!(0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_4')) {
461
+ return;
462
+ }
463
+ // `delete` returns false when the id was not tracked (already emitted, or
464
+ // the block was not created empty this session), so this both dedupes and
465
+ // scopes emission to genuine first-content transitions in one check.
466
+ if (!this.awaitingFirstContent.delete(resourceId)) {
467
+ return;
468
+ }
469
+ (_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 || _this$fireAnalyticsEv7.call(this, (0, _errorHandling.addContentSuccessPayload)(resourceId, blockInstanceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
425
470
  }
426
471
  }, {
427
472
  key: "registerConfirmationCallback",
@@ -461,16 +506,28 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
461
506
  * @param attrs attributes Ids of the node
462
507
  * @param node the ProseMirror node to cache
463
508
  * @param onCompletion callback invoked when creation completes
509
+ * @param enrichment optional creation-type signals stashed and attached to the
510
+ * `syncedBlockCreate` event when the async create resolves. When
511
+ * `createdEmpty` is true the block is also registered for the
512
+ * first-content-added event.
464
513
  */
465
514
  }, {
466
515
  key: "createBodiedSyncBlockNode",
467
- value: function createBodiedSyncBlockNode(attrs, node, onCompletion) {
516
+ value: function createBodiedSyncBlockNode(attrs, node, onCompletion, enrichment) {
468
517
  var _this4 = this;
469
518
  if (this.viewMode === 'view') {
470
519
  return;
471
520
  }
472
521
  var resourceId = attrs.resourceId,
473
522
  blockInstanceId = attrs.localId;
523
+ // Stash creation-type signals for commitPendingCreation to read.
524
+ if (enrichment) {
525
+ this.creationEnrichment.set(resourceId, enrichment);
526
+ // Only empty-created blocks can produce an empty→content transition.
527
+ if (enrichment.createdEmpty) {
528
+ this.awaitingFirstContent.add(resourceId);
529
+ }
530
+ }
474
531
  try {
475
532
  var _this$createExperienc;
476
533
  if (!this.dataProvider) {
@@ -520,14 +577,14 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
520
577
  });
521
578
  this.pendingCreationPromises.set(resourceId, creationPromise);
522
579
  } catch (error) {
523
- var _this$fireAnalyticsEv7;
580
+ var _this$fireAnalyticsEv8;
524
581
  if (this.isPendingCreation(resourceId)) {
525
582
  this.commitPendingCreation(false, resourceId);
526
583
  }
527
584
  (0, _monitoring.logException)(error, {
528
585
  location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
529
586
  });
530
- (_this$fireAnalyticsEv7 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv7 === void 0 || _this$fireAnalyticsEv7.call(this, (0, _errorHandling.createErrorPayload)(error.message, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
587
+ (_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 || _this$fireAnalyticsEv8.call(this, (0, _errorHandling.createErrorPayload)(error.message, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
531
588
  }
532
589
  }
533
590
  }, {
@@ -565,11 +622,11 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
565
622
  }, {
566
623
  key: "emitDeleteSuccess",
567
624
  value: function emitDeleteSuccess(resourceId, reason, mechanism) {
568
- var _this$syncBlockCache$2, _this$fireAnalyticsEv9;
625
+ var _this$syncBlockCache$2, _this$fireAnalyticsEv0;
569
626
  var sourceProduct = (0, _utils.getSourceProductFromResourceIdSafe)(resourceId);
570
627
  if (!(0, _platformFeatureFlags.fg)('platform_editor_blocks_patch_4')) {
571
- var _this$fireAnalyticsEv8;
572
- (_this$fireAnalyticsEv8 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv8 === void 0 || _this$fireAnalyticsEv8.call(this, (0, _errorHandling.deleteSuccessPayload)(resourceId, sourceProduct));
628
+ var _this$fireAnalyticsEv9;
629
+ (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, (0, _errorHandling.deleteSuccessPayload)(resourceId, sourceProduct));
573
630
  return;
574
631
  }
575
632
  var now = Date.now();
@@ -584,7 +641,7 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
584
641
  deletionReason: reason,
585
642
  mechanism: mechanism
586
643
  };
587
- (_this$fireAnalyticsEv9 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv9 === void 0 || _this$fireAnalyticsEv9.call(this, (0, _errorHandling.deleteSuccessPayload)(resourceId, sourceProduct, enrichment));
644
+ (_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 || _this$fireAnalyticsEv0.call(this, (0, _errorHandling.deleteSuccessPayload)(resourceId, sourceProduct, enrichment));
588
645
  }
589
646
  }, {
590
647
  key: "delete",
@@ -933,11 +990,11 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
933
990
  return sourceInfo;
934
991
  });
935
992
  } catch (error) {
936
- var _this$fireAnalyticsEv0;
993
+ var _this$fireAnalyticsEv1;
937
994
  (0, _monitoring.logException)(error, {
938
995
  location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
939
996
  });
940
- (_this$fireAnalyticsEv0 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv0 === void 0 || _this$fireAnalyticsEv0.call(this, (0, _errorHandling.getSourceInfoErrorPayload)(error.message));
997
+ (_this$fireAnalyticsEv1 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv1 === void 0 || _this$fireAnalyticsEv1.call(this, (0, _errorHandling.getSourceInfoErrorPayload)(error.message));
941
998
  return Promise.resolve(undefined);
942
999
  }
943
1000
  }
@@ -950,11 +1007,11 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
950
1007
  }
951
1008
  return this.dataProvider.fetchReferences(resourceId, true);
952
1009
  } catch (error) {
953
- var _this$fireAnalyticsEv1;
1010
+ var _this$fireAnalyticsEv10;
954
1011
  (0, _monitoring.logException)(error, {
955
1012
  location: 'editor-synced-block-provider/sourceSyncBlockStoreManager'
956
1013
  });
957
- (_this$fireAnalyticsEv1 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv1 === void 0 || _this$fireAnalyticsEv1.call(this, (0, _errorHandling.fetchReferencesErrorPayload)(error.message, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
1014
+ (_this$fireAnalyticsEv10 = this.fireAnalyticsEvent) === null || _this$fireAnalyticsEv10 === void 0 || _this$fireAnalyticsEv10.call(this, (0, _errorHandling.fetchReferencesErrorPayload)(error.message, resourceId, (0, _utils.getSourceProductFromResourceIdSafe)(resourceId)));
958
1015
  return Promise.resolve({
959
1016
  error: _types.SyncBlockError.Errored
960
1017
  });
@@ -971,6 +1028,8 @@ var SourceSyncBlockStoreManager = exports.SourceSyncBlockStoreManager = /*#__PUR
971
1028
  this.postCreationFlushCallback = undefined;
972
1029
  this.pendingCreationPromises.clear();
973
1030
  this.creationsTimedOutDuringFlush.clear();
1031
+ this.creationEnrichment.clear();
1032
+ this.awaitingFirstContent.clear();
974
1033
  this.recentDeleteEmissions.clear();
975
1034
  this.dataProvider = undefined;
976
1035
  (_this$saveExperience4 = this.saveExperience) === null || _this$saveExperience4 === void 0 || _this$saveExperience4.abort({