@atlaskit/editor-plugin-annotation 2.8.3 → 2.9.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 (31) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/cjs/editor-commands/index.js +50 -1
  3. package/dist/cjs/pm-plugins/annotation-manager-hooks.js +166 -4
  4. package/dist/cjs/pm-plugins/inline-comment.js +169 -30
  5. package/dist/cjs/pm-plugins/plugin-factory.js +51 -1
  6. package/dist/cjs/pm-plugins/reducer.js +18 -1
  7. package/dist/cjs/pm-plugins/toolbar.js +10 -7
  8. package/dist/cjs/pm-plugins/types.js +2 -0
  9. package/dist/es2019/editor-commands/index.js +42 -0
  10. package/dist/es2019/pm-plugins/annotation-manager-hooks.js +160 -5
  11. package/dist/es2019/pm-plugins/inline-comment.js +146 -9
  12. package/dist/es2019/pm-plugins/plugin-factory.js +51 -1
  13. package/dist/es2019/pm-plugins/reducer.js +22 -1
  14. package/dist/es2019/pm-plugins/toolbar.js +10 -8
  15. package/dist/es2019/pm-plugins/types.js +2 -0
  16. package/dist/esm/editor-commands/index.js +49 -0
  17. package/dist/esm/pm-plugins/annotation-manager-hooks.js +167 -5
  18. package/dist/esm/pm-plugins/inline-comment.js +159 -20
  19. package/dist/esm/pm-plugins/plugin-factory.js +51 -1
  20. package/dist/esm/pm-plugins/reducer.js +18 -1
  21. package/dist/esm/pm-plugins/toolbar.js +10 -7
  22. package/dist/esm/pm-plugins/types.js +2 -0
  23. package/dist/types/editor-commands/index.d.ts +5 -0
  24. package/dist/types/pm-plugins/annotation-manager-hooks.d.ts +4 -1
  25. package/dist/types/pm-plugins/plugin-factory.d.ts +4 -0
  26. package/dist/types/pm-plugins/types.d.ts +26 -1
  27. package/dist/types-ts4.5/editor-commands/index.d.ts +5 -0
  28. package/dist/types-ts4.5/pm-plugins/annotation-manager-hooks.d.ts +4 -1
  29. package/dist/types-ts4.5/pm-plugins/plugin-factory.d.ts +4 -0
  30. package/dist/types-ts4.5/pm-plugins/types.d.ts +26 -1
  31. package/package.json +6 -3
@@ -4,11 +4,12 @@ import _regeneratorRuntime from "@babel/runtime/regenerator";
4
4
  import { AnnotationTypes } from '@atlaskit/adf-schema';
5
5
  import { RESOLVE_METHOD } from '@atlaskit/editor-common/analytics';
6
6
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
7
+ import { getAnnotationInlineNodeTypes } from '@atlaskit/editor-common/utils';
7
8
  import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
9
  import { fg } from '@atlaskit/platform-feature-flags';
9
- import { clearDirtyMark, closeComponent, setHoveredAnnotation, setInlineCommentsVisibility, setSelectedAnnotation, updateInlineCommentResolvedState, updateMouseState } from '../editor-commands';
10
+ import { clearDirtyMark, closeComponent, setHoveredAnnotation, setInlineCommentsVisibility, setSelectedAnnotation, flushPendingSelections, updateInlineCommentResolvedState, updateMouseState, setPendingSelectedAnnotation, setInlineCommentDraftState } from '../editor-commands';
10
11
  import { getAnnotationViewClassname, getBlockAnnotationViewClassname } from '../nodeviews';
11
- import { allowAnnotation, applyDraft, clearDraft, getDraft, startDraft } from './annotation-manager-hooks';
12
+ import { allowAnnotation, applyDraft, clearDraft, clearAnnotation, getDraft, setIsAnnotationHovered, setIsAnnotationSelected, startDraft } from './annotation-manager-hooks';
12
13
  import { createPluginState } from './plugin-factory';
13
14
  import { decorationKey, getAllAnnotations, getPluginState, inlineCommentPluginKey } from './utils';
14
15
  var fetchProviderStates = /*#__PURE__*/function () {
@@ -97,7 +98,9 @@ var initialState = function initialState() {
97
98
  isVisible: true,
98
99
  skipSelectionHandling: false,
99
100
  featureFlagsPluginState: featureFlagsPluginState,
100
- isDrafting: false
101
+ isDrafting: false,
102
+ pendingSelectedAnnotations: [],
103
+ pendingSelectedAnnotationsUpdateCount: 0
101
104
  };
102
105
  };
103
106
  var hideToolbar = function hideToolbar(state, dispatch) {
@@ -156,12 +159,33 @@ export var inlineCommentPlugin = function inlineCommentPlugin(options) {
156
159
  key: inlineCommentPluginKey,
157
160
  state: createPluginState(options.dispatch, initialState(provider.disallowOnWhitespace, featureFlagsPluginState)),
158
161
  view: function view(editorView) {
162
+ var allowAnnotationFn;
163
+ var startDraftFn;
164
+ var clearDraftFn;
165
+ var applyDraftFn;
166
+ var getDraftFn;
167
+ var setIsAnnotationSelectedFn;
168
+ var setIsAnnotationHoveredFn;
169
+ var clearAnnotationFn;
159
170
  if (annotationManager && fg('platform_editor_comments_api_manager')) {
160
- annotationManager.hook('allowAnnotation', allowAnnotation(editorView, options));
161
- annotationManager.hook('startDraft', startDraft(editorView, options));
162
- annotationManager.hook('clearDraft', clearDraft(editorView, options));
163
- annotationManager.hook('applyDraft', applyDraft(editorView, options));
164
- annotationManager.hook('getDraft', getDraft(editorView, options));
171
+ allowAnnotationFn = allowAnnotation(editorView, options);
172
+ startDraftFn = startDraft(editorView, options);
173
+ clearDraftFn = clearDraft(editorView, options);
174
+ applyDraftFn = applyDraft(editorView, options);
175
+ getDraftFn = getDraft(editorView, options);
176
+ annotationManager.hook('allowAnnotation', allowAnnotationFn);
177
+ annotationManager.hook('startDraft', startDraftFn);
178
+ annotationManager.hook('clearDraft', clearDraftFn);
179
+ annotationManager.hook('applyDraft', applyDraftFn);
180
+ annotationManager.hook('getDraft', getDraftFn);
181
+ if (fg('platform_editor_comments_api_manager_select')) {
182
+ setIsAnnotationSelectedFn = setIsAnnotationSelected(editorView, options);
183
+ setIsAnnotationHoveredFn = setIsAnnotationHovered(editorView, options);
184
+ clearAnnotationFn = clearAnnotation(editorView, options);
185
+ annotationManager.hook('setIsAnnotationSelected', setIsAnnotationSelectedFn);
186
+ annotationManager.hook('setIsAnnotationHovered', setIsAnnotationHoveredFn);
187
+ annotationManager.hook('clearAnnotation', clearAnnotationFn);
188
+ }
165
189
  }
166
190
  // Get initial state
167
191
  // Need to pass `editorView` to mitigate editor state going stale
@@ -219,6 +243,13 @@ export var inlineCommentPlugin = function inlineCommentPlugin(options) {
219
243
 
220
244
  // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
221
245
  editorView.root.addEventListener('mouseup', mouseUp);
246
+
247
+ /**
248
+ * This flag is used to prevent the preemptive gate from being called multiple times while a check is in-flight.
249
+ * If a check is still pending then it's most likely because the product is busy and trying to block the
250
+ * selection of an annotation.
251
+ */
252
+ var isPreemptiveGateActive = false;
222
253
  return {
223
254
  update: function update(view, _prevState) {
224
255
  var _prevSelectedAnnotati;
@@ -239,8 +270,85 @@ export var inlineCommentPlugin = function inlineCommentPlugin(options) {
239
270
  // The selectComponentExperience is using a simplified object, which is why it's type asserted.
240
271
  (_options$selectCommen = options.selectCommentExperience) === null || _options$selectCommen === void 0 || _options$selectCommen.selectAnnotation.complete(selectedAnnotationId);
241
272
  }
242
- var _ref6 = getPluginState(view.state) || {},
243
- dirtyAnnotations = _ref6.dirtyAnnotations;
273
+ if (fg('platform_editor_comments_api_manager_select')) {
274
+ // In the Editor, Annotations can be selected in three ways:
275
+ // 1. By clicking on the annotation in the editor
276
+ // 2. By using the annotation manager to select the annotation
277
+ // 3. By moving the cursor to the annotation and using the keyboard to select it
278
+ // Item 1 & 3 need to be protected by the preemptive gate. This is because these actions could be performed by a user
279
+ // at a time when changing the selection could cause data loss.
280
+ // The following preemptive check is designed to cover these items.
281
+
282
+ var _ref6 = getPluginState(view.state) || {},
283
+ pendingSelectedAnnotations = _ref6.pendingSelectedAnnotations,
284
+ pendingSelectedAnnotationsUpdateCount = _ref6.pendingSelectedAnnotationsUpdateCount;
285
+ var _ref7 = getPluginState(_prevState) || {},
286
+ prevPendingSelectedAnnotationsUpdateCount = _ref7.pendingSelectedAnnotationsUpdateCount;
287
+ if (!isPreemptiveGateActive && pendingSelectedAnnotationsUpdateCount !== prevPendingSelectedAnnotationsUpdateCount && !!(pendingSelectedAnnotations !== null && pendingSelectedAnnotations !== void 0 && pendingSelectedAnnotations.length)) {
288
+ // Need to set a lock to avoid calling gate multiple times. The lock will be released
289
+ // when the preemptive gate is complete.
290
+ isPreemptiveGateActive = true;
291
+ annotationManager === null || annotationManager === void 0 || annotationManager.checkPreemptiveGate().then(function (canSelectAnnotation) {
292
+ var _ref8 = getPluginState(view.state) || {},
293
+ isDrafting = _ref8.isDrafting,
294
+ latestPendingSelectedAnnotations = _ref8.pendingSelectedAnnotations,
295
+ latestSelectedAnnotations = _ref8.selectedAnnotations;
296
+ if (canSelectAnnotation) {
297
+ if (isDrafting) {
298
+ // The user must have chosen to discard there draft. So before we flush the pending selections
299
+ // we need to clear the draft if there is one.
300
+ setInlineCommentDraftState(options.editorAnalyticsAPI)(false)(view.state, view.dispatch);
301
+ }
302
+
303
+ // Flush the pending selections into the selected annotations list.
304
+ flushPendingSelections(true)(view.state, view.dispatch);
305
+ latestSelectedAnnotations === null || latestSelectedAnnotations === void 0 || latestSelectedAnnotations.filter(function (annotation) {
306
+ return (latestPendingSelectedAnnotations === null || latestPendingSelectedAnnotations === void 0 ? void 0 : latestPendingSelectedAnnotations.findIndex(function (pendingAnnotation) {
307
+ return pendingAnnotation.id === annotation.id;
308
+ })) === -1;
309
+ }).forEach(function (annotation) {
310
+ var _options$annotationMa, _getAnnotationInlineN;
311
+ (_options$annotationMa = options.annotationManager) === null || _options$annotationMa === void 0 || _options$annotationMa.emit({
312
+ name: 'annotationSelectionChanged',
313
+ data: {
314
+ annotationId: annotation.id,
315
+ isSelected: false,
316
+ inlineNodeTypes: (_getAnnotationInlineN = getAnnotationInlineNodeTypes(editorView.state, annotation.id)) !== null && _getAnnotationInlineN !== void 0 ? _getAnnotationInlineN : []
317
+ }
318
+ });
319
+ });
320
+
321
+ // Notify the annotation manager that the pending selection has changed.
322
+ latestPendingSelectedAnnotations === null || latestPendingSelectedAnnotations === void 0 || latestPendingSelectedAnnotations.forEach(function (_ref9) {
323
+ var _options$annotationMa2, _getAnnotationInlineN2;
324
+ var id = _ref9.id;
325
+ (_options$annotationMa2 = options.annotationManager) === null || _options$annotationMa2 === void 0 || _options$annotationMa2.emit({
326
+ name: 'annotationSelectionChanged',
327
+ data: {
328
+ annotationId: id,
329
+ isSelected: true,
330
+ inlineNodeTypes: (_getAnnotationInlineN2 = getAnnotationInlineNodeTypes(view.state, id)) !== null && _getAnnotationInlineN2 !== void 0 ? _getAnnotationInlineN2 : []
331
+ }
332
+ });
333
+ });
334
+ } else {
335
+ // Clears the pending selections if the preemptive gate returns false.
336
+ // We should need to worry about dispatching change events here because the pending selections
337
+ // are being aborted and the selections will remain unchanged.
338
+ flushPendingSelections(false)(view.state, view.dispatch);
339
+ }
340
+ }).catch(function (error) {
341
+ // TODO: EDITOR-595 - Ensure and anlytic is fired to indicate which reports on the error.
342
+
343
+ // If an error has occured we will clear any pending selections to avoid accidentally setting the wrong thing.
344
+ flushPendingSelections(false)(view.state, view.dispatch);
345
+ }).finally(function () {
346
+ isPreemptiveGateActive = false;
347
+ });
348
+ }
349
+ }
350
+ var _ref10 = getPluginState(view.state) || {},
351
+ dirtyAnnotations = _ref10.dirtyAnnotations;
244
352
  if (!dirtyAnnotations) {
245
353
  return;
246
354
  }
@@ -253,6 +361,16 @@ export var inlineCommentPlugin = function inlineCommentPlugin(options) {
253
361
  if (updateSubscriber) {
254
362
  updateSubscriber.off('resolve', resolve).off('delete', resolve).off('unresolve', unResolve).off('create', unResolve).off('setvisibility', setVisibility).off('setselectedannotation', setSelectedAnnotationFn).off('sethoveredannotation', setHoveredAnnotationFn).off('removehoveredannotation', removeHoveredannotationFn).off('closeinlinecomment', closeInlineCommentFn);
255
363
  }
364
+ if (annotationManager && fg('platform_editor_comments_api_manager')) {
365
+ annotationManager.unhook('allowAnnotation', allowAnnotationFn);
366
+ annotationManager.unhook('startDraft', startDraftFn);
367
+ annotationManager.unhook('clearDraft', clearDraftFn);
368
+ annotationManager.unhook('applyDraft', applyDraftFn);
369
+ annotationManager.unhook('getDraft', getDraftFn);
370
+ annotationManager.unhook('setIsAnnotationSelected', setIsAnnotationSelectedFn);
371
+ annotationManager.unhook('setIsAnnotationHovered', setIsAnnotationHoveredFn);
372
+ annotationManager.unhook('clearAnnotation', clearAnnotationFn);
373
+ }
256
374
  }
257
375
  };
258
376
  },
@@ -293,27 +411,48 @@ export var inlineCommentPlugin = function inlineCommentPlugin(options) {
293
411
  if (isSelected && !(pluginState !== null && pluginState !== void 0 && pluginState.isInlineCommentViewClosed)) {
294
412
  return false;
295
413
  }
296
- var _ref7 = pluginState || {},
297
- annotations = _ref7.annotations;
414
+ var _ref11 = pluginState || {},
415
+ annotations = _ref11.annotations;
298
416
  var isUnresolved = annotations && annotations[annotationId] === false;
299
417
  if (!isUnresolved) {
300
418
  return false;
301
419
  }
302
- setSelectedAnnotation(annotationId)(view.state, view.dispatch);
420
+ if (fg('platform_editor_comments_api_manager_select')) {
421
+ var _pluginState$pendingS;
422
+ // The manager disable setting the selected annotation on click because in the editor this is already
423
+ // handled by the selection update handler. When the manager is enabled, and a selection changes it's pushed into
424
+ // the pendingSelectedAnnotations array. This is then used to update the selection when the preemptive gate
425
+ // is released.
426
+ var isPendingSelection = pluginState === null || pluginState === void 0 || (_pluginState$pendingS = pluginState.pendingSelectedAnnotations) === null || _pluginState$pendingS === void 0 ? void 0 : _pluginState$pendingS.some(function (selectedAnnotation) {
427
+ return selectedAnnotation.id === annotationId;
428
+ });
429
+ // If the annotation is selected and the inline comment view is open, do nothing
430
+ // as the user is already in the comment view.
431
+ if (isPendingSelection) {
432
+ return false;
433
+ }
434
+ setPendingSelectedAnnotation(annotationId)(view.state, view.dispatch);
435
+ } else {
436
+ setSelectedAnnotation(annotationId)(view.state, view.dispatch);
437
+ }
303
438
  return true;
304
439
  }
305
440
  },
306
441
  decorations: function decorations(state) {
307
442
  // highlight comments, depending on state
308
- var _ref8 = getPluginState(state) || {},
309
- draftDecorationSet = _ref8.draftDecorationSet,
310
- annotations = _ref8.annotations,
311
- selectedAnnotations = _ref8.selectedAnnotations,
312
- isVisible = _ref8.isVisible,
313
- isInlineCommentViewClosed = _ref8.isInlineCommentViewClosed,
314
- hoveredAnnotations = _ref8.hoveredAnnotations;
443
+ var _ref12 = getPluginState(state) || {},
444
+ draftDecorationSet = _ref12.draftDecorationSet,
445
+ annotations = _ref12.annotations,
446
+ selectedAnnotations = _ref12.selectedAnnotations,
447
+ isVisible = _ref12.isVisible,
448
+ isInlineCommentViewClosed = _ref12.isInlineCommentViewClosed,
449
+ hoveredAnnotations = _ref12.hoveredAnnotations;
315
450
  var decorations = draftDecorationSet !== null && draftDecorationSet !== void 0 ? draftDecorationSet : DecorationSet.empty;
316
451
  var focusDecorations = [];
452
+
453
+ // TODO: EDITOR-760 - This needs to be optimised, it's not a good idea to scan the entire document
454
+ // everytime we need to update the decorations. This handler will be called alot. We should be caching
455
+ // the decorations in plugin state and only updating them when required.
317
456
  state.doc.descendants(function (node, pos) {
318
457
  var _provider$supportedBl;
319
458
  // Inline comment on mediaInline is not supported as part of comments on media project
@@ -4,6 +4,7 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
4
4
  import { pluginFactory } from '@atlaskit/editor-common/utils';
5
5
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
6
6
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
7
+ import { fg } from '@atlaskit/platform-feature-flags';
7
8
  import reducer from './reducer';
8
9
  import { decorationKey, findAnnotationsInSelection, inlineCommentPluginKey, isBlockNodeAnnotationsSelected, isSelectedAnnotationsChanged } from './utils';
9
10
  var handleDocChanged = function handleDocChanged(tr, prevPluginState) {
@@ -19,6 +20,10 @@ var handleDocChanged = function handleDocChanged(tr, prevPluginState) {
19
20
  * We clear bookmark on the following conditions:
20
21
  * 1. if current selection is an empty selection, or
21
22
  * 2. if the current selection and bookmark selection are different
23
+ * @param tr
24
+ * @param editorState
25
+ * @param bookmark
26
+ * @example
22
27
  */
23
28
  export var shouldClearBookMarkCheck = function shouldClearBookMarkCheck(tr, editorState, bookmark) {
24
29
  if (editorState.selection.empty || !bookmark) {
@@ -46,7 +51,7 @@ export var shouldClearBookMarkCheck = function shouldClearBookMarkCheck(tr, edit
46
51
  // by default we discard bookmark
47
52
  return true;
48
53
  };
49
- var getSelectionChangedHandler = function getSelectionChangedHandler(reopenCommentView) {
54
+ var getSelectionChangeHandlerOld = function getSelectionChangeHandlerOld(reopenCommentView) {
50
55
  return function (tr, pluginState) {
51
56
  if (pluginState.skipSelectionHandling) {
52
57
  return _objectSpread(_objectSpread({}, pluginState), {}, {
@@ -86,6 +91,51 @@ var getSelectionChangedHandler = function getSelectionChangedHandler(reopenComme
86
91
  });
87
92
  };
88
93
  };
94
+ var getSelectionChangeHandlerNew = function getSelectionChangeHandlerNew(reopenCommentView) {
95
+ return function (tr, pluginState) {
96
+ if (pluginState.skipSelectionHandling) {
97
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
98
+ skipSelectionHandling: false
99
+ }, reopenCommentView && {
100
+ isInlineCommentViewClosed: false
101
+ });
102
+ }
103
+ var selectedAnnotations = findAnnotationsInSelection(tr.selection, tr.doc);
104
+
105
+ // NOTE: I've left this commented code here as a reference that the previous old code would reset the selected annotations
106
+ // if the selection is empty. If this is no longer needed, we can remove this code.
107
+ // clean up with platform_editor_comments_api_manager_select
108
+ // if (selectedAnnotations.length === 0) {
109
+ // return {
110
+ // ...pluginState,
111
+ // pendingSelectedAnnotations: selectedAnnotations,
112
+ // pendingSelectedAnnotationsUpdateCount:
113
+ // pluginState.pendingSelectedAnnotationsUpdateCount + 1,
114
+ // isInlineCommentViewClosed: true,
115
+ // selectAnnotationMethod: undefined,
116
+ // };
117
+ // }
118
+
119
+ if (isSelectedAnnotationsChanged(selectedAnnotations, pluginState.pendingSelectedAnnotations)) {
120
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
121
+ pendingSelectedAnnotations: selectedAnnotations,
122
+ pendingSelectedAnnotationsUpdateCount: pluginState.pendingSelectedAnnotationsUpdateCount + 1
123
+ }, reopenCommentView && {
124
+ isInlineCommentViewClosed: false
125
+ });
126
+ }
127
+ return _objectSpread(_objectSpread(_objectSpread({}, pluginState), reopenCommentView && {
128
+ isInlineCommentViewClosed: false
129
+ }), {}, {
130
+ selectAnnotationMethod: undefined
131
+ });
132
+ };
133
+ };
134
+ var getSelectionChangedHandler = function getSelectionChangedHandler(reopenCommentView) {
135
+ return function (tr, pluginState) {
136
+ return fg('platform_editor_comments_api_manager_select') ? getSelectionChangeHandlerNew(reopenCommentView)(tr, pluginState) : getSelectionChangeHandlerOld(reopenCommentView)(tr, pluginState);
137
+ };
138
+ };
89
139
  var _pluginFactory = pluginFactory(inlineCommentPluginKey, reducer, {
90
140
  onSelectionChanged: getSelectionChangedHandler(true),
91
141
  onDocChanged: handleDocChanged,
@@ -25,12 +25,14 @@ export default (function (pluginState, action) {
25
25
  annotations: {}
26
26
  });
27
27
  case ACTIONS.CLOSE_COMPONENT:
28
- return _objectSpread(_objectSpread({}, pluginState), {}, {
28
+ return _objectSpread(_objectSpread(_objectSpread({}, pluginState), {}, {
29
29
  isInlineCommentViewClosed: true,
30
30
  isDrafting: false,
31
31
  isOpeningMediaCommentFromToolbar: false
32
32
  }, fg('platform_editor_annotation_selected_annotation') && {
33
33
  selectedAnnotations: []
34
+ }), fg('platform_editor_comments_api_manager_select') && {
35
+ selectedAnnotations: []
34
36
  });
35
37
  case ACTIONS.ADD_INLINE_COMMENT:
36
38
  var updatedPluginState = getNewDraftState(pluginState, action.data.drafting, action.data.editorState);
@@ -39,6 +41,8 @@ export default (function (pluginState, action) {
39
41
  annotations: _objectSpread(_objectSpread({}, pluginState.annotations), action.data.inlineComments),
40
42
  isInlineCommentViewClosed: false,
41
43
  selectAnnotationMethod: undefined
44
+ }, fg('platform_editor_comments_api_manager_select') && {
45
+ skipSelectionHandling: true
42
46
  });
43
47
  case ACTIONS.INLINE_COMMENT_SET_VISIBLE:
44
48
  var isVisible = action.data.isVisible;
@@ -62,6 +66,19 @@ export default (function (pluginState, action) {
62
66
  skipSelectionHandling: true,
63
67
  isInlineCommentViewClosed: false
64
68
  });
69
+ case ACTIONS.FLUSH_PENDING_SELECTIONS:
70
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
71
+ selectedAnnotations: action.data.canSetAsSelectedAnnotations ? _toConsumableArray(pluginState.pendingSelectedAnnotations) : pluginState.selectedAnnotations,
72
+ pendingSelectedAnnotations: [],
73
+ isInlineCommentViewClosed: false
74
+ });
75
+ case ACTIONS.SET_PENDING_SELECTIONS:
76
+ return _objectSpread(_objectSpread({}, pluginState), {}, {
77
+ pendingSelectedAnnotations: _toConsumableArray(action.data.selectedAnnotations),
78
+ pendingSelectedAnnotationsUpdateCount: pluginState.pendingSelectedAnnotationsUpdateCount + 1,
79
+ skipSelectionHandling: true,
80
+ isInlineCommentViewClosed: false
81
+ });
65
82
  default:
66
83
  return pluginState;
67
84
  }
@@ -130,7 +130,7 @@ export var buildToolbar = function buildToolbar(editorAnalyticsAPI) {
130
130
  }
131
131
  if (fg('platform_editor_comments_api_manager')) {
132
132
  if (!annotationManager) {
133
- // TODO: EDITOR-188 - If we've reached here and the manager is not initialized, we should
133
+ // TODO: EDITOR-595 - If we've reached here and the manager is not initialized, we should
134
134
  // dispatch an analytics event to indicate that the user has clicked the button but
135
135
  // the action was not completed.
136
136
  return false;
@@ -144,16 +144,19 @@ export var buildToolbar = function buildToolbar(editorAnalyticsAPI) {
144
144
  }
145
145
  });
146
146
  createCommentExperience === null || createCommentExperience === void 0 || createCommentExperience.initExperience.start();
147
- var _annotationManager$st = annotationManager.startDraft(),
148
- success = _annotationManager$st.success;
149
- if (!success) {
150
- // TODO: EDITOR-188 - Report start draft attempt failed.
147
+ var result = annotationManager.startDraft();
148
+ if (result.success) {
149
+ // TODO: EDITOR-595 - Ensure and anlytic is fired to indicate that the user has started a draft.
150
+ } else {
151
+ // TODO: EDITOR-595 - Fire an analytics event to indicate that the user has clicked the button
152
+ // but the action was not completed, the result should contain a reason.
151
153
  }
152
154
  } else {
153
- // TODO: EDITOR-188 - Dispatch analytics event
155
+ // TODO: EDITOR-595 - Track the toolbar comment button was clicked but the preemptive gate
156
+ // check returned false and the draft cannot be started.
154
157
  }
155
158
  }).catch(function () {
156
- // TODO: EDITOR-188 - Handle preemptive gate check error and dispatch analytics event
159
+ // TODO: EDITOR-595 - Handle preemptive gate check error. Something went very wrong in the gate.
157
160
  });
158
161
  return true;
159
162
  } else {
@@ -8,5 +8,7 @@ export var ACTIONS = /*#__PURE__*/function (ACTIONS) {
8
8
  ACTIONS[ACTIONS["CLOSE_COMPONENT"] = 6] = "CLOSE_COMPONENT";
9
9
  ACTIONS[ACTIONS["SET_SELECTED_ANNOTATION"] = 7] = "SET_SELECTED_ANNOTATION";
10
10
  ACTIONS[ACTIONS["SET_HOVERED_ANNOTATION"] = 8] = "SET_HOVERED_ANNOTATION";
11
+ ACTIONS[ACTIONS["FLUSH_PENDING_SELECTIONS"] = 9] = "FLUSH_PENDING_SELECTIONS";
12
+ ACTIONS[ACTIONS["SET_PENDING_SELECTIONS"] = 10] = "SET_PENDING_SELECTIONS";
11
13
  return ACTIONS;
12
14
  }({});
@@ -9,10 +9,15 @@ import type { InlineCommentInputMethod, TargetType } from '../types';
9
9
  export declare const updateInlineCommentResolvedState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (partialNewState: InlineCommentMap, resolveMethod?: RESOLVE_METHOD) => Command;
10
10
  export declare const closeComponent: () => Command;
11
11
  export declare const clearDirtyMark: () => Command;
12
+ export declare const flushPendingSelections: (canSetAsSelectedAnnotations: boolean) => Command;
13
+ export declare const setPendingSelectedAnnotation: (id: string) => Command;
12
14
  export declare const removeInlineCommentNearSelection: (id: string, supportedNodes?: string[]) => Command;
15
+ export declare const removeInlineCommentFromDoc: (id: string, supportedNodes?: string[]) => Command;
13
16
  /**
14
17
  * Show active inline comments for a given block node, otherwise,
15
18
  * return false if the node has no comments or no unresolved comments.
19
+ * @param supportedBlockNodes
20
+ * @example
16
21
  */
17
22
  export declare const showInlineCommentForBlockNode: (supportedBlockNodes?: string[]) => (node: PMNode | null, viewMethod?: VIEW_METHOD, isOpeningMediaCommentFromToolbar?: boolean) => Command;
18
23
  export declare const setInlineCommentDraftState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined, supportedBlockNodes?: string[]) => (drafting: boolean, inputMethod?: InlineCommentInputMethod, targetType?: TargetType, targetNodeId?: string | undefined, isOpeningMediaCommentFromToolbar?: boolean) => Command;
@@ -1,5 +1,5 @@
1
1
  import { type AnnotationId } from '@atlaskit/adf-schema';
2
- import type { ApplyDraftResult, ClearDraftResult, GetDraftResult, StartDraftResult } from '@atlaskit/editor-common/annotation';
2
+ import type { ApplyDraftResult, ClearAnnotationResult, ClearDraftResult, GetDraftResult, HoverAnnotationResult, SelectAnnotationResult, StartDraftResult } from '@atlaskit/editor-common/annotation';
3
3
  import { type EditorView } from '@atlaskit/editor-prosemirror/view';
4
4
  import type { InlineCommentPluginOptions } from './types';
5
5
  export declare const allowAnnotation: (editorView: EditorView, options: InlineCommentPluginOptions) => () => boolean;
@@ -7,3 +7,6 @@ export declare const startDraft: (editorView: EditorView, options: InlineComment
7
7
  export declare const clearDraft: (editorView: EditorView, options: InlineCommentPluginOptions) => () => ClearDraftResult;
8
8
  export declare const applyDraft: (editorView: EditorView, options: InlineCommentPluginOptions) => (id: AnnotationId) => ApplyDraftResult;
9
9
  export declare const getDraft: (editorView: EditorView, options: InlineCommentPluginOptions) => () => GetDraftResult;
10
+ export declare const setIsAnnotationSelected: (editorView: EditorView, options: InlineCommentPluginOptions) => (id: AnnotationId, isSelected: boolean) => SelectAnnotationResult;
11
+ export declare const setIsAnnotationHovered: (editorView: EditorView, options: InlineCommentPluginOptions) => (id: AnnotationId, isHovered: boolean) => HoverAnnotationResult;
12
+ export declare const clearAnnotation: (editorView: EditorView, options: InlineCommentPluginOptions) => (id: AnnotationId) => ClearAnnotationResult;
@@ -4,6 +4,10 @@ import type { InlineCommentPluginState } from './types';
4
4
  * We clear bookmark on the following conditions:
5
5
  * 1. if current selection is an empty selection, or
6
6
  * 2. if the current selection and bookmark selection are different
7
+ * @param tr
8
+ * @param editorState
9
+ * @param bookmark
10
+ * @example
7
11
  */
8
12
  export declare const shouldClearBookMarkCheck: (tr: ReadonlyTransaction | Transaction, editorState: EditorState, bookmark?: SelectionBookmark) => boolean;
9
13
  export declare const createPluginState: (dispatch: import("@atlaskit/editor-common/event-dispatcher").Dispatch, initialState: InlineCommentPluginState | ((state: EditorState) => InlineCommentPluginState)) => import("prosemirror-state").SafeStateField<InlineCommentPluginState>, createCommand: <A = import("./types").InlineCommentAction>(action: A | ((state: Readonly<EditorState>) => false | A), transform?: ((tr: Transaction, state: EditorState) => Transaction) | undefined) => import("@atlaskit/editor-common/types").Command;
@@ -15,7 +15,9 @@ export declare enum ACTIONS {
15
15
  INLINE_COMMENT_SET_VISIBLE = 5,
16
16
  CLOSE_COMPONENT = 6,
17
17
  SET_SELECTED_ANNOTATION = 7,
18
- SET_HOVERED_ANNOTATION = 8
18
+ SET_HOVERED_ANNOTATION = 8,
19
+ FLUSH_PENDING_SELECTIONS = 9,
20
+ SET_PENDING_SELECTIONS = 10
19
21
  }
20
22
  export interface InlineCommentPluginOptions {
21
23
  dispatch: Dispatch;
@@ -80,6 +82,16 @@ export type InlineCommentAction = {
80
82
  hoveredAnnotations: AnnotationInfo[];
81
83
  selectAnnotationMethod?: VIEW_METHOD;
82
84
  };
85
+ } | {
86
+ type: ACTIONS.FLUSH_PENDING_SELECTIONS;
87
+ data: {
88
+ canSetAsSelectedAnnotations: boolean;
89
+ };
90
+ } | {
91
+ type: ACTIONS.SET_PENDING_SELECTIONS;
92
+ data: {
93
+ selectedAnnotations: AnnotationInfo[];
94
+ };
83
95
  };
84
96
  export type InlineCommentPluginState = {
85
97
  /**
@@ -137,4 +149,17 @@ export type InlineCommentPluginState = {
137
149
  selectAnnotationMethod?: VIEW_METHOD;
138
150
  isOpeningMediaCommentFromToolbar?: boolean;
139
151
  selectCommentExperience?: AnnotationProviders['selectCommentExperience'];
152
+ /**
153
+ * This is a list of annotations which are to be selected. This is updated all the time when the selection changes, and
154
+ * are periodically flushed to selectedAnnotations. This flush event results in the annotations being selected in the editor.
155
+ * This functionality has come about due to the fact that the editor can select annotations in 3 different ways. And the fact
156
+ * that we need to introduce a preemptive gate check which is async and can block annotations from being selected before they're
157
+ * selected.
158
+ */
159
+ pendingSelectedAnnotations: AnnotationInfo[];
160
+ /**
161
+ * This is a count of the number of times the pendingSelectedAnnotations has been updated. This can be used to determine
162
+ * if the pendingSelectedAnnotations has been updated since the last time it was flushed to selectedAnnotations.
163
+ */
164
+ pendingSelectedAnnotationsUpdateCount: number;
140
165
  };
@@ -9,10 +9,15 @@ import type { InlineCommentInputMethod, TargetType } from '../types';
9
9
  export declare const updateInlineCommentResolvedState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined) => (partialNewState: InlineCommentMap, resolveMethod?: RESOLVE_METHOD) => Command;
10
10
  export declare const closeComponent: () => Command;
11
11
  export declare const clearDirtyMark: () => Command;
12
+ export declare const flushPendingSelections: (canSetAsSelectedAnnotations: boolean) => Command;
13
+ export declare const setPendingSelectedAnnotation: (id: string) => Command;
12
14
  export declare const removeInlineCommentNearSelection: (id: string, supportedNodes?: string[]) => Command;
15
+ export declare const removeInlineCommentFromDoc: (id: string, supportedNodes?: string[]) => Command;
13
16
  /**
14
17
  * Show active inline comments for a given block node, otherwise,
15
18
  * return false if the node has no comments or no unresolved comments.
19
+ * @param supportedBlockNodes
20
+ * @example
16
21
  */
17
22
  export declare const showInlineCommentForBlockNode: (supportedBlockNodes?: string[]) => (node: PMNode | null, viewMethod?: VIEW_METHOD, isOpeningMediaCommentFromToolbar?: boolean) => Command;
18
23
  export declare const setInlineCommentDraftState: (editorAnalyticsAPI: EditorAnalyticsAPI | undefined, supportedBlockNodes?: string[]) => (drafting: boolean, inputMethod?: InlineCommentInputMethod, targetType?: TargetType, targetNodeId?: string | undefined, isOpeningMediaCommentFromToolbar?: boolean) => Command;
@@ -1,5 +1,5 @@
1
1
  import { type AnnotationId } from '@atlaskit/adf-schema';
2
- import type { ApplyDraftResult, ClearDraftResult, GetDraftResult, StartDraftResult } from '@atlaskit/editor-common/annotation';
2
+ import type { ApplyDraftResult, ClearAnnotationResult, ClearDraftResult, GetDraftResult, HoverAnnotationResult, SelectAnnotationResult, StartDraftResult } from '@atlaskit/editor-common/annotation';
3
3
  import { type EditorView } from '@atlaskit/editor-prosemirror/view';
4
4
  import type { InlineCommentPluginOptions } from './types';
5
5
  export declare const allowAnnotation: (editorView: EditorView, options: InlineCommentPluginOptions) => () => boolean;
@@ -7,3 +7,6 @@ export declare const startDraft: (editorView: EditorView, options: InlineComment
7
7
  export declare const clearDraft: (editorView: EditorView, options: InlineCommentPluginOptions) => () => ClearDraftResult;
8
8
  export declare const applyDraft: (editorView: EditorView, options: InlineCommentPluginOptions) => (id: AnnotationId) => ApplyDraftResult;
9
9
  export declare const getDraft: (editorView: EditorView, options: InlineCommentPluginOptions) => () => GetDraftResult;
10
+ export declare const setIsAnnotationSelected: (editorView: EditorView, options: InlineCommentPluginOptions) => (id: AnnotationId, isSelected: boolean) => SelectAnnotationResult;
11
+ export declare const setIsAnnotationHovered: (editorView: EditorView, options: InlineCommentPluginOptions) => (id: AnnotationId, isHovered: boolean) => HoverAnnotationResult;
12
+ export declare const clearAnnotation: (editorView: EditorView, options: InlineCommentPluginOptions) => (id: AnnotationId) => ClearAnnotationResult;
@@ -4,6 +4,10 @@ import type { InlineCommentPluginState } from './types';
4
4
  * We clear bookmark on the following conditions:
5
5
  * 1. if current selection is an empty selection, or
6
6
  * 2. if the current selection and bookmark selection are different
7
+ * @param tr
8
+ * @param editorState
9
+ * @param bookmark
10
+ * @example
7
11
  */
8
12
  export declare const shouldClearBookMarkCheck: (tr: ReadonlyTransaction | Transaction, editorState: EditorState, bookmark?: SelectionBookmark) => boolean;
9
13
  export declare const createPluginState: (dispatch: import("@atlaskit/editor-common/event-dispatcher").Dispatch, initialState: InlineCommentPluginState | ((state: EditorState) => InlineCommentPluginState)) => import("prosemirror-state").SafeStateField<InlineCommentPluginState>, createCommand: <A = import("./types").InlineCommentAction>(action: A | ((state: Readonly<EditorState>) => false | A), transform?: ((tr: Transaction, state: EditorState) => Transaction) | undefined) => import("@atlaskit/editor-common/types").Command;
@@ -15,7 +15,9 @@ export declare enum ACTIONS {
15
15
  INLINE_COMMENT_SET_VISIBLE = 5,
16
16
  CLOSE_COMPONENT = 6,
17
17
  SET_SELECTED_ANNOTATION = 7,
18
- SET_HOVERED_ANNOTATION = 8
18
+ SET_HOVERED_ANNOTATION = 8,
19
+ FLUSH_PENDING_SELECTIONS = 9,
20
+ SET_PENDING_SELECTIONS = 10
19
21
  }
20
22
  export interface InlineCommentPluginOptions {
21
23
  dispatch: Dispatch;
@@ -80,6 +82,16 @@ export type InlineCommentAction = {
80
82
  hoveredAnnotations: AnnotationInfo[];
81
83
  selectAnnotationMethod?: VIEW_METHOD;
82
84
  };
85
+ } | {
86
+ type: ACTIONS.FLUSH_PENDING_SELECTIONS;
87
+ data: {
88
+ canSetAsSelectedAnnotations: boolean;
89
+ };
90
+ } | {
91
+ type: ACTIONS.SET_PENDING_SELECTIONS;
92
+ data: {
93
+ selectedAnnotations: AnnotationInfo[];
94
+ };
83
95
  };
84
96
  export type InlineCommentPluginState = {
85
97
  /**
@@ -137,4 +149,17 @@ export type InlineCommentPluginState = {
137
149
  selectAnnotationMethod?: VIEW_METHOD;
138
150
  isOpeningMediaCommentFromToolbar?: boolean;
139
151
  selectCommentExperience?: AnnotationProviders['selectCommentExperience'];
152
+ /**
153
+ * This is a list of annotations which are to be selected. This is updated all the time when the selection changes, and
154
+ * are periodically flushed to selectedAnnotations. This flush event results in the annotations being selected in the editor.
155
+ * This functionality has come about due to the fact that the editor can select annotations in 3 different ways. And the fact
156
+ * that we need to introduce a preemptive gate check which is async and can block annotations from being selected before they're
157
+ * selected.
158
+ */
159
+ pendingSelectedAnnotations: AnnotationInfo[];
160
+ /**
161
+ * This is a count of the number of times the pendingSelectedAnnotations has been updated. This can be used to determine
162
+ * if the pendingSelectedAnnotations has been updated since the last time it was flushed to selectedAnnotations.
163
+ */
164
+ pendingSelectedAnnotationsUpdateCount: number;
140
165
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-annotation",
3
- "version": "2.8.3",
3
+ "version": "2.9.0",
4
4
  "description": "Annotation plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -33,7 +33,7 @@
33
33
  "dependencies": {
34
34
  "@atlaskit/adf-schema": "^47.6.0",
35
35
  "@atlaskit/analytics-next": "^11.0.0",
36
- "@atlaskit/editor-common": "^105.10.0",
36
+ "@atlaskit/editor-common": "^105.11.0",
37
37
  "@atlaskit/editor-plugin-analytics": "^2.3.0",
38
38
  "@atlaskit/editor-plugin-connectivity": "^2.0.0",
39
39
  "@atlaskit/editor-plugin-editor-viewmode-effects": "^2.0.0",
@@ -42,7 +42,7 @@
42
42
  "@atlaskit/icon": "^26.3.0",
43
43
  "@atlaskit/onboarding": "^14.1.0",
44
44
  "@atlaskit/platform-feature-flags": "^1.1.0",
45
- "@atlaskit/tmp-editor-statsig": "^5.0.0",
45
+ "@atlaskit/tmp-editor-statsig": "^5.1.0",
46
46
  "@babel/runtime": "^7.0.0"
47
47
  },
48
48
  "peerDependencies": {
@@ -97,6 +97,9 @@
97
97
  "platform_editor_comments_api_manager": {
98
98
  "type": "boolean"
99
99
  },
100
+ "platform_editor_comments_api_manager_select": {
101
+ "type": "boolean"
102
+ },
100
103
  "editor_inline_comments_on_inline_nodes": {
101
104
  "type": "boolean"
102
105
  },