@atlaskit/editor-plugin-annotation 2.8.2 → 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 (36) hide show
  1. package/CHANGELOG.md +19 -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/cjs/ui/InlineCommentView.js +14 -1
  10. package/dist/es2019/editor-commands/index.js +42 -0
  11. package/dist/es2019/pm-plugins/annotation-manager-hooks.js +160 -5
  12. package/dist/es2019/pm-plugins/inline-comment.js +146 -9
  13. package/dist/es2019/pm-plugins/plugin-factory.js +51 -1
  14. package/dist/es2019/pm-plugins/reducer.js +22 -1
  15. package/dist/es2019/pm-plugins/toolbar.js +10 -8
  16. package/dist/es2019/pm-plugins/types.js +2 -0
  17. package/dist/es2019/ui/InlineCommentView.js +11 -1
  18. package/dist/esm/editor-commands/index.js +49 -0
  19. package/dist/esm/pm-plugins/annotation-manager-hooks.js +167 -5
  20. package/dist/esm/pm-plugins/inline-comment.js +159 -20
  21. package/dist/esm/pm-plugins/plugin-factory.js +51 -1
  22. package/dist/esm/pm-plugins/reducer.js +18 -1
  23. package/dist/esm/pm-plugins/toolbar.js +10 -7
  24. package/dist/esm/pm-plugins/types.js +2 -0
  25. package/dist/esm/ui/InlineCommentView.js +11 -1
  26. package/dist/types/editor-commands/index.d.ts +5 -0
  27. package/dist/types/pm-plugins/annotation-manager-hooks.d.ts +4 -1
  28. package/dist/types/pm-plugins/plugin-factory.d.ts +4 -0
  29. package/dist/types/pm-plugins/types.d.ts +26 -1
  30. package/dist/types/types/index.d.ts +1 -0
  31. package/dist/types-ts4.5/editor-commands/index.d.ts +5 -0
  32. package/dist/types-ts4.5/pm-plugins/annotation-manager-hooks.d.ts +4 -1
  33. package/dist/types-ts4.5/pm-plugins/plugin-factory.d.ts +4 -0
  34. package/dist/types-ts4.5/pm-plugins/types.d.ts +26 -1
  35. package/dist/types-ts4.5/types/index.d.ts +1 -0
  36. package/package.json +7 -4
@@ -1,11 +1,12 @@
1
1
  import { AnnotationTypes } from '@atlaskit/adf-schema';
2
2
  import { RESOLVE_METHOD } from '@atlaskit/editor-common/analytics';
3
3
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
4
+ import { getAnnotationInlineNodeTypes } from '@atlaskit/editor-common/utils';
4
5
  import { Decoration, DecorationSet } from '@atlaskit/editor-prosemirror/view';
5
6
  import { fg } from '@atlaskit/platform-feature-flags';
6
- import { clearDirtyMark, closeComponent, setHoveredAnnotation, setInlineCommentsVisibility, setSelectedAnnotation, updateInlineCommentResolvedState, updateMouseState } from '../editor-commands';
7
+ import { clearDirtyMark, closeComponent, setHoveredAnnotation, setInlineCommentsVisibility, setSelectedAnnotation, flushPendingSelections, updateInlineCommentResolvedState, updateMouseState, setPendingSelectedAnnotation, setInlineCommentDraftState } from '../editor-commands';
7
8
  import { getAnnotationViewClassname, getBlockAnnotationViewClassname } from '../nodeviews';
8
- import { allowAnnotation, applyDraft, clearDraft, getDraft, startDraft } from './annotation-manager-hooks';
9
+ import { allowAnnotation, applyDraft, clearDraft, clearAnnotation, getDraft, setIsAnnotationHovered, setIsAnnotationSelected, startDraft } from './annotation-manager-hooks';
9
10
  import { createPluginState } from './plugin-factory';
10
11
  import { decorationKey, getAllAnnotations, getPluginState, inlineCommentPluginKey } from './utils';
11
12
  const fetchProviderStates = async (provider, annotationIds) => {
@@ -49,7 +50,9 @@ const initialState = (disallowOnWhitespace = false, featureFlagsPluginState) =>
49
50
  isVisible: true,
50
51
  skipSelectionHandling: false,
51
52
  featureFlagsPluginState,
52
- isDrafting: false
53
+ isDrafting: false,
54
+ pendingSelectedAnnotations: [],
55
+ pendingSelectedAnnotationsUpdateCount: 0
53
56
  };
54
57
  };
55
58
  const hideToolbar = (state, dispatch) => () => {
@@ -103,12 +106,33 @@ export const inlineCommentPlugin = options => {
103
106
  key: inlineCommentPluginKey,
104
107
  state: createPluginState(options.dispatch, initialState(provider.disallowOnWhitespace, featureFlagsPluginState)),
105
108
  view(editorView) {
109
+ let allowAnnotationFn;
110
+ let startDraftFn;
111
+ let clearDraftFn;
112
+ let applyDraftFn;
113
+ let getDraftFn;
114
+ let setIsAnnotationSelectedFn;
115
+ let setIsAnnotationHoveredFn;
116
+ let clearAnnotationFn;
106
117
  if (annotationManager && fg('platform_editor_comments_api_manager')) {
107
- annotationManager.hook('allowAnnotation', allowAnnotation(editorView, options));
108
- annotationManager.hook('startDraft', startDraft(editorView, options));
109
- annotationManager.hook('clearDraft', clearDraft(editorView, options));
110
- annotationManager.hook('applyDraft', applyDraft(editorView, options));
111
- annotationManager.hook('getDraft', getDraft(editorView, options));
118
+ allowAnnotationFn = allowAnnotation(editorView, options);
119
+ startDraftFn = startDraft(editorView, options);
120
+ clearDraftFn = clearDraft(editorView, options);
121
+ applyDraftFn = applyDraft(editorView, options);
122
+ getDraftFn = getDraft(editorView, options);
123
+ annotationManager.hook('allowAnnotation', allowAnnotationFn);
124
+ annotationManager.hook('startDraft', startDraftFn);
125
+ annotationManager.hook('clearDraft', clearDraftFn);
126
+ annotationManager.hook('applyDraft', applyDraftFn);
127
+ annotationManager.hook('getDraft', getDraftFn);
128
+ if (fg('platform_editor_comments_api_manager_select')) {
129
+ setIsAnnotationSelectedFn = setIsAnnotationSelected(editorView, options);
130
+ setIsAnnotationHoveredFn = setIsAnnotationHovered(editorView, options);
131
+ clearAnnotationFn = clearAnnotation(editorView, options);
132
+ annotationManager.hook('setIsAnnotationSelected', setIsAnnotationSelectedFn);
133
+ annotationManager.hook('setIsAnnotationHovered', setIsAnnotationHoveredFn);
134
+ annotationManager.hook('clearAnnotation', clearAnnotationFn);
135
+ }
112
136
  }
113
137
  // Get initial state
114
138
  // Need to pass `editorView` to mitigate editor state going stale
@@ -160,6 +184,13 @@ export const inlineCommentPlugin = options => {
160
184
 
161
185
  // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
162
186
  editorView.root.addEventListener('mouseup', mouseUp);
187
+
188
+ /**
189
+ * This flag is used to prevent the preemptive gate from being called multiple times while a check is in-flight.
190
+ * If a check is still pending then it's most likely because the product is busy and trying to block the
191
+ * selection of an annotation.
192
+ */
193
+ let isPreemptiveGateActive = false;
163
194
  return {
164
195
  update(view, _prevState) {
165
196
  var _prevSelectedAnnotati;
@@ -182,6 +213,83 @@ export const inlineCommentPlugin = options => {
182
213
  // The selectComponentExperience is using a simplified object, which is why it's type asserted.
183
214
  (_options$selectCommen = options.selectCommentExperience) === null || _options$selectCommen === void 0 ? void 0 : _options$selectCommen.selectAnnotation.complete(selectedAnnotationId);
184
215
  }
216
+ if (fg('platform_editor_comments_api_manager_select')) {
217
+ // In the Editor, Annotations can be selected in three ways:
218
+ // 1. By clicking on the annotation in the editor
219
+ // 2. By using the annotation manager to select the annotation
220
+ // 3. By moving the cursor to the annotation and using the keyboard to select it
221
+ // Item 1 & 3 need to be protected by the preemptive gate. This is because these actions could be performed by a user
222
+ // at a time when changing the selection could cause data loss.
223
+ // The following preemptive check is designed to cover these items.
224
+
225
+ const {
226
+ pendingSelectedAnnotations,
227
+ pendingSelectedAnnotationsUpdateCount
228
+ } = getPluginState(view.state) || {};
229
+ const {
230
+ pendingSelectedAnnotationsUpdateCount: prevPendingSelectedAnnotationsUpdateCount
231
+ } = getPluginState(_prevState) || {};
232
+ if (!isPreemptiveGateActive && pendingSelectedAnnotationsUpdateCount !== prevPendingSelectedAnnotationsUpdateCount && !!(pendingSelectedAnnotations !== null && pendingSelectedAnnotations !== void 0 && pendingSelectedAnnotations.length)) {
233
+ // Need to set a lock to avoid calling gate multiple times. The lock will be released
234
+ // when the preemptive gate is complete.
235
+ isPreemptiveGateActive = true;
236
+ annotationManager === null || annotationManager === void 0 ? void 0 : annotationManager.checkPreemptiveGate().then(canSelectAnnotation => {
237
+ const {
238
+ isDrafting,
239
+ pendingSelectedAnnotations: latestPendingSelectedAnnotations,
240
+ selectedAnnotations: latestSelectedAnnotations
241
+ } = getPluginState(view.state) || {};
242
+ if (canSelectAnnotation) {
243
+ if (isDrafting) {
244
+ // The user must have chosen to discard there draft. So before we flush the pending selections
245
+ // we need to clear the draft if there is one.
246
+ setInlineCommentDraftState(options.editorAnalyticsAPI)(false)(view.state, view.dispatch);
247
+ }
248
+
249
+ // Flush the pending selections into the selected annotations list.
250
+ flushPendingSelections(true)(view.state, view.dispatch);
251
+ latestSelectedAnnotations === null || latestSelectedAnnotations === void 0 ? void 0 : latestSelectedAnnotations.filter(annotation => (latestPendingSelectedAnnotations === null || latestPendingSelectedAnnotations === void 0 ? void 0 : latestPendingSelectedAnnotations.findIndex(pendingAnnotation => pendingAnnotation.id === annotation.id)) === -1).forEach(annotation => {
252
+ var _options$annotationMa, _getAnnotationInlineN;
253
+ (_options$annotationMa = options.annotationManager) === null || _options$annotationMa === void 0 ? void 0 : _options$annotationMa.emit({
254
+ name: 'annotationSelectionChanged',
255
+ data: {
256
+ annotationId: annotation.id,
257
+ isSelected: false,
258
+ inlineNodeTypes: (_getAnnotationInlineN = getAnnotationInlineNodeTypes(editorView.state, annotation.id)) !== null && _getAnnotationInlineN !== void 0 ? _getAnnotationInlineN : []
259
+ }
260
+ });
261
+ });
262
+
263
+ // Notify the annotation manager that the pending selection has changed.
264
+ latestPendingSelectedAnnotations === null || latestPendingSelectedAnnotations === void 0 ? void 0 : latestPendingSelectedAnnotations.forEach(({
265
+ id
266
+ }) => {
267
+ var _options$annotationMa2, _getAnnotationInlineN2;
268
+ (_options$annotationMa2 = options.annotationManager) === null || _options$annotationMa2 === void 0 ? void 0 : _options$annotationMa2.emit({
269
+ name: 'annotationSelectionChanged',
270
+ data: {
271
+ annotationId: id,
272
+ isSelected: true,
273
+ inlineNodeTypes: (_getAnnotationInlineN2 = getAnnotationInlineNodeTypes(view.state, id)) !== null && _getAnnotationInlineN2 !== void 0 ? _getAnnotationInlineN2 : []
274
+ }
275
+ });
276
+ });
277
+ } else {
278
+ // Clears the pending selections if the preemptive gate returns false.
279
+ // We should need to worry about dispatching change events here because the pending selections
280
+ // are being aborted and the selections will remain unchanged.
281
+ flushPendingSelections(false)(view.state, view.dispatch);
282
+ }
283
+ }).catch(error => {
284
+ // TODO: EDITOR-595 - Ensure and anlytic is fired to indicate which reports on the error.
285
+
286
+ // If an error has occured we will clear any pending selections to avoid accidentally setting the wrong thing.
287
+ flushPendingSelections(false)(view.state, view.dispatch);
288
+ }).finally(() => {
289
+ isPreemptiveGateActive = false;
290
+ });
291
+ }
292
+ }
185
293
  const {
186
294
  dirtyAnnotations
187
295
  } = getPluginState(view.state) || {};
@@ -197,6 +305,16 @@ export const inlineCommentPlugin = options => {
197
305
  if (updateSubscriber) {
198
306
  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);
199
307
  }
308
+ if (annotationManager && fg('platform_editor_comments_api_manager')) {
309
+ annotationManager.unhook('allowAnnotation', allowAnnotationFn);
310
+ annotationManager.unhook('startDraft', startDraftFn);
311
+ annotationManager.unhook('clearDraft', clearDraftFn);
312
+ annotationManager.unhook('applyDraft', applyDraftFn);
313
+ annotationManager.unhook('getDraft', getDraftFn);
314
+ annotationManager.unhook('setIsAnnotationSelected', setIsAnnotationSelectedFn);
315
+ annotationManager.unhook('setIsAnnotationHovered', setIsAnnotationHoveredFn);
316
+ annotationManager.unhook('clearAnnotation', clearAnnotationFn);
317
+ }
200
318
  }
201
319
  };
202
320
  },
@@ -242,7 +360,22 @@ export const inlineCommentPlugin = options => {
242
360
  if (!isUnresolved) {
243
361
  return false;
244
362
  }
245
- setSelectedAnnotation(annotationId)(view.state, view.dispatch);
363
+ if (fg('platform_editor_comments_api_manager_select')) {
364
+ var _pluginState$pendingS;
365
+ // The manager disable setting the selected annotation on click because in the editor this is already
366
+ // handled by the selection update handler. When the manager is enabled, and a selection changes it's pushed into
367
+ // the pendingSelectedAnnotations array. This is then used to update the selection when the preemptive gate
368
+ // is released.
369
+ const isPendingSelection = pluginState === null || pluginState === void 0 ? void 0 : (_pluginState$pendingS = pluginState.pendingSelectedAnnotations) === null || _pluginState$pendingS === void 0 ? void 0 : _pluginState$pendingS.some(selectedAnnotation => selectedAnnotation.id === annotationId);
370
+ // If the annotation is selected and the inline comment view is open, do nothing
371
+ // as the user is already in the comment view.
372
+ if (isPendingSelection) {
373
+ return false;
374
+ }
375
+ setPendingSelectedAnnotation(annotationId)(view.state, view.dispatch);
376
+ } else {
377
+ setSelectedAnnotation(annotationId)(view.state, view.dispatch);
378
+ }
246
379
  return true;
247
380
  }
248
381
  },
@@ -258,6 +391,10 @@ export const inlineCommentPlugin = options => {
258
391
  } = getPluginState(state) || {};
259
392
  let decorations = draftDecorationSet !== null && draftDecorationSet !== void 0 ? draftDecorationSet : DecorationSet.empty;
260
393
  const focusDecorations = [];
394
+
395
+ // TODO: EDITOR-760 - This needs to be optimised, it's not a good idea to scan the entire document
396
+ // everytime we need to update the decorations. This handler will be called alot. We should be caching
397
+ // the decorations in plugin state and only updating them when required.
261
398
  state.doc.descendants((node, pos) => {
262
399
  var _provider$supportedBl;
263
400
  // Inline comment on mediaInline is not supported as part of comments on media project
@@ -1,6 +1,7 @@
1
1
  import { pluginFactory } from '@atlaskit/editor-common/utils';
2
2
  import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
3
3
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
4
+ import { fg } from '@atlaskit/platform-feature-flags';
4
5
  import reducer from './reducer';
5
6
  import { decorationKey, findAnnotationsInSelection, inlineCommentPluginKey, isBlockNodeAnnotationsSelected, isSelectedAnnotationsChanged } from './utils';
6
7
  const handleDocChanged = (tr, prevPluginState) => {
@@ -17,6 +18,10 @@ const handleDocChanged = (tr, prevPluginState) => {
17
18
  * We clear bookmark on the following conditions:
18
19
  * 1. if current selection is an empty selection, or
19
20
  * 2. if the current selection and bookmark selection are different
21
+ * @param tr
22
+ * @param editorState
23
+ * @param bookmark
24
+ * @example
20
25
  */
21
26
  export const shouldClearBookMarkCheck = (tr, editorState, bookmark) => {
22
27
  if (editorState.selection.empty || !bookmark) {
@@ -44,7 +49,7 @@ export const shouldClearBookMarkCheck = (tr, editorState, bookmark) => {
44
49
  // by default we discard bookmark
45
50
  return true;
46
51
  };
47
- const getSelectionChangedHandler = reopenCommentView => (tr, pluginState) => {
52
+ const getSelectionChangeHandlerOld = reopenCommentView => (tr, pluginState) => {
48
53
  if (pluginState.skipSelectionHandling) {
49
54
  return {
50
55
  ...pluginState,
@@ -92,6 +97,51 @@ const getSelectionChangedHandler = reopenCommentView => (tr, pluginState) => {
92
97
  selectAnnotationMethod: undefined
93
98
  };
94
99
  };
100
+ const getSelectionChangeHandlerNew = reopenCommentView => (tr, pluginState) => {
101
+ if (pluginState.skipSelectionHandling) {
102
+ return {
103
+ ...pluginState,
104
+ skipSelectionHandling: false,
105
+ ...(reopenCommentView && {
106
+ isInlineCommentViewClosed: false
107
+ })
108
+ };
109
+ }
110
+ const selectedAnnotations = findAnnotationsInSelection(tr.selection, tr.doc);
111
+
112
+ // NOTE: I've left this commented code here as a reference that the previous old code would reset the selected annotations
113
+ // if the selection is empty. If this is no longer needed, we can remove this code.
114
+ // clean up with platform_editor_comments_api_manager_select
115
+ // if (selectedAnnotations.length === 0) {
116
+ // return {
117
+ // ...pluginState,
118
+ // pendingSelectedAnnotations: selectedAnnotations,
119
+ // pendingSelectedAnnotationsUpdateCount:
120
+ // pluginState.pendingSelectedAnnotationsUpdateCount + 1,
121
+ // isInlineCommentViewClosed: true,
122
+ // selectAnnotationMethod: undefined,
123
+ // };
124
+ // }
125
+
126
+ if (isSelectedAnnotationsChanged(selectedAnnotations, pluginState.pendingSelectedAnnotations)) {
127
+ return {
128
+ ...pluginState,
129
+ pendingSelectedAnnotations: selectedAnnotations,
130
+ pendingSelectedAnnotationsUpdateCount: pluginState.pendingSelectedAnnotationsUpdateCount + 1,
131
+ ...(reopenCommentView && {
132
+ isInlineCommentViewClosed: false
133
+ })
134
+ };
135
+ }
136
+ return {
137
+ ...pluginState,
138
+ ...(reopenCommentView && {
139
+ isInlineCommentViewClosed: false
140
+ }),
141
+ selectAnnotationMethod: undefined
142
+ };
143
+ };
144
+ const getSelectionChangedHandler = reopenCommentView => (tr, pluginState) => fg('platform_editor_comments_api_manager_select') ? getSelectionChangeHandlerNew(reopenCommentView)(tr, pluginState) : getSelectionChangeHandlerOld(reopenCommentView)(tr, pluginState);
95
145
  export const {
96
146
  createPluginState,
97
147
  createCommand
@@ -34,6 +34,9 @@ export default ((pluginState, action) => {
34
34
  isOpeningMediaCommentFromToolbar: false,
35
35
  ...(fg('platform_editor_annotation_selected_annotation') && {
36
36
  selectedAnnotations: []
37
+ }),
38
+ ...(fg('platform_editor_comments_api_manager_select') && {
39
+ selectedAnnotations: []
37
40
  })
38
41
  };
39
42
  case ACTIONS.ADD_INLINE_COMMENT:
@@ -46,7 +49,10 @@ export default ((pluginState, action) => {
46
49
  ...action.data.inlineComments
47
50
  },
48
51
  isInlineCommentViewClosed: false,
49
- selectAnnotationMethod: undefined
52
+ selectAnnotationMethod: undefined,
53
+ ...(fg('platform_editor_comments_api_manager_select') && {
54
+ skipSelectionHandling: true
55
+ })
50
56
  };
51
57
  case ACTIONS.INLINE_COMMENT_SET_VISIBLE:
52
58
  const {
@@ -75,6 +81,21 @@ export default ((pluginState, action) => {
75
81
  skipSelectionHandling: true,
76
82
  isInlineCommentViewClosed: false
77
83
  };
84
+ case ACTIONS.FLUSH_PENDING_SELECTIONS:
85
+ return {
86
+ ...pluginState,
87
+ selectedAnnotations: action.data.canSetAsSelectedAnnotations ? [...pluginState.pendingSelectedAnnotations] : pluginState.selectedAnnotations,
88
+ pendingSelectedAnnotations: [],
89
+ isInlineCommentViewClosed: false
90
+ };
91
+ case ACTIONS.SET_PENDING_SELECTIONS:
92
+ return {
93
+ ...pluginState,
94
+ pendingSelectedAnnotations: [...action.data.selectedAnnotations],
95
+ pendingSelectedAnnotationsUpdateCount: pluginState.pendingSelectedAnnotationsUpdateCount + 1,
96
+ skipSelectionHandling: true,
97
+ isInlineCommentViewClosed: false
98
+ };
78
99
  default:
79
100
  return pluginState;
80
101
  }
@@ -135,7 +135,7 @@ export const buildToolbar = editorAnalyticsAPI => ({
135
135
  }
136
136
  if (fg('platform_editor_comments_api_manager')) {
137
137
  if (!annotationManager) {
138
- // TODO: EDITOR-188 - If we've reached here and the manager is not initialized, we should
138
+ // TODO: EDITOR-595 - If we've reached here and the manager is not initialized, we should
139
139
  // dispatch an analytics event to indicate that the user has clicked the button but
140
140
  // the action was not completed.
141
141
  return false;
@@ -149,17 +149,19 @@ export const buildToolbar = editorAnalyticsAPI => ({
149
149
  }
150
150
  });
151
151
  createCommentExperience === null || createCommentExperience === void 0 ? void 0 : createCommentExperience.initExperience.start();
152
- const {
153
- success
154
- } = annotationManager.startDraft();
155
- if (!success) {
156
- // TODO: EDITOR-188 - Report start draft attempt failed.
152
+ const result = annotationManager.startDraft();
153
+ if (result.success) {
154
+ // TODO: EDITOR-595 - Ensure and anlytic is fired to indicate that the user has started a draft.
155
+ } else {
156
+ // TODO: EDITOR-595 - Fire an analytics event to indicate that the user has clicked the button
157
+ // but the action was not completed, the result should contain a reason.
157
158
  }
158
159
  } else {
159
- // TODO: EDITOR-188 - Dispatch analytics event
160
+ // TODO: EDITOR-595 - Track the toolbar comment button was clicked but the preemptive gate
161
+ // check returned false and the draft cannot be started.
160
162
  }
161
163
  }).catch(() => {
162
- // TODO: EDITOR-188 - Handle preemptive gate check error and dispatch analytics event
164
+ // TODO: EDITOR-595 - Handle preemptive gate check error. Something went very wrong in the gate.
163
165
  });
164
166
  return true;
165
167
  } else {
@@ -8,5 +8,7 @@ export let 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
  }({});
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useRef } from 'react';
2
2
  import { AnnotationTypes } from '@atlaskit/adf-schema';
3
3
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, CONTENT_COMPONENT, EVENT_TYPE, RESOLVE_METHOD } from '@atlaskit/editor-common/analytics';
4
4
  import { sharedPluginStateHookMigratorFactory } from '@atlaskit/editor-common/hooks';
@@ -78,6 +78,7 @@ export function InlineCommentView({
78
78
  state,
79
79
  dispatch
80
80
  } = editorView;
81
+ const lastSelectedAnnotationId = useRef();
81
82
  const {
82
83
  createComponent: CreateComponent,
83
84
  viewComponent: ViewComponent
@@ -133,9 +134,17 @@ export function InlineCommentView({
133
134
 
134
135
  // Create Component
135
136
  if (bookmark) {
137
+ var _selectedAnnotations$;
136
138
  if (!CreateComponent) {
137
139
  return null;
138
140
  }
141
+ const currentlySelectedAnnotation = selectedAnnotations === null || selectedAnnotations === void 0 ? void 0 : (_selectedAnnotations$ = selectedAnnotations[0]) === null || _selectedAnnotations$ === void 0 ? void 0 : _selectedAnnotations$.id;
142
+ const isAnnotationSelectionChanged = currentlySelectedAnnotation !== lastSelectedAnnotationId.current;
143
+
144
+ // Update the last selected annotation ID if the selection was updated
145
+ if (isAnnotationSelectionChanged) {
146
+ lastSelectedAnnotationId.current = currentlySelectedAnnotation;
147
+ }
139
148
  const inlineNodeTypes = getRangeInlineNodeNames({
140
149
  doc: state.doc,
141
150
  pos: selection
@@ -149,6 +158,7 @@ export function InlineCommentView({
149
158
  }, /*#__PURE__*/React.createElement(CreateComponent, {
150
159
  dom: dom,
151
160
  textSelection: textSelection,
161
+ wasNewAnnotationSelected: !!currentlySelectedAnnotation && isAnnotationSelectionChanged,
152
162
  onCreate: id => {
153
163
  if (!fg('platform_editor_comments_api_manager')) {
154
164
  const createAnnotationResult = createAnnotation(editorAnalyticsAPI, editorAPI)(id, AnnotationTypes.INLINE_COMMENT, inlineCommentProvider.supportedBlockNodes)(editorView.state, editorView.dispatch);
@@ -44,6 +44,25 @@ export var clearDirtyMark = function clearDirtyMark() {
44
44
  type: ACTIONS.INLINE_COMMENT_CLEAR_DIRTY_MARK
45
45
  });
46
46
  };
47
+ export var flushPendingSelections = function flushPendingSelections(canSetAsSelectedAnnotations) {
48
+ return createCommand({
49
+ type: ACTIONS.FLUSH_PENDING_SELECTIONS,
50
+ data: {
51
+ canSetAsSelectedAnnotations: canSetAsSelectedAnnotations
52
+ }
53
+ });
54
+ };
55
+ export var setPendingSelectedAnnotation = function setPendingSelectedAnnotation(id) {
56
+ return createCommand({
57
+ type: ACTIONS.SET_PENDING_SELECTIONS,
58
+ data: {
59
+ selectedAnnotations: [{
60
+ id: id,
61
+ type: AnnotationTypes.INLINE_COMMENT
62
+ }]
63
+ }
64
+ });
65
+ };
47
66
  var removeInlineCommentFromNode = function removeInlineCommentFromNode(id) {
48
67
  var supportedBlockNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
49
68
  var state = arguments.length > 2 ? arguments[2] : undefined;
@@ -105,6 +124,34 @@ export var removeInlineCommentNearSelection = function removeInlineCommentNearSe
105
124
  return true;
106
125
  };
107
126
  };
127
+ export var removeInlineCommentFromDoc = function removeInlineCommentFromDoc(id) {
128
+ var supportedNodes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
129
+ return function (state, dispatch) {
130
+ var tr = state.tr;
131
+ state.doc.descendants(function (node, pos) {
132
+ // Inline comment on mediaInline is not supported as part of comments on media project
133
+ // Thus, we skip the decoration for mediaInline node
134
+ if (node.type.name === 'mediaInline') {
135
+ return false;
136
+ }
137
+ var isSupportedBlockNode = node.isBlock && (supportedNodes === null || supportedNodes === void 0 ? void 0 : supportedNodes.includes(node.type.name));
138
+ node.marks.filter(function (mark) {
139
+ return mark.type === state.schema.marks.annotation && mark.attrs.id === id;
140
+ }).forEach(function (mark) {
141
+ if (isSupportedBlockNode) {
142
+ tr.removeNodeMark(pos, mark);
143
+ } else {
144
+ tr.removeMark(pos, pos + node.nodeSize, mark);
145
+ }
146
+ });
147
+ });
148
+ if (dispatch) {
149
+ dispatch(tr);
150
+ return true;
151
+ }
152
+ return false;
153
+ };
154
+ };
108
155
  var getDraftCommandAction = function getDraftCommandAction(drafting, targetType, targetNodeId, supportedBlockNodes, isOpeningMediaCommentFromToolbar) {
109
156
  return function (editorState) {
110
157
  // validate selection only when entering draft mode
@@ -128,6 +175,8 @@ var getDraftCommandAction = function getDraftCommandAction(drafting, targetType,
128
175
  /**
129
176
  * Show active inline comments for a given block node, otherwise,
130
177
  * return false if the node has no comments or no unresolved comments.
178
+ * @param supportedBlockNodes
179
+ * @example
131
180
  */
132
181
  export var showInlineCommentForBlockNode = function showInlineCommentForBlockNode() {
133
182
  var supportedBlockNodes = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];