feat: Don't add midpoint until dragged beyond a threshold (#5927)

* Don't add midpoint until dragged beyond a threshold

* remove unnecessary code

* fix tests

* fix

* add spec

* remove isMidpoint

* cleanup

* fix threshold for zoom

* split into shouldAddMidpoint and addMidpoint

* wrap in flushSync for synchronous updates

* remove threshold for line editor and add spec

* [unrelated] fix stack overflow state update

* fix tests

* don't drag arrow when dragging to add mid point

* add specs

Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
Aakansha Doshi 2022-11-29 00:01:53 +05:30 committed by GitHub
parent baf9651d34
commit 25c6056b03
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 258 additions and 63 deletions

View file

@ -2885,7 +2885,10 @@ class App extends React.Component<AppProps, AppState> {
if (editingLinearElement?.lastUncommittedPoint != null) {
this.maybeSuggestBindingAtCursor(scenePointer);
} else {
this.setState({ suggestedBindings: [] });
// causes stack overflow if not sync
flushSync(() => {
this.setState({ suggestedBindings: [] });
});
}
}
@ -3825,7 +3828,7 @@ class App extends React.Component<AppProps, AppState> {
this.setState({ editingLinearElement: ret.linearElementEditor });
}
}
if (ret.didAddPoint && !ret.isMidPoint) {
if (ret.didAddPoint) {
return true;
}
}
@ -4315,7 +4318,6 @@ class App extends React.Component<AppProps, AppState> {
// to ensure we don't create a 2-point arrow by mistake when
// user clicks mouse in a way that it moves a tiny bit (thus
// triggering pointermove)
if (
!pointerDownState.drag.hasOccurred &&
(this.state.activeTool.type === "arrow" ||
@ -4343,6 +4345,56 @@ class App extends React.Component<AppProps, AppState> {
if (this.state.selectedLinearElement) {
const linearElementEditor =
this.state.editingLinearElement || this.state.selectedLinearElement;
if (
LinearElementEditor.shouldAddMidpoint(
this.state.selectedLinearElement,
pointerCoords,
this.state,
)
) {
const ret = LinearElementEditor.addMidpoint(
this.state.selectedLinearElement,
pointerCoords,
this.state,
);
if (!ret) {
return;
}
// Since we are reading from previous state which is not possible with
// automatic batching in React 18 hence using flush sync to synchronously
// update the state. Check https://github.com/excalidraw/excalidraw/pull/5508 for more details.
flushSync(() => {
if (this.state.selectedLinearElement) {
this.setState({
selectedLinearElement: {
...this.state.selectedLinearElement,
pointerDownState: ret.pointerDownState,
selectedPointsIndices: ret.selectedPointsIndices,
},
});
}
if (this.state.editingLinearElement) {
this.setState({
editingLinearElement: {
...this.state.editingLinearElement,
pointerDownState: ret.pointerDownState,
selectedPointsIndices: ret.selectedPointsIndices,
},
});
}
});
return;
} else if (
linearElementEditor.pointerDownState.segmentMidpoint.value !== null &&
!linearElementEditor.pointerDownState.segmentMidpoint.added
) {
return;
}
const didDrag = LinearElementEditor.handlePointDragging(
event,
this.state,