@atlaskit/editor-plugin-collab-edit
Version:
Collab Edit plugin for @atlaskit/editor-core
121 lines (119 loc) • 3.31 kB
JavaScript
// Ignored via go/ees005
// eslint-disable-next-line import/no-namespace
import * as allAdfSchemaSteps from '@atlaskit/adf-schema/steps';
// Ignored via go/ees005
// eslint-disable-next-line import/no-namespace
import * as allAtlaskitCustomSteps from '@atlaskit/custom-steps';
import { AllSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
import { Step } from '@atlaskit/editor-prosemirror/transform';
import { receiveTransaction } from '@atlaskit/prosemirror-collab';
import { replaceDocument } from './utils';
/*
* This is a non-op function to force ProseMirror to load and register all custom steps in the same bundle
*/
export const registerAllCustomSteps = () => {
Object.entries(allAtlaskitCustomSteps).forEach(() => {});
Object.entries(allAdfSchemaSteps).forEach(() => {});
};
export const handleInit = (initData, view, options, editorAnalyticsApi) => {
const {
doc,
json,
version,
reserveCursor
} = initData;
if (doc) {
const {
state
} = view;
const tr = replaceDocument(doc, state, version, options, reserveCursor, editorAnalyticsApi);
tr.setMeta('isRemote', true);
view.dispatch(tr);
} else if (json) {
applyRemoteSteps(json, view);
}
};
export const handleConnection = (connectionData, view) => {
const {
state: {
tr
}
} = view;
view.dispatch(tr.setMeta('sessionId', connectionData));
};
export const handlePresence = (presenceData, view) => {
const {
state: {
tr
}
} = view;
view.dispatch(tr.setMeta('presence', presenceData));
};
export const applyRemoteData = (remoteData, view, options) => {
const {
json,
userIds = []
} = remoteData;
if (json) {
applyRemoteSteps(json, view, userIds, options);
}
};
export const applyRemoteSteps = (json, view, userIds, options) => {
if (!json || !json.length) {
return;
}
const {
state,
state: {
schema
}
} = view;
const steps = json.map(step => Step.fromJSON(schema, step));
let tr;
if (options && options.useNativePlugin && userIds) {
tr = receiveTransaction(state, steps, userIds, {
mapSelectionBackward: true
});
} else {
tr = state.tr;
steps.forEach(step => tr.step(step));
}
if (tr) {
tr.setMeta('addToHistory', false);
tr.setMeta('isRemote', true);
/*
* Persist marks across transactions. Fixes an issue where
* marks are lost if remote transactions are dispatched
* between a user creating the mark and typing.
*/
if (state.tr.storedMarks) {
tr.setStoredMarks(state.tr.storedMarks);
}
view.dispatch(tr);
}
};
export const handleTelePointer = (telepointerData, view) => {
const {
state: {
tr
}
} = view;
view.dispatch(tr.setMeta('telepointer', telepointerData));
};
function isAllSelection(selection) {
return selection instanceof AllSelection;
}
function isNodeSelection(selection) {
return selection instanceof NodeSelection;
}
export const getSendableSelection = selection => {
/**
* <kbd>CMD + A</kbd> triggers a AllSelection
* <kbd>escape</kbd> triggers a NodeSelection
*/
return {
type: 'textSelection',
anchor: selection.anchor,
head: isAllSelection(selection) || isNodeSelection(selection) ? selection.head - 1 : selection.head
};
};