From 2e46e27490b08a5da66e8e3b64e3c7251f2a5e09 Mon Sep 17 00:00:00 2001 From: David Luzar Date: Fri, 14 Jul 2023 20:21:02 +0200 Subject: [PATCH 01/22] fix: use actual dock state to not close docked library on insert (#6766) --- src/components/App.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index 611ff47b4..7f747dbd4 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -330,6 +330,7 @@ import { activeConfirmDialogAtom } from "./ActiveConfirmDialog"; import { actionWrapTextInContainer } from "../actions/actionBoundText"; import BraveMeasureTextError from "./BraveMeasureTextError"; import { activeEyeDropperAtom } from "./EyeDropper"; +import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; const AppContext = React.createContext(null!); const AppPropsContext = React.createContext(null!); @@ -473,8 +474,6 @@ class App extends React.Component { name, width: window.innerWidth, height: window.innerHeight, - showHyperlinkPopup: false, - defaultSidebarDockedPreference: false, }; this.id = nanoid(); @@ -2031,7 +2030,7 @@ class App extends React.Component { openSidebar: this.state.openSidebar && this.device.canDeviceFitSidebar && - this.state.defaultSidebarDockedPreference + jotaiStore.get(isSidebarDockedAtom) ? this.state.openSidebar : null, selectedElementIds: nextElementsToSelect.reduce( From 9f76f8677baa1e95fc1af011e35f31f87631167b Mon Sep 17 00:00:00 2001 From: David Luzar Date: Mon, 17 Jul 2023 01:09:44 +0200 Subject: [PATCH 02/22] 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 ef69a60de..feb4725e8 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 d917f8037..5697a707e 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 }) => (