fix: multiple line editor bugs (#9760)

Co-authored-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Omar Brikaa
2025-07-24 10:11:04 +03:00
committed by GitHub
parent f38f381989
commit 416da62138
4 changed files with 37 additions and 29 deletions

View File

@ -1040,10 +1040,12 @@ export class LinearElementEditor {
if (lastPoint === lastUncommittedPoint) { if (lastPoint === lastUncommittedPoint) {
LinearElementEditor.deletePoints(element, app, [points.length - 1]); LinearElementEditor.deletePoints(element, app, [points.length - 1]);
} }
return { return appState.editingLinearElement.lastUncommittedPoint
...appState.editingLinearElement, ? {
lastUncommittedPoint: null, ...appState.editingLinearElement,
}; lastUncommittedPoint: null,
}
: appState.editingLinearElement;
} }
let newPoint: LocalPoint; let newPoint: LocalPoint;

View File

@ -367,7 +367,7 @@ describe("Test Linear Elements", () => {
// drag line from midpoint // drag line from midpoint
drag(midpoint, pointFrom(midpoint[0] + delta, midpoint[1] + delta)); drag(midpoint, pointFrom(midpoint[0] + delta, midpoint[1] + delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`, `11`,
); );
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`); expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`);
@ -469,7 +469,7 @@ describe("Test Linear Elements", () => {
drag(startPoint, endPoint); drag(startPoint, endPoint);
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`, `11`,
); );
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`); expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`);
@ -537,7 +537,7 @@ describe("Test Linear Elements", () => {
); );
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`16`, `14`,
); );
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`); expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`);
@ -588,7 +588,7 @@ describe("Test Linear Elements", () => {
drag(hitCoords, pointFrom(hitCoords[0] - delta, hitCoords[1] - delta)); drag(hitCoords, pointFrom(hitCoords[0] - delta, hitCoords[1] - delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`, `11`,
); );
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`); expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`);
@ -629,7 +629,7 @@ describe("Test Linear Elements", () => {
drag(hitCoords, pointFrom(hitCoords[0] + delta, hitCoords[1] + delta)); drag(hitCoords, pointFrom(hitCoords[0] + delta, hitCoords[1] + delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`, `11`,
); );
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`); expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`);
@ -677,7 +677,7 @@ describe("Test Linear Elements", () => {
deletePoint(points[2]); deletePoint(points[2]);
expect(line.points.length).toEqual(3); expect(line.points.length).toEqual(3);
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`18`, `17`,
); );
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`); expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`);
@ -735,7 +735,7 @@ describe("Test Linear Elements", () => {
), ),
); );
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`16`, `14`,
); );
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`); expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`7`);
expect(line.points.length).toEqual(5); expect(line.points.length).toEqual(5);
@ -833,7 +833,7 @@ describe("Test Linear Elements", () => {
drag(hitCoords, pointFrom(hitCoords[0] + delta, hitCoords[1] + delta)); drag(hitCoords, pointFrom(hitCoords[0] + delta, hitCoords[1] + delta));
expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot( expect(renderInteractiveScene.mock.calls.length).toMatchInlineSnapshot(
`12`, `11`,
); );
expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`); expect(renderStaticScene.mock.calls.length).toMatchInlineSnapshot(`6`);

View File

@ -225,8 +225,11 @@ export const actionDeleteSelected = register({
return false; return false;
} }
// case: deleting last remaining point // case: deleting all points
if (element.points.length < 2) { if (
element.points.length < 2 ||
selectedPointsIndices.length === element.points.length
) {
const nextElements = elements.map((el) => { const nextElements = elements.map((el) => {
if (el.id === element.id) { if (el.id === element.id) {
return newElementWith(el, { isDeleted: true }); return newElementWith(el, { isDeleted: true });

View File

@ -5868,6 +5868,9 @@ class App extends React.Component<AppProps, AppState> {
scenePointerY, scenePointerY,
this, this,
); );
const linearElement = editingLinearElement
? this.scene.getElement(editingLinearElement.elementId)
: null;
if ( if (
editingLinearElement && editingLinearElement &&
@ -5882,16 +5885,17 @@ class App extends React.Component<AppProps, AppState> {
}); });
}); });
} }
if (editingLinearElement?.lastUncommittedPoint != null) { if (
editingLinearElement?.lastUncommittedPoint != null &&
linearElement &&
isBindingElementType(linearElement.type)
) {
this.maybeSuggestBindingAtCursor( this.maybeSuggestBindingAtCursor(
scenePointer, scenePointer,
editingLinearElement.elbowed, editingLinearElement.elbowed,
); );
} else { } else if (this.state.suggestedBindings.length) {
// causes stack overflow if not sync this.setState({ suggestedBindings: [] });
flushSync(() => {
this.setState({ suggestedBindings: [] });
});
} }
} }
@ -6155,15 +6159,6 @@ class App extends React.Component<AppProps, AppState> {
setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO); setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO);
} else if (isOverScrollBar) { } else if (isOverScrollBar) {
setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO); setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO);
} else if (
this.state.selectedLinearElement &&
hitElement?.id === this.state.selectedLinearElement.elementId
) {
this.handleHoverSelectedLinearElement(
this.state.selectedLinearElement,
scenePointerX,
scenePointerY,
);
} else if ( } else if (
// if using cmd/ctrl, we're not dragging // if using cmd/ctrl, we're not dragging
!event[KEYS.CTRL_OR_CMD] !event[KEYS.CTRL_OR_CMD]
@ -6205,6 +6200,14 @@ class App extends React.Component<AppProps, AppState> {
} else { } else {
setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO); setCursor(this.interactiveCanvas, CURSOR_TYPE.AUTO);
} }
if (this.state.selectedLinearElement) {
this.handleHoverSelectedLinearElement(
this.state.selectedLinearElement,
scenePointerX,
scenePointerY,
);
}
} }
if (this.state.openDialog?.name === "elementLinkSelector" && hitElement) { if (this.state.openDialog?.name === "elementLinkSelector" && hitElement) {