fix: ignore no-op map edge edits

This commit is contained in:
Nico 2026-06-04 23:21:07 -07:00
parent ac028bc446
commit 932033682d
2 changed files with 46 additions and 20 deletions

View File

@ -38,6 +38,31 @@ function clampResizedObjectToMap(object, mapSize) {
}; };
} }
function hasObjectBoundsChanged(object, nextObject) {
return (
object.x !== nextObject.x ||
object.y !== nextObject.y ||
object.width !== nextObject.width ||
object.height !== nextObject.height
);
}
function getDraggedObjectUpdate(object, dragState, deltaX, deltaY, mapSize) {
if (dragState.type === "resize") {
return clampResizedObjectToMap({
...object,
width: Math.max(40, dragState.startObject.width + deltaX),
height: Math.max(40, dragState.startObject.height + deltaY),
}, mapSize);
}
return clampObjectToMap({
...object,
x: dragState.startObject.x + deltaX,
y: dragState.startObject.y + deltaY,
}, mapSize);
}
export default function LocationMapCanvas({ export default function LocationMapCanvas({
mode, mode,
objects, objects,
@ -198,6 +223,11 @@ export default function LocationMapCanvas({
Math.abs(deltaY) >= DRAG_CHANGE_THRESHOLD; Math.abs(deltaY) >= DRAG_CHANGE_THRESHOLD;
if (!hasMeaningfulChange) return; if (!hasMeaningfulChange) return;
const draggedObject = objects.find((object) => getObjectKey(object) === dragState.key);
if (!draggedObject) return;
const nextDraggedObject = getDraggedObjectUpdate(draggedObject, dragState, deltaX, deltaY, mapSize);
if (!hasObjectBoundsChanged(draggedObject, nextDraggedObject)) return;
if (!objectDragHistoryCapturedRef.current) { if (!objectDragHistoryCapturedRef.current) {
remember(); remember();
objectDragHistoryCapturedRef.current = true; objectDragHistoryCapturedRef.current = true;
@ -206,18 +236,7 @@ export default function LocationMapCanvas({
updateObjects((currentObjects) => updateObjects((currentObjects) =>
currentObjects.map((object) => { currentObjects.map((object) => {
if (getObjectKey(object) !== dragState.key) return object; if (getObjectKey(object) !== dragState.key) return object;
if (dragState.type === "resize") { return getDraggedObjectUpdate(object, dragState, deltaX, deltaY, mapSize);
return clampResizedObjectToMap({
...object,
width: Math.max(40, dragState.startObject.width + deltaX),
height: Math.max(40, dragState.startObject.height + deltaY),
}, mapSize);
}
return clampObjectToMap({
...object,
x: dragState.startObject.x + deltaX,
y: dragState.startObject.y + deltaY,
}, mapSize);
}) })
); );
}; };
@ -264,17 +283,20 @@ export default function LocationMapCanvas({
const nudgeAmount = event.shiftKey ? 25 : 10; const nudgeAmount = event.shiftKey ? 25 : 10;
const deltaX = event.key === "ArrowLeft" ? -nudgeAmount : event.key === "ArrowRight" ? nudgeAmount : 0; const deltaX = event.key === "ArrowLeft" ? -nudgeAmount : event.key === "ArrowRight" ? nudgeAmount : 0;
const deltaY = event.key === "ArrowUp" ? -nudgeAmount : event.key === "ArrowDown" ? nudgeAmount : 0; const deltaY = event.key === "ArrowUp" ? -nudgeAmount : event.key === "ArrowDown" ? nudgeAmount : 0;
const nextObject = clampObjectToMap({
...object,
x: object.x + deltaX,
y: object.y + deltaY,
}, mapSize);
setSelectedObjectKey(getObjectKey(object));
if (!hasObjectBoundsChanged(object, nextObject)) return;
remember(); remember();
setSelectedObjectKey(getObjectKey(object));
updateObjects((currentObjects) => updateObjects((currentObjects) =>
currentObjects.map((candidate) => currentObjects.map((candidate) =>
getObjectKey(candidate) === getObjectKey(object) getObjectKey(candidate) === getObjectKey(object)
? clampObjectToMap({ ? nextObject
...candidate,
x: candidate.x + deltaX,
y: candidate.y + deltaY,
}, mapSize)
: candidate : candidate
) )
); );

View File

@ -2131,7 +2131,9 @@ test("admin cannot nudge map areas outside the canvas", async ({ page }) => {
await expect(bakeryArea).toHaveAttribute("x", "740"); await expect(bakeryArea).toHaveAttribute("x", "740");
await expect(bakeryArea).toHaveAttribute("y", "540"); await expect(bakeryArea).toHaveAttribute("y", "540");
await expect(page.locator(".location-map-status")).toHaveText("Unsaved Draft"); await expect(page.locator(".location-map-status")).toHaveText("Draft");
await expect(page.getByRole("button", { name: "Save Draft" })).toHaveCount(0);
await expect(page.getByRole("button", { name: "Undo" })).toBeDisabled();
}); });
test("admin cannot resize map areas beyond the canvas", async ({ page }) => { test("admin cannot resize map areas beyond the canvas", async ({ page }) => {
@ -2191,7 +2193,9 @@ test("admin cannot resize map areas beyond the canvas", async ({ page }) => {
await expect(bakeryArea).toHaveAttribute("y", "580"); await expect(bakeryArea).toHaveAttribute("y", "580");
await expect(bakeryArea).toHaveAttribute("width", "180"); await expect(bakeryArea).toHaveAttribute("width", "180");
await expect(bakeryArea).toHaveAttribute("height", "120"); await expect(bakeryArea).toHaveAttribute("height", "120");
await expect(page.locator(".location-map-status")).toHaveText("Unsaved Draft"); await expect(page.locator(".location-map-status")).toHaveText("Draft");
await expect(page.getByRole("button", { name: "Save Draft" })).toHaveCount(0);
await expect(page.getByRole("button", { name: "Undo" })).toBeDisabled();
}); });
test("admin selected map area uses compact editable fields", async ({ page }) => { test("admin selected map area uses compact editable fields", async ({ page }) => {