First iter

Signed-off-by: Mark Tolmacs <mark@lazycat.hu>
This commit is contained in:
Mark Tolmacs 2025-04-29 18:15:14 +02:00
parent 195a743874
commit 14bd9d3829
No known key found for this signature in database
2 changed files with 53 additions and 46 deletions

View file

@ -16,6 +16,12 @@ import { isPathALoop } from "@excalidraw/element/shapes";
import { isInvisiblySmallElement } from "@excalidraw/element/sizeHelpers";
import type {
ExcalidrawElement,
ExcalidrawLinearElement,
NonDeleted,
} from "@excalidraw/element/types";
import { t } from "../i18n";
import { resetCursor } from "../cursor";
import { done } from "../components/icons";
@ -82,48 +88,55 @@ export const actionFinalize = register({
focusContainer();
}
const multiPointElement = appState.multiElement
? appState.multiElement
: appState.newElement?.type === "freedraw"
? appState.newElement
: null;
let element: NonDeleted<ExcalidrawElement> | null = null;
if (appState.multiElement) {
element = appState.multiElement;
} else if (
appState.newElement?.type === "freedraw" ||
isBindingElement(appState.newElement)
) {
element = appState.newElement;
} else if (Object.keys(appState.selectedElementIds).length === 1) {
const candidate = elementsMap.get(
Object.keys(appState.selectedElementIds)[0],
) as NonDeleted<ExcalidrawLinearElement> | undefined;
if (candidate) {
element = candidate;
}
}
if (multiPointElement) {
if (element) {
// pen and mouse have hover
if (
multiPointElement.type !== "freedraw" &&
appState.multiElement &&
element.type !== "freedraw" &&
appState.lastPointerDownWith !== "touch"
) {
const { points, lastCommittedPoint } = multiPointElement;
const { points, lastCommittedPoint } = element;
if (
!lastCommittedPoint ||
points[points.length - 1] !== lastCommittedPoint
) {
scene.mutateElement(multiPointElement, {
points: multiPointElement.points.slice(0, -1),
scene.mutateElement(element, {
points: element.points.slice(0, -1),
});
}
}
if (isInvisiblySmallElement(multiPointElement)) {
if (isInvisiblySmallElement(element)) {
// TODO: #7348 in theory this gets recorded by the store, so the invisible elements could be restored by the undo/redo, which might be not what we would want
newElements = newElements.filter(
(el) => el.id !== multiPointElement.id,
);
newElements = newElements.filter((el) => el.id !== element.id);
}
// If the multi point line closes the loop,
// set the last point to first point.
// This ensures that loop remains closed at different scales.
const isLoop = isPathALoop(multiPointElement.points, appState.zoom.value);
if (
multiPointElement.type === "line" ||
multiPointElement.type === "freedraw"
) {
const isLoop = isPathALoop(element.points, appState.zoom.value);
if (element.type === "line" || element.type === "freedraw") {
if (isLoop) {
const linePoints = multiPointElement.points;
const linePoints = element.points;
const firstPoint = linePoints[0];
scene.mutateElement(multiPointElement, {
scene.mutateElement(element, {
points: linePoints.map((p, index) =>
index === linePoints.length - 1
? pointFrom(firstPoint[0], firstPoint[1])
@ -134,23 +147,24 @@ export const actionFinalize = register({
}
if (
isBindingElement(multiPointElement) &&
isBindingElement(element) &&
!isLoop &&
multiPointElement.points.length > 1
element.points.length > 1 &&
!appState.selectedElementIds[element.id]
) {
const [x, y] = LinearElementEditor.getPointAtIndexGlobalCoordinates(
multiPointElement,
element,
-1,
arrayToMap(elements),
);
maybeBindLinearElement(multiPointElement, appState, { x, y }, scene);
maybeBindLinearElement(element, appState, { x, y }, scene);
}
}
if (
(!appState.activeTool.locked &&
appState.activeTool.type !== "freedraw") ||
!multiPointElement
!element
) {
resetCursor(interactiveCanvas);
}
@ -177,7 +191,7 @@ export const actionFinalize = register({
activeTool:
(appState.activeTool.locked ||
appState.activeTool.type === "freedraw") &&
multiPointElement
element
? appState.activeTool
: activeTool,
activeEmbeddable: null,
@ -188,21 +202,18 @@ export const actionFinalize = register({
startBoundElement: null,
suggestedBindings: [],
selectedElementIds:
multiPointElement &&
element &&
!appState.activeTool.locked &&
appState.activeTool.type !== "freedraw"
? {
...appState.selectedElementIds,
[multiPointElement.id]: true,
[element.id]: true,
}
: appState.selectedElementIds,
// To select the linear element when user has finished mutipoint editing
selectedLinearElement:
multiPointElement && isLinearElement(multiPointElement)
? new LinearElementEditor(
multiPointElement,
arrayToMap(newElements),
)
element && isLinearElement(element)
? new LinearElementEditor(element, arrayToMap(newElements))
: appState.selectedLinearElement,
pendingImageElementId: null,
},

View file

@ -9022,12 +9022,13 @@ class App extends React.Component<AppProps, AppState> {
linearElementEditor;
const element = this.scene.getElement(linearElementEditor.elementId);
if (isBindingElement(element)) {
bindOrUnbindLinearElement(
element,
startBindingElement,
endBindingElement,
this.scene,
);
this.actionManager.executeAction(actionFinalize);
// bindOrUnbindLinearElement(
// element,
// startBindingElement,
// endBindingElement,
// this.scene,
// );
}
if (linearElementEditor !== this.state.selectedLinearElement) {
@ -9162,12 +9163,7 @@ class App extends React.Component<AppProps, AppState> {
isBindingEnabled(this.state) &&
isBindingElement(newElement, false)
) {
maybeBindLinearElement(
newElement,
this.state,
pointerCoords,
this.scene,
);
this.actionManager.executeAction(actionFinalize);
}
this.setState({ suggestedBindings: [], startBoundElement: null });
if (!activeTool.locked) {