@atlaskit/editor-synced-block-provider 3.31.0 → 3.31.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/store-manager/referenceSyncBlockStoreManager.js +117 -9
  3. package/dist/cjs/store-manager/sourceSyncBlockStoreManager.js +16 -0
  4. package/dist/cjs/store-manager/syncBlockBatchFetcher.js +76 -0
  5. package/dist/cjs/store-manager/syncBlockInMemorySessionCache.js +26 -0
  6. package/dist/cjs/store-manager/syncBlockProviderFactoryManager.js +175 -0
  7. package/dist/cjs/store-manager/syncBlockSubscriptionManager.js +198 -0
  8. package/dist/es2019/store-manager/referenceSyncBlockStoreManager.js +93 -9
  9. package/dist/es2019/store-manager/sourceSyncBlockStoreManager.js +12 -0
  10. package/dist/es2019/store-manager/syncBlockBatchFetcher.js +56 -0
  11. package/dist/es2019/store-manager/syncBlockInMemorySessionCache.js +24 -0
  12. package/dist/es2019/store-manager/syncBlockProviderFactoryManager.js +158 -0
  13. package/dist/es2019/store-manager/syncBlockSubscriptionManager.js +136 -0
  14. package/dist/esm/store-manager/referenceSyncBlockStoreManager.js +117 -9
  15. package/dist/esm/store-manager/sourceSyncBlockStoreManager.js +16 -0
  16. package/dist/esm/store-manager/syncBlockBatchFetcher.js +69 -0
  17. package/dist/esm/store-manager/syncBlockInMemorySessionCache.js +26 -0
  18. package/dist/esm/store-manager/syncBlockProviderFactoryManager.js +168 -0
  19. package/dist/esm/store-manager/syncBlockSubscriptionManager.js +191 -0
  20. package/dist/types/store-manager/referenceSyncBlockStoreManager.d.ts +3 -0
  21. package/dist/types/store-manager/sourceSyncBlockStoreManager.d.ts +2 -0
  22. package/dist/types/store-manager/syncBlockBatchFetcher.d.ts +25 -0
  23. package/dist/types/store-manager/syncBlockInMemorySessionCache.d.ts +18 -0
  24. package/dist/types/store-manager/syncBlockProviderFactoryManager.d.ts +25 -0
  25. package/dist/types/store-manager/syncBlockSubscriptionManager.d.ts +38 -0
  26. package/dist/types-ts4.5/store-manager/referenceSyncBlockStoreManager.d.ts +3 -0
  27. package/dist/types-ts4.5/store-manager/sourceSyncBlockStoreManager.d.ts +2 -0
  28. package/dist/types-ts4.5/store-manager/syncBlockBatchFetcher.d.ts +25 -0
  29. package/dist/types-ts4.5/store-manager/syncBlockInMemorySessionCache.d.ts +18 -0
  30. package/dist/types-ts4.5/store-manager/syncBlockProviderFactoryManager.d.ts +25 -0
  31. package/dist/types-ts4.5/store-manager/syncBlockSubscriptionManager.d.ts +38 -0
  32. package/package.json +5 -2
@@ -0,0 +1,158 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { logException } from '@atlaskit/editor-common/monitoring';
3
+ import { ProviderFactory } from '@atlaskit/editor-common/provider-factory';
4
+ import { fetchErrorPayload } from '../utils/errorHandling';
5
+ import { parseResourceId } from '../utils/resourceId';
6
+ /**
7
+ * Manages creation and caching of ProviderFactory instances used to
8
+ * render synced block content (media, emoji, smart links, etc.).
9
+ */
10
+ export class SyncBlockProviderFactoryManager {
11
+ constructor(deps) {
12
+ _defineProperty(this, "providerFactories", new Map());
13
+ this.deps = deps;
14
+ }
15
+ getProviderFactory(resourceId) {
16
+ const dataProvider = this.deps.getDataProvider();
17
+ if (!dataProvider) {
18
+ var _this$deps$getFireAna;
19
+ const error = new Error('Data provider not set');
20
+ logException(error, {
21
+ location: 'editor-synced-block-provider/syncBlockProviderFactoryManager'
22
+ });
23
+ (_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 ? void 0 : _this$deps$getFireAna(fetchErrorPayload(error.message));
24
+ return undefined;
25
+ }
26
+ const {
27
+ parentDataProviders,
28
+ providerCreator
29
+ } = dataProvider.getSyncedBlockRendererProviderOptions();
30
+ let providerFactory = this.providerFactories.get(resourceId);
31
+ if (!providerFactory) {
32
+ providerFactory = ProviderFactory.create({
33
+ mentionProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.mentionProvider,
34
+ profilecardProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.profilecardProvider,
35
+ taskDecisionProvider: parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider
36
+ });
37
+ this.providerFactories.set(resourceId, providerFactory);
38
+ } else {
39
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.mentionProvider) {
40
+ providerFactory.setProvider('mentionProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.mentionProvider);
41
+ }
42
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.profilecardProvider) {
43
+ providerFactory.setProvider('profilecardProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.profilecardProvider);
44
+ }
45
+ if (parentDataProviders !== null && parentDataProviders !== void 0 && parentDataProviders.taskDecisionProvider) {
46
+ providerFactory.setProvider('taskDecisionProvider', parentDataProviders === null || parentDataProviders === void 0 ? void 0 : parentDataProviders.taskDecisionProvider);
47
+ }
48
+ }
49
+ if (providerCreator) {
50
+ try {
51
+ this.retrieveDynamicProviders(resourceId, providerFactory, providerCreator);
52
+ } catch (error) {
53
+ var _this$deps$getFireAna2;
54
+ logException(error, {
55
+ location: 'editor-synced-block-provider/syncBlockProviderFactoryManager'
56
+ });
57
+ (_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 ? void 0 : _this$deps$getFireAna2(fetchErrorPayload(error.message, resourceId));
58
+ }
59
+ }
60
+ return providerFactory;
61
+ }
62
+ getSSRProviders(resourceId) {
63
+ const dataProvider = this.deps.getDataProvider();
64
+ if (!dataProvider) {
65
+ return null;
66
+ }
67
+ const {
68
+ providerCreator
69
+ } = dataProvider.getSyncedBlockRendererProviderOptions();
70
+ if (!(providerCreator !== null && providerCreator !== void 0 && providerCreator.createSSRMediaProvider)) {
71
+ return null;
72
+ }
73
+ const parsedResourceId = parseResourceId(resourceId);
74
+ if (!parsedResourceId) {
75
+ return null;
76
+ }
77
+ const {
78
+ contentId,
79
+ product: contentProduct
80
+ } = parsedResourceId;
81
+ try {
82
+ const mediaProvider = providerCreator.createSSRMediaProvider({
83
+ contentId,
84
+ contentProduct
85
+ });
86
+ if (mediaProvider) {
87
+ return {
88
+ media: mediaProvider
89
+ };
90
+ }
91
+ } catch (error) {
92
+ logException(error, {
93
+ location: 'editor-synced-block-provider/syncBlockProviderFactoryManager'
94
+ });
95
+ }
96
+ return null;
97
+ }
98
+ deleteFactory(resourceId) {
99
+ this.providerFactories.delete(resourceId);
100
+ }
101
+ destroy() {
102
+ this.providerFactories.forEach(pf => pf.destroy());
103
+ this.providerFactories.clear();
104
+ }
105
+ retrieveDynamicProviders(resourceId, providerFactory, providerCreator) {
106
+ const dataProvider = this.deps.getDataProvider();
107
+ if (!dataProvider) {
108
+ throw new Error('Data provider not set');
109
+ }
110
+ const hasMediaProvider = providerFactory.hasProvider('mediaProvider');
111
+ const hasEmojiProvider = providerFactory.hasProvider('emojiProvider');
112
+ const hasCardProvider = providerFactory.hasProvider('cardProvider');
113
+ if (hasMediaProvider && hasEmojiProvider && hasCardProvider) {
114
+ return;
115
+ }
116
+ const syncBlock = this.deps.getFromCache(resourceId);
117
+ if (!(syncBlock !== null && syncBlock !== void 0 && syncBlock.data)) {
118
+ return;
119
+ }
120
+ if (!syncBlock.data.sourceAri || !syncBlock.data.product) {
121
+ var _this$deps$getFireAna3;
122
+ (_this$deps$getFireAna3 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna3 === void 0 ? void 0 : _this$deps$getFireAna3(fetchErrorPayload('Sync block source ari or product not found'));
123
+ return;
124
+ }
125
+ const parentInfo = dataProvider.retrieveSyncBlockParentInfo(syncBlock.data.sourceAri, syncBlock.data.product);
126
+ if (!parentInfo) {
127
+ throw new Error('Unable to retrieve sync block parent info');
128
+ }
129
+ const {
130
+ contentId,
131
+ contentProduct
132
+ } = parentInfo;
133
+ if (!hasMediaProvider && providerCreator.createMediaProvider && contentId && contentProduct) {
134
+ const mediaProvider = providerCreator.createMediaProvider({
135
+ contentProduct,
136
+ contentId
137
+ });
138
+ if (mediaProvider) {
139
+ providerFactory.setProvider('mediaProvider', mediaProvider);
140
+ }
141
+ }
142
+ if (!hasEmojiProvider && providerCreator.createEmojiProvider && contentId && contentProduct) {
143
+ const emojiProvider = providerCreator.createEmojiProvider({
144
+ contentProduct,
145
+ contentId
146
+ });
147
+ if (emojiProvider) {
148
+ providerFactory.setProvider('emojiProvider', emojiProvider);
149
+ }
150
+ }
151
+ if (!hasCardProvider && providerCreator.createSmartLinkProvider) {
152
+ const smartLinkProvider = providerCreator.createSmartLinkProvider();
153
+ if (smartLinkProvider) {
154
+ providerFactory.setProvider('cardProvider', smartLinkProvider);
155
+ }
156
+ }
157
+ }
158
+ }
@@ -0,0 +1,136 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import { logException } from '@atlaskit/editor-common/monitoring';
3
+ import { fg } from '@atlaskit/platform-feature-flags';
4
+ import { fetchErrorPayload, fetchSuccessPayload } from '../utils/errorHandling';
5
+ import { resolveSyncBlockInstance } from '../utils/resolveSyncBlockInstance';
6
+ /**
7
+ * Manages the lifecycle of GraphQL WebSocket subscriptions for sync block
8
+ * real-time updates, and provides a listener API so React components can
9
+ * react when the set of subscribed resource IDs changes.
10
+ */
11
+ export class SyncBlockSubscriptionManager {
12
+ constructor(deps) {
13
+ _defineProperty(this, "graphqlSubscriptions", new Map());
14
+ _defineProperty(this, "subscriptionChangeListeners", new Set());
15
+ _defineProperty(this, "useRealTimeSubscriptions", false);
16
+ this.deps = deps;
17
+ }
18
+ setRealTimeSubscriptionsEnabled(enabled) {
19
+ if (this.useRealTimeSubscriptions === enabled) {
20
+ return;
21
+ }
22
+ this.useRealTimeSubscriptions = enabled;
23
+ if (enabled) {
24
+ this.setupSubscriptionsForAllBlocks();
25
+ } else {
26
+ this.cleanupAll();
27
+ }
28
+ }
29
+ isRealTimeSubscriptionsEnabled() {
30
+ return this.useRealTimeSubscriptions;
31
+ }
32
+ getSubscribedResourceIds() {
33
+ return Array.from(this.deps.getSubscriptions().keys());
34
+ }
35
+ onSubscriptionsChanged(listener) {
36
+ this.subscriptionChangeListeners.add(listener);
37
+ return () => {
38
+ this.subscriptionChangeListeners.delete(listener);
39
+ };
40
+ }
41
+ notifySubscriptionChangeListeners() {
42
+ this.subscriptionChangeListeners.forEach(listener => {
43
+ try {
44
+ listener();
45
+ } catch (error) {
46
+ var _this$deps$getFireAna;
47
+ logException(error, {
48
+ location: 'editor-synced-block-provider/syncBlockSubscriptionManager/notifySubscriptionChangeListeners'
49
+ });
50
+ (_this$deps$getFireAna = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 ? void 0 : _this$deps$getFireAna(fetchErrorPayload(error.message));
51
+ }
52
+ });
53
+ }
54
+ handleSubscriptionUpdate(syncBlockInstance) {
55
+ if (!syncBlockInstance.resourceId) {
56
+ return;
57
+ }
58
+ const existing = this.deps.getFromCache(syncBlockInstance.resourceId);
59
+ const resolved = existing ? resolveSyncBlockInstance(existing, syncBlockInstance) : syncBlockInstance;
60
+ this.deps.updateCache(resolved);
61
+ if (!syncBlockInstance.error) {
62
+ this.deps.fetchSyncBlockSourceInfo(resolved.resourceId);
63
+ }
64
+ }
65
+ setupSubscription(resourceId) {
66
+ if (this.graphqlSubscriptions.has(resourceId)) {
67
+ return;
68
+ }
69
+ const dataProvider = this.deps.getDataProvider();
70
+ if (!(dataProvider !== null && dataProvider !== void 0 && dataProvider.subscribeToBlockUpdates)) {
71
+ return;
72
+ }
73
+ const unsubscribe = dataProvider.subscribeToBlockUpdates(resourceId, syncBlockInstance => {
74
+ this.handleGraphQLUpdate(syncBlockInstance);
75
+ }, error => {
76
+ var _this$deps$getFireAna2;
77
+ logException(error, {
78
+ location: 'editor-synced-block-provider/syncBlockSubscriptionManager/graphql-subscription'
79
+ });
80
+ (_this$deps$getFireAna2 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna2 === void 0 ? void 0 : _this$deps$getFireAna2(fetchErrorPayload(error.message));
81
+ });
82
+ if (unsubscribe) {
83
+ this.graphqlSubscriptions.set(resourceId, unsubscribe);
84
+ }
85
+ }
86
+ cleanupSubscription(resourceId) {
87
+ const unsubscribe = this.graphqlSubscriptions.get(resourceId);
88
+ if (unsubscribe) {
89
+ unsubscribe();
90
+ this.graphqlSubscriptions.delete(resourceId);
91
+ }
92
+ }
93
+ setupSubscriptionsForAllBlocks() {
94
+ for (const resourceId of this.deps.getSubscriptions().keys()) {
95
+ this.setupSubscription(resourceId);
96
+ }
97
+ }
98
+ cleanupAll() {
99
+ for (const unsubscribe of this.graphqlSubscriptions.values()) {
100
+ unsubscribe();
101
+ }
102
+ this.graphqlSubscriptions.clear();
103
+ }
104
+ destroy() {
105
+ this.cleanupAll();
106
+ this.subscriptionChangeListeners.clear();
107
+ this.useRealTimeSubscriptions = false;
108
+ }
109
+ shouldUseRealTime() {
110
+ return this.useRealTimeSubscriptions;
111
+ }
112
+ handleGraphQLUpdate(syncBlockInstance) {
113
+ if (!syncBlockInstance.resourceId) {
114
+ if (fg('platform_synced_block_patch_5')) {
115
+ return;
116
+ }
117
+ throw new Error('Sync block instance provided to graphql subscription update missing resource id');
118
+ }
119
+ const existing = this.deps.getFromCache(syncBlockInstance.resourceId);
120
+ const resolved = existing ? resolveSyncBlockInstance(existing, syncBlockInstance) : syncBlockInstance;
121
+ this.deps.updateCache(resolved);
122
+ if (!syncBlockInstance.error) {
123
+ const callbacks = this.deps.getSubscriptions().get(syncBlockInstance.resourceId);
124
+ const localIds = callbacks ? Object.keys(callbacks) : [];
125
+ localIds.forEach(localId => {
126
+ var _this$deps$getFireAna3, _syncBlockInstance$da;
127
+ (_this$deps$getFireAna3 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna3 === void 0 ? void 0 : _this$deps$getFireAna3(fetchSuccessPayload(syncBlockInstance.resourceId, localId, (_syncBlockInstance$da = syncBlockInstance.data) === null || _syncBlockInstance$da === void 0 ? void 0 : _syncBlockInstance$da.product));
128
+ });
129
+ this.deps.fetchSyncBlockSourceInfo(resolved.resourceId);
130
+ } else {
131
+ var _syncBlockInstance$er, _syncBlockInstance$er2, _syncBlockInstance$er3, _this$deps$getFireAna4;
132
+ const errorMessage = fg('platform_synced_block_patch_3') ? ((_syncBlockInstance$er = syncBlockInstance.error) === null || _syncBlockInstance$er === void 0 ? void 0 : _syncBlockInstance$er.reason) || ((_syncBlockInstance$er2 = syncBlockInstance.error) === null || _syncBlockInstance$er2 === void 0 ? void 0 : _syncBlockInstance$er2.type) : (_syncBlockInstance$er3 = syncBlockInstance.error) === null || _syncBlockInstance$er3 === void 0 ? void 0 : _syncBlockInstance$er3.type;
133
+ (_this$deps$getFireAna4 = this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna4 === void 0 ? void 0 : _this$deps$getFireAna4(fetchErrorPayload(errorMessage, syncBlockInstance.resourceId));
134
+ }
135
+ }
136
+ }
@@ -20,7 +20,10 @@ import { getFetchExperience, getFetchSourceInfoExperience, getSaveReferenceExper
20
20
  import { resolveSyncBlockInstance } from '../utils/resolveSyncBlockInstance';
21
21
  import { parseResourceId } from '../utils/resourceId';
22
22
  import { createSyncBlockNode } from '../utils/utils';
23
+ import { SyncBlockBatchFetcher } from './syncBlockBatchFetcher';
23
24
  import { syncBlockInMemorySessionCache } from './syncBlockInMemorySessionCache';
25
+ import { SyncBlockProviderFactoryManager } from './syncBlockProviderFactoryManager';
26
+ import { SyncBlockSubscriptionManager } from './syncBlockSubscriptionManager';
24
27
  var CACHE_KEY_PREFIX = 'sync-block-data-';
25
28
 
26
29
  // A store manager responsible for the lifecycle and state management of reference sync blocks in an editor instance.
@@ -78,6 +81,50 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
78
81
  this.graphqlSubscriptions = new Map();
79
82
  this.subscriptionChangeListeners = new Set();
80
83
  this.newlyAddedSyncBlocks = new Set();
84
+ if (fg('platform_synced_block_patch_5')) {
85
+ this._subscriptionManager = new SyncBlockSubscriptionManager({
86
+ getDataProvider: function getDataProvider() {
87
+ return _this.dataProvider;
88
+ },
89
+ getSubscriptions: function getSubscriptions() {
90
+ return _this.subscriptions;
91
+ },
92
+ getFromCache: function getFromCache(rid) {
93
+ return _this.getFromCache(rid);
94
+ },
95
+ updateCache: function updateCache(inst) {
96
+ return _this.updateCache(inst);
97
+ },
98
+ fetchSyncBlockSourceInfo: function fetchSyncBlockSourceInfo(rid) {
99
+ return _this.fetchSyncBlockSourceInfo(rid);
100
+ },
101
+ getFireAnalyticsEvent: function getFireAnalyticsEvent() {
102
+ return _this.fireAnalyticsEvent;
103
+ }
104
+ });
105
+ this._providerFactoryManager = new SyncBlockProviderFactoryManager({
106
+ getDataProvider: function getDataProvider() {
107
+ return _this.dataProvider;
108
+ },
109
+ getFromCache: function getFromCache(rid) {
110
+ return _this.getFromCache(rid);
111
+ },
112
+ getFireAnalyticsEvent: function getFireAnalyticsEvent() {
113
+ return _this.fireAnalyticsEvent;
114
+ }
115
+ });
116
+ this._batchFetcher = new SyncBlockBatchFetcher({
117
+ getSubscriptions: function getSubscriptions() {
118
+ return _this.subscriptions;
119
+ },
120
+ fetchSyncBlocksData: function fetchSyncBlocksData(nodes) {
121
+ return _this.fetchSyncBlocksData(nodes);
122
+ },
123
+ getFireAnalyticsEvent: function getFireAnalyticsEvent() {
124
+ return _this.fireAnalyticsEvent;
125
+ }
126
+ });
127
+ }
81
128
 
82
129
  // The provider might have SSR data cache already set, so we need to update the cache in session memory storage
83
130
  this.setSSRDataInSessionCache((_this$dataProvider = this.dataProvider) === null || _this$dataProvider === void 0 ? void 0 : _this$dataProvider.getNodeDataCacheKeys());
@@ -92,6 +139,10 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
92
139
  return _createClass(ReferenceSyncBlockStoreManager, [{
93
140
  key: "setRealTimeSubscriptionsEnabled",
94
141
  value: function setRealTimeSubscriptionsEnabled(enabled) {
142
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
143
+ this._subscriptionManager.setRealTimeSubscriptionsEnabled(enabled);
144
+ return;
145
+ }
95
146
  if (this.useRealTimeSubscriptions === enabled) {
96
147
  return;
97
148
  }
@@ -111,6 +162,9 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
111
162
  }, {
112
163
  key: "isRealTimeSubscriptionsEnabled",
113
164
  value: function isRealTimeSubscriptionsEnabled() {
165
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
166
+ return this._subscriptionManager.isRealTimeSubscriptionsEnabled();
167
+ }
114
168
  return this.useRealTimeSubscriptions;
115
169
  }
116
170
 
@@ -121,6 +175,9 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
121
175
  }, {
122
176
  key: "getSubscribedResourceIds",
123
177
  value: function getSubscribedResourceIds() {
178
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
179
+ return this._subscriptionManager.getSubscribedResourceIds();
180
+ }
124
181
  return Array.from(this.subscriptions.keys());
125
182
  }
126
183
 
@@ -133,6 +190,9 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
133
190
  key: "onSubscriptionsChanged",
134
191
  value: function onSubscriptionsChanged(listener) {
135
192
  var _this2 = this;
193
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
194
+ return this._subscriptionManager.onSubscriptionsChanged(listener);
195
+ }
136
196
  this.subscriptionChangeListeners.add(listener);
137
197
  return function () {
138
198
  _this2.subscriptionChangeListeners.delete(listener);
@@ -146,6 +206,10 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
146
206
  key: "notifySubscriptionChangeListeners",
147
207
  value: function notifySubscriptionChangeListeners() {
148
208
  var _this3 = this;
209
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
210
+ this._subscriptionManager.notifySubscriptionChangeListeners();
211
+ return;
212
+ }
149
213
  this.subscriptionChangeListeners.forEach(function (listener) {
150
214
  try {
151
215
  listener();
@@ -167,6 +231,10 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
167
231
  }, {
168
232
  key: "handleSubscriptionUpdate",
169
233
  value: function handleSubscriptionUpdate(syncBlockInstance) {
234
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
235
+ this._subscriptionManager.handleSubscriptionUpdate(syncBlockInstance);
236
+ return;
237
+ }
170
238
  if (!syncBlockInstance.resourceId) {
171
239
  return;
172
240
  }
@@ -354,6 +422,11 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
354
422
  value: function setupGraphQLSubscription(resourceId) {
355
423
  var _this$dataProvider3,
356
424
  _this4 = this;
425
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
426
+ this._subscriptionManager.setupSubscription(resourceId);
427
+ return;
428
+ }
429
+
357
430
  // Don't set up duplicate subscriptions
358
431
  if (this.graphqlSubscriptions.has(resourceId)) {
359
432
  return;
@@ -415,6 +488,10 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
415
488
  }, {
416
489
  key: "cleanupGraphQLSubscription",
417
490
  value: function cleanupGraphQLSubscription(resourceId) {
491
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
492
+ this._subscriptionManager.cleanupSubscription(resourceId);
493
+ return;
494
+ }
418
495
  var unsubscribe = this.graphqlSubscriptions.get(resourceId);
419
496
  if (unsubscribe) {
420
497
  unsubscribe();
@@ -428,6 +505,10 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
428
505
  }, {
429
506
  key: "setupGraphQLSubscriptionsForAllBlocks",
430
507
  value: function setupGraphQLSubscriptionsForAllBlocks() {
508
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
509
+ this._subscriptionManager.setupSubscriptionsForAllBlocks();
510
+ return;
511
+ }
431
512
  var _iterator2 = _createForOfIteratorHelper(this.subscriptions.keys()),
432
513
  _step2;
433
514
  try {
@@ -448,6 +529,10 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
448
529
  }, {
449
530
  key: "cleanupAllGraphQLSubscriptions",
450
531
  value: function cleanupAllGraphQLSubscriptions() {
532
+ if (this._subscriptionManager && fg('platform_synced_block_patch_5')) {
533
+ this._subscriptionManager.cleanupAll();
534
+ return;
535
+ }
451
536
  var _iterator3 = _createForOfIteratorHelper(this.graphqlSubscriptions.values()),
452
537
  _step3;
453
538
  try {
@@ -776,14 +861,13 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
776
861
  hasUnexpectedError = true;
777
862
  }
778
863
  return;
779
- } else {
780
- var callbacks = _this9.subscriptions.get(syncBlockInstance.resourceId);
781
- var localIds = callbacks ? Object.keys(callbacks) : [];
782
- localIds.forEach(function (localId) {
783
- var _this9$fireAnalyticsE4, _syncBlockInstance$da2;
784
- (_this9$fireAnalyticsE4 = _this9.fireAnalyticsEvent) === null || _this9$fireAnalyticsE4 === void 0 || _this9$fireAnalyticsE4.call(_this9, fetchSuccessPayload(syncBlockInstance.resourceId, localId, (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product));
785
- });
786
864
  }
865
+ var callbacks = _this9.subscriptions.get(syncBlockInstance.resourceId);
866
+ var localIds = callbacks ? Object.keys(callbacks) : [];
867
+ localIds.forEach(function (localId) {
868
+ var _this9$fireAnalyticsE4, _syncBlockInstance$da2;
869
+ (_this9$fireAnalyticsE4 = _this9.fireAnalyticsEvent) === null || _this9$fireAnalyticsE4 === void 0 || _this9$fireAnalyticsE4.call(_this9, fetchSuccessPayload(syncBlockInstance.resourceId, localId, (_syncBlockInstance$da2 = syncBlockInstance.data) === null || _syncBlockInstance$da2 === void 0 ? void 0 : _syncBlockInstance$da2.product));
870
+ });
787
871
  _this9.fetchSyncBlockSourceInfo(resolvedSyncBlockInstance.resourceId);
788
872
  });
789
873
  return {
@@ -849,11 +933,19 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
849
933
  value: function deleteFromCache(resourceId) {
850
934
  var _this$dataProvider6;
851
935
  (_this$dataProvider6 = this.dataProvider) === null || _this$dataProvider6 === void 0 || _this$dataProvider6.removeFromCache([resourceId]);
852
- this.providerFactories.delete(resourceId);
936
+ if (this._providerFactoryManager && fg('platform_synced_block_patch_5')) {
937
+ this._providerFactoryManager.deleteFactory(resourceId);
938
+ } else {
939
+ this.providerFactories.delete(resourceId);
940
+ }
853
941
  }
854
942
  }, {
855
943
  key: "debouncedBatchedFetchSyncBlocks",
856
944
  value: function debouncedBatchedFetchSyncBlocks(resourceId) {
945
+ if (this._batchFetcher && fg('platform_synced_block_patch_5')) {
946
+ this._batchFetcher.queueFetch(resourceId);
947
+ return;
948
+ }
857
949
  // Only add to pending requests if there are active subscriptions for this resource
858
950
  if (this.subscriptions.has(resourceId) && Object.keys(this.subscriptions.get(resourceId) || {}).length > 0) {
859
951
  this.pendingFetchRequests.add(resourceId);
@@ -909,7 +1001,8 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
909
1001
  }
910
1002
 
911
1003
  // Set up GraphQL subscription if real-time subscriptions are enabled
912
- if (this.useRealTimeSubscriptions) {
1004
+ var useRealTime = this._subscriptionManager && fg('platform_synced_block_patch_5') ? this._subscriptionManager.shouldUseRealTime() : this.useRealTimeSubscriptions;
1005
+ if (useRealTime) {
913
1006
  this.setupGraphQLSubscription(resourceId);
914
1007
  }
915
1008
  return function () {
@@ -1024,6 +1117,9 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
1024
1117
  }, {
1025
1118
  key: "getProviderFactory",
1026
1119
  value: function getProviderFactory(resourceId) {
1120
+ if (this._providerFactoryManager && fg('platform_synced_block_patch_5')) {
1121
+ return this._providerFactoryManager.getProviderFactory(resourceId);
1122
+ }
1027
1123
  if (!this.dataProvider) {
1028
1124
  var _this$fireAnalyticsEv8;
1029
1125
  var error = new Error('Data provider not set');
@@ -1071,6 +1167,9 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
1071
1167
  }, {
1072
1168
  key: "getSSRProviders",
1073
1169
  value: function getSSRProviders(resourceId) {
1170
+ if (this._providerFactoryManager && fg('platform_synced_block_patch_5')) {
1171
+ return this._providerFactoryManager.getSSRProviders(resourceId);
1172
+ }
1074
1173
  if (!this.dataProvider) {
1075
1174
  return null;
1076
1175
  }
@@ -1333,6 +1432,12 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
1333
1432
  clearTimeout(this.queuedFlushTimeout);
1334
1433
  this.queuedFlushTimeout = undefined;
1335
1434
  }
1435
+ if (fg('platform_synced_block_patch_5')) {
1436
+ var _this$_subscriptionMa, _this$_providerFactor, _this$_batchFetcher;
1437
+ (_this$_subscriptionMa = this._subscriptionManager) === null || _this$_subscriptionMa === void 0 || _this$_subscriptionMa.destroy();
1438
+ (_this$_providerFactor = this._providerFactoryManager) === null || _this$_providerFactor === void 0 || _this$_providerFactor.destroy();
1439
+ (_this$_batchFetcher = this._batchFetcher) === null || _this$_batchFetcher === void 0 || _this$_batchFetcher.destroy();
1440
+ }
1336
1441
 
1337
1442
  // Clean up all GraphQL subscriptions first
1338
1443
  this.cleanupAllGraphQLSubscriptions();
@@ -1361,6 +1466,9 @@ export var ReferenceSyncBlockStoreManager = /*#__PURE__*/function () {
1361
1466
  reason: 'editorDestroyed'
1362
1467
  });
1363
1468
  this.fireAnalyticsEvent = undefined;
1469
+ if (fg('platform_synced_block_patch_5')) {
1470
+ syncBlockInMemorySessionCache.clear();
1471
+ }
1364
1472
  }
1365
1473
  }]);
1366
1474
  }();
@@ -5,7 +5,9 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
5
5
  import _regeneratorRuntime from "@babel/runtime/regenerator";
6
6
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
7
  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) { _defineProperty(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; }
8
+ import isEqual from 'lodash/isEqual';
8
9
  import { logException } from '@atlaskit/editor-common/monitoring';
10
+ import { fg } from '@atlaskit/platform-feature-flags';
9
11
  import { SyncBlockError } from '../common/types';
10
12
  import { updateErrorPayload, createErrorPayload, deleteErrorPayload, updateCacheErrorPayload, getSourceInfoErrorPayload, updateSuccessPayload, createSuccessPayload, deleteSuccessPayload, fetchReferencesErrorPayload } from '../utils/errorHandling';
11
13
  import { getCreateSourceExperience, getDeleteSourceExperience, getSaveSourceExperience, getFetchSourceInfoExperience } from '../utils/experienceTracking';
@@ -19,6 +21,7 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
19
21
  function SourceSyncBlockStoreManager(dataProvider) {
20
22
  var _this = this;
21
23
  _classCallCheck(this, SourceSyncBlockStoreManager);
24
+ _defineProperty(this, "hasReceivedContentChange", false);
22
25
  _defineProperty(this, "setPendingDeletion", function (Ids, value) {
23
26
  var syncBlock = _this.syncBlockCache.get(Ids.resourceId);
24
27
  if (syncBlock) {
@@ -62,6 +65,12 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
62
65
  throw new Error('Local ID or resource ID is not set');
63
66
  }
64
67
  var syncBlockData = convertSyncBlockPMNodeToSyncBlockData(syncBlockNode);
68
+ if (fg('platform_synced_block_patch_5')) {
69
+ var cachedBlock = this.syncBlockCache.get(resourceId);
70
+ if (cachedBlock && !isEqual(syncBlockData.content, cachedBlock.content)) {
71
+ this.hasReceivedContentChange = true;
72
+ }
73
+ }
65
74
  this.syncBlockCache.set(resourceId, _objectSpread(_objectSpread({}, syncBlockData), {}, {
66
75
  isDirty: true
67
76
  }));
@@ -190,6 +199,13 @@ export var SourceSyncBlockStoreManager = /*#__PURE__*/function () {
190
199
  }
191
200
  return flush;
192
201
  }())
202
+ }, {
203
+ key: "hasUnsavedChanges",
204
+ value: function hasUnsavedChanges() {
205
+ return this.hasReceivedContentChange && Array.from(this.syncBlockCache.values()).some(function (syncBlockData) {
206
+ return syncBlockData.isDirty;
207
+ });
208
+ }
193
209
  }, {
194
210
  key: "isPendingCreation",
195
211
  value: function isPendingCreation(resourceId) {
@@ -0,0 +1,69 @@
1
+ import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
2
+ import _createClass from "@babel/runtime/helpers/createClass";
3
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
+ import rafSchedule from 'raf-schd';
5
+ import { logException } from '@atlaskit/editor-common/monitoring';
6
+ import { fetchErrorPayload } from '../utils/errorHandling';
7
+ import { createSyncBlockNode } from '../utils/utils';
8
+ /**
9
+ * Handles debounced batch-fetching of sync block data via `raf-schd`.
10
+ * Accumulates resource IDs and flushes them in a single fetch per
11
+ * animation frame.
12
+ */
13
+ export var SyncBlockBatchFetcher = /*#__PURE__*/function () {
14
+ function SyncBlockBatchFetcher(deps) {
15
+ var _this = this;
16
+ _classCallCheck(this, SyncBlockBatchFetcher);
17
+ _defineProperty(this, "pendingFetchRequests", new Set());
18
+ this.deps = deps;
19
+ this.scheduledBatchFetch = rafSchedule(function () {
20
+ if (_this.pendingFetchRequests.size === 0) {
21
+ return;
22
+ }
23
+ var resourceIds = Array.from(_this.pendingFetchRequests);
24
+ var syncBlockNodes = resourceIds.map(function (resId) {
25
+ var subscriptions = _this.deps.getSubscriptions().get(resId) || {};
26
+ var firstLocalId = Object.keys(subscriptions)[0] || '';
27
+ return createSyncBlockNode(firstLocalId, resId);
28
+ });
29
+ _this.pendingFetchRequests.clear();
30
+ _this.deps.fetchSyncBlocksData(syncBlockNodes).catch(function (error) {
31
+ logException(error, {
32
+ location: 'editor-synced-block-provider/syncBlockBatchFetcher/batchedFetchSyncBlocks'
33
+ });
34
+ resourceIds.forEach(function (resId) {
35
+ var _this$deps$getFireAna;
36
+ (_this$deps$getFireAna = _this.deps.getFireAnalyticsEvent()) === null || _this$deps$getFireAna === void 0 || _this$deps$getFireAna(fetchErrorPayload(error.message, resId));
37
+ });
38
+ });
39
+ });
40
+ }
41
+ return _createClass(SyncBlockBatchFetcher, [{
42
+ key: "queueFetch",
43
+ value: function queueFetch(resourceId) {
44
+ var subscriptions = this.deps.getSubscriptions();
45
+ if (subscriptions.has(resourceId) && Object.keys(subscriptions.get(resourceId) || {}).length > 0) {
46
+ this.pendingFetchRequests.add(resourceId);
47
+ this.scheduledBatchFetch();
48
+ } else {
49
+ this.pendingFetchRequests.delete(resourceId);
50
+ }
51
+ }
52
+ }, {
53
+ key: "cancel",
54
+ value: function cancel() {
55
+ this.scheduledBatchFetch.cancel();
56
+ }
57
+ }, {
58
+ key: "clearPending",
59
+ value: function clearPending() {
60
+ this.pendingFetchRequests.clear();
61
+ }
62
+ }, {
63
+ key: "destroy",
64
+ value: function destroy() {
65
+ this.cancel();
66
+ this.clearPending();
67
+ }
68
+ }]);
69
+ }();