@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.
- package/CHANGELOG.md +19 -0
- package/dist/cjs/editor-commands/index.js +50 -1
- package/dist/cjs/pm-plugins/annotation-manager-hooks.js +166 -4
- package/dist/cjs/pm-plugins/inline-comment.js +169 -30
- package/dist/cjs/pm-plugins/plugin-factory.js +51 -1
- package/dist/cjs/pm-plugins/reducer.js +18 -1
- package/dist/cjs/pm-plugins/toolbar.js +10 -7
- package/dist/cjs/pm-plugins/types.js +2 -0
- package/dist/cjs/ui/InlineCommentView.js +14 -1
- package/dist/es2019/editor-commands/index.js +42 -0
- package/dist/es2019/pm-plugins/annotation-manager-hooks.js +160 -5
- package/dist/es2019/pm-plugins/inline-comment.js +146 -9
- package/dist/es2019/pm-plugins/plugin-factory.js +51 -1
- package/dist/es2019/pm-plugins/reducer.js +22 -1
- package/dist/es2019/pm-plugins/toolbar.js +10 -8
- package/dist/es2019/pm-plugins/types.js +2 -0
- package/dist/es2019/ui/InlineCommentView.js +11 -1
- package/dist/esm/editor-commands/index.js +49 -0
- package/dist/esm/pm-plugins/annotation-manager-hooks.js +167 -5
- package/dist/esm/pm-plugins/inline-comment.js +159 -20
- package/dist/esm/pm-plugins/plugin-factory.js +51 -1
- package/dist/esm/pm-plugins/reducer.js +18 -1
- package/dist/esm/pm-plugins/toolbar.js +10 -7
- package/dist/esm/pm-plugins/types.js +2 -0
- package/dist/esm/ui/InlineCommentView.js +11 -1
- package/dist/types/editor-commands/index.d.ts +5 -0
- package/dist/types/pm-plugins/annotation-manager-hooks.d.ts +4 -1
- package/dist/types/pm-plugins/plugin-factory.d.ts +4 -0
- package/dist/types/pm-plugins/types.d.ts +26 -1
- package/dist/types/types/index.d.ts +1 -0
- package/dist/types-ts4.5/editor-commands/index.d.ts +5 -0
- package/dist/types-ts4.5/pm-plugins/annotation-manager-hooks.d.ts +4 -1
- package/dist/types-ts4.5/pm-plugins/plugin-factory.d.ts +4 -0
- package/dist/types-ts4.5/pm-plugins/types.d.ts +26 -1
- package/dist/types-ts4.5/types/index.d.ts +1 -0
- 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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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
|
-
|
|
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
|
|
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-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
// TODO: EDITOR-
|
|
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-
|
|
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-
|
|
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] : [];
|