@atlaskit/editor-plugin-synced-block 5.3.33 → 5.3.35

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.
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.syncedBlockPluginKey = exports.createPlugin = void 0;
8
+ var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
+ var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
8
10
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
11
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
12
  var _analytics = require("@atlaskit/editor-common/analytics");
@@ -18,13 +20,14 @@ var _view = require("@atlaskit/editor-prosemirror/view");
18
20
  var _editorSyncedBlockProvider = require("@atlaskit/editor-synced-block-provider");
19
21
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
20
22
  var _bodiedLazySyncedBlock = require("../nodeviews/bodiedLazySyncedBlock");
23
+ var _bodiedSyncedBlock = require("../nodeviews/bodiedSyncedBlock");
21
24
  var _syncedBlock = require("../nodeviews/syncedBlock");
22
25
  var _types = require("../types");
23
26
  var _handleBodiedSyncBlockCreation = require("./utils/handle-bodied-sync-block-creation");
24
27
  var _handleBodiedSyncBlockRemoval = require("./utils/handle-bodied-sync-block-removal");
25
28
  var _ignoreDomEvent = require("./utils/ignore-dom-event");
26
29
  var _selectionDecorations = require("./utils/selection-decorations");
27
- var _trackSyncBlocks6 = require("./utils/track-sync-blocks");
30
+ var _trackSyncBlocks8 = require("./utils/track-sync-blocks");
28
31
  var _utils2 = require("./utils/utils");
29
32
  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; }
30
33
  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; }
@@ -66,8 +69,7 @@ var mapRetryCreationPosMap = function mapRetryCreationPosMap(oldMap, newRetryCre
66
69
  return newMap;
67
70
  };
68
71
  var showCopiedFlag = function showCopiedFlag(api) {
69
- // Use setTimeout to dispatch transaction in next tick and avoid re-entrant dispatch
70
- setTimeout(function () {
72
+ (0, _utils2.deferDispatch)(function () {
71
73
  api === null || api === void 0 || api.core.actions.execute(function (_ref) {
72
74
  var tr = _ref.tr;
73
75
  return tr.setMeta(syncedBlockPluginKey, {
@@ -76,7 +78,7 @@ var showCopiedFlag = function showCopiedFlag(api) {
76
78
  }
77
79
  });
78
80
  });
79
- }, 0);
81
+ });
80
82
  };
81
83
  var showInlineExtensionInSyncBlockWarningIfNeeded = function showInlineExtensionInSyncBlockWarningIfNeeded(tr, state, api, inlineExtensionFlagShown) {
82
84
  var _api$connectivity;
@@ -90,8 +92,7 @@ var showInlineExtensionInSyncBlockWarningIfNeeded = function showInlineExtension
90
92
  // Only show the flag on the first instance per sync block (same as UNPUBLISHED_SYNC_BLOCK_PASTED)
91
93
  if (resourceId && !inlineExtensionFlagShown.has(resourceId)) {
92
94
  inlineExtensionFlagShown.add(resourceId);
93
- // Use setTimeout to dispatch in next tick and avoid re-entrant dispatch from filterTransaction
94
- setTimeout(function () {
95
+ (0, _utils2.deferDispatch)(function () {
95
96
  api === null || api === void 0 || api.core.actions.execute(function (_ref2) {
96
97
  var tr = _ref2.tr;
97
98
  return tr.setMeta(syncedBlockPluginKey, {
@@ -100,7 +101,7 @@ var showInlineExtensionInSyncBlockWarningIfNeeded = function showInlineExtension
100
101
  }
101
102
  });
102
103
  });
103
- }, 0);
104
+ });
104
105
  }
105
106
  };
106
107
  var getDeleteReason = function getDeleteReason(tr) {
@@ -110,36 +111,176 @@ var getDeleteReason = function getDeleteReason(tr) {
110
111
  }
111
112
  return reason;
112
113
  };
114
+ var filterTransactionOnline = function filterTransactionOnline(_ref3) {
115
+ var tr = _ref3.tr,
116
+ state = _ref3.state,
117
+ syncBlockStore = _ref3.syncBlockStore,
118
+ api = _ref3.api,
119
+ confirmationTransactionRef = _ref3.confirmationTransactionRef,
120
+ bodiedSyncBlockRemoved = _ref3.bodiedSyncBlockRemoved,
121
+ bodiedSyncBlockAdded = _ref3.bodiedSyncBlockAdded,
122
+ inlineExtensionFlagShown = _ref3.inlineExtensionFlagShown;
123
+ var _trackSyncBlocks = (0, _trackSyncBlocks8.trackSyncBlocks)(function (node) {
124
+ return node.type.name === 'syncBlock';
125
+ }, tr, state),
126
+ syncBlockRemoved = _trackSyncBlocks.removed,
127
+ syncBlockAdded = _trackSyncBlocks.added;
128
+ syncBlockRemoved.forEach(function (syncBlock) {
129
+ var _api$analytics;
130
+ api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.fireAnalyticsEvent({
131
+ action: _analytics.ACTION.DELETED,
132
+ actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK,
133
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_DELETE,
134
+ attributes: {
135
+ resourceId: syncBlock.attrs.resourceId,
136
+ blockInstanceId: syncBlock.attrs.localId
137
+ },
138
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL
139
+ });
140
+ });
141
+ syncBlockAdded.forEach(function (syncBlock) {
142
+ if ((0, _platformFeatureFlags.fg)('platform_synced_block_patch_3')) {
143
+ var _api$analytics2;
144
+ api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.fireAnalyticsEvent({
145
+ action: _analytics.ACTION.INSERTED,
146
+ actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
147
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK,
148
+ attributes: {
149
+ resourceId: syncBlock.attrs.resourceId,
150
+ blockInstanceId: syncBlock.attrs.localId
151
+ },
152
+ eventType: _analytics.EVENT_TYPE.TRACK
153
+ });
154
+ } else {
155
+ var _api$analytics3;
156
+ api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || (_api$analytics3 = _api$analytics3.actions) === null || _api$analytics3 === void 0 || _api$analytics3.fireAnalyticsEvent({
157
+ action: _analytics.ACTION.INSERTED,
158
+ actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK,
159
+ actionSubjectId: _analytics.ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_CREATE,
160
+ attributes: {
161
+ resourceId: syncBlock.attrs.resourceId,
162
+ blockInstanceId: syncBlock.attrs.localId
163
+ },
164
+ eventType: _analytics.EVENT_TYPE.OPERATIONAL
165
+ });
166
+ }
167
+ });
168
+ if (bodiedSyncBlockRemoved.length > 0) {
169
+ // eslint-disable-next-line no-param-reassign
170
+ confirmationTransactionRef.current = tr;
171
+ return (0, _handleBodiedSyncBlockRemoval.handleBodiedSyncBlockRemoval)(bodiedSyncBlockRemoved, syncBlockStore, api, confirmationTransactionRef, getDeleteReason(tr));
172
+ }
173
+ if (bodiedSyncBlockAdded.length > 0) {
174
+ if (tr.getMeta(_utils.pmHistoryPluginKey)) {
175
+ // We don't allow bodiedSyncBlock creation via redo, however, we need to return true here to let transaction through so history can be updated properly.
176
+ // If we simply returns false, creation from redo is blocked as desired, but this results in editor showing redo as possible even though it's not.
177
+ // After true is returned here and the node is created, we delete the node in the filterTransaction immediately, which cancels out the creation
178
+ return true;
179
+ }
180
+ (0, _handleBodiedSyncBlockCreation.handleBodiedSyncBlockCreation)(bodiedSyncBlockAdded, state, api);
181
+ return true;
182
+ }
183
+ showInlineExtensionInSyncBlockWarningIfNeeded(tr, state, api, inlineExtensionFlagShown);
184
+ return true;
185
+ };
186
+ var filterTransactionOffline = function filterTransactionOffline(_ref4) {
187
+ var tr = _ref4.tr,
188
+ state = _ref4.state,
189
+ api = _ref4.api,
190
+ isConfirmedSyncBlockDeletion = _ref4.isConfirmedSyncBlockDeletion,
191
+ bodiedSyncBlockRemoved = _ref4.bodiedSyncBlockRemoved,
192
+ bodiedSyncBlockAdded = _ref4.bodiedSyncBlockAdded;
193
+ var _trackSyncBlocks2 = (0, _trackSyncBlocks8.trackSyncBlocks)(function (node) {
194
+ return node.type.name === 'syncBlock';
195
+ }, tr, state),
196
+ syncBlockRemoved = _trackSyncBlocks2.removed,
197
+ syncBlockAdded = _trackSyncBlocks2.added;
198
+ var errorFlag = false;
199
+ if (isConfirmedSyncBlockDeletion || bodiedSyncBlockRemoved.length > 0 || syncBlockRemoved.length > 0) {
200
+ errorFlag = _types.FLAG_ID.CANNOT_DELETE_WHEN_OFFLINE;
201
+ } else if (bodiedSyncBlockAdded.length > 0 || syncBlockAdded.length > 0) {
202
+ errorFlag = _types.FLAG_ID.CANNOT_CREATE_WHEN_OFFLINE;
203
+ } else if ((0, _trackSyncBlocks8.hasEditInSyncBlock)(tr, state)) {
204
+ errorFlag = _types.FLAG_ID.CANNOT_EDIT_WHEN_OFFLINE;
205
+ }
206
+ if (errorFlag) {
207
+ (0, _utils2.deferDispatch)(function () {
208
+ api === null || api === void 0 || api.core.actions.execute(function (_ref5) {
209
+ var tr = _ref5.tr;
210
+ return tr.setMeta(syncedBlockPluginKey, {
211
+ activeFlag: {
212
+ id: errorFlag
213
+ }
214
+ });
215
+ });
216
+ });
217
+ return false;
218
+ }
219
+ return true;
220
+ };
221
+
222
+ /**
223
+ * Encapsulates mutable state that persists across transactions in the
224
+ * synced block plugin. Replaces module-level closure variables so state
225
+ * is explicitly scoped to a single plugin instance.
226
+ */
227
+ var SyncedBlockPluginContext = /*#__PURE__*/function () {
228
+ function SyncedBlockPluginContext() {
229
+ (0, _classCallCheck2.default)(this, SyncedBlockPluginContext);
230
+ (0, _defineProperty2.default)(this, "confirmationTransactionRef", {
231
+ current: undefined
232
+ });
233
+ (0, _defineProperty2.default)(this, "_isCopyEvent", false);
234
+ (0, _defineProperty2.default)(this, "unpublishedFlagShown", new Set());
235
+ (0, _defineProperty2.default)(this, "inlineExtensionFlagShown", new Set());
236
+ }
237
+ return (0, _createClass2.default)(SyncedBlockPluginContext, [{
238
+ key: "isCopyEvent",
239
+ get: function get() {
240
+ return this._isCopyEvent;
241
+ }
242
+ }, {
243
+ key: "markCopyEvent",
244
+ value: function markCopyEvent() {
245
+ this._isCopyEvent = true;
246
+ }
247
+ }, {
248
+ key: "consumeCopyEvent",
249
+ value: function consumeCopyEvent() {
250
+ var was = this._isCopyEvent;
251
+ this._isCopyEvent = false;
252
+ return was;
253
+ }
254
+ }]);
255
+ }();
113
256
  var createPlugin = exports.createPlugin = function createPlugin(options, pmPluginFactoryParams, syncBlockStore, api) {
114
- var _ref3 = options || {},
115
- _ref3$useLongPressSel = _ref3.useLongPressSelection,
116
- useLongPressSelection = _ref3$useLongPressSel === void 0 ? false : _ref3$useLongPressSel;
117
- var confirmationTransactionRef = {
257
+ var _ctx$confirmationTran, _ctx$unpublishedFlagS, _ctx$inlineExtensionF;
258
+ var _ref6 = options || {},
259
+ _ref6$useLongPressSel = _ref6.useLongPressSelection,
260
+ useLongPressSelection = _ref6$useLongPressSel === void 0 ? false : _ref6$useLongPressSel;
261
+ var ctx = (0, _platformFeatureFlags.fg)('platform_synced_block_patch_5') ? new SyncedBlockPluginContext() : undefined;
262
+ var confirmationTransactionRef = (_ctx$confirmationTran = ctx === null || ctx === void 0 ? void 0 : ctx.confirmationTransactionRef) !== null && _ctx$confirmationTran !== void 0 ? _ctx$confirmationTran : {
118
263
  current: undefined
119
264
  };
120
- // Track if a copy event occurred to distinguish copy from drag and drop
121
265
  var isCopyEvent = false;
122
- // Track which sync blocks have already triggered the unpublished flag
123
- var unpublishedFlagShown = new Set();
124
- // Track which sync blocks have already triggered the inline extension in sync block flag
125
- var inlineExtensionFlagShown = new Set();
266
+ var unpublishedFlagShown = (_ctx$unpublishedFlagS = ctx === null || ctx === void 0 ? void 0 : ctx.unpublishedFlagShown) !== null && _ctx$unpublishedFlagS !== void 0 ? _ctx$unpublishedFlagS : new Set();
267
+ var inlineExtensionFlagShown = (_ctx$inlineExtensionF = ctx === null || ctx === void 0 ? void 0 : ctx.inlineExtensionFlagShown) !== null && _ctx$inlineExtensionF !== void 0 ? _ctx$inlineExtensionF : new Set();
126
268
 
127
269
  // Set up callback to detect unpublished sync blocks when they're fetched
128
270
  syncBlockStore.referenceManager.setOnUnpublishedSyncBlockDetected(function (resourceId) {
129
271
  // Only show the flag once per sync block
130
272
  if (!unpublishedFlagShown.has(resourceId)) {
131
273
  unpublishedFlagShown.add(resourceId);
132
- // Use setTimeout to dispatch transaction in next tick and avoid re-entrant dispatch
133
- setTimeout(function () {
134
- api === null || api === void 0 || api.core.actions.execute(function (_ref4) {
135
- var tr = _ref4.tr;
274
+ (0, _utils2.deferDispatch)(function () {
275
+ api === null || api === void 0 || api.core.actions.execute(function (_ref7) {
276
+ var tr = _ref7.tr;
136
277
  return tr.setMeta(syncedBlockPluginKey, {
137
278
  activeFlag: {
138
279
  id: _types.FLAG_ID.UNPUBLISHED_SYNC_BLOCK_PASTED
139
280
  }
140
281
  });
141
282
  });
142
- }, 0);
283
+ });
143
284
  }
144
285
  });
145
286
  return new _safePlugin.SafePlugin({
@@ -182,22 +323,29 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
182
323
  props: {
183
324
  nodeViews: {
184
325
  syncBlock: function syncBlock(node, view, getPos, _decorations) {
185
- // To support SSR, pass `syncBlockStore` here
186
- // and do not use lazy loading.
187
- // We cannot start rendering and then load `syncBlockStore` asynchronously,
188
- // because obtaining it is asynchronous (sharedPluginState.currentState() is delayed).
189
- return new _syncedBlock.SyncBlock({
190
- api: api,
191
- options: options,
192
- node: node,
193
- view: view,
194
- getPos: getPos,
195
- portalProviderAPI: pmPluginFactoryParams.portalProviderAPI,
196
- eventDispatcher: pmPluginFactoryParams.eventDispatcher,
197
- syncBlockStore: syncBlockStore
198
- }).init();
326
+ return (
327
+ // To support SSR, pass `syncBlockStore` here
328
+ // and do not use lazy loading.
329
+ // We cannot start rendering and then load `syncBlockStore` asynchronously,
330
+ // because obtaining it is asynchronous (sharedPluginState.currentState() is delayed).
331
+ new _syncedBlock.SyncBlock({
332
+ api: api,
333
+ options: options,
334
+ node: node,
335
+ view: view,
336
+ getPos: getPos,
337
+ portalProviderAPI: pmPluginFactoryParams.portalProviderAPI,
338
+ eventDispatcher: pmPluginFactoryParams.eventDispatcher,
339
+ syncBlockStore: syncBlockStore
340
+ }).init()
341
+ );
199
342
  },
200
- bodiedSyncBlock: (0, _bodiedLazySyncedBlock.lazyBodiedSyncBlockView)({
343
+ bodiedSyncBlock: (0, _platformFeatureFlags.fg)('platform_synced_block_patch_5') ? (0, _bodiedSyncedBlock.bodiedSyncBlockNodeView)({
344
+ pluginOptions: options,
345
+ pmPluginFactoryParams: pmPluginFactoryParams,
346
+ api: api,
347
+ syncBlockStore: syncBlockStore
348
+ }) : (0, _bodiedLazySyncedBlock.lazyBodiedSyncBlockView)({
201
349
  pluginOptions: options,
202
350
  pmPluginFactoryParams: pmPluginFactoryParams,
203
351
  api: api
@@ -246,17 +394,23 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
246
394
  return (0, _ignoreDomEvent.shouldIgnoreDomEvent)(view, event, api);
247
395
  },
248
396
  copy: function copy() {
249
- isCopyEvent = true;
397
+ if (ctx) {
398
+ ctx.markCopyEvent();
399
+ } else {
400
+ isCopyEvent = true;
401
+ }
250
402
  return false;
251
403
  }
252
404
  },
253
- transformCopied: function transformCopied(slice, _ref5) {
254
- var state = _ref5.state;
405
+ transformCopied: function transformCopied(slice, _ref8) {
406
+ var state = _ref8.state;
255
407
  var pluginState = syncedBlockPluginKey.getState(state);
256
408
  var syncBlockStore = pluginState === null || pluginState === void 0 ? void 0 : pluginState.syncBlockStore;
257
409
  var schema = state.schema;
258
- var isCopy = isCopyEvent;
259
- isCopyEvent = false;
410
+ var isCopy = ctx ? ctx.consumeCopyEvent() : isCopyEvent;
411
+ if (!ctx) {
412
+ isCopyEvent = false;
413
+ }
260
414
  if (!syncBlockStore || !isCopy) {
261
415
  return slice;
262
416
  }
@@ -295,11 +449,10 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
295
449
 
296
450
  // Track newly added reference sync blocks before processing the transaction
297
451
  if (tr.docChanged && !tr.getMeta('isRemote')) {
298
- var _trackSyncBlocks = (0, _trackSyncBlocks6.trackSyncBlocks)(function (node) {
452
+ var _trackSyncBlocks3 = (0, _trackSyncBlocks8.trackSyncBlocks)(function (node) {
299
453
  return node.type.name === 'syncBlock';
300
454
  }, tr, state),
301
- added = _trackSyncBlocks.added;
302
- // Mark newly added sync blocks so we can detect unpublished status when data is fetched
455
+ added = _trackSyncBlocks3.added;
303
456
  added.forEach(function (nodeInfo) {
304
457
  var _nodeInfo$attrs;
305
458
  if ((_nodeInfo$attrs = nodeInfo.attrs) !== null && _nodeInfo$attrs !== void 0 && _nodeInfo$attrs.resourceId) {
@@ -307,26 +460,40 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
307
460
  }
308
461
  });
309
462
  }
310
-
311
- // Ignore transactions that don't change the document
312
- // or are from remote (collab) or already confirmed sync block deletion
313
- // We only care about local changes that change the document
314
- // and are not yet confirmed for sync block deletion
315
463
  if (!tr.docChanged || Boolean(tr.getMeta('isRemote')) || !isOffline && isConfirmedSyncBlockDeletion) {
316
464
  return true;
317
465
  }
318
- var _trackSyncBlocks2 = (0, _trackSyncBlocks6.trackSyncBlocks)(syncBlockStore.sourceManager.isSourceBlock, tr, state),
319
- bodiedSyncBlockRemoved = _trackSyncBlocks2.removed,
320
- bodiedSyncBlockAdded = _trackSyncBlocks2.added;
466
+ var _trackSyncBlocks4 = (0, _trackSyncBlocks8.trackSyncBlocks)(syncBlockStore.sourceManager.isSourceBlock, tr, state),
467
+ bodiedSyncBlockRemoved = _trackSyncBlocks4.removed,
468
+ bodiedSyncBlockAdded = _trackSyncBlocks4.added;
469
+ if ((0, _platformFeatureFlags.fg)('platform_synced_block_patch_5')) {
470
+ return isOffline ? filterTransactionOffline({
471
+ tr: tr,
472
+ state: state,
473
+ api: api,
474
+ isConfirmedSyncBlockDeletion: isConfirmedSyncBlockDeletion,
475
+ bodiedSyncBlockRemoved: bodiedSyncBlockRemoved,
476
+ bodiedSyncBlockAdded: bodiedSyncBlockAdded
477
+ }) : filterTransactionOnline({
478
+ tr: tr,
479
+ state: state,
480
+ syncBlockStore: syncBlockStore,
481
+ api: api,
482
+ confirmationTransactionRef: confirmationTransactionRef,
483
+ bodiedSyncBlockRemoved: bodiedSyncBlockRemoved,
484
+ bodiedSyncBlockAdded: bodiedSyncBlockAdded,
485
+ inlineExtensionFlagShown: inlineExtensionFlagShown
486
+ });
487
+ }
321
488
  if (!isOffline) {
322
- var _trackSyncBlocks3 = (0, _trackSyncBlocks6.trackSyncBlocks)(function (node) {
489
+ var _trackSyncBlocks5 = (0, _trackSyncBlocks8.trackSyncBlocks)(function (node) {
323
490
  return node.type.name === 'syncBlock';
324
491
  }, tr, state),
325
- syncBlockRemoved = _trackSyncBlocks3.removed,
326
- syncBlockAdded = _trackSyncBlocks3.added;
327
- syncBlockRemoved.forEach(function (syncBlock) {
328
- var _api$analytics;
329
- api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.fireAnalyticsEvent({
492
+ _syncBlockRemoved = _trackSyncBlocks5.removed,
493
+ _syncBlockAdded = _trackSyncBlocks5.added;
494
+ _syncBlockRemoved.forEach(function (syncBlock) {
495
+ var _api$analytics4;
496
+ api === null || api === void 0 || (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 || (_api$analytics4 = _api$analytics4.actions) === null || _api$analytics4 === void 0 || _api$analytics4.fireAnalyticsEvent({
330
497
  action: _analytics.ACTION.DELETED,
331
498
  actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK,
332
499
  actionSubjectId: _analytics.ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_DELETE,
@@ -337,10 +504,10 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
337
504
  eventType: _analytics.EVENT_TYPE.OPERATIONAL
338
505
  });
339
506
  });
340
- syncBlockAdded.forEach(function (syncBlock) {
507
+ _syncBlockAdded.forEach(function (syncBlock) {
341
508
  if ((0, _platformFeatureFlags.fg)('platform_synced_block_patch_3')) {
342
- var _api$analytics2;
343
- api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.fireAnalyticsEvent({
509
+ var _api$analytics5;
510
+ api === null || api === void 0 || (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 || (_api$analytics5 = _api$analytics5.actions) === null || _api$analytics5 === void 0 || _api$analytics5.fireAnalyticsEvent({
344
511
  action: _analytics.ACTION.INSERTED,
345
512
  actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
346
513
  actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK,
@@ -351,8 +518,8 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
351
518
  eventType: _analytics.EVENT_TYPE.TRACK
352
519
  });
353
520
  } else {
354
- var _api$analytics3;
355
- api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || (_api$analytics3 = _api$analytics3.actions) === null || _api$analytics3 === void 0 || _api$analytics3.fireAnalyticsEvent({
521
+ var _api$analytics6;
522
+ api === null || api === void 0 || (_api$analytics6 = api.analytics) === null || _api$analytics6 === void 0 || (_api$analytics6 = _api$analytics6.actions) === null || _api$analytics6 === void 0 || _api$analytics6.fireAnalyticsEvent({
356
523
  action: _analytics.ACTION.INSERTED,
357
524
  actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK,
358
525
  actionSubjectId: _analytics.ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_CREATE,
@@ -369,7 +536,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
369
536
  return (0, _handleBodiedSyncBlockRemoval.handleBodiedSyncBlockRemoval)(bodiedSyncBlockRemoved, syncBlockStore, api, confirmationTransactionRef, getDeleteReason(tr));
370
537
  }
371
538
  if (bodiedSyncBlockAdded.length > 0) {
372
- if (Boolean(tr.getMeta(_utils.pmHistoryPluginKey))) {
539
+ if (tr.getMeta(_utils.pmHistoryPluginKey)) {
373
540
  // We don't allow bodiedSyncBlock creation via redo, however, we need to return true here to let transaction through so history can be updated properly.
374
541
  // If we simply returns false, creation from redo is blocked as desired, but this results in editor showing redo as possible even though it's not.
375
542
  // After true is returned here and the node is created, we delete the node in the filterTransaction immediately, which cancels out the creation
@@ -380,36 +547,34 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
380
547
  }
381
548
  showInlineExtensionInSyncBlockWarningIfNeeded(tr, state, api, inlineExtensionFlagShown);
382
549
  return true;
383
- } else {
384
- var _trackSyncBlocks4 = (0, _trackSyncBlocks6.trackSyncBlocks)(function (node) {
385
- return node.type.name === 'syncBlock';
386
- }, tr, state),
387
- _syncBlockRemoved = _trackSyncBlocks4.removed,
388
- _syncBlockAdded = _trackSyncBlocks4.added;
389
- var errorFlag = false;
550
+ }
551
+ var _trackSyncBlocks6 = (0, _trackSyncBlocks8.trackSyncBlocks)(function (node) {
552
+ return node.type.name === 'syncBlock';
553
+ }, tr, state),
554
+ syncBlockRemoved = _trackSyncBlocks6.removed,
555
+ syncBlockAdded = _trackSyncBlocks6.added;
556
+ var errorFlag = false;
390
557
 
391
- // Disable (bodied)syncBlock node deletion/creation/edition in offline mode and trigger an error flag instead
392
- if (isConfirmedSyncBlockDeletion || bodiedSyncBlockRemoved.length > 0 || _syncBlockRemoved.length > 0) {
393
- errorFlag = _types.FLAG_ID.CANNOT_DELETE_WHEN_OFFLINE;
394
- } else if (bodiedSyncBlockAdded.length > 0 || _syncBlockAdded.length > 0) {
395
- errorFlag = _types.FLAG_ID.CANNOT_CREATE_WHEN_OFFLINE;
396
- } else if ((0, _trackSyncBlocks6.hasEditInSyncBlock)(tr, state)) {
397
- errorFlag = _types.FLAG_ID.CANNOT_EDIT_WHEN_OFFLINE;
398
- }
399
- if (errorFlag) {
400
- // Use setTimeout to dispatch transaction in next tick and avoid re-entrant dispatch
401
- setTimeout(function () {
402
- api === null || api === void 0 || api.core.actions.execute(function (_ref6) {
403
- var tr = _ref6.tr;
404
- return tr.setMeta(syncedBlockPluginKey, {
405
- activeFlag: {
406
- id: errorFlag
407
- }
408
- });
558
+ // Disable (bodied)syncBlock node deletion/creation/edition in offline mode and trigger an error flag instead
559
+ if (isConfirmedSyncBlockDeletion || bodiedSyncBlockRemoved.length > 0 || syncBlockRemoved.length > 0) {
560
+ errorFlag = _types.FLAG_ID.CANNOT_DELETE_WHEN_OFFLINE;
561
+ } else if (bodiedSyncBlockAdded.length > 0 || syncBlockAdded.length > 0) {
562
+ errorFlag = _types.FLAG_ID.CANNOT_CREATE_WHEN_OFFLINE;
563
+ } else if ((0, _trackSyncBlocks8.hasEditInSyncBlock)(tr, state)) {
564
+ errorFlag = _types.FLAG_ID.CANNOT_EDIT_WHEN_OFFLINE;
565
+ }
566
+ if (errorFlag) {
567
+ (0, _utils2.deferDispatch)(function () {
568
+ api === null || api === void 0 || api.core.actions.execute(function (_ref9) {
569
+ var tr = _ref9.tr;
570
+ return tr.setMeta(syncedBlockPluginKey, {
571
+ activeFlag: {
572
+ id: errorFlag
573
+ }
409
574
  });
410
- }, 0);
411
- return false;
412
- }
575
+ });
576
+ });
577
+ return false;
413
578
  }
414
579
  return true;
415
580
  },
@@ -426,29 +591,27 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
426
591
  try {
427
592
  var _loop = function _loop() {
428
593
  var tr = _step2.value;
429
- if (!tr.getMeta(_utils.pmHistoryPluginKey)) {
430
- return 0; // continue
431
- }
432
- var _trackSyncBlocks5 = (0, _trackSyncBlocks6.trackSyncBlocks)(syncBlockStore.sourceManager.isSourceBlock, tr, oldState),
433
- added = _trackSyncBlocks5.added;
434
- if (added.length > 0) {
435
- // Delete bodiedSyncBlock if it's originated from history, i.e. redo creation
436
- // See filterTransaction above for more details
437
- var _tr = newState.tr;
438
- added.forEach(function (node) {
439
- if (node.from !== undefined && node.to !== undefined) {
440
- _tr.delete(node.from, node.to);
441
- }
442
- });
443
- return {
444
- v: _tr
445
- };
594
+ if (tr.getMeta(_utils.pmHistoryPluginKey)) {
595
+ var _trackSyncBlocks7 = (0, _trackSyncBlocks8.trackSyncBlocks)(syncBlockStore.sourceManager.isSourceBlock, tr, oldState),
596
+ added = _trackSyncBlocks7.added;
597
+ if (added.length > 0) {
598
+ // Delete bodiedSyncBlock if it's originated from history, i.e. redo creation
599
+ // See filterTransaction above for more details
600
+ var _tr = newState.tr;
601
+ added.forEach(function (node) {
602
+ if (node.from !== undefined && node.to !== undefined) {
603
+ _tr.delete(node.from, node.to);
604
+ }
605
+ });
606
+ return {
607
+ v: _tr
608
+ };
609
+ }
446
610
  }
447
611
  },
448
612
  _ret;
449
613
  for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
450
614
  _ret = _loop();
451
- if (_ret === 0) continue;
452
615
  if (_ret) return _ret.v;
453
616
  }
454
617
  } catch (err) {
@@ -9,6 +9,7 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
9
9
  var _state = require("@atlaskit/editor-prosemirror/state");
10
10
  var _types = require("../../types");
11
11
  var _main = require("../main");
12
+ var _utils = require("./utils");
12
13
  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; }
13
14
  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; }
14
15
  var onRetry = function onRetry(api, resourceId) {
@@ -86,7 +87,7 @@ var handleBodiedSyncBlockCreation = exports.handleBodiedSyncBlockCreation = func
86
87
  to: node.to
87
88
  };
88
89
  var resourceId = node.attrs.resourceId;
89
- setTimeout(function () {
90
+ (0, _utils.deferDispatch)(function () {
90
91
  var _api$core3;
91
92
  api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref2) {
92
93
  var tr = _ref2.tr;
@@ -3,11 +3,23 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.wasInlineExtensionInsertedInBodiedSyncBlock = exports.sliceFullyContainsNode = exports.isBodiedSyncBlockNode = exports.findSyncBlockOrBodiedSyncBlock = exports.findSyncBlock = exports.findBodiedSyncBlock = exports.canBeConvertedToSyncBlock = void 0;
6
+ exports.wasInlineExtensionInsertedInBodiedSyncBlock = exports.sliceFullyContainsNode = exports.isBodiedSyncBlockNode = exports.findSyncBlockOrBodiedSyncBlock = exports.findSyncBlock = exports.findBodiedSyncBlock = exports.deferDispatch = exports.canBeConvertedToSyncBlock = void 0;
7
7
  var _selection = require("@atlaskit/editor-common/selection");
8
8
  var _model = require("@atlaskit/editor-prosemirror/model");
9
9
  var _transform = require("@atlaskit/editor-prosemirror/transform");
10
10
  var _utils = require("@atlaskit/editor-prosemirror/utils");
11
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
12
+ /**
13
+ * Defers a callback to the next microtask (when gated) or next macrotask via setTimeout(0).
14
+ * Used to avoid re-entrant ProseMirror dispatch cycles.
15
+ */
16
+ var deferDispatch = exports.deferDispatch = function deferDispatch(fn) {
17
+ if ((0, _platformFeatureFlags.fg)('platform_synced_block_patch_5')) {
18
+ queueMicrotask(fn);
19
+ } else {
20
+ setTimeout(fn, 0);
21
+ }
22
+ };
11
23
  var findSyncBlock = exports.findSyncBlock = function findSyncBlock(schema, selection) {
12
24
  var syncBlock = schema.nodes.syncBlock;
13
25
  return (0, _utils.findSelectedNodeOfType)(syncBlock)(selection);
@@ -5,7 +5,7 @@ import { DOMSerializer, Fragment } from '@atlaskit/editor-prosemirror/model';
5
5
  import { TextSelection } from '@atlaskit/editor-prosemirror/state';
6
6
  import { findSelectedNodeOfType, removeParentNodeOfType, removeSelectedNode, safeInsert } from '@atlaskit/editor-prosemirror/utils';
7
7
  import { syncedBlockPluginKey } from '../pm-plugins/main';
8
- import { canBeConvertedToSyncBlock, findSyncBlock, findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
8
+ import { canBeConvertedToSyncBlock, deferDispatch, findSyncBlock, findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
9
9
  import { FLAG_ID } from '../types';
10
10
  import { pasteSyncBlockHTMLContent } from './utils';
11
11
  export const createSyncedBlock = ({
@@ -88,9 +88,7 @@ export const copySyncedBlockReferenceToClipboardEditorCommand = (syncBlockStore,
88
88
  }
89
89
  return null;
90
90
  };
91
- export const copySyncedBlockReferenceToClipboard = (syncBlockStore, inputMethod, api) => (state, _dispatch, _view) => {
92
- return copySyncedBlockReferenceToClipboardInternal(state.tr.doc.type.schema, state.tr.selection, syncBlockStore, inputMethod, api);
93
- };
91
+ export const copySyncedBlockReferenceToClipboard = (syncBlockStore, inputMethod, api) => (state, _dispatch, _view) => copySyncedBlockReferenceToClipboardInternal(state.tr.doc.type.schema, state.tr.selection, syncBlockStore, inputMethod, api);
94
92
  const copySyncedBlockReferenceToClipboardInternal = (schema, selection, syncBlockStore, inputMethod, api) => {
95
93
  const syncBlockFindResult = findSyncBlockOrBodiedSyncBlock(schema, selection);
96
94
  if (!syncBlockFindResult) {
@@ -154,9 +152,7 @@ const copySyncedBlockReferenceToClipboardInternal = (schema, selection, syncBloc
154
152
  }
155
153
  const domNode = toDOM(referenceSyncBlockNode, schema);
156
154
  copyDomNode(domNode, referenceSyncBlockNode.type, selection);
157
-
158
- // Use setTimeout to dispatch transaction in next tick and avoid re-entrant dispatch
159
- setTimeout(() => {
155
+ deferDispatch(() => {
160
156
  api === null || api === void 0 ? void 0 : api.core.actions.execute(({
161
157
  tr
162
158
  }) => {
@@ -177,7 +173,7 @@ const copySyncedBlockReferenceToClipboardInternal = (schema, selection, syncBloc
177
173
  }
178
174
  });
179
175
  });
180
- }, 0);
176
+ });
181
177
  return true;
182
178
  };
183
179
  export const editSyncedBlockSource = (syncBlockStore, api) => (state, dispatch, _view) => {
@@ -202,7 +198,9 @@ export const editSyncedBlockSource = (syncBlockStore, api) => (state, dispatch,
202
198
  window.open(syncBlockURL, '_blank');
203
199
  } else {
204
200
  var _api$analytics6, _api$analytics6$actio;
205
- const tr = state.tr;
201
+ const {
202
+ tr
203
+ } = state;
206
204
  api === null || api === void 0 ? void 0 : (_api$analytics6 = api.analytics) === null || _api$analytics6 === void 0 ? void 0 : (_api$analytics6$actio = _api$analytics6.actions) === null || _api$analytics6$actio === void 0 ? void 0 : _api$analytics6$actio.attachAnalyticsEvent({
207
205
  eventType: EVENT_TYPE.OPERATIONAL,
208
206
  action: ACTION.ERROR,
@@ -268,7 +266,9 @@ export const unsync = (storeManager, isBodiedSyncBlock, view) => {
268
266
  }
269
267
  if (isBodiedSyncBlock) {
270
268
  const content = syncBlock === null || syncBlock === void 0 ? void 0 : syncBlock.node.content;
271
- const tr = state.tr;
269
+ const {
270
+ tr
271
+ } = state;
272
272
  tr.replaceWith(syncBlock.pos, syncBlock.pos + syncBlock.node.nodeSize, content).setMeta('deletionReason', 'source-block-unsynced');
273
273
  view.dispatch(tr);
274
274
  return true;