@atlaskit/editor-plugin-synced-block 8.3.3 → 8.3.4
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/AGENTS.md +1 -2
- package/CHANGELOG.md +8 -0
- package/dist/cjs/nodeviews/bodiedSyncedBlock.js +7 -25
- package/dist/cjs/nodeviews/syncedBlock.js +1 -4
- package/dist/cjs/pm-plugins/main.js +54 -60
- package/dist/cjs/pm-plugins/menu-and-toolbar-experiences.js +10 -19
- package/dist/cjs/pm-plugins/utils/utils.js +3 -10
- package/dist/cjs/syncedBlockPlugin.js +1 -7
- package/dist/cjs/ui/DeleteConfirmationModal.js +29 -93
- package/dist/cjs/ui/SyncBlockLabel.js +1 -4
- package/dist/cjs/ui/SyncedLocationDropdown.js +2 -2
- package/dist/cjs/ui/floating-toolbar.js +1 -2
- package/dist/cjs/ui/quick-insert.js +2 -3
- package/dist/es2019/nodeviews/bodiedSyncedBlock.js +7 -23
- package/dist/es2019/nodeviews/syncedBlock.js +1 -4
- package/dist/es2019/pm-plugins/main.js +42 -48
- package/dist/es2019/pm-plugins/menu-and-toolbar-experiences.js +7 -19
- package/dist/es2019/pm-plugins/utils/utils.js +3 -11
- package/dist/es2019/syncedBlockPlugin.js +1 -7
- package/dist/es2019/ui/DeleteConfirmationModal.js +36 -77
- package/dist/es2019/ui/SyncBlockLabel.js +1 -4
- package/dist/es2019/ui/SyncedLocationDropdown.js +2 -2
- package/dist/es2019/ui/floating-toolbar.js +1 -2
- package/dist/es2019/ui/quick-insert.js +2 -2
- package/dist/esm/nodeviews/bodiedSyncedBlock.js +7 -25
- package/dist/esm/nodeviews/syncedBlock.js +1 -4
- package/dist/esm/pm-plugins/main.js +54 -60
- package/dist/esm/pm-plugins/menu-and-toolbar-experiences.js +10 -19
- package/dist/esm/pm-plugins/utils/utils.js +3 -11
- package/dist/esm/syncedBlockPlugin.js +1 -7
- package/dist/esm/ui/DeleteConfirmationModal.js +29 -93
- package/dist/esm/ui/SyncBlockLabel.js +1 -4
- package/dist/esm/ui/SyncedLocationDropdown.js +2 -2
- package/dist/esm/ui/floating-toolbar.js +1 -2
- package/dist/esm/ui/quick-insert.js +2 -3
- package/dist/types/nodeviews/bodiedSyncedBlock.d.ts +1 -3
- package/dist/types-ts4.5/nodeviews/bodiedSyncedBlock.d.ts +1 -3
- package/docs/0-intro.tsx +1 -1
- package/package.json +2 -17
- package/dist/cjs/nodeviews/bodiedSyncBlockNodeWithToDOMFixed.js +0 -35
- package/dist/es2019/nodeviews/bodiedSyncBlockNodeWithToDOMFixed.js +0 -27
- package/dist/esm/nodeviews/bodiedSyncBlockNodeWithToDOMFixed.js +0 -28
- package/dist/types/nodeviews/bodiedSyncBlockNodeWithToDOMFixed.d.ts +0 -6
- package/dist/types-ts4.5/nodeviews/bodiedSyncBlockNodeWithToDOMFixed.d.ts +0 -6
|
@@ -13,7 +13,6 @@ var _messages = require("@atlaskit/editor-common/messages");
|
|
|
13
13
|
var _syncBlock = require("@atlaskit/editor-common/sync-block");
|
|
14
14
|
var _blockSynced = _interopRequireDefault(require("@atlaskit/icon-lab/core/block-synced"));
|
|
15
15
|
var _compiled = require("@atlaskit/primitives/compiled");
|
|
16
|
-
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
17
16
|
var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
|
|
18
17
|
var _visuallyHidden = _interopRequireDefault(require("@atlaskit/visually-hidden"));
|
|
19
18
|
var _time = require("./utils/time");
|
|
@@ -80,9 +79,7 @@ var SyncBlockLabelComponent = function SyncBlockLabelComponent(_ref) {
|
|
|
80
79
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
81
80
|
,
|
|
82
81
|
className: _syncBlock.SyncBlockLabelSharedCssClassName.labelClassName,
|
|
83
|
-
"aria-describedby":
|
|
84
|
-
exposure: true
|
|
85
|
-
}) ? undefined : ariaDescribedById
|
|
82
|
+
"aria-describedby": isSource || isUnsyncedBlock ? undefined : ariaDescribedById
|
|
86
83
|
}, /*#__PURE__*/_react.default.createElement(_blockSynced.default, {
|
|
87
84
|
color: "var(--ds-icon-subtle, #505258)",
|
|
88
85
|
size: "small",
|
|
@@ -278,7 +278,7 @@ var processReferenceData = exports.processReferenceData = function processRefere
|
|
|
278
278
|
var references = _step.value;
|
|
279
279
|
if (references.length > 1) {
|
|
280
280
|
references.forEach(function (reference, index) {
|
|
281
|
-
return reference.title = "".concat(reference.title === '' && reference.hasAccess
|
|
281
|
+
return reference.title = "".concat(reference.title === '' && reference.hasAccess ? formatMessage(_messages.syncBlockMessages.syncedLocationDropdownUntitledPage) : reference.title, ": ").concat(formatMessage(_messages.syncBlockMessages.syncedLocationDropdownTitleBlockIndex, {
|
|
282
282
|
index: index + 1
|
|
283
283
|
}));
|
|
284
284
|
});
|
|
@@ -428,7 +428,7 @@ var DropdownContent = function DropdownContent(_ref7) {
|
|
|
428
428
|
count: "".concat(referenceData.length > 99 ? '99+' : referenceData.length)
|
|
429
429
|
})
|
|
430
430
|
}, referenceData.map(function (reference) {
|
|
431
|
-
var title = reference.title === '' && reference.hasAccess
|
|
431
|
+
var title = reference.title === '' && reference.hasAccess ? formatMessage(_messages.syncBlockMessages.syncedLocationDropdownUntitledPage) : reference.title || reference.url || '';
|
|
432
432
|
return /*#__PURE__*/React.createElement("div", {
|
|
433
433
|
key: reference.title,
|
|
434
434
|
className: (0, _runtime.ax)(["_2ll012x7"])
|
|
@@ -18,7 +18,6 @@ var _copy = _interopRequireDefault(require("@atlaskit/icon/core/copy"));
|
|
|
18
18
|
var _delete = _interopRequireDefault(require("@atlaskit/icon/core/delete"));
|
|
19
19
|
var _edit = _interopRequireDefault(require("@atlaskit/icon/core/edit"));
|
|
20
20
|
var _linkBroken = _interopRequireDefault(require("@atlaskit/icon/core/link-broken"));
|
|
21
|
-
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
22
21
|
var _editorCommands = require("../editor-commands");
|
|
23
22
|
var _utils2 = require("../pm-plugins/utils/utils");
|
|
24
23
|
var _types = require("../types");
|
|
@@ -87,7 +86,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(stat
|
|
|
87
86
|
var _syncBlockInstance$da;
|
|
88
87
|
return /*#__PURE__*/_react.default.createElement(_ui.FloatingToolbarButton, {
|
|
89
88
|
areAnyNewToolbarFlagsEnabled: true,
|
|
90
|
-
disabled: (
|
|
89
|
+
disabled: (syncBlockInstance === null || syncBlockInstance === void 0 || (_syncBlockInstance$da = syncBlockInstance.data) === null || _syncBlockInstance$da === void 0 ? void 0 : _syncBlockInstance$da.status) === 'unpublished',
|
|
91
90
|
icon: /*#__PURE__*/_react.default.createElement(_linkBroken.default, {
|
|
92
91
|
label: ""
|
|
93
92
|
}),
|
|
@@ -10,7 +10,6 @@ exports.getQuickInsertConfig = void 0;
|
|
|
10
10
|
require("./quick-insert.compiled.css");
|
|
11
11
|
var React = _interopRequireWildcard(require("react"));
|
|
12
12
|
var _runtime = require("@compiled/react/runtime");
|
|
13
|
-
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
14
13
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
15
14
|
var _quickInsert = require("@atlaskit/editor-common/quick-insert");
|
|
16
15
|
var _lozenge = _interopRequireDefault(require("@atlaskit/lozenge"));
|
|
@@ -29,8 +28,8 @@ var getQuickInsertConfig = exports.getQuickInsertConfig = function getQuickInser
|
|
|
29
28
|
id: 'syncBlock',
|
|
30
29
|
title: formatMessage(_messages.blockTypeMessages.syncedBlock),
|
|
31
30
|
description: formatMessage(_messages.blockTypeMessages.syncedBlockDescription),
|
|
32
|
-
priority:
|
|
33
|
-
keywords: ['synced', 'block', 'synced-block', 'sync', 'sync-block', 'auto', 'update', 'excerpt', 'connect'
|
|
31
|
+
priority: 400,
|
|
32
|
+
keywords: ['synced', 'block', 'synced-block', 'sync', 'sync-block', 'auto', 'update', 'excerpt', 'connect', 'create'],
|
|
34
33
|
isDisabledOffline: true,
|
|
35
34
|
keyshortcut: '',
|
|
36
35
|
lozenge: /*#__PURE__*/React.createElement("span", {
|
|
@@ -5,7 +5,6 @@ import ReactNodeView from '@atlaskit/editor-common/react-node-view';
|
|
|
5
5
|
import { BodiedSyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
|
|
6
6
|
import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
|
|
7
7
|
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
8
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
9
8
|
import { BodiedSyncBlockWrapper } from '../ui/BodiedSyncBlockWrapper';
|
|
10
9
|
import { SyncBlockLabel } from '../ui/SyncBlockLabel';
|
|
11
10
|
const toDOMOld = () => ['div', {
|
|
@@ -138,12 +137,11 @@ const toDOM = node => ['div', {
|
|
|
138
137
|
contenteditable: 'true'
|
|
139
138
|
}, 0]];
|
|
140
139
|
export class BodiedSyncBlock {
|
|
141
|
-
constructor(node, view, getPos, api, nodeViewPortalProviderAPI
|
|
140
|
+
constructor(node, view, getPos, api, nodeViewPortalProviderAPI) {
|
|
142
141
|
this.node = node;
|
|
143
142
|
this.view = view;
|
|
144
143
|
this.getPos = getPos;
|
|
145
144
|
this.api = api;
|
|
146
|
-
this.syncBlockStore = syncBlockStore;
|
|
147
145
|
this.nodeViewPortalProviderAPI = nodeViewPortalProviderAPI;
|
|
148
146
|
const {
|
|
149
147
|
dom,
|
|
@@ -170,12 +168,8 @@ export class BodiedSyncBlock {
|
|
|
170
168
|
this.handleConnectivityModeChange();
|
|
171
169
|
this.handleViewModeChange();
|
|
172
170
|
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
if (!fg('platform_synced_block_update_refactor')) {
|
|
176
|
-
var _this$syncedBlockStor;
|
|
177
|
-
(_this$syncedBlockStor = this.syncedBlockStore) === null || _this$syncedBlockStor === void 0 ? void 0 : _this$syncedBlockStor.sourceManager.updateSyncBlockData(node, false);
|
|
178
|
-
}
|
|
171
|
+
// Cache is populated in state.init() and updated in appendTransaction,
|
|
172
|
+
// so no additional updateSyncBlockData call is needed here.
|
|
179
173
|
}
|
|
180
174
|
updateContentEditable({
|
|
181
175
|
nextConnectivityMode,
|
|
@@ -213,22 +207,13 @@ export class BodiedSyncBlock {
|
|
|
213
207
|
});
|
|
214
208
|
}
|
|
215
209
|
}
|
|
216
|
-
get syncedBlockStore() {
|
|
217
|
-
var _this$api$syncedBlock2, _this$api10, _this$api10$syncedBlo, _this$api10$syncedBlo2;
|
|
218
|
-
return (_this$api$syncedBlock2 = (_this$api10 = this.api) === null || _this$api10 === void 0 ? void 0 : (_this$api10$syncedBlo = _this$api10.syncedBlock.sharedState) === null || _this$api10$syncedBlo === void 0 ? void 0 : (_this$api10$syncedBlo2 = _this$api10$syncedBlo.currentState()) === null || _this$api10$syncedBlo2 === void 0 ? void 0 : _this$api10$syncedBlo2.syncBlockStore) !== null && _this$api$syncedBlock2 !== void 0 ? _this$api$syncedBlock2 : this.syncBlockStore;
|
|
219
|
-
}
|
|
220
210
|
update(node) {
|
|
221
211
|
if (this.node.type !== node.type) {
|
|
222
212
|
return false;
|
|
223
213
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
if (!fg('platform_synced_block_update_refactor')) {
|
|
228
|
-
var _this$syncedBlockStor2;
|
|
229
|
-
(_this$syncedBlockStor2 = this.syncedBlockStore) === null || _this$syncedBlockStor2 === void 0 ? void 0 : _this$syncedBlockStor2.sourceManager.updateSyncBlockData(node, false);
|
|
230
|
-
}
|
|
231
|
-
}
|
|
214
|
+
|
|
215
|
+
// Cache updates are handled in appendTransaction where we can
|
|
216
|
+
// filter out non-user changes (remote collab, table auto-scale, etc.)
|
|
232
217
|
this.node = node;
|
|
233
218
|
return true;
|
|
234
219
|
}
|
|
@@ -248,12 +233,11 @@ export class BodiedSyncBlock {
|
|
|
248
233
|
export const bodiedSyncBlockNodeView = props => {
|
|
249
234
|
const {
|
|
250
235
|
api,
|
|
251
|
-
syncBlockStore,
|
|
252
236
|
pmPluginFactoryParams: {
|
|
253
237
|
nodeViewPortalProviderAPI
|
|
254
238
|
}
|
|
255
239
|
} = props;
|
|
256
240
|
return (node, view, getPos) => {
|
|
257
|
-
return new BodiedSyncBlock(node, view, getPos, api, nodeViewPortalProviderAPI
|
|
241
|
+
return new BodiedSyncBlock(node, view, getPos, api, nodeViewPortalProviderAPI);
|
|
258
242
|
};
|
|
259
243
|
};
|
|
@@ -5,7 +5,6 @@ import { ErrorBoundary } from '@atlaskit/editor-common/error-boundary';
|
|
|
5
5
|
import ReactNodeView from '@atlaskit/editor-common/react-node-view';
|
|
6
6
|
import { SyncBlockSharedCssClassName, SyncBlockActionsProvider } from '@atlaskit/editor-common/sync-block';
|
|
7
7
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
8
|
-
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
9
8
|
import { removeSyncedBlockAtPos } from '../editor-commands';
|
|
10
9
|
import { SyncBlockRendererWrapper } from '../ui/SyncBlockRendererWrapper';
|
|
11
10
|
export class SyncBlock extends ReactNodeView {
|
|
@@ -42,9 +41,7 @@ export class SyncBlock extends ReactNodeView {
|
|
|
42
41
|
return currentNode.attrs.localId === newNode.attrs.localId && currentNode.attrs.resourceId === newNode.attrs.resourceId;
|
|
43
42
|
}
|
|
44
43
|
update(node, decorations, innerDecorations) {
|
|
45
|
-
return super.update(node, decorations, innerDecorations,
|
|
46
|
-
exposure: true
|
|
47
|
-
}) ? this.validUpdate : undefined);
|
|
44
|
+
return super.update(node, decorations, innerDecorations, this.validUpdate);
|
|
48
45
|
}
|
|
49
46
|
render({
|
|
50
47
|
getPos
|
|
@@ -337,18 +337,14 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
337
337
|
|
|
338
338
|
// Populate source sync block cache from initial document
|
|
339
339
|
// When fg is ON, this replaces the constructor call in the nodeview
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
syncBlockStore.sourceManager.updateSyncBlockData(node, false);
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
// Fetch statuses from the backend so we can identify unpublished blocks on cancel
|
|
348
|
-
if (fg('platform_synced_block_patch_10')) {
|
|
349
|
-
syncBlockStore.sourceManager.fetchAndCacheStatuses();
|
|
340
|
+
instance.doc.forEach(node => {
|
|
341
|
+
if (syncBlockStore.sourceManager.isSourceBlock(node)) {
|
|
342
|
+
syncBlockStore.sourceManager.updateSyncBlockData(node, false);
|
|
350
343
|
}
|
|
351
|
-
}
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// Fetch statuses from the backend so we can identify unpublished blocks on cancel
|
|
347
|
+
syncBlockStore.sourceManager.fetchAndCacheStatuses();
|
|
352
348
|
}
|
|
353
349
|
|
|
354
350
|
// Read initial shared-state signals for status decorations
|
|
@@ -666,7 +662,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
666
662
|
}
|
|
667
663
|
}
|
|
668
664
|
const viewMode = api === null || api === void 0 ? void 0 : (_api$editorViewMode4 = api.editorViewMode) === null || _api$editorViewMode4 === void 0 ? void 0 : (_api$editorViewMode4$ = _api$editorViewMode4.sharedState.currentState()) === null || _api$editorViewMode4$ === void 0 ? void 0 : _api$editorViewMode4$.mode;
|
|
669
|
-
if (viewMode === 'view'
|
|
665
|
+
if (viewMode === 'view') {
|
|
670
666
|
return true;
|
|
671
667
|
}
|
|
672
668
|
const isOffline = isOfflineMode(api === null || api === void 0 ? void 0 : (_api$connectivity5 = api.connectivity) === null || _api$connectivity5 === void 0 ? void 0 : (_api$connectivity5$sh = _api$connectivity5.sharedState.currentState()) === null || _api$connectivity5$sh === void 0 ? void 0 : _api$connectivity5$sh.mode);
|
|
@@ -684,31 +680,30 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
684
680
|
}
|
|
685
681
|
});
|
|
686
682
|
}
|
|
687
|
-
if (fg('platform_synced_block_update_refactor')) {
|
|
688
|
-
// if doc changed and it's a remote transaction, check if any synced block were added,
|
|
689
|
-
// and if so, for source synced blocks, ensure we update the cache with them
|
|
690
|
-
// and for reference synced blocks, ensure we fetch the data from the server
|
|
691
|
-
if (tr.docChanged && tr.getMeta('isRemote')) {
|
|
692
|
-
const {
|
|
693
|
-
added
|
|
694
|
-
} = trackSyncBlocks(node => syncBlockStore.isSyncBlock(node), tr, state);
|
|
695
|
-
const sourceSyncBlockNodes = added.filter(nodeInfo => nodeInfo.node && syncBlockStore.sourceManager.isSourceBlock(nodeInfo.node));
|
|
696
|
-
const referenceSyncBlockNodes = added.filter(nodeInfo => nodeInfo.node && syncBlockStore.referenceManager.isReferenceBlock(nodeInfo.node));
|
|
697
|
-
sourceSyncBlockNodes.forEach(nodeInfo => {
|
|
698
|
-
var _nodeInfo$attrs2;
|
|
699
|
-
if ((_nodeInfo$attrs2 = nodeInfo.attrs) !== null && _nodeInfo$attrs2 !== void 0 && _nodeInfo$attrs2.resourceId && nodeInfo.node) {
|
|
700
|
-
syncBlockStore.sourceManager.updateSyncBlockData(nodeInfo.node, tr.getMeta('isRemote'));
|
|
701
|
-
}
|
|
702
|
-
});
|
|
703
683
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
684
|
+
// if doc changed and it's a remote transaction, check if any synced block were added,
|
|
685
|
+
// and if so, for source synced blocks, ensure we update the cache with them
|
|
686
|
+
// and for reference synced blocks, ensure we fetch the data from the server
|
|
687
|
+
if (tr.docChanged && tr.getMeta('isRemote')) {
|
|
688
|
+
const {
|
|
689
|
+
added
|
|
690
|
+
} = trackSyncBlocks(node => syncBlockStore.isSyncBlock(node), tr, state);
|
|
691
|
+
const sourceSyncBlockNodes = added.filter(nodeInfo => nodeInfo.node && syncBlockStore.sourceManager.isSourceBlock(nodeInfo.node));
|
|
692
|
+
const referenceSyncBlockNodes = added.filter(nodeInfo => nodeInfo.node && syncBlockStore.referenceManager.isReferenceBlock(nodeInfo.node));
|
|
693
|
+
sourceSyncBlockNodes.forEach(nodeInfo => {
|
|
694
|
+
var _nodeInfo$attrs2;
|
|
695
|
+
if ((_nodeInfo$attrs2 = nodeInfo.attrs) !== null && _nodeInfo$attrs2 !== void 0 && _nodeInfo$attrs2.resourceId && nodeInfo.node) {
|
|
696
|
+
syncBlockStore.sourceManager.updateSyncBlockData(nodeInfo.node, tr.getMeta('isRemote'));
|
|
708
697
|
}
|
|
709
|
-
|
|
710
|
-
|
|
698
|
+
});
|
|
699
|
+
|
|
700
|
+
// Fetch statuses for remotely-added source sync blocks
|
|
701
|
+
// so we can identify unpublished blocks on cancel
|
|
702
|
+
if (sourceSyncBlockNodes.length > 0) {
|
|
703
|
+
syncBlockStore.sourceManager.fetchAndCacheStatuses();
|
|
711
704
|
}
|
|
705
|
+
const syncBlockNodes = referenceSyncBlockNodes.map(nodeInfo => nodeInfo.node).filter(node => node !== undefined);
|
|
706
|
+
syncBlockStore.referenceManager.fetchSyncBlocksData(convertPMNodesToSyncBlockNodes(syncBlockNodes));
|
|
712
707
|
}
|
|
713
708
|
if (!tr.docChanged || Boolean(tr.getMeta('isRemote')) || !isOffline && isConfirmedSyncBlockDeletion) {
|
|
714
709
|
return true;
|
|
@@ -751,22 +746,21 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
751
746
|
}
|
|
752
747
|
}
|
|
753
748
|
const viewMode = api === null || api === void 0 ? void 0 : (_api$editorViewMode5 = api.editorViewMode) === null || _api$editorViewMode5 === void 0 ? void 0 : (_api$editorViewMode5$ = _api$editorViewMode5.sharedState.currentState()) === null || _api$editorViewMode5$ === void 0 ? void 0 : _api$editorViewMode5$.mode;
|
|
754
|
-
if (viewMode === 'view'
|
|
749
|
+
if (viewMode === 'view') {
|
|
755
750
|
return null;
|
|
756
751
|
}
|
|
757
752
|
|
|
758
|
-
// Update source sync block cache for user-initiated changes only
|
|
759
|
-
//
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
}
|
|
753
|
+
// Update source sync block cache for user-initiated changes only.
|
|
754
|
+
// Cache updates are handled here instead of in the nodeview update() so we
|
|
755
|
+
// can filter out non-user changes (remote collab, dirty programmatic txns).
|
|
756
|
+
const isUserChange = tr => tr.docChanged && !isDirtyTransaction(tr) && !tr.getMeta('isRemote');
|
|
757
|
+
const hasSourceBlockEdit = trs.some(tr => isUserChange(tr) && hasEditInSyncBlock(tr, oldState));
|
|
758
|
+
if (hasSourceBlockEdit) {
|
|
759
|
+
newState.doc.forEach(node => {
|
|
760
|
+
if (syncBlockStore.sourceManager.isSourceBlock(node)) {
|
|
761
|
+
syncBlockStore.sourceManager.updateSyncBlockData(node, false);
|
|
762
|
+
}
|
|
763
|
+
});
|
|
770
764
|
}
|
|
771
765
|
trs.filter(tr => tr.docChanged).forEach(tr => {
|
|
772
766
|
if (confirmationTransactionRef.current) {
|
|
@@ -800,7 +794,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
800
794
|
// first occurrence and delete subsequent duplicates entirely (including their
|
|
801
795
|
// contents), since a document must not contain two source sync blocks with the
|
|
802
796
|
// same resourceId.
|
|
803
|
-
if (trs.some(tr => tr.docChanged && !tr.getMeta('isRemote'))
|
|
797
|
+
if (trs.some(tr => tr.docChanged && !tr.getMeta('isRemote'))) {
|
|
804
798
|
// Quick check: only walk the full document when at least one
|
|
805
799
|
// transaction inserted a source synced block. This avoids an
|
|
806
800
|
// expensive descendants() traversal on every local edit.
|
|
@@ -3,7 +3,6 @@ import { ACTION, ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics';
|
|
|
3
3
|
import { Experience, EXPERIENCE_ID, ExperienceCheckDomMutation, ExperienceCheckTimeout, getNodeQuery, getPopupContainerFromEditorView, popupWithNestedElement, getSelectionAncestorDOM } from '@atlaskit/editor-common/experiences';
|
|
4
4
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
5
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
7
6
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
8
7
|
import { SYNCED_BLOCK_BUTTON_TEST_ID } from '../types';
|
|
9
8
|
import { syncedBlockPluginKey } from './main';
|
|
@@ -11,7 +10,6 @@ const TIMEOUT_DURATION = 30000;
|
|
|
11
10
|
const pluginKey = new PluginKey('syncedBlockMenuAndToolbarExperience');
|
|
12
11
|
const SYNCED_BLOCK_BUTTON_TEST_IDS = Object.values(SYNCED_BLOCK_BUTTON_TEST_ID);
|
|
13
12
|
const syncedBlockButtonIds = new Set(SYNCED_BLOCK_BUTTON_TEST_IDS);
|
|
14
|
-
let targetEl;
|
|
15
13
|
export const getMenuAndToolbarExperiencesPlugin = ({
|
|
16
14
|
refs,
|
|
17
15
|
dispatchAnalyticsEvent
|
|
@@ -139,7 +137,7 @@ export const getMenuAndToolbarExperiencesPlugin = ({
|
|
|
139
137
|
if (!typeaheadPopup || !(typeaheadPopup instanceof HTMLElement)) {
|
|
140
138
|
return;
|
|
141
139
|
}
|
|
142
|
-
const targetElement =
|
|
140
|
+
const targetElement = typeaheadPopup.querySelector('[role="option"][aria-selected="true"]');
|
|
143
141
|
if (!targetElement || !(targetElement instanceof HTMLElement)) {
|
|
144
142
|
return;
|
|
145
143
|
}
|
|
@@ -297,16 +295,6 @@ const handleButtonClick = ({
|
|
|
297
295
|
const isEnterKey = key => {
|
|
298
296
|
return key === 'Enter';
|
|
299
297
|
};
|
|
300
|
-
const getTarget = containerElement => {
|
|
301
|
-
if (!targetEl) {
|
|
302
|
-
const element = containerElement === null || containerElement === void 0 ? void 0 : containerElement.querySelector('.ProseMirror');
|
|
303
|
-
if (!element || !(element instanceof HTMLElement)) {
|
|
304
|
-
return null;
|
|
305
|
-
}
|
|
306
|
-
targetEl = element;
|
|
307
|
-
}
|
|
308
|
-
return targetEl;
|
|
309
|
-
};
|
|
310
298
|
const syncedBlockAddedToDomCheck = (refs, editorViewRef) => new ExperienceCheckDomMutation({
|
|
311
299
|
onDomMutation: ({
|
|
312
300
|
mutations
|
|
@@ -321,20 +309,20 @@ const syncedBlockAddedToDomCheck = (refs, editorViewRef) => new ExperienceCheckD
|
|
|
321
309
|
observeConfig: () => {
|
|
322
310
|
var _editorViewRef$curren2;
|
|
323
311
|
return [{
|
|
324
|
-
target:
|
|
312
|
+
target: editorViewRef === null || editorViewRef === void 0 ? void 0 : (_editorViewRef$curren2 = editorViewRef.current) === null || _editorViewRef$curren2 === void 0 ? void 0 : _editorViewRef$curren2.dom,
|
|
325
313
|
options: {
|
|
326
314
|
childList: true
|
|
327
315
|
}
|
|
328
316
|
},
|
|
329
317
|
// When wrapping a node with breakout mark with sync block, breakout dom is reused
|
|
330
318
|
// hence we need to observe subtree to catch sync block mutation
|
|
331
|
-
|
|
319
|
+
{
|
|
332
320
|
target: getSelectionAncestorDOM(editorViewRef === null || editorViewRef === void 0 ? void 0 : editorViewRef.current),
|
|
333
321
|
options: {
|
|
334
322
|
childList: true,
|
|
335
323
|
subtree: true
|
|
336
324
|
}
|
|
337
|
-
}]
|
|
325
|
+
}];
|
|
338
326
|
}
|
|
339
327
|
});
|
|
340
328
|
const isBodiedSyncBlockAddedInMutation = ({
|
|
@@ -358,17 +346,17 @@ const referenceSyncBlockRemovedFromDomCheck = (refs, editorViewRef) => new Exper
|
|
|
358
346
|
observeConfig: () => {
|
|
359
347
|
var _editorViewRef$curren3;
|
|
360
348
|
return [{
|
|
361
|
-
target:
|
|
349
|
+
target: editorViewRef === null || editorViewRef === void 0 ? void 0 : (_editorViewRef$curren3 = editorViewRef.current) === null || _editorViewRef$curren3 === void 0 ? void 0 : _editorViewRef$curren3.dom,
|
|
362
350
|
options: {
|
|
363
351
|
childList: true
|
|
364
352
|
}
|
|
365
|
-
},
|
|
353
|
+
}, {
|
|
366
354
|
target: getSelectionAncestorDOM(editorViewRef === null || editorViewRef === void 0 ? void 0 : editorViewRef.current),
|
|
367
355
|
options: {
|
|
368
356
|
childList: true,
|
|
369
357
|
subtree: true
|
|
370
358
|
}
|
|
371
|
-
}]
|
|
359
|
+
}];
|
|
372
360
|
}
|
|
373
361
|
});
|
|
374
362
|
const isSyncBlockRemovedInMutation = ({
|
|
@@ -2,8 +2,6 @@ import { expandSelectionToBlockRange } from '@atlaskit/editor-common/selection';
|
|
|
2
2
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
4
4
|
import { findParentNodeOfType, findParentNodeOfTypeClosestToPos, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
5
|
-
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
6
|
-
|
|
7
5
|
/**
|
|
8
6
|
* Defers a callback to the next microtask (when gated) or next macrotask via setTimeout(0).
|
|
9
7
|
* Used to avoid re-entrant ProseMirror dispatch cycles.
|
|
@@ -96,9 +94,7 @@ const fragmentContainsExtension = fragment => {
|
|
|
96
94
|
if (found) {
|
|
97
95
|
return;
|
|
98
96
|
}
|
|
99
|
-
if (
|
|
100
|
-
exposure: true
|
|
101
|
-
}) ? EXTENSION_NODES.has(node.type.name) : node.type.name === 'inlineExtension') {
|
|
97
|
+
if (EXTENSION_NODES.has(node.type.name)) {
|
|
102
98
|
found = true;
|
|
103
99
|
} else if (node.content.size) {
|
|
104
100
|
if (fragmentContainsExtension(node.content)) {
|
|
@@ -159,17 +155,13 @@ export const wasExtensionInsertedInBodiedSyncBlock = (tr, state) => {
|
|
|
159
155
|
if (resourceId !== undefined) {
|
|
160
156
|
return false;
|
|
161
157
|
}
|
|
162
|
-
if (
|
|
163
|
-
exposure: true
|
|
164
|
-
}) ? EXTENSION_NODES.has(node.type.name) : node.type.name === 'inlineExtension') {
|
|
158
|
+
if (EXTENSION_NODES.has(node.type.name)) {
|
|
165
159
|
const $pos = tr.doc.resolve(pos);
|
|
166
160
|
const parent = findParentNodeOfTypeClosestToPos($pos, bodiedSyncBlock);
|
|
167
161
|
if (parent !== null && parent !== void 0 && parent.node.attrs.resourceId) {
|
|
168
162
|
const mappedPos = tr.mapping.invert().map(pos);
|
|
169
163
|
const nodeBefore = state.doc.nodeAt(mappedPos);
|
|
170
|
-
if (!nodeBefore || (
|
|
171
|
-
exposure: true
|
|
172
|
-
}) ? EXTENSION_NODES.has(nodeBefore.type.name) : nodeBefore.type.name !== 'inlineExtension')) {
|
|
164
|
+
if (!nodeBefore || EXTENSION_NODES.has(nodeBefore.type.name)) {
|
|
173
165
|
resourceId = parent.node.attrs.resourceId;
|
|
174
166
|
return false;
|
|
175
167
|
}
|
|
@@ -4,10 +4,8 @@ import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks'
|
|
|
4
4
|
import { SyncBlockStoreManager } from '@atlaskit/editor-synced-block-provider';
|
|
5
5
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
6
6
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
7
|
-
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
8
7
|
import { flushBodiedSyncBlocks, flushSyncBlocks, discardUnpublishedSyncBlocks } from './editor-actions';
|
|
9
8
|
import { copySyncedBlockReferenceToClipboardEditorCommand, createSyncedBlock } from './editor-commands';
|
|
10
|
-
import { bodiedSyncBlockNodeWithToDOMFixed } from './nodeviews/bodiedSyncBlockNodeWithToDOMFixed';
|
|
11
9
|
import { createPlugin, syncedBlockPluginKey } from './pm-plugins/main';
|
|
12
10
|
import { getMenuAndToolbarExperiencesPlugin } from './pm-plugins/menu-and-toolbar-experiences';
|
|
13
11
|
import { getBlockMenuComponents } from './ui/block-menu-components';
|
|
@@ -78,11 +76,7 @@ export const syncedBlockPlugin = ({
|
|
|
78
76
|
node: syncBlock
|
|
79
77
|
}, {
|
|
80
78
|
name: 'bodiedSyncBlock',
|
|
81
|
-
node:
|
|
82
|
-
exposure: true
|
|
83
|
-
}) ?
|
|
84
|
-
// delete bodiedSyncBlockNodeWithToDOMFixed when cleaning up platform_synced_block_patch_6
|
|
85
|
-
bodiedSyncBlockNodeWithToDOMFixed() : bodiedSyncBlock
|
|
79
|
+
node: bodiedSyncBlock
|
|
86
80
|
}];
|
|
87
81
|
},
|
|
88
82
|
pmPlugins() {
|
|
@@ -8,33 +8,9 @@ import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks'
|
|
|
8
8
|
import { syncBlockMessages as messages } from '@atlaskit/editor-common/messages';
|
|
9
9
|
import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
|
|
10
10
|
import ModalDialog, { ModalBody, ModalFooter, ModalHeader, ModalTitle, ModalTransition } from '@atlaskit/modal-dialog';
|
|
11
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
11
|
import { Text, Box } from '@atlaskit/primitives/compiled';
|
|
13
12
|
import Spinner from '@atlaskit/spinner';
|
|
14
13
|
import { syncedBlockPluginKey } from '../pm-plugins/main';
|
|
15
|
-
const modalContentMapOld = {
|
|
16
|
-
'source-block-deleted': {
|
|
17
|
-
titleMultiple: messages.deleteConfirmationModalTitleMultiple,
|
|
18
|
-
titleSingle: messages.deletionConfirmationModalTitleSingle,
|
|
19
|
-
descriptionSingle: messages.deletionConfirmationModalDescriptionNoRef,
|
|
20
|
-
descriptionMultiple: messages.deletionConfirmationModalDescription,
|
|
21
|
-
confirmButtonLabel: messages.deleteConfirmationModalDeleteButton
|
|
22
|
-
},
|
|
23
|
-
'source-block-unpublished': {
|
|
24
|
-
titleMultiple: messages.deleteConfirmationModalTitleMultiple,
|
|
25
|
-
titleSingle: messages.deletionConfirmationModalTitleSingle,
|
|
26
|
-
descriptionSingle: messages.deletionConfirmationModalDescriptionNoRef,
|
|
27
|
-
descriptionMultiple: messages.deletionConfirmationModalDescription,
|
|
28
|
-
confirmButtonLabel: messages.deleteConfirmationModalDeleteButton
|
|
29
|
-
},
|
|
30
|
-
'source-block-unsynced': {
|
|
31
|
-
titleMultiple: messages.unsyncConfirmationModalTitle,
|
|
32
|
-
titleSingle: messages.unsyncConfirmationModalTitle,
|
|
33
|
-
descriptionSingle: messages.unsyncConfirmModalDescriptionSingle,
|
|
34
|
-
descriptionMultiple: messages.unsyncConfirmModalDescriptionMultiple,
|
|
35
|
-
confirmButtonLabel: messages.deleteConfirmationModalUnsyncButton
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
14
|
const modalContentMap = {
|
|
39
15
|
'source-block-deleted': {
|
|
40
16
|
titleMultiple: messages.deleteConfirmationModalTitleMultiple,
|
|
@@ -87,10 +63,9 @@ export const DeleteConfirmationModal = ({
|
|
|
87
63
|
} = useIntl();
|
|
88
64
|
const resolverRef = React.useRef(undefined);
|
|
89
65
|
|
|
90
|
-
// When
|
|
91
|
-
//
|
|
92
|
-
//
|
|
93
|
-
// close the modal (which was never open).
|
|
66
|
+
// When a source block with no references is deleted, the modal is never shown but
|
|
67
|
+
// onDeleteCompleted still sets bodiedSyncBlockDeletionStatus to 'completed'. This ref signals
|
|
68
|
+
// the useEffect to silently reset the status without trying to close the modal (which was never open).
|
|
94
69
|
const skipModalOnCompletedRef = React.useRef(false);
|
|
95
70
|
const handleClick = useCallback(confirm => () => {
|
|
96
71
|
var _api$core;
|
|
@@ -137,38 +112,36 @@ export const DeleteConfirmationModal = ({
|
|
|
137
112
|
return references.reduce((sum, count) => sum + count, 0);
|
|
138
113
|
};
|
|
139
114
|
const confirmationCallback = useCallback(async (syncBlockIds, deleteReason) => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
} : {})
|
|
166
|
-
});
|
|
115
|
+
// Fetch references before opening the modal. If none exist, skip the modal
|
|
116
|
+
// entirely and auto-confirm the deletion. On fetch error, default to showing
|
|
117
|
+
// the modal to avoid accidental data loss.
|
|
118
|
+
let count;
|
|
119
|
+
try {
|
|
120
|
+
count = await fetchReferenceCountRef.current(syncBlockIds);
|
|
121
|
+
} catch {
|
|
122
|
+
count = 1;
|
|
123
|
+
}
|
|
124
|
+
if (count === 0) {
|
|
125
|
+
var _api$core3;
|
|
126
|
+
// No references — auto-confirm without showing the modal.
|
|
127
|
+
// Clear activeFlag to avoid issues with subsequent deletion attempts.
|
|
128
|
+
// We do NOT reset bodiedSyncBlockDeletionStatus here because onDeleteCompleted
|
|
129
|
+
// will set it to 'completed' after the delete call returns. Instead we use a
|
|
130
|
+
// ref to signal that the next 'completed' status should be silently reset
|
|
131
|
+
// without trying to close the modal.
|
|
132
|
+
skipModalOnCompletedRef.current = true;
|
|
133
|
+
api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(({
|
|
134
|
+
tr
|
|
135
|
+
}) => {
|
|
136
|
+
return tr.setMeta(syncedBlockPluginKey, {
|
|
137
|
+
...(activeFlagRef.current ? {
|
|
138
|
+
activeFlag: false
|
|
139
|
+
} : {})
|
|
167
140
|
});
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
setReferenceCount(count);
|
|
141
|
+
});
|
|
142
|
+
return true;
|
|
171
143
|
}
|
|
144
|
+
setReferenceCount(count);
|
|
172
145
|
setIsOpen(true);
|
|
173
146
|
setSyncBlockIds(syncBlockIds);
|
|
174
147
|
if (deleteReason) {
|
|
@@ -201,7 +174,7 @@ export const DeleteConfirmationModal = ({
|
|
|
201
174
|
};
|
|
202
175
|
}, [syncBlockStoreManager, confirmationCallback]);
|
|
203
176
|
useEffect(() => {
|
|
204
|
-
if (skipModalOnCompletedRef.current
|
|
177
|
+
if (skipModalOnCompletedRef.current) {
|
|
205
178
|
if (bodiedSyncBlockDeletionStatus === 'completed') {
|
|
206
179
|
var _api$core6;
|
|
207
180
|
// Deletion was auto-confirmed without showing the modal (no references).
|
|
@@ -238,24 +211,10 @@ export const DeleteConfirmationModal = ({
|
|
|
238
211
|
});
|
|
239
212
|
}
|
|
240
213
|
}, [api === null || api === void 0 ? void 0 : (_api$core8 = api.core) === null || _api$core8 === void 0 ? void 0 : _api$core8.actions, bodiedSyncBlockDeletionStatus, isOpen]);
|
|
241
|
-
useEffect(() => {
|
|
242
|
-
// When the flag is off, fetch references after the modal opens (original behaviour).
|
|
243
|
-
// When the flag is on, references are fetched and set before the modal opens in
|
|
244
|
-
// confirmationCallback, so this useEffect is skipped to avoid a duplicate fetch.
|
|
245
|
-
if (isOpen && syncBlockIds !== undefined && !fg('platform_synced_block_patch_9')) {
|
|
246
|
-
const fetchReferences = async () => {
|
|
247
|
-
try {
|
|
248
|
-
const totalCount = await fetchReferenceCountRef.current(syncBlockIds);
|
|
249
|
-
setReferenceCount(totalCount);
|
|
250
|
-
} catch {
|
|
251
|
-
setReferenceCount(0);
|
|
252
|
-
}
|
|
253
|
-
};
|
|
254
214
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
}, [isOpen, syncBlockIds]);
|
|
215
|
+
// References are fetched and set before the modal opens in
|
|
216
|
+
// confirmationCallback, so no additional fetch is needed here.
|
|
217
|
+
|
|
259
218
|
return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
|
|
260
219
|
onClose: handleClick(false),
|
|
261
220
|
testId: "sync-block-delete-confirmation",
|
|
@@ -265,7 +224,7 @@ export const DeleteConfirmationModal = ({
|
|
|
265
224
|
}, /*#__PURE__*/React.createElement(Spinner, {
|
|
266
225
|
size: "large"
|
|
267
226
|
})) : /*#__PURE__*/React.createElement(ModalContent, {
|
|
268
|
-
content:
|
|
227
|
+
content: modalContentMap[deleteReason],
|
|
269
228
|
referenceCount: referenceCount,
|
|
270
229
|
handleClick: handleClick,
|
|
271
230
|
formatMessage: formatMessage,
|