Skip to content

Commit a92c1a6

Browse files
1aurendjen-castiron
authored andcommitted
[B] Fix restore focus after removing a highlight
1 parent ae99985 commit a92c1a6

File tree

1 file changed

+50
-8
lines changed

1 file changed

+50
-8
lines changed

client/src/reader/containers/annotation/Annotatable.js

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,21 @@ export class Annotatable extends Component {
5959
if (!isEqual(this.props.annotations, prevProps.annotations))
6060
this.setState({ renderedAnnotations: this.props.annotations });
6161

62+
// if the user just removed a highlight, restore focus to the previous selection
63+
const lastAnnotation = this.state.renderedAnnotations[
64+
this.state.renderedAnnotations.length - 1
65+
];
66+
const wasRemoved = lastAnnotation?.attributes.removed;
67+
const prevLastAnnotation =
68+
prevState.renderedAnnotations[this.state.renderedAnnotations.length - 1];
69+
const prevWasRemoved = prevLastAnnotation?.attributes.removed;
70+
if (wasRemoved !== prevWasRemoved) {
71+
this.restoreFocusAndSelection({
72+
restoreFocusTo: "selection",
73+
restoreSelectionTo: "selection"
74+
});
75+
}
76+
6277
const { selection } = this.state.selectionState ?? {};
6378
const { range, ...selectionData } = selection ?? {};
6479
const { selection: prevSelection } = prevState.selectionState ?? {};
@@ -265,6 +280,15 @@ export class Annotatable extends Component {
265280
return res.promise;
266281
};
267282

283+
/* Currently, this callback is used only for removing highlights.
284+
Annotations are deleted using a call in the global component that
285+
does not attempt to restore focus. In order to restore focus after
286+
delete, we create a *fake* here on success and reset selection and
287+
annotation state. We can't call this.resetState here because we
288+
don't want to overwrite this.state.renderedAnnotations once we push
289+
the fake. Then we call focus on the new node in componentDidUpdate
290+
to ensure that it happens after state updates there.
291+
*/
268292
destroyAnnotation = annotation => {
269293
if (!annotation) return;
270294
const call = annotationsAPI.destroy(annotation.id);
@@ -273,14 +297,31 @@ export class Annotatable extends Component {
273297
request(call, requests.rAnnotationDestroy, options)
274298
);
275299
res.promise.then(() => {
276-
// recreate destroyed node and move selection to it after state is reset
300+
// recreate destroyed node and append to renderedAnnotations
277301
const selectionAnnotation = this.createAnnotationFromSelection(
278-
this.state.selectionState.selectionAnnotation
302+
this.state.selectionState.selectionAnnotation,
303+
"previous",
304+
true
279305
);
280-
this.appendLastSelectionAnnotation(selectionAnnotation);
281-
this.resetState({
282-
restoreFocusTo: this.pendingAnnotationNode,
283-
restoreSelectionTo: this.pendingAnnotationNode
306+
// this state update gets overwritten by the one in componentDidUpdate
307+
// if not pushed to the bottom of the stack with setTimeout
308+
setTimeout(() => {
309+
this.setState({
310+
selectionState: {
311+
selection: null,
312+
selectionComplete: false,
313+
selectionAnnotation: null,
314+
popupTriggerX: null,
315+
popupTriggerY: null
316+
},
317+
activeEvent: null,
318+
annotation: null,
319+
annotationState: null,
320+
renderedAnnotations: [
321+
...this.state.renderedAnnotations,
322+
selectionAnnotation
323+
]
324+
});
284325
});
285326
});
286327
return res.promise;
@@ -336,13 +377,14 @@ export class Annotatable extends Component {
336377
});
337378
};
338379

339-
createAnnotationFromSelection = selection => {
380+
createAnnotationFromSelection = (selection, style, removed) => {
340381
return {
341382
id: "selection",
342383
attributes: {
343384
userIsCreator: true,
344385
annotationStyle: "pending",
345-
format: "highlight",
386+
format: style ?? "highlight",
387+
removed,
346388
...selection
347389
}
348390
};

0 commit comments

Comments
 (0)