This commit is contained in:
Ryan Di 2025-03-21 14:12:44 +11:00
parent 2a826f8162
commit ea4f653c44
2 changed files with 50 additions and 48 deletions

View file

@ -391,7 +391,11 @@ import {
getMinTextElementWidth, getMinTextElementWidth,
} from "../element/textMeasurements"; } from "../element/textMeasurements";
import ShapeSwitch, { shapeSwitchAtom } from "./ShapeSwitch"; import ShapeSwitch, {
GENERIC_SWITCHABLE_SHAPES,
LINEAR_SWITCHABLE_SHAPES,
shapeSwitchAtom,
} from "./ShapeSwitch";
import { activeConfirmDialogAtom } from "./ActiveConfirmDialog"; import { activeConfirmDialogAtom } from "./ActiveConfirmDialog";
import BraveMeasureTextError from "./BraveMeasureTextError"; import BraveMeasureTextError from "./BraveMeasureTextError";
@ -4116,25 +4120,29 @@ class App extends React.Component<AppProps, AppState> {
if (event.key === KEYS.ESCAPE) { if (event.key === KEYS.ESCAPE) {
editorJotaiStore.set(shapeSwitchAtom, null); editorJotaiStore.set(shapeSwitchAtom, null);
} else if (event.key === KEYS.SLASH || event.key === KEYS.TAB) { } else if (event.key === KEYS.SLASH || event.key === KEYS.TAB) {
if (editorJotaiStore.get(shapeSwitchAtom) === "panel") { event.preventDefault();
if (isGenericSwitchable) {
const index = ["rectangle", "diamond", "ellipse"].indexOf( if (editorJotaiStore.get(shapeSwitchAtom)?.type === "panel") {
selectedElements[0].type, const index = isGenericSwitchable
); ? GENERIC_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type)
const nextType = ["rectangle", "diamond", "ellipse"][ : LINEAR_SWITCHABLE_SHAPES.indexOf(selectedElements[0].type);
(index + 1) % 3
] as ToolType; const nextType = (
this.setActiveTool({ type: nextType }); isGenericSwitchable
} else if (isLinearSwitchable) { ? GENERIC_SWITCHABLE_SHAPES[
const index = ["arrow", "line"].indexOf( (index + 1) % GENERIC_SWITCHABLE_SHAPES.length
selectedElements[0].type, ]
); : LINEAR_SWITCHABLE_SHAPES[
const nextType = ["arrow", "line"][(index + 1) % 2] as ToolType; (index + 1) % LINEAR_SWITCHABLE_SHAPES.length
this.setActiveTool({ type: nextType }); ]
} ) as ToolType;
this.setActiveTool({ type: nextType });
} }
editorJotaiStore.set(shapeSwitchAtom, "panel"); editorJotaiStore.set(shapeSwitchAtom, {
type: "panel",
});
} }
} }
@ -4700,7 +4708,10 @@ class App extends React.Component<AppProps, AppState> {
}); });
} }
editorJotaiStore.set(shapeSwitchAtom, "hint"); editorJotaiStore.set(shapeSwitchAtom, {
type: "hint",
id: firstNode.id,
});
} }
this.flowChartCreator.clear(); this.flowChartCreator.clear();

View file

@ -31,7 +31,20 @@ import type { ToolType } from "../types";
const GAP_HORIZONTAL = 8; const GAP_HORIZONTAL = 8;
const GAP_VERTICAL = 10; const GAP_VERTICAL = 10;
export const shapeSwitchAtom = atom<"hint" | "panel" | null>(null); export const GENERIC_SWITCHABLE_SHAPES = ["rectangle", "diamond", "ellipse"];
export const LINEAR_SWITCHABLE_SHAPES = ["line", "arrow"];
export const shapeSwitchAtom = atom<
| {
type: "hint";
id: string;
}
| {
type: "panel";
}
| null
>(null);
const ShapeSwitch = ({ app }: { app: App }) => { const ShapeSwitch = ({ app }: { app: App }) => {
const [shapeSwitch, setShapeSwitch] = useAtom(shapeSwitchAtom); const [shapeSwitch, setShapeSwitch] = useAtom(shapeSwitchAtom);
@ -46,8 +59,13 @@ const ShapeSwitch = ({ app }: { app: App }) => {
); );
const firstElement = selectedElements[0]; const firstElement = selectedElements[0];
if (shapeSwitch.type === "hint" && firstElement.id !== shapeSwitch.id) {
setShapeSwitch(null);
return null;
}
if (firstElement && selectedElements.length === 1) { if (firstElement && selectedElements.length === 1) {
switch (shapeSwitch) { switch (shapeSwitch.type) {
case "hint": case "hint":
return <Hint app={app} element={firstElement} />; return <Hint app={app} element={firstElement} />;
case "panel": case "panel":
@ -64,13 +82,6 @@ const ShapeSwitch = ({ app }: { app: App }) => {
const Hint = ({ app, element }: { app: App; element: ExcalidrawElement }) => { const Hint = ({ app, element }: { app: App; element: ExcalidrawElement }) => {
const [, setShapeSwitch] = useAtom(shapeSwitchAtom); const [, setShapeSwitch] = useAtom(shapeSwitchAtom);
const hintRef = useRef<HTMLDivElement>(null); const hintRef = useRef<HTMLDivElement>(null);
const initialElementRef = useRef(element);
useEffect(() => {
if (element !== initialElementRef.current) {
setShapeSwitch(null);
}
}, [element, setShapeSwitch]);
useEffect(() => { useEffect(() => {
const hint = hintRef.current; const hint = hintRef.current;
@ -90,10 +101,6 @@ const Hint = ({ app, element }: { app: App; element: ExcalidrawElement }) => {
}; };
}, [setShapeSwitch]); }, [setShapeSwitch]);
if (element !== initialElementRef.current) {
return null;
}
const [x1, y1, , , cx, cy] = getElementAbsoluteCoords( const [x1, y1, , , cx, cy] = getElementAbsoluteCoords(
element, element,
app.scene.getNonDeletedElementsMap(), app.scene.getNonDeletedElementsMap(),
@ -140,22 +147,6 @@ const Hint = ({ app, element }: { app: App; element: ExcalidrawElement }) => {
}; };
const Panel = ({ app, element }: { app: App; element: ExcalidrawElement }) => { const Panel = ({ app, element }: { app: App; element: ExcalidrawElement }) => {
const [shapeSwitch, setShapeSwitch] = useAtom(shapeSwitchAtom);
const isMounted = useRef(true);
useEffect(() => {
isMounted.current = true;
return () => {
isMounted.current = false;
requestAnimationFrame(() => {
if (!isMounted.current && shapeSwitch === "panel") {
setShapeSwitch(null);
}
});
};
}, [shapeSwitch, setShapeSwitch]);
const [x1, , , y2, cx, cy] = getElementAbsoluteCoords( const [x1, , , y2, cx, cy] = getElementAbsoluteCoords(
element, element,
app.scene.getNonDeletedElementsMap(), app.scene.getNonDeletedElementsMap(),