feat: Enter and Exit line editor via context menu (#5719)

* feat: Enter and exit line editor via context menu

* Add tests

* fix

* review fixes

* fix
This commit is contained in:
Aakansha Doshi 2022-09-27 16:54:50 +05:30 committed by GitHub
parent b477c2ad6b
commit 6c1246ef77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 103 additions and 2 deletions

View File

@ -0,0 +1,49 @@
import { getNonDeletedElements } from "../element";
import { LinearElementEditor } from "../element/linearElementEditor";
import { isLinearElement } from "../element/typeChecks";
import { ExcalidrawLinearElement } from "../element/types";
import { getSelectedElements } from "../scene";
import { register } from "./register";
export const actionToggleLinearEditor = register({
name: "toggleLinearEditor",
trackEvent: {
category: "element",
},
contextItemPredicate: (elements, appState) => {
const selectedElements = getSelectedElements(elements, appState);
if (selectedElements.length === 1 && isLinearElement(selectedElements[0])) {
return true;
}
return false;
},
perform(elements, appState, _, app) {
const selectedElement = getSelectedElements(
getNonDeletedElements(elements),
appState,
true,
)[0] as ExcalidrawLinearElement;
const editingLinearElement =
appState.editingLinearElement?.elementId === selectedElement.id
? null
: new LinearElementEditor(selectedElement, app.scene);
return {
appState: {
...appState,
editingLinearElement,
},
commitToHistory: false,
};
},
contextItemLabel: (elements, appState) => {
const selectedElement = getSelectedElements(
getNonDeletedElements(elements),
appState,
true,
)[0] as ExcalidrawLinearElement;
return appState.editingLinearElement?.elementId === selectedElement.id
? "labels.lineEditor.exit"
: "labels.lineEditor.edit";
},
});

View File

@ -85,3 +85,4 @@ export { actionToggleStats } from "./actionToggleStats";
export { actionUnbindText, actionBindText } from "./actionBoundText";
export { actionLink } from "../element/Hyperlink";
export { actionToggleLock } from "./actionToggleLock";
export { actionToggleLinearEditor } from "./actionLinearEditor";

View File

@ -111,7 +111,8 @@ export type ActionName =
| "hyperlink"
| "eraser"
| "bindText"
| "toggleLock";
| "toggleLock"
| "toggleLinearEditor";
export type PanelComponentProps = {
elements: readonly ExcalidrawElement[];

View File

@ -34,6 +34,7 @@ import {
actionUngroup,
actionLink,
actionToggleLock,
actionToggleLinearEditor,
} from "../actions";
import { createRedoAction, createUndoAction } from "../actions/actionHistory";
import { ActionManager } from "../actions/manager";
@ -5876,6 +5877,12 @@ class App extends React.Component<AppProps, AppState> {
this.actionManager.getAppState(),
);
const mayBeAllowToggleLineEditing =
actionToggleLinearEditor.contextItemPredicate(
this.actionManager.getElementsIncludingDeleted(),
this.actionManager.getAppState(),
);
const separator = "separator";
const elements = this.scene.getNonDeletedElements();
@ -6017,6 +6024,7 @@ class App extends React.Component<AppProps, AppState> {
maybeFlipHorizontal && actionFlipHorizontal,
maybeFlipVertical && actionFlipVertical,
(maybeFlipHorizontal || maybeFlipVertical) && separator,
mayBeAllowToggleLineEditing && actionToggleLinearEditor,
actionLink.contextItemPredicate(elements, this.state) && actionLink,
actionDuplicateSelection,
actionToggleLock,

View File

@ -114,6 +114,11 @@
"create": "Create link",
"label": "Link"
},
"lineEditor": {
"edit": "Edit line",
"exit": "Exit line editor"
},
"elementLock": {
"lock": "Lock",
"unlock": "Unlock",

View File

@ -5,11 +5,12 @@ import { centerPoint } from "../math";
import { reseed } from "../random";
import * as Renderer from "../renderer/renderScene";
import { Keyboard, Pointer } from "./helpers/ui";
import { screen, render, fireEvent } from "./test-utils";
import { screen, render, fireEvent, GlobalTestState } from "./test-utils";
import { API } from "../tests/helpers/api";
import { Point } from "../types";
import { KEYS } from "../keys";
import { LinearElementEditor } from "../element/linearElementEditor";
import { queryByText } from "@testing-library/react";
const renderScene = jest.spyOn(Renderer, "renderScene");
@ -150,6 +151,42 @@ describe(" Test Linear Elements", () => {
`);
});
it("should allow entering and exiting line editor via context menu", () => {
createTwoPointerLinearElement("line");
fireEvent.contextMenu(GlobalTestState.canvas, {
button: 2,
clientX: midpoint[0],
clientY: midpoint[1],
});
// Enter line editor
let contextMenu = document.querySelector(".context-menu");
fireEvent.contextMenu(GlobalTestState.canvas, {
button: 2,
clientX: midpoint[0],
clientY: midpoint[1],
});
fireEvent.click(queryByText(contextMenu as HTMLElement, "Edit line")!);
expect(h.state.editingLinearElement?.elementId).toEqual(h.elements[0].id);
// Exiting line editor
fireEvent.contextMenu(GlobalTestState.canvas, {
button: 2,
clientX: midpoint[0],
clientY: midpoint[1],
});
contextMenu = document.querySelector(".context-menu");
fireEvent.contextMenu(GlobalTestState.canvas, {
button: 2,
clientX: midpoint[0],
clientY: midpoint[1],
});
fireEvent.click(
queryByText(contextMenu as HTMLElement, "Exit line editor")!,
);
expect(h.state.editingLinearElement?.elementId).toBeUndefined();
});
describe("Inside editor", () => {
it("should allow dragging line from midpoint in 2 pointer lines", async () => {
createTwoPointerLinearElement("line");