mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
cache linear when panel shows up
This commit is contained in:
parent
7541fadf9c
commit
de6acc4bad
2 changed files with 146 additions and 19 deletions
|
@ -326,7 +326,6 @@ import type {
|
||||||
MagicGenerationData,
|
MagicGenerationData,
|
||||||
ExcalidrawNonSelectionElement,
|
ExcalidrawNonSelectionElement,
|
||||||
ExcalidrawArrowElement,
|
ExcalidrawArrowElement,
|
||||||
ConvertibleGenericTypes,
|
|
||||||
} from "@excalidraw/element/types";
|
} from "@excalidraw/element/types";
|
||||||
|
|
||||||
import type { ValueOf } from "@excalidraw/common/utility-types";
|
import type { ValueOf } from "@excalidraw/common/utility-types";
|
||||||
|
@ -465,7 +464,6 @@ import { isMaybeMermaidDefinition } from "../mermaid";
|
||||||
import ShapeSwitch, {
|
import ShapeSwitch, {
|
||||||
getSwitchableTypeFromElements,
|
getSwitchableTypeFromElements,
|
||||||
shapeSwitchAtom,
|
shapeSwitchAtom,
|
||||||
shapeSwitchFontSizeAtom,
|
|
||||||
switchShapes,
|
switchShapes,
|
||||||
} from "./ShapeSwitch";
|
} from "./ShapeSwitch";
|
||||||
|
|
||||||
|
@ -4182,23 +4180,6 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
editorJotaiStore.set(shapeSwitchAtom, {
|
editorJotaiStore.set(shapeSwitchAtom, {
|
||||||
type: "panel",
|
type: "panel",
|
||||||
});
|
});
|
||||||
if (!editorJotaiStore.get(shapeSwitchFontSizeAtom)) {
|
|
||||||
selectedElements.forEach((element) => {
|
|
||||||
const boundText = getBoundTextElement(
|
|
||||||
element,
|
|
||||||
this.scene.getNonDeletedElementsMap(),
|
|
||||||
);
|
|
||||||
if (boundText && generic && element) {
|
|
||||||
editorJotaiStore.set(shapeSwitchFontSizeAtom, {
|
|
||||||
...editorJotaiStore.get(shapeSwitchFontSizeAtom),
|
|
||||||
[element.id]: {
|
|
||||||
fontSize: boundText.fontSize,
|
|
||||||
elementType: element.type as ConvertibleGenericTypes,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6470,6 +6451,10 @@ class App extends React.Component<AppProps, AppState> {
|
||||||
editorJotaiStore.set(searchItemInFocusAtom, null);
|
editorJotaiStore.set(searchItemInFocusAtom, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (editorJotaiStore.get(shapeSwitchAtom)) {
|
||||||
|
editorJotaiStore.set(shapeSwitchAtom, null);
|
||||||
|
}
|
||||||
|
|
||||||
// since contextMenu options are potentially evaluated on each render,
|
// since contextMenu options are potentially evaluated on each render,
|
||||||
// and an contextMenu action may depend on selection state, we must
|
// and an contextMenu action may depend on selection state, we must
|
||||||
// close the contextMenu before we update the selection on pointerDown
|
// close the contextMenu before we update the selection on pointerDown
|
||||||
|
|
|
@ -44,7 +44,9 @@ import type {
|
||||||
ConvertibleGenericTypes,
|
ConvertibleGenericTypes,
|
||||||
ConvertibleLinearTypes,
|
ConvertibleLinearTypes,
|
||||||
ElementsMap,
|
ElementsMap,
|
||||||
|
ExcalidrawArrowElement,
|
||||||
ExcalidrawDiamondElement,
|
ExcalidrawDiamondElement,
|
||||||
|
ExcalidrawElbowArrowElement,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
ExcalidrawEllipseElement,
|
ExcalidrawEllipseElement,
|
||||||
ExcalidrawLinearElement,
|
ExcalidrawLinearElement,
|
||||||
|
@ -87,9 +89,19 @@ export const shapeSwitchFontSizeAtom = atom<{
|
||||||
};
|
};
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
|
|
||||||
|
export const shapeSwitchLinearAtom = atom<{
|
||||||
|
[id: string]: {
|
||||||
|
properties:
|
||||||
|
| Partial<ExcalidrawLinearElement>
|
||||||
|
| Partial<ExcalidrawElbowArrowElement>;
|
||||||
|
initialType: ConvertibleLinearTypes;
|
||||||
|
};
|
||||||
|
} | null>(null);
|
||||||
|
|
||||||
const ShapeSwitch = ({ app }: { app: App }) => {
|
const ShapeSwitch = ({ app }: { app: App }) => {
|
||||||
const [shapeSwitch, setShapeSwitch] = useAtom(shapeSwitchAtom);
|
const [shapeSwitch, setShapeSwitch] = useAtom(shapeSwitchAtom);
|
||||||
const [, setShapeSwitchFontSize] = useAtom(shapeSwitchFontSizeAtom);
|
const [, setShapeSwitchFontSize] = useAtom(shapeSwitchFontSizeAtom);
|
||||||
|
const [, setShapeSwitchLinear] = useAtom(shapeSwitchLinearAtom);
|
||||||
|
|
||||||
const selectedElements = useMemo(
|
const selectedElements = useMemo(
|
||||||
() => getSelectedElements(app.scene.getNonDeletedElementsMap(), app.state),
|
() => getSelectedElements(app.scene.getNonDeletedElementsMap(), app.state),
|
||||||
|
@ -117,6 +129,7 @@ const ShapeSwitch = ({ app }: { app: App }) => {
|
||||||
// clear if not active
|
// clear if not active
|
||||||
if (!shapeSwitch) {
|
if (!shapeSwitch) {
|
||||||
setShapeSwitchFontSize(null);
|
setShapeSwitchFontSize(null);
|
||||||
|
setShapeSwitchLinear(null);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +210,56 @@ const Panel = ({
|
||||||
setPanelPosition({ x, y });
|
setPanelPosition({ x, y });
|
||||||
}, [genericElements, linearElements, app.scene, app.state]);
|
}, [genericElements, linearElements, app.scene, app.state]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editorJotaiStore.get(shapeSwitchLinearAtom)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const linearElement of linearElements) {
|
||||||
|
const initialType = getArrowType(linearElement);
|
||||||
|
const cachedProperties =
|
||||||
|
initialType === "line"
|
||||||
|
? getLineProperties(linearElement)
|
||||||
|
: initialType === "sharpArrow"
|
||||||
|
? getSharpArrowProperties(linearElement)
|
||||||
|
: initialType === "curvedArrow"
|
||||||
|
? getCurvedArrowProperties(linearElement)
|
||||||
|
: initialType === "elbowArrow"
|
||||||
|
? getElbowArrowProperties(linearElement)
|
||||||
|
: {};
|
||||||
|
|
||||||
|
editorJotaiStore.set(shapeSwitchLinearAtom, {
|
||||||
|
...editorJotaiStore.get(shapeSwitchLinearAtom),
|
||||||
|
[linearElement.id]: {
|
||||||
|
properties: cachedProperties,
|
||||||
|
initialType,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [linearElements]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (editorJotaiStore.get(shapeSwitchFontSizeAtom)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const element of genericElements) {
|
||||||
|
const boundText = getBoundTextElement(
|
||||||
|
element,
|
||||||
|
app.scene.getNonDeletedElementsMap(),
|
||||||
|
);
|
||||||
|
if (boundText) {
|
||||||
|
editorJotaiStore.set(shapeSwitchFontSizeAtom, {
|
||||||
|
...editorJotaiStore.get(shapeSwitchFontSizeAtom),
|
||||||
|
[element.id]: {
|
||||||
|
fontSize: boundText.fontSize,
|
||||||
|
elementType: element.type as ConvertibleGenericTypes,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [genericElements, app.scene]);
|
||||||
|
|
||||||
const SHAPES: [string, ReactNode][] = linear
|
const SHAPES: [string, ReactNode][] = linear
|
||||||
? [
|
? [
|
||||||
["line", LineIcon],
|
["line", LineIcon],
|
||||||
|
@ -429,6 +492,19 @@ export const switchShapes = (
|
||||||
for (const element of selectedLinearSwitchableElements) {
|
for (const element of selectedLinearSwitchableElements) {
|
||||||
convertElementType(element, nextType, app, false);
|
convertElementType(element, nextType, app, false);
|
||||||
|
|
||||||
|
const cachedLinear = editorJotaiStore.get(shapeSwitchLinearAtom)?.[
|
||||||
|
element.id
|
||||||
|
];
|
||||||
|
|
||||||
|
if (cachedLinear) {
|
||||||
|
const { properties, initialType } = cachedLinear;
|
||||||
|
|
||||||
|
if (initialType === nextType) {
|
||||||
|
mutateElement(element, properties, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isElbowArrow(element)) {
|
if (isElbowArrow(element)) {
|
||||||
const nextPoints = convertLineToElbow(element);
|
const nextPoints = convertLineToElbow(element);
|
||||||
|
|
||||||
|
@ -557,6 +633,72 @@ const getArrowType = (element: ExcalidrawLinearElement) => {
|
||||||
return "line";
|
return "line";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getLineProperties = (
|
||||||
|
element: ExcalidrawLinearElement,
|
||||||
|
): Partial<ExcalidrawLinearElement> => {
|
||||||
|
if (element.type === "line") {
|
||||||
|
return {
|
||||||
|
points: element.points,
|
||||||
|
roundness: element.roundness,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getSharpArrowProperties = (
|
||||||
|
element: ExcalidrawLinearElement,
|
||||||
|
): Partial<ExcalidrawArrowElement> => {
|
||||||
|
if (isSharpArrow(element)) {
|
||||||
|
return {
|
||||||
|
points: element.points,
|
||||||
|
startArrowhead: element.startArrowhead,
|
||||||
|
endArrowhead: element.endArrowhead,
|
||||||
|
startBinding: element.startBinding,
|
||||||
|
endBinding: element.endBinding,
|
||||||
|
roundness: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurvedArrowProperties = (
|
||||||
|
element: ExcalidrawLinearElement,
|
||||||
|
): Partial<ExcalidrawArrowElement> => {
|
||||||
|
if (isCurvedArrow(element)) {
|
||||||
|
return {
|
||||||
|
points: element.points,
|
||||||
|
startArrowhead: element.startArrowhead,
|
||||||
|
endArrowhead: element.endArrowhead,
|
||||||
|
startBinding: element.startBinding,
|
||||||
|
endBinding: element.endBinding,
|
||||||
|
roundness: element.roundness,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
|
const getElbowArrowProperties = (
|
||||||
|
element: ExcalidrawLinearElement,
|
||||||
|
): Partial<ExcalidrawElbowArrowElement> => {
|
||||||
|
if (isElbowArrow(element)) {
|
||||||
|
return {
|
||||||
|
points: element.points,
|
||||||
|
startArrowhead: element.startArrowhead,
|
||||||
|
endArrowhead: element.endArrowhead,
|
||||||
|
startBinding: element.startBinding,
|
||||||
|
endBinding: element.endBinding,
|
||||||
|
roundness: element.roundness,
|
||||||
|
fixedSegments: element.fixedSegments,
|
||||||
|
startIsSpecial: element.startIsSpecial,
|
||||||
|
endIsSpecial: element.endIsSpecial,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
const getGenericSwitchableElements = (elements: ExcalidrawElement[]) =>
|
const getGenericSwitchableElements = (elements: ExcalidrawElement[]) =>
|
||||||
elements.filter((element) => isConvertibleGenericType(element.type)) as Array<
|
elements.filter((element) => isConvertibleGenericType(element.type)) as Array<
|
||||||
| ExcalidrawRectangleElement
|
| ExcalidrawRectangleElement
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue