@atlaskit/editor-plugin-collab-edit 0.1.0

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 (69) hide show
  1. package/CHANGELOG.md +1 -0
  2. package/LICENSE.md +13 -0
  3. package/README.md +30 -0
  4. package/dist/cjs/actions.js +110 -0
  5. package/dist/cjs/analytics.js +47 -0
  6. package/dist/cjs/events/handlers.js +88 -0
  7. package/dist/cjs/events/initialize.js +58 -0
  8. package/dist/cjs/events/send-transaction.js +48 -0
  9. package/dist/cjs/index.js +128 -0
  10. package/dist/cjs/native-collab-provider-plugin.js +37 -0
  11. package/dist/cjs/participants.js +95 -0
  12. package/dist/cjs/plugin-key.js +8 -0
  13. package/dist/cjs/plugin-state.js +241 -0
  14. package/dist/cjs/plugin.js +102 -0
  15. package/dist/cjs/types.js +5 -0
  16. package/dist/cjs/utils.js +150 -0
  17. package/dist/es2019/actions.js +119 -0
  18. package/dist/es2019/analytics.js +41 -0
  19. package/dist/es2019/events/handlers.js +72 -0
  20. package/dist/es2019/events/initialize.js +44 -0
  21. package/dist/es2019/events/send-transaction.js +42 -0
  22. package/dist/es2019/index.js +86 -0
  23. package/dist/es2019/native-collab-provider-plugin.js +32 -0
  24. package/dist/es2019/participants.js +57 -0
  25. package/dist/es2019/plugin-key.js +2 -0
  26. package/dist/es2019/plugin-state.js +219 -0
  27. package/dist/es2019/plugin.js +83 -0
  28. package/dist/es2019/types.js +1 -0
  29. package/dist/es2019/utils.js +133 -0
  30. package/dist/esm/actions.js +103 -0
  31. package/dist/esm/analytics.js +41 -0
  32. package/dist/esm/events/handlers.js +82 -0
  33. package/dist/esm/events/initialize.js +51 -0
  34. package/dist/esm/events/send-transaction.js +42 -0
  35. package/dist/esm/index.js +116 -0
  36. package/dist/esm/native-collab-provider-plugin.js +31 -0
  37. package/dist/esm/participants.js +88 -0
  38. package/dist/esm/plugin-key.js +2 -0
  39. package/dist/esm/plugin-state.js +229 -0
  40. package/dist/esm/plugin.js +85 -0
  41. package/dist/esm/types.js +1 -0
  42. package/dist/esm/utils.js +136 -0
  43. package/dist/types/actions.d.ts +11 -0
  44. package/dist/types/analytics.d.ts +6 -0
  45. package/dist/types/events/handlers.d.ts +24 -0
  46. package/dist/types/events/initialize.d.ts +16 -0
  47. package/dist/types/events/send-transaction.d.ts +11 -0
  48. package/dist/types/index.d.ts +29 -0
  49. package/dist/types/native-collab-provider-plugin.d.ts +7 -0
  50. package/dist/types/participants.d.ts +18 -0
  51. package/dist/types/plugin-key.d.ts +3 -0
  52. package/dist/types/plugin-state.d.ts +25 -0
  53. package/dist/types/plugin.d.ts +11 -0
  54. package/dist/types/types.d.ts +8 -0
  55. package/dist/types/utils.d.ts +16 -0
  56. package/dist/types-ts4.5/actions.d.ts +11 -0
  57. package/dist/types-ts4.5/analytics.d.ts +6 -0
  58. package/dist/types-ts4.5/events/handlers.d.ts +24 -0
  59. package/dist/types-ts4.5/events/initialize.d.ts +16 -0
  60. package/dist/types-ts4.5/events/send-transaction.d.ts +11 -0
  61. package/dist/types-ts4.5/index.d.ts +29 -0
  62. package/dist/types-ts4.5/native-collab-provider-plugin.d.ts +7 -0
  63. package/dist/types-ts4.5/participants.d.ts +18 -0
  64. package/dist/types-ts4.5/plugin-key.d.ts +3 -0
  65. package/dist/types-ts4.5/plugin-state.d.ts +25 -0
  66. package/dist/types-ts4.5/plugin.d.ts +11 -0
  67. package/dist/types-ts4.5/types.d.ts +8 -0
  68. package/dist/types-ts4.5/utils.d.ts +16 -0
  69. package/package.json +104 -0
@@ -0,0 +1,133 @@
1
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ import { colors } from '@atlaskit/editor-common/collab';
3
+ import { ZERO_WIDTH_JOINER } from '@atlaskit/editor-common/utils';
4
+ import { Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
5
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
6
+ export { colors };
7
+ export const findPointers = (id, decorations) => decorations.find().reduce((arr, deco) => deco.spec.pointer.sessionId === id ? arr.concat(deco) : arr, []);
8
+ function style(options) {
9
+ const color = options && options.color || 'black';
10
+ return `border-left: 1px solid ${color}; border-right: 1px solid ${color}; margin-right: -2px;`;
11
+ }
12
+ export function getAvatarColor(str) {
13
+ let hash = 0;
14
+ for (let i = 0; i < str.length; i++) {
15
+ /* eslint-disable no-bitwise */
16
+ hash = (hash << 5) - hash + str.charCodeAt(i);
17
+ hash = hash & hash;
18
+ /* eslint-enable no-bitwise */
19
+ }
20
+
21
+ const index = Math.abs(hash) % colors.length;
22
+ return {
23
+ index,
24
+ color: colors[index]
25
+ };
26
+ }
27
+ export const createTelepointers = (from, to, sessionId, isSelection, initial) => {
28
+ let decorations = [];
29
+ const avatarColor = getAvatarColor(sessionId);
30
+ const color = avatarColor.index.toString();
31
+ if (isSelection) {
32
+ const className = `telepointer color-${color} telepointer-selection`;
33
+ decorations.push(Decoration.inline(from, to, {
34
+ class: className,
35
+ 'data-initial': initial
36
+ }, {
37
+ pointer: {
38
+ sessionId
39
+ }
40
+ }));
41
+ }
42
+ const spaceJoinerBefore = document.createElement('span');
43
+ spaceJoinerBefore.textContent = ZERO_WIDTH_JOINER;
44
+ const spaceJoinerAfter = document.createElement('span');
45
+ spaceJoinerAfter.textContent = ZERO_WIDTH_JOINER;
46
+ const cursor = document.createElement('span');
47
+ cursor.textContent = ZERO_WIDTH_JOINER;
48
+ cursor.className = `telepointer color-${color} telepointer-selection-badge`;
49
+ cursor.style.cssText = `${style({
50
+ color: avatarColor.color.solid
51
+ })};`;
52
+ cursor.setAttribute('data-initial', initial);
53
+ return decorations.concat(Decoration.widget(to, spaceJoinerAfter, {
54
+ pointer: {
55
+ sessionId
56
+ },
57
+ key: `telepointer-${sessionId}-zero`
58
+ })).concat(Decoration.widget(to, cursor, {
59
+ pointer: {
60
+ sessionId
61
+ },
62
+ key: `telepointer-${sessionId}`
63
+ })).concat(Decoration.widget(to, spaceJoinerBefore, {
64
+ pointer: {
65
+ sessionId
66
+ },
67
+ key: `telepointer-${sessionId}-zero`
68
+ }));
69
+ };
70
+ export const replaceDocument = (doc, state, version, options, reserveCursor) => {
71
+ const {
72
+ schema,
73
+ tr
74
+ } = state;
75
+ let content = (doc.content || []).map(child => schema.nodeFromJSON(child));
76
+ let hasContent = !!content.length;
77
+ if (hasContent) {
78
+ tr.setMeta('addToHistory', false);
79
+ tr.replaceWith(0, state.doc.nodeSize - 2, content);
80
+ const selection = state.selection;
81
+ if (reserveCursor) {
82
+ // If the cursor is still in the range of the new document,
83
+ // keep where it was.
84
+ if (selection.to < tr.doc.content.size - 2) {
85
+ const $from = tr.doc.resolve(selection.from);
86
+ const $to = tr.doc.resolve(selection.to);
87
+ const newselection = new TextSelection($from, $to);
88
+ tr.setSelection(newselection);
89
+ }
90
+ } else {
91
+ tr.setSelection(Selection.atStart(tr.doc));
92
+ }
93
+ tr.setMeta('replaceDocument', true);
94
+ if (typeof version !== undefined && options && options.useNativePlugin) {
95
+ const collabState = {
96
+ version,
97
+ unconfirmed: []
98
+ };
99
+ tr.setMeta('collab$', collabState);
100
+ }
101
+ }
102
+ return tr;
103
+ };
104
+ export const scrollToCollabCursor = (editorView, participants, sessionId, index, editorAnalyticsAPI) => {
105
+ const selectedUser = participants[index];
106
+ if (selectedUser && selectedUser.cursorPos !== undefined && selectedUser.sessionId !== sessionId) {
107
+ const {
108
+ state
109
+ } = editorView;
110
+ let tr = state.tr;
111
+ const analyticsPayload = {
112
+ action: ACTION.MATCHED,
113
+ actionSubject: ACTION_SUBJECT.SELECTION,
114
+ eventType: EVENT_TYPE.TRACK
115
+ };
116
+ tr.setSelection(Selection.near(tr.doc.resolve(selectedUser.cursorPos)));
117
+ editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 ? void 0 : editorAnalyticsAPI.attachAnalyticsEvent(analyticsPayload)(tr);
118
+ tr.scrollIntoView();
119
+ editorView.dispatch(tr);
120
+ if (!editorView.hasFocus()) {
121
+ editorView.focus();
122
+ }
123
+ }
124
+ };
125
+ export const getPositionOfTelepointer = (sessionId, decorationSet) => {
126
+ let scrollPosition;
127
+ decorationSet.find().forEach(deco => {
128
+ if (deco.type.spec.pointer.sessionId === sessionId) {
129
+ scrollPosition = deco.from;
130
+ }
131
+ });
132
+ return scrollPosition;
133
+ };
@@ -0,0 +1,103 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { receiveTransaction } from 'prosemirror-collab';
3
+ import { AllSelection, NodeSelection } from '@atlaskit/editor-prosemirror/state';
4
+ import { Step } from '@atlaskit/editor-prosemirror/transform';
5
+ import { replaceDocument } from './utils';
6
+ export var handleInit = function handleInit(initData, view, options) {
7
+ var doc = initData.doc,
8
+ json = initData.json,
9
+ version = initData.version,
10
+ reserveCursor = initData.reserveCursor;
11
+ if (doc) {
12
+ var state = view.state;
13
+ var tr = replaceDocument(doc, state, version, options, reserveCursor);
14
+ tr.setMeta('isRemote', true);
15
+ view.dispatch(tr);
16
+ } else if (json) {
17
+ applyRemoteSteps(json, view);
18
+ }
19
+ };
20
+ export var handleConnection = function handleConnection(connectionData, view) {
21
+ var tr = view.state.tr;
22
+ view.dispatch(tr.setMeta('sessionId', connectionData));
23
+ };
24
+ export var handlePresence = function handlePresence(presenceData, view) {
25
+ var tr = view.state.tr;
26
+ view.dispatch(tr.setMeta('presence', presenceData));
27
+ };
28
+ export var applyRemoteData = function applyRemoteData(remoteData, view, options) {
29
+ var json = remoteData.json,
30
+ _remoteData$userIds = remoteData.userIds,
31
+ userIds = _remoteData$userIds === void 0 ? [] : _remoteData$userIds;
32
+ if (json) {
33
+ applyRemoteSteps(json, view, userIds, options);
34
+ }
35
+ };
36
+ export var applyRemoteSteps = function applyRemoteSteps(json, view, userIds, options) {
37
+ if (!json || !json.length) {
38
+ return;
39
+ }
40
+ var state = view.state,
41
+ schema = view.state.schema;
42
+ var steps = json.map(function (step) {
43
+ return Step.fromJSON(schema, step);
44
+ });
45
+ var tr;
46
+ if (options && options.useNativePlugin && userIds) {
47
+ tr = receiveTransaction(state, steps, userIds);
48
+ } else {
49
+ tr = state.tr;
50
+ steps.forEach(function (step) {
51
+ return tr.step(step);
52
+ });
53
+ }
54
+ if (tr) {
55
+ tr.setMeta('addToHistory', false);
56
+ tr.setMeta('isRemote', true);
57
+ var _state$selection = state.selection,
58
+ from = _state$selection.from,
59
+ to = _state$selection.to;
60
+ var _json = _slicedToArray(json, 1),
61
+ firstStep = _json[0];
62
+
63
+ /*
64
+ * Persist marks across transactions. Fixes an issue where
65
+ * marks are lost if remote transactions are dispatched
66
+ * between a user creating the mark and typing.
67
+ */
68
+ if (state.tr.storedMarks) {
69
+ tr.setStoredMarks(state.tr.storedMarks);
70
+ }
71
+
72
+ /**
73
+ * If the cursor is a the same position as the first step in
74
+ * the remote data, we need to manually set it back again
75
+ * in order to prevent the cursor from moving.
76
+ */
77
+ if (from === firstStep.from && to === firstStep.to) {
78
+ tr.setSelection(state.selection.map(tr.doc, tr.mapping));
79
+ }
80
+ view.dispatch(tr);
81
+ }
82
+ };
83
+ export var handleTelePointer = function handleTelePointer(telepointerData, view) {
84
+ var tr = view.state.tr;
85
+ view.dispatch(tr.setMeta('telepointer', telepointerData));
86
+ };
87
+ function isAllSelection(selection) {
88
+ return selection instanceof AllSelection;
89
+ }
90
+ function isNodeSelection(selection) {
91
+ return selection instanceof NodeSelection;
92
+ }
93
+ export var getSendableSelection = function getSendableSelection(selection) {
94
+ /**
95
+ * <kbd>CMD + A</kbd> triggers a AllSelection
96
+ * <kbd>escape</kbd> triggers a NodeSelection
97
+ */
98
+ return {
99
+ type: 'textSelection',
100
+ anchor: selection.anchor,
101
+ head: isAllSelection(selection) || isNodeSelection(selection) ? selection.head - 1 : selection.head
102
+ };
103
+ };
@@ -0,0 +1,41 @@
1
+ import { ACTION, ACTION_SUBJECT, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
2
+ import { getDocStructure } from '@atlaskit/editor-common/core-utils';
3
+ import { sniffUserBrowserExtensions } from '@atlaskit/editor-common/utils';
4
+ export var addSynchronyErrorAnalytics = function addSynchronyErrorAnalytics(state, tr, featureFlags, editorAnalyticsApi) {
5
+ return function (error) {
6
+ var browserExtensions = sniffUserBrowserExtensions({
7
+ extensions: ['grammarly']
8
+ });
9
+ var payload = {
10
+ action: ACTION.SYNCHRONY_ERROR,
11
+ actionSubject: ACTION_SUBJECT.EDITOR,
12
+ eventType: EVENT_TYPE.OPERATIONAL,
13
+ attributes: {
14
+ error: error,
15
+ browserExtensions: browserExtensions
16
+ }
17
+ };
18
+ if (featureFlags.synchronyErrorDocStructure) {
19
+ payload.attributes.docStructure = getDocStructure(state.doc, {
20
+ compact: true
21
+ });
22
+ }
23
+ editorAnalyticsApi === null || editorAnalyticsApi === void 0 || editorAnalyticsApi.attachAnalyticsEvent(payload)(tr);
24
+ return tr;
25
+ };
26
+ };
27
+ export var addSynchronyEntityAnalytics = function addSynchronyEntityAnalytics(state, tr) {
28
+ return function (type, editorAnalyticsApi) {
29
+ editorAnalyticsApi === null || editorAnalyticsApi === void 0 || editorAnalyticsApi.attachAnalyticsEvent({
30
+ action: type === 'error' ? ACTION.SYNCHRONY_ENTITY_ERROR : ACTION.SYNCHRONY_DISCONNECTED,
31
+ actionSubject: ACTION_SUBJECT.EDITOR,
32
+ eventType: EVENT_TYPE.OPERATIONAL,
33
+ attributes: {
34
+ // https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine
35
+ onLine: navigator.onLine,
36
+ visibilityState: document.visibilityState
37
+ }
38
+ })(tr);
39
+ return tr;
40
+ };
41
+ };
@@ -0,0 +1,82 @@
1
+ import { applyRemoteData, handleConnection, handleInit, handlePresence, handleTelePointer } from '../actions';
2
+ import { addSynchronyEntityAnalytics, addSynchronyErrorAnalytics } from '../analytics';
3
+ var effect = function effect(fn, eq) {
4
+ var previousDeps;
5
+ var cleanup;
6
+ return function () {
7
+ for (var _len = arguments.length, currentDeps = new Array(_len), _key = 0; _key < _len; _key++) {
8
+ currentDeps[_key] = arguments[_key];
9
+ }
10
+ if (cleanup && eq(previousDeps, currentDeps)) {
11
+ return cleanup;
12
+ }
13
+ cleanup = fn.apply(void 0, currentDeps);
14
+ previousDeps = currentDeps;
15
+ return cleanup;
16
+ };
17
+ };
18
+ export var subscribe = effect(function (view, provider, options, featureFlags, _providerFactory, editorAnalyticsApi) {
19
+ var entityRef;
20
+ var entityHandlers = {
21
+ disconnectedHandler: function disconnectedHandler() {
22
+ addSynchronyEntityAnalytics(view.state, view.state.tr)('disconnected', editorAnalyticsApi);
23
+ },
24
+ errorHandler: function errorHandler() {
25
+ addSynchronyEntityAnalytics(view.state, view.state.tr)('error', editorAnalyticsApi);
26
+ }
27
+ };
28
+ var unsubscribeSynchronyEntity = function unsubscribeSynchronyEntity() {
29
+ if (entityRef) {
30
+ entityRef.off('disconnected', entityHandlers.disconnectedHandler);
31
+ entityRef.off('error', entityHandlers.errorHandler);
32
+ }
33
+ };
34
+ var handlers = {
35
+ initHandler: function initHandler(data) {
36
+ view.dispatch(view.state.tr.setMeta('collabInitialised', true));
37
+ handleInit(data, view, options);
38
+ },
39
+ connectedHandler: function connectedHandler(data) {
40
+ return handleConnection(data, view);
41
+ },
42
+ dataHandler: function dataHandler(data) {
43
+ return applyRemoteData(data, view, options);
44
+ },
45
+ presenceHandler: function presenceHandler(data) {
46
+ return handlePresence(data, view);
47
+ },
48
+ telepointerHandler: function telepointerHandler(data) {
49
+ return handleTelePointer(data, view);
50
+ },
51
+ localStepsHandler: function localStepsHandler(data) {
52
+ var steps = data.steps;
53
+ var state = view.state;
54
+ var tr = state.tr;
55
+ steps.forEach(function (step) {
56
+ return tr.step(step);
57
+ });
58
+ view.dispatch(tr);
59
+ },
60
+ errorHandler: function errorHandler(error) {
61
+ addSynchronyErrorAnalytics(view.state, view.state.tr, featureFlags, editorAnalyticsApi)(error);
62
+ },
63
+ entityHandler: function entityHandler(_ref) {
64
+ var entity = _ref.entity;
65
+ unsubscribeSynchronyEntity();
66
+ if (options.EXPERIMENTAL_allowInternalErrorAnalytics) {
67
+ entity.on('disconnected', entityHandlers.disconnectedHandler);
68
+ entity.on('error', entityHandlers.errorHandler);
69
+ entityRef = entity;
70
+ }
71
+ }
72
+ };
73
+ provider.on('init', handlers.initHandler).on('connected', handlers.connectedHandler).on('data', handlers.dataHandler).on('presence', handlers.presenceHandler).on('telepointer', handlers.telepointerHandler).on('local-steps', handlers.localStepsHandler).on('error', handlers.errorHandler).on('entity', handlers.entityHandler);
74
+ return function () {
75
+ unsubscribeSynchronyEntity();
76
+ provider.off('init', handlers.initHandler).off('connected', handlers.connectedHandler).off('data', handlers.dataHandler).off('presence', handlers.presenceHandler).off('telepointer', handlers.telepointerHandler).off('local-steps', handlers.localStepsHandler).off('error', handlers.errorHandler).off('entity', handlers.entityHandler);
77
+ };
78
+ }, function (previousDeps, currentDeps) {
79
+ return currentDeps && currentDeps.every(function (dep, i) {
80
+ return dep === previousDeps[i];
81
+ });
82
+ });
@@ -0,0 +1,51 @@
1
+ import memoizeOne from 'memoize-one';
2
+ import { Step } from '@atlaskit/editor-prosemirror/transform';
3
+ import { pluginKey } from '../plugin-key';
4
+ import { subscribe } from './handlers';
5
+ var initCollab = function initCollab(collabEditProvider, view) {
6
+ if (collabEditProvider.initialize) {
7
+ collabEditProvider.initialize(function () {
8
+ return view.state;
9
+ }, function (json) {
10
+ return Step.fromJSON(view.state.schema, json);
11
+ });
12
+ }
13
+ };
14
+ var initNewCollab = function initNewCollab(collabEditProvider, view, onSyncUpError) {
15
+ collabEditProvider.setup({
16
+ getState: function getState() {
17
+ return view.state;
18
+ },
19
+ onSyncUpError: onSyncUpError
20
+ });
21
+ };
22
+ var initCollabMemo = memoizeOne(initCollab);
23
+ export var initialize = function initialize(_ref) {
24
+ var options = _ref.options,
25
+ providerFactory = _ref.providerFactory,
26
+ view = _ref.view,
27
+ featureFlags = _ref.featureFlags,
28
+ editorAnalyticsApi = _ref.editorAnalyticsApi;
29
+ return function (provider) {
30
+ var cleanup;
31
+ var pluginState = pluginKey.getState(view.state);
32
+ if (pluginState !== null && pluginState !== void 0 && pluginState.isReady && cleanup) {
33
+ cleanup();
34
+ }
35
+ cleanup = subscribe(view, provider, options, featureFlags, providerFactory, editorAnalyticsApi);
36
+
37
+ // Initialize provider
38
+ if (options.useNativePlugin) {
39
+ // ED-13912 For NCS we don't want to use memoizeOne because it causes
40
+ // infinite text while changing page-width
41
+ initNewCollab(provider, view, options.onSyncUpError);
42
+ } else {
43
+ /**
44
+ * We only want to initialise once, if we reload/reconfigure this plugin
45
+ * We dont want to re-init collab, it would break existing sessions
46
+ */
47
+ initCollabMemo(provider, view);
48
+ }
49
+ return cleanup;
50
+ };
51
+ };
@@ -0,0 +1,42 @@
1
+ import { getSendableSelection } from '../actions';
2
+ import { pluginKey } from '../plugin-key';
3
+ export var sendTransaction = function sendTransaction(_ref) {
4
+ var originalTransaction = _ref.originalTransaction,
5
+ transactions = _ref.transactions,
6
+ oldEditorState = _ref.oldEditorState,
7
+ newEditorState = _ref.newEditorState,
8
+ useNativePlugin = _ref.useNativePlugin;
9
+ return function (provider) {
10
+ var docChangedTransaction = transactions.find(function (tr) {
11
+ return tr.docChanged;
12
+ });
13
+ var currentPluginState = pluginKey.getState(newEditorState);
14
+ if (!(currentPluginState !== null && currentPluginState !== void 0 && currentPluginState.isReady)) {
15
+ return;
16
+ }
17
+ var shouldSendStepForSynchronyCollabProvider = !originalTransaction.getMeta('isRemote') &&
18
+ // TODO: ED-8995
19
+ // We need to do this check to reduce the number of race conditions when working with tables.
20
+ // This metadata is coming from the scaleTable command in table-resizing plugin
21
+ !originalTransaction.getMeta('scaleTable') && docChangedTransaction;
22
+ if (useNativePlugin || shouldSendStepForSynchronyCollabProvider) {
23
+ provider.send(docChangedTransaction, oldEditorState, newEditorState);
24
+ }
25
+ var prevPluginState = pluginKey.getState(oldEditorState);
26
+ var _ref2 = prevPluginState || {},
27
+ prevActiveParticipants = _ref2.activeParticipants;
28
+ var activeParticipants = currentPluginState.activeParticipants,
29
+ sessionId = currentPluginState.sessionId;
30
+ var selectionChanged = !oldEditorState.selection.eq(newEditorState.selection);
31
+ var participantsChanged = prevActiveParticipants && !prevActiveParticipants.eq(activeParticipants);
32
+ if (sessionId && selectionChanged && !docChangedTransaction || sessionId && participantsChanged) {
33
+ var selection = getSendableSelection(newEditorState.selection);
34
+ var message = {
35
+ type: 'telepointer',
36
+ selection: selection,
37
+ sessionId: sessionId
38
+ };
39
+ provider.sendMessage(message);
40
+ }
41
+ };
42
+ };
@@ -0,0 +1,116 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
+ import { collab } from 'prosemirror-collab';
5
+ import { addSynchronyErrorAnalytics } from './analytics';
6
+ import { sendTransaction } from './events/send-transaction';
7
+ import { nativeCollabProviderPlugin } from './native-collab-provider-plugin';
8
+ import { createPlugin, pluginKey } from './plugin';
9
+ export { pluginKey };
10
+ import { getAvatarColor } from './utils';
11
+ var providerBuilder = function providerBuilder(collabEditProviderPromise) {
12
+ return /*#__PURE__*/function () {
13
+ var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(codeToExecute, onError) {
14
+ var provider;
15
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
16
+ while (1) switch (_context.prev = _context.next) {
17
+ case 0:
18
+ _context.prev = 0;
19
+ _context.next = 3;
20
+ return collabEditProviderPromise;
21
+ case 3:
22
+ provider = _context.sent;
23
+ if (!provider) {
24
+ _context.next = 6;
25
+ break;
26
+ }
27
+ return _context.abrupt("return", codeToExecute(provider));
28
+ case 6:
29
+ _context.next = 11;
30
+ break;
31
+ case 8:
32
+ _context.prev = 8;
33
+ _context.t0 = _context["catch"](0);
34
+ if (onError) {
35
+ onError(_context.t0);
36
+ } else {
37
+ // eslint-disable-next-line no-console
38
+ console.error(_context.t0);
39
+ }
40
+ case 11:
41
+ case "end":
42
+ return _context.stop();
43
+ }
44
+ }, _callee, null, [[0, 8]]);
45
+ }));
46
+ return function (_x, _x2) {
47
+ return _ref.apply(this, arguments);
48
+ };
49
+ }();
50
+ };
51
+ export var collabEditPlugin = function collabEditPlugin(_ref2) {
52
+ var _api$featureFlags;
53
+ var options = _ref2.config,
54
+ api = _ref2.api;
55
+ var featureFlags = (api === null || api === void 0 || (_api$featureFlags = api.featureFlags) === null || _api$featureFlags === void 0 ? void 0 : _api$featureFlags.sharedState.currentState()) || {};
56
+ var providerResolver = function providerResolver() {};
57
+ var collabEditProviderPromise = new Promise(function (_providerResolver) {
58
+ providerResolver = _providerResolver;
59
+ });
60
+ var executeProviderCode = providerBuilder(collabEditProviderPromise);
61
+ return {
62
+ name: 'collabEdit',
63
+ getSharedState: function getSharedState(state) {
64
+ if (!state) {
65
+ return undefined;
66
+ }
67
+ var collabPluginState = pluginKey.getState(state);
68
+ return {
69
+ activeParticipants: collabPluginState === null || collabPluginState === void 0 ? void 0 : collabPluginState.activeParticipants,
70
+ sessionId: collabPluginState === null || collabPluginState === void 0 ? void 0 : collabPluginState.sessionId
71
+ };
72
+ },
73
+ actions: {
74
+ getAvatarColor: getAvatarColor
75
+ },
76
+ pmPlugins: function pmPlugins() {
77
+ var _ref3 = options || {},
78
+ _ref3$useNativePlugin = _ref3.useNativePlugin,
79
+ useNativePlugin = _ref3$useNativePlugin === void 0 ? false : _ref3$useNativePlugin,
80
+ userId = _ref3.userId;
81
+ return [].concat(_toConsumableArray(useNativePlugin ? [{
82
+ name: 'pmCollab',
83
+ plugin: function plugin() {
84
+ return collab({
85
+ clientID: userId
86
+ });
87
+ }
88
+ }, {
89
+ name: 'nativeCollabProviderPlugin',
90
+ plugin: function plugin() {
91
+ return nativeCollabProviderPlugin({
92
+ providerPromise: collabEditProviderPromise
93
+ });
94
+ }
95
+ }] : []), [{
96
+ name: 'collab',
97
+ plugin: function plugin(_ref4) {
98
+ var dispatch = _ref4.dispatch,
99
+ providerFactory = _ref4.providerFactory;
100
+ return createPlugin(dispatch, providerFactory, providerResolver, executeProviderCode, options, featureFlags, api);
101
+ }
102
+ }]);
103
+ },
104
+ onEditorViewStateUpdated: function onEditorViewStateUpdated(props) {
105
+ var _api$analytics, _options$useNativePlu;
106
+ var addErrorAnalytics = addSynchronyErrorAnalytics(props.newEditorState, props.newEditorState.tr, featureFlags, api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions);
107
+ executeProviderCode(sendTransaction({
108
+ originalTransaction: props.originalTransaction,
109
+ transactions: props.transactions,
110
+ oldEditorState: props.oldEditorState,
111
+ newEditorState: props.newEditorState,
112
+ useNativePlugin: (_options$useNativePlu = options === null || options === void 0 ? void 0 : options.useNativePlugin) !== null && _options$useNativePlu !== void 0 ? _options$useNativePlu : false
113
+ }), addErrorAnalytics);
114
+ }
115
+ };
116
+ };
@@ -0,0 +1,31 @@
1
+ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
+ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
3
+ var nativeCollabProviderPluginKey = new PluginKey('nativeCollabProviderPlugin');
4
+ export var nativeCollabProviderPlugin = function nativeCollabProviderPlugin(_ref) {
5
+ var providerPromise = _ref.providerPromise;
6
+ return new SafePlugin({
7
+ key: nativeCollabProviderPluginKey,
8
+ state: {
9
+ init: function init() {
10
+ return null;
11
+ },
12
+ apply: function apply(tr, currentPluginState) {
13
+ var provider = tr.getMeta(nativeCollabProviderPluginKey);
14
+ return provider ? provider : currentPluginState;
15
+ }
16
+ },
17
+ view: function view(editorView) {
18
+ providerPromise.then(function (provider) {
19
+ var dispatch = editorView.dispatch,
20
+ state = editorView.state;
21
+ var tr = state.tr;
22
+ tr.setMeta(nativeCollabProviderPluginKey, provider);
23
+ dispatch(tr);
24
+ });
25
+ return {};
26
+ }
27
+ });
28
+ };
29
+ export var getCollabProvider = function getCollabProvider(editorState) {
30
+ return nativeCollabProviderPluginKey.getState(editorState);
31
+ };