mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
fix: resolve 50+ bugs across editor store, canvas, panels, and tools
- Store: loadImage resets state, applyCrop updates sourceImageSize, setTool clears stale cropState, layer ordering preserved across layers, rotateCanvas/flipCanvas account for object dimensions, trimCanvas implemented, resizeCanvas supports anchor positioning - Canvas: crop overlay interactive, move tool drag events wired, hand tool panning, stage ref effect mount-only, checkerboard tracks pan offset, filter cache clearing - Panels: hslToHex color fix for hue 240-360, adjustments single setAdjustment call, curves draggingIndex after sort, history panel fresh temporal reads, export transparent setting, canvas resize dialog re-sync, hex input respects picker target - Tools: text tool fixed positioning and event cleanup, shape tool deferred addObject, selection mode wired to store, magic wand tolerance controlled, eyedropper coordinate transform - Options: dodge-burn/shape/clone/fill/gradient/pixel-brush use proper store actions instead of raw setState - Added 20+ store actions for tool settings - Updated tests for corrected rotation/flip/trim behavior - Excluded e2e-editor from vitest config
This commit is contained in:
@@ -1168,8 +1168,8 @@ describe("Canvas Transforms", () => {
|
||||
act((s) => s.addObject(makeRect({ id: "r1", x: 100, y: 200 })));
|
||||
act((s) => s.rotateCanvas(90));
|
||||
const obj = state().objects[0];
|
||||
// After 90 rotation: newX = canvasHeight - y = 600 - 200, newY = x = 100
|
||||
expect(obj.type === "rect" && obj.attrs.x).toBe(400);
|
||||
// After 90 rotation: newX = canvasHeight - y - height = 600 - 200 - 50, newY = x = 100
|
||||
expect(obj.type === "rect" && obj.attrs.x).toBe(350);
|
||||
expect(obj.type === "rect" && obj.attrs.y).toBe(100);
|
||||
});
|
||||
|
||||
@@ -1178,8 +1178,9 @@ describe("Canvas Transforms", () => {
|
||||
act((s) => s.addObject(makeRect({ id: "r1", x: 100, y: 200 })));
|
||||
act((s) => s.flipCanvasHorizontal());
|
||||
const obj = state().objects[0];
|
||||
expect(obj.type === "rect" && obj.attrs.x).toBe(700); // 800 - 100
|
||||
expect(obj.type === "rect" && obj.attrs.y).toBe(200); // unchanged
|
||||
// 800 - 100 - width(100) = 600
|
||||
expect(obj.type === "rect" && obj.attrs.x).toBe(600);
|
||||
expect(obj.type === "rect" && obj.attrs.y).toBe(200);
|
||||
});
|
||||
|
||||
it("flipCanvasVertical flips object y positions", () => {
|
||||
@@ -1187,13 +1188,27 @@ describe("Canvas Transforms", () => {
|
||||
act((s) => s.addObject(makeRect({ id: "r1", x: 100, y: 200 })));
|
||||
act((s) => s.flipCanvasVertical());
|
||||
const obj = state().objects[0];
|
||||
expect(obj.type === "rect" && obj.attrs.x).toBe(100); // unchanged
|
||||
expect(obj.type === "rect" && obj.attrs.y).toBe(400); // 600 - 200
|
||||
expect(obj.type === "rect" && obj.attrs.x).toBe(100);
|
||||
// 600 - 200 - height(50) = 350
|
||||
expect(obj.type === "rect" && obj.attrs.y).toBe(350);
|
||||
});
|
||||
|
||||
it("trimCanvas marks dirty", () => {
|
||||
it("trimCanvas trims to object bounds", () => {
|
||||
act((s) => s.loadImage("blob:test", 800, 600));
|
||||
act((s) => s.addObject(makeRect({ id: "r1", x: 100, y: 200 })));
|
||||
act((s) => s.trimCanvas());
|
||||
expect(state().isDirty).toBe(true);
|
||||
expect(state().canvasSize).toEqual({ width: 100, height: 50 });
|
||||
const obj = state().objects[0];
|
||||
expect(obj.type === "rect" && obj.attrs.x).toBe(0);
|
||||
expect(obj.type === "rect" && obj.attrs.y).toBe(0);
|
||||
});
|
||||
|
||||
it("trimCanvas no-ops when no objects exist", () => {
|
||||
act((s) => s.loadImage("blob:test", 800, 600));
|
||||
act((s) => s.trimCanvas());
|
||||
expect(state().isDirty).toBe(false);
|
||||
expect(state().canvasSize).toEqual({ width: 800, height: 600 });
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user