diff --git a/src/stages/page_chase.ts b/src/stages/page_chase.ts index 6a4bf5d..2420b87 100644 --- a/src/stages/page_chase.ts +++ b/src/stages/page_chase.ts @@ -1,4 +1,5 @@ import { BaseScene } from "@/scene/BaseScene"; +import { sceneManager } from "@/scene/SceneManager"; import { SceneType } from "@/enums/SceneType"; import { ChaseGameModel } from "@/game/chase/model"; import type { Difficulty, NodeId } from "@/game/chase/types"; @@ -41,6 +42,7 @@ export default class ChaseScene extends BaseScene { private seedInput = ""; private difficultyLocked = false; private inputAttached = false; + private unsubscribeStageChange?: () => void; constructor(options: ChaseSceneOptions = {}) { super("chase", SceneType.Normal); @@ -96,10 +98,21 @@ export default class ChaseScene extends BaseScene { } protected onSceneEnter(): void { + if (!this.unsubscribeStageChange) { + this.unsubscribeStageChange = sceneManager.onStageChange((current) => { + if (current.name !== this.name) { + this.detachSeedInputBridge(); + return; + } + this.syncSeedInputBridge(); + }); + } this.syncSeedInputBridge(); } protected onSceneExit(): void { + this.unsubscribeStageChange?.(); + this.unsubscribeStageChange = undefined; this.detachSeedInputBridge(); } diff --git a/tests/stages/page_chase.test.ts b/tests/stages/page_chase.test.ts index ce1892a..fbb0db5 100644 --- a/tests/stages/page_chase.test.ts +++ b/tests/stages/page_chase.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it, vi } from "vitest"; import ChaseScene from "../../src/stages/page_chase"; import InitScene from "../../src/stages/page_init"; +import { sceneManager } from "../../src/scene/SceneManager"; import { Text } from "pixi.js"; function createSceneState() { @@ -250,4 +251,34 @@ describe("chase stage skeleton", () => { scene.update(0, "chase", {} as any); expect((scene as any).seedInputElement).toBeUndefined(); }); + + it("detaches seed input immediately on stage change callback", () => { + const fakeDocument = createFakeDocument(); + const getState = vi.fn().mockReturnValue(createSceneState()); + let stageChangeHandler: ((current: { name: string }) => void) | undefined; + let unsubscribed = false; + const onStageChangeSpy = vi + .spyOn(sceneManager, "onStageChange") + .mockImplementation((cb: any) => { + stageChangeHandler = cb; + return () => { + unsubscribed = true; + }; + }); + + const scene = new ChaseScene({ + documentRef: fakeDocument as any, + model: { getState, moveThief: vi.fn(), newRound: vi.fn() } as any, + }); + void (scene as any).onSceneLayout(); + (scene as any).onSceneEnter(); + expect((scene as any).seedInputElement).toBeTruthy(); + + stageChangeHandler?.({ name: "init" }); + expect((scene as any).seedInputElement).toBeUndefined(); + + (scene as any).onSceneExit(); + expect(unsubscribed).toBe(true); + onStageChangeSpy.mockRestore(); + }); });