From 9f76f8677baa1e95fc1af011e35f31f87631167b Mon Sep 17 00:00:00 2001 From: David Luzar Date: Mon, 17 Jul 2023 01:09:44 +0200 Subject: [PATCH] feat: cache most of element selection (#6747) --- src/actions/actionAddToLibrary.ts | 15 +- src/actions/actionAlign.tsx | 66 +- src/actions/actionBoundText.tsx | 36 +- src/actions/actionCanvas.tsx | 16 +- src/actions/actionClipboard.tsx | 54 +- src/actions/actionDistribute.tsx | 37 +- src/actions/actionDuplicateSelection.tsx | 1 + src/actions/actionElementLock.ts | 20 +- src/actions/actionFlip.ts | 6 +- src/actions/actionFrame.ts | 33 +- src/actions/actionGroup.tsx | 37 +- src/actions/actionLinearEditor.ts | 30 +- src/actions/actionSelectAll.ts | 1 + src/actions/manager.tsx | 2 + src/actions/types.ts | 3 + src/components/App.tsx | 132 +- src/components/ContextMenu.tsx | 4 +- src/components/HintViewer.tsx | 19 +- src/components/LayerUI.tsx | 5 +- src/components/MobileMenu.tsx | 12 +- src/frame.ts | 9 +- src/groups.ts | 24 +- src/scene/Scene.ts | 93 + .../__snapshots__/contextmenu.test.tsx.snap | 72 +- .../regressionTests.test.tsx.snap | 3476 +---------------- src/tests/zindex.test.tsx | 1 + src/utility-types.ts | 3 + 27 files changed, 452 insertions(+), 3755 deletions(-) diff --git a/src/actions/actionAddToLibrary.ts b/src/actions/actionAddToLibrary.ts index ef69a60d..feb4725e 100644 --- a/src/actions/actionAddToLibrary.ts +++ b/src/actions/actionAddToLibrary.ts @@ -1,6 +1,4 @@ import { register } from "./register"; -import { getSelectedElements } from "../scene"; -import { getNonDeletedElements } from "../element"; import { deepCopyElement } from "../element/newElement"; import { randomId } from "../random"; import { t } from "../i18n"; @@ -9,14 +7,11 @@ export const actionAddToLibrary = register({ name: "addToLibrary", trackEvent: { category: "element" }, perform: (elements, appState, _, app) => { - const selectedElements = getSelectedElements( - getNonDeletedElements(elements), - appState, - { - includeBoundTextElement: true, - includeElementsInFrames: true, - }, - ); + const selectedElements = app.scene.getSelectedElements({ + selectedElementIds: appState.selectedElementIds, + includeBoundTextElement: true, + includeElementsInFrames: true, + }); if (selectedElements.some((element) => element.type === "image")) { return { commitToHistory: false, diff --git a/src/actions/actionAlign.tsx b/src/actions/actionAlign.tsx index d917f803..5697a707 100644 --- a/src/actions/actionAlign.tsx +++ b/src/actions/actionAlign.tsx @@ -13,19 +13,18 @@ import { ExcalidrawElement } from "../element/types"; import { updateFrameMembershipOfSelectedElements } from "../frame"; import { t } from "../i18n"; import { KEYS } from "../keys"; -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { AppState } from "../types"; +import { isSomeElementSelected } from "../scene"; +import { AppClassProperties, AppState } from "../types"; import { arrayToMap, getShortcutKey } from "../utils"; import { register } from "./register"; const alignActionsPredicate = ( elements: readonly ExcalidrawElement[], appState: AppState, + _: unknown, + app: AppClassProperties, ) => { - const selectedElements = getSelectedElements( - getNonDeletedElements(elements), - appState, - ); + const selectedElements = app.scene.getSelectedElements(appState); return ( selectedElements.length > 1 && // TODO enable aligning frames when implemented properly @@ -36,12 +35,10 @@ const alignActionsPredicate = ( const alignSelectedElements = ( elements: readonly ExcalidrawElement[], appState: Readonly, + app: AppClassProperties, alignment: Alignment, ) => { - const selectedElements = getSelectedElements( - getNonDeletedElements(elements), - appState, - ); + const selectedElements = app.scene.getSelectedElements(appState); const updatedElements = alignElements(selectedElements, alignment); @@ -50,6 +47,7 @@ const alignSelectedElements = ( return updateFrameMembershipOfSelectedElements( elements.map((element) => updatedElementsMap.get(element.id) || element), appState, + app, ); }; @@ -57,10 +55,10 @@ export const actionAlignTop = register({ name: "alignTop", trackEvent: { category: "element" }, predicate: alignActionsPredicate, - perform: (elements, appState) => { + perform: (elements, appState, _, app) => { return { appState, - elements: alignSelectedElements(elements, appState, { + elements: alignSelectedElements(elements, appState, app, { position: "start", axis: "y", }), @@ -69,9 +67,9 @@ export const actionAlignTop = register({ }, keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === KEYS.ARROW_UP, - PanelComponent: ({ elements, appState, updateData }) => ( + PanelComponent: ({ elements, appState, updateData, app }) => (