diff --git a/src/phaser/EditorScene.ts b/src/phaser/EditorScene.ts index 5a1960e..552b71e 100644 --- a/src/phaser/EditorScene.ts +++ b/src/phaser/EditorScene.ts @@ -227,7 +227,8 @@ export class EditorScene extends Phaser.Scene { const nextZoom = clampZoom(view.zoom, maxZoom); this.currentZoom = nextZoom; this.cameras.main.setZoom(nextZoom); - this.applyScroll(view.scrollX, view.scrollY); + // Preserve stored scroll exactly; clamping against a slightly different viewport can shift the restored position. + this.applyScroll(view.scrollX, view.scrollY, false); this.hasInitializedView = true; this.emitViewState(); } @@ -804,8 +805,8 @@ export class EditorScene extends Phaser.Scene { const nextZoom = clampZoom(this.pendingViewState.zoom, maxZoom); this.currentZoom = nextZoom; this.cameras.main.setZoom(nextZoom); - // Preserve the captured scroll exactly; `applyScroll` will clamp using the current viewport. - this.applyScroll(this.pendingViewState.scrollX, this.pendingViewState.scrollY); + // Preserve the captured scroll exactly; clamping against a slightly different viewport can shift the restored position. + this.applyScroll(this.pendingViewState.scrollX, this.pendingViewState.scrollY, false); this.pendingViewState = undefined; this.hasInitializedView = true; this.emitViewState(); diff --git a/tests/e2e/app-shell.spec.ts b/tests/e2e/app-shell.spec.ts index 2382663..3352a71 100644 --- a/tests/e2e/app-shell.spec.ts +++ b/tests/e2e/app-shell.spec.ts @@ -127,12 +127,12 @@ test('resets zoom and view position when a different project is loaded', async ( await waitForEmptyScene(page); - // Different project should reset view (should not retain prior zoom). - await expect(page.getByTestId('zoom-pill')).not.toHaveText(zoomAfter); + // Different project should reset view (should not retain prior view state). + // Zoom percent can coincidentally match across projects, so assert the full view state diverges. await expect.poll(async () => { - const view = await getSceneSnapshot<{ scrollX: number; scrollY: number }>(page); - return { scrollX: view.scrollX, scrollY: view.scrollY }; - }).not.toEqual({ scrollX: viewAfterPan.scrollX, scrollY: viewAfterPan.scrollY }); + const view = await getSceneSnapshot<{ zoom: number; scrollX: number; scrollY: number }>(page); + return { zoom: view.zoom, scrollX: view.scrollX, scrollY: view.scrollY }; + }).not.toEqual({ zoom: viewAfterPan.zoom, scrollX: viewAfterPan.scrollX, scrollY: viewAfterPan.scrollY }); fs.unlinkSync(tmpPath); });