Skip to content

Commit

Permalink
[FIX] figure: crash on deleting dragged figure
Browse files Browse the repository at this point in the history
There was a traceback if a figure was deleted while being dragged.

closes #5328

Task: 4329240
X-original-commit: f535004
Signed-off-by: Lucas Lefèvre (lul) <[email protected]>
Signed-off-by: Adrien Minne (adrm) <[email protected]>
  • Loading branch information
hokolomopo committed Dec 9, 2024
1 parent 4ec1734 commit 434bbae
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
32 changes: 24 additions & 8 deletions src/components/figures/figure_container/figure_container.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, onMounted, useState } from "@odoo/owl";
import { Component, onMounted, onWillUpdateProps, useState } from "@odoo/owl";
import { ComponentsImportance, MIN_FIG_SIZE } from "../../../constants";
import { isDefined } from "../../../helpers";
import { rectIntersection, rectUnion } from "../../../helpers/rectangle";
Expand Down Expand Up @@ -43,6 +43,7 @@ interface DndState {
draggedFigure?: Figure;
horizontalSnap?: Snap<HFigureAxisType>;
verticalSnap?: Snap<VFigureAxisType>;
cancelDnd: (() => void) | undefined;
}

css/*SCSS*/ `
Expand Down Expand Up @@ -132,6 +133,7 @@ export class FiguresContainer extends Component<Props, SpreadsheetChildEnv> {
draggedFigure: undefined,
horizontalSnap: undefined,
verticalSnap: undefined,
cancelDnd: undefined,
});

setup() {
Expand All @@ -145,6 +147,19 @@ export class FiguresContainer extends Component<Props, SpreadsheetChildEnv> {
// new rendering
this.render();
});
onWillUpdateProps(() => {
const sheetId = this.env.model.getters.getActiveSheetId();
const draggedFigureId = this.dnd.draggedFigure?.id;
if (draggedFigureId && !this.env.model.getters.getFigure(sheetId, draggedFigureId)) {
if (this.dnd.cancelDnd) {
this.dnd.cancelDnd();
}
this.dnd.draggedFigure = undefined;
this.dnd.horizontalSnap = undefined;
this.dnd.verticalSnap = undefined;
this.dnd.cancelDnd = undefined;
}
});
}

private getVisibleFigures(): Figure[] {
Expand All @@ -153,12 +168,13 @@ export class FiguresContainer extends Component<Props, SpreadsheetChildEnv> {
this.dnd.draggedFigure &&
!visibleFigures.some((figure) => figure.id === this.dnd.draggedFigure?.id)
) {
visibleFigures.push(
this.env.model.getters.getFigure(
this.env.model.getters.getActiveSheetId(),
this.dnd.draggedFigure?.id
)!
const draggedFigure = this.env.model.getters.getFigure(
this.env.model.getters.getActiveSheetId(),
this.dnd.draggedFigure?.id
);
if (draggedFigure) {
visibleFigures.push(draggedFigure);
}
}
return visibleFigures;
}
Expand Down Expand Up @@ -311,7 +327,7 @@ export class FiguresContainer extends Component<Props, SpreadsheetChildEnv> {
this.dnd.verticalSnap = undefined;
this.env.model.dispatch("UPDATE_FIGURE", { sheetId, id: figure.id, x, y });
};
startDnd(onMouseMove, onMouseUp);
this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
}

/**
Expand Down Expand Up @@ -379,7 +395,7 @@ export class FiguresContainer extends Component<Props, SpreadsheetChildEnv> {
this.dnd.horizontalSnap = undefined;
this.dnd.verticalSnap = undefined;
};
startDnd(onMouseMove, onMouseUp);
this.dnd.cancelDnd = startDnd(onMouseMove, onMouseUp);
}

private getOtherFigures(figId: UID): Figure[] {
Expand Down
15 changes: 12 additions & 3 deletions src/components/helpers/drag_and_drop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,27 @@ import { HeaderIndex } from "../../types/misc";
import { gridOverlayPosition } from "./dom_helpers";
type EventFn = (ev: MouseEvent) => void;

/**
* Start listening to pointer events and apply the given callbacks.
*
* @returns A function to remove the listeners.
*/
export function startDnd(
onMouseMove: EventFn,
onMouseUp: EventFn,
onMouseDown: EventFn = () => {}
) {
const _onMouseUp = (ev: MouseEvent) => {
onMouseUp(ev);

const removeListeners = () => {
window.removeEventListener("mousedown", onMouseDown);
window.removeEventListener("mouseup", _onMouseUp);
window.removeEventListener("dragstart", _onDragStart);
window.removeEventListener("mousemove", onMouseMove);
window.removeEventListener("wheel", onMouseMove);
};
const _onMouseUp = (ev: MouseEvent) => {
onMouseUp(ev);
removeListeners();
};
function _onDragStart(ev: DragEvent) {
ev.preventDefault();
}
Expand All @@ -29,6 +36,8 @@ export function startDnd(
// preventDefault() is not allowed in passive event handler.
// https://chromestatus.com/feature/6662647093133312
window.addEventListener("wheel", onMouseMove, { passive: false });

return removeListeners;
}

/**
Expand Down
9 changes: 9 additions & 0 deletions tests/figures/figure_component.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,15 @@ describe("figures", () => {
);
}
);

test("Deleting a figure during drag and drop does not crash", async () => {
createFigure(model, { id: "someuuid", x: 200, y: 100 });
await nextTick();
await dragElement(".o-figure", { x: 150, y: 100 }, undefined, false);
model.dispatch("DELETE_FIGURE", { id: "someuuid", sheetId });
await nextTick();
expect(model.getters.getFigure(sheetId, "someuuid")).toEqual(undefined);
});
});

test("Cannot select/move figure in readonly mode", async () => {
Expand Down

0 comments on commit 434bbae

Please sign in to comment.