@atlaskit/editor-plugin-synced-block
Version:
SyncedBlock plugin for @atlaskit/editor-core
135 lines (133 loc) • 5.9 kB
JavaScript
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
import { FLAG_ID } from '../../types';
import { syncedBlockPluginKey } from '../main';
import { deferDispatch } from './utils';
const onRetry = (api, resourceId) => {
return () => {
var _api$core, _api$core2;
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.focus();
api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(({
tr
}) => {
var _api$syncedBlock, _api$syncedBlock$shar, _api$syncedBlock$shar2, _api$syncedBlock2;
const pos = api === null || api === void 0 ? void 0 : (_api$syncedBlock = api.syncedBlock) === null || _api$syncedBlock === void 0 ? void 0 : (_api$syncedBlock$shar = _api$syncedBlock.sharedState.currentState()) === null || _api$syncedBlock$shar === void 0 ? void 0 : (_api$syncedBlock$shar2 = _api$syncedBlock$shar.retryCreationPosMap) === null || _api$syncedBlock$shar2 === void 0 ? void 0 : _api$syncedBlock$shar2.get(resourceId);
const from = pos === null || pos === void 0 ? void 0 : pos.from;
const to = pos === null || pos === void 0 ? void 0 : pos.to;
if (from === undefined || to === undefined) {
return tr;
}
tr.setSelection(TextSelection.create(tr.doc, from, to)).setMeta(syncedBlockPluginKey, {
activeFlag: false
});
api === null || api === void 0 ? void 0 : (_api$syncedBlock2 = api.syncedBlock) === null || _api$syncedBlock2 === void 0 ? void 0 : _api$syncedBlock2.commands.insertSyncedBlock()({
tr
});
return tr;
});
};
};
const getRevertCreationPos = (api, doc, resourceId) => {
var _api$syncedBlock3, _api$syncedBlock3$sha, _api$syncedBlock3$sha2;
const retryCreationPos = api === null || api === void 0 ? void 0 : (_api$syncedBlock3 = api.syncedBlock) === null || _api$syncedBlock3 === void 0 ? void 0 : (_api$syncedBlock3$sha = _api$syncedBlock3.sharedState.currentState()) === null || _api$syncedBlock3$sha === void 0 ? void 0 : (_api$syncedBlock3$sha2 = _api$syncedBlock3$sha.retryCreationPosMap) === null || _api$syncedBlock3$sha2 === void 0 ? void 0 : _api$syncedBlock3$sha2.get(resourceId);
if (retryCreationPos) {
return retryCreationPos;
}
// Fallback to find the positions in case BE call returns before plugin state becomes available
// which is highly unlikely
let currentPos;
doc.descendants((node, pos) => {
if (currentPos) {
return false;
}
if (node.type.name === 'bodiedSyncBlock' && resourceId === node.attrs.resourceId) {
currentPos = {
from: pos,
to: pos + node.nodeSize
};
return false;
}
});
return currentPos;
};
const buildRevertCreationTr = (tr, pos) => {
var _tr$doc$nodeAt;
const content = (_tr$doc$nodeAt = tr.doc.nodeAt(pos.from)) === null || _tr$doc$nodeAt === void 0 ? void 0 : _tr$doc$nodeAt.content;
if (content) {
tr.replaceWith(pos.from, pos.to, content);
const contentFrom = tr.mapping.map(pos.from);
tr.setSelection(TextSelection.create(tr.doc, contentFrom, contentFrom + content.size));
} else {
tr.delete(pos.from, pos.to);
}
return tr;
};
/**
*
* Save the new bodiedSyncBlock to backend with empty content and handles revert (if failed) and retry flow
*/
export const handleBodiedSyncBlockCreation = (bodiedSyncBlockAdded, editorState, api) => {
const syncBlockStore = syncedBlockPluginKey.getState(editorState).syncBlockStore;
bodiedSyncBlockAdded.forEach(node => {
if (node.from === undefined || node.to === undefined) {
return;
}
const retryCreationPos = {
from: node.from,
to: node.to
};
const resourceId = node.attrs.resourceId;
deferDispatch(() => {
var _api$core3;
api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(({
tr
}) => {
return tr.setMeta(syncedBlockPluginKey, {
retryCreationPos: {
resourceId,
pos: retryCreationPos
}
});
});
});
syncBlockStore.sourceManager.createBodiedSyncBlockNode(node.attrs, node.node, success => {
if (success) {
var _api$core4, _api$core5;
api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(({
tr
}) => {
return tr.setMeta(syncedBlockPluginKey, {
retryCreationPos: {
resourceId,
pos: undefined
}
});
});
api === null || api === void 0 ? void 0 : (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions.focus();
} else {
var _api$core6;
api === null || api === void 0 ? void 0 : (_api$core6 = api.core) === null || _api$core6 === void 0 ? void 0 : _api$core6.actions.execute(({
tr
}) => {
const revertCreationPos = getRevertCreationPos(api, tr.doc, resourceId);
if (!revertCreationPos) {
return tr;
}
const revertTr = buildRevertCreationTr(tr, revertCreationPos);
return revertTr.setMeta('isConfirmedSyncBlockDeletion', true).setMeta('addToHistory', false).setMeta(syncedBlockPluginKey, {
activeFlag: {
id: FLAG_ID.CANNOT_CREATE_SYNC_BLOCK,
onRetry: onRetry(api, resourceId),
onDismissed: tr => tr.setMeta(syncedBlockPluginKey, {
...tr.getMeta(syncedBlockPluginKey),
retryCreationPos: {
resourceId,
pos: undefined
}
})
}
});
});
}
});
});
};