Browse Source

fix(chase): detach seed input on scene switch via stage-change subscription

Made-with: Cursor
master
npmrun 2 weeks ago
parent
commit
b5947cfec7
  1. 13
      src/stages/page_chase.ts
  2. 31
      tests/stages/page_chase.test.ts

13
src/stages/page_chase.ts

@ -1,4 +1,5 @@
import { BaseScene } from "@/scene/BaseScene"; import { BaseScene } from "@/scene/BaseScene";
import { sceneManager } from "@/scene/SceneManager";
import { SceneType } from "@/enums/SceneType"; import { SceneType } from "@/enums/SceneType";
import { ChaseGameModel } from "@/game/chase/model"; import { ChaseGameModel } from "@/game/chase/model";
import type { Difficulty, NodeId } from "@/game/chase/types"; import type { Difficulty, NodeId } from "@/game/chase/types";
@ -41,6 +42,7 @@ export default class ChaseScene extends BaseScene {
private seedInput = ""; private seedInput = "";
private difficultyLocked = false; private difficultyLocked = false;
private inputAttached = false; private inputAttached = false;
private unsubscribeStageChange?: () => void;
constructor(options: ChaseSceneOptions = {}) { constructor(options: ChaseSceneOptions = {}) {
super("chase", SceneType.Normal); super("chase", SceneType.Normal);
@ -96,10 +98,21 @@ export default class ChaseScene extends BaseScene {
} }
protected onSceneEnter(): void { protected onSceneEnter(): void {
if (!this.unsubscribeStageChange) {
this.unsubscribeStageChange = sceneManager.onStageChange((current) => {
if (current.name !== this.name) {
this.detachSeedInputBridge();
return;
}
this.syncSeedInputBridge();
});
}
this.syncSeedInputBridge(); this.syncSeedInputBridge();
} }
protected onSceneExit(): void { protected onSceneExit(): void {
this.unsubscribeStageChange?.();
this.unsubscribeStageChange = undefined;
this.detachSeedInputBridge(); this.detachSeedInputBridge();
} }

31
tests/stages/page_chase.test.ts

@ -1,6 +1,7 @@
import { describe, expect, it, vi } from "vitest"; import { describe, expect, it, vi } from "vitest";
import ChaseScene from "../../src/stages/page_chase"; import ChaseScene from "../../src/stages/page_chase";
import InitScene from "../../src/stages/page_init"; import InitScene from "../../src/stages/page_init";
import { sceneManager } from "../../src/scene/SceneManager";
import { Text } from "pixi.js"; import { Text } from "pixi.js";
function createSceneState() { function createSceneState() {
@ -250,4 +251,34 @@ describe("chase stage skeleton", () => {
scene.update(0, "chase", {} as any); scene.update(0, "chase", {} as any);
expect((scene as any).seedInputElement).toBeUndefined(); 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();
});
}); });

Loading…
Cancel
Save