Compare commits

..

3 Commits

Author SHA1 Message Date
k88936 a0b5a84d61 Merge branch 'master' into fix/cant-pan-after-ui-editor
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Waiting to run
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Waiting to run
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Waiting to run
Project CI / AI game creator shell Rust smoke (pull_request) Waiting to run
Project CI / AI game creator shell Rust crates (pull_request) Waiting to run
Project CI / Backend tests (pull_request) Waiting to run
Project CI / Native shell tests (pull_request) Waiting to run
Project CI / Frontend tests (pull_request) Waiting to run
Project CI / Repository checks (pull_request) Waiting to run
Project CI / AI game creator shell web tests (pull_request) Waiting to run
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Waiting to run
2026-09-14 19:00:47 +08:00
k88936 a8aacb27bd 修正资源画布回归测试 IPC 桩
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
使用 manifest projectId 匹配真实布局读取契约

补充初始化布局更新命令回执
2026-09-14 18:53:52 +08:00
k88936 c485ce94a1 修复 UI 编辑器返回后资源画布平移
Project CI / AI game creator shell Rust shard 1/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 2/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 3/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust shard 4/4 (pull_request) Has been cancelled
Project CI / AI game creator shell Rust smoke (pull_request) Has been cancelled
Project CI / AI game creator shell Rust crates (pull_request) Has been cancelled
Project CI / Backend tests (pull_request) Has been cancelled
Project CI / Native shell tests (pull_request) Has been cancelled
Project CI / Frontend tests (pull_request) Has been cancelled
Project CI / Repository checks (pull_request) Has been cancelled
Project CI / AI game creator shell web tests (pull_request) Has been cancelled
资源管理卸载重挂时重新绑定画布 wheel 监听

补充 UI 编辑器返回后的资源画布平移回归用例

记录资源画布事件监听重挂排障经验
2026-09-14 18:30:33 +08:00
3 changed files with 157 additions and 1 deletions
@@ -4633,7 +4633,12 @@ export default function ProjectDevelopmentView({
passive: false,
});
return () => manager.removeEventListener('wheel', handleResourceBookWheel);
}, [handleResourceBookWheel, mode]);
}, [
handleResourceBookWheel,
mode,
// UI 编辑器会卸载整个资源 manager;返回时 ref 指向新节点,必须重新绑定原生 wheel。
uiEditorRoute,
]);
const handleResourceBookMainPointerDown = useCallback(
(event: ReactPointerEvent<HTMLDivElement>) => {
@@ -5916,6 +5916,149 @@ export function registerProjectWorkbenchFoundationTests() {
);
});
it('restores resource canvas panning after returning from the UI editor', async () => {
class TestResizeObserver {
constructor(_callback: ResizeObserverCallback) {}
observe() {}
disconnect() {}
}
vi.stubGlobal('ResizeObserver', TestResizeObserver);
const manifest = createGameCreationAppManifest(
'workbench-ui-editor-return-pan',
'UI 编辑器返回平移测试',
);
manifest.assets = [
{
id: 'ui-design-resource',
kind: 'UI',
mediaType: 'application/json',
localPath: 'assets/ui-design.json',
source: { kind: 'generated' },
},
];
const invoke = vi.fn(
async (command: string, args?: Record<string, unknown>) => {
if (command === 'read_local_project_resource_graph') {
return resourceGraphForInputs(args);
}
if (command === 'read_local_project_resource_canvas_layout') {
return {
schemaVersion: 'game-creator-resource-layout.v1',
projectId: manifest.projectId,
mode: args?.mode,
revision: 0,
positions: [],
updatedAt: 0,
};
}
if (command === 'update_local_project_resource_canvas_layout') {
return {
status: 'updated',
layout: {
schemaVersion: 'game-creator-resource-layout.v1',
projectId: manifest.projectId,
mode: args?.mode,
revision: 1,
positions: args?.positions,
updatedAt: 1,
},
};
}
if (command === 'load_ui_design_state') {
return {
revision: 0,
state: {
ui_trees: [],
ui_design_images: {},
sprite_assets: {},
font_assets: {},
},
};
}
throw new Error(`unexpected invoke ${command}`);
},
);
window.__TAURI__ = { core: { invoke } };
render(
React.createElement(ProjectDevelopmentView, {
projectName: manifest.name,
projectPath: '/tmp/workbench-ui-editor-return-pan',
manifest,
attachments: [],
recentRunStatus: null,
recentRunStopReason: null,
supervisor: React.createElement('div', null, '项目总控'),
onHomeOpen: vi.fn(),
onProjectsOpen: vi.fn(),
}),
);
await openResourceBookCategory('UI 交互');
const canvas = await screen.findByRole('region', { name: 'UI 交互' });
const scene = document.querySelector<HTMLElement>(
'[data-resource-book-view="child"] .game-resource-book-scene',
);
const wheel = (target: HTMLElement, deltaY: number) => {
const event = new WheelEvent('wheel', {
bubbles: true,
cancelable: true,
deltaY,
clientX: 120,
clientY: 100,
});
act(() => target.dispatchEvent(event));
expect(event.defaultPrevented).toBe(true);
};
wheel(scene ?? canvas, 120);
const world = canvas.querySelector<HTMLElement>('[data-resource-viewport]');
expect(world?.getAttribute('data-resource-viewport')).toMatch(
/^(?!48,48,1)/u,
);
fireEvent.click(
screen.getByRole('button', {
name: '选中资源:UI 交互 ui-design.json',
}),
);
fireEvent.click(await screen.findByRole('button', { name: 'UI 编辑器' }));
await screen.findByRole('button', { name: '返回资源' });
fireEvent.click(screen.getByRole('button', { name: '返回资源' }));
await waitFor(() =>
expect(screen.queryByRole('button', { name: '返回资源' })).toBeNull(),
);
const restoredCanvas = await screen.findByRole('region', {
name: 'UI 交互',
});
const restoredWorld = restoredCanvas.querySelector<HTMLElement>(
'[data-resource-viewport]',
);
const beforeReturn = world?.getAttribute('data-resource-viewport');
const restoredBeforePan = restoredWorld?.getAttribute(
'data-resource-viewport',
);
expect(restoredBeforePan).toBe(beforeReturn);
const restoredScene = document.querySelector<HTMLElement>(
'[data-resource-book-view="child"] .game-resource-book-scene',
);
const restoredWheelEvent = new WheelEvent('wheel', {
bubbles: true,
cancelable: true,
deltaY: 120,
clientX: 120,
clientY: 100,
});
act(() =>
(restoredScene ?? restoredCanvas).dispatchEvent(restoredWheelEvent),
);
expect(restoredWheelEvent.defaultPrevented).toBe(true);
expect(restoredWorld?.getAttribute('data-resource-viewport')).not.toBe(
restoredBeforePan,
);
});
it('clears the resource preview cache and cancels the old preview scope on project switch', async () => {
// 60d8b8fbb 删掉了从未被写入的 `resourcePreviewVersionByResourceId` 死接线,原先钉
// 那条 prop 与它的清空语句的断言随之取消;用例真正要守的意图不变——项目切换必须把
@@ -1,5 +1,13 @@
# 踩坑与排障记录
## 2026-09-14 UI 编辑器返回后资源画布滚轮平移失效
- **现象**:资源管理打开 UI 编辑器再返回后,资源画布滚轮平移/缩放不再响应;返回前同一手势正常。
- **原因**:资源画布的非 passive `wheel` 监听绑定在 `resourceBookManagerRef` 当前 DOM 上,但 effect 只依赖 `handleResourceBookWheel``mode`。UI 编辑器切换会卸载旧 manager 并挂载新 manager,依赖不变导致新节点没有重新绑定监听。
- **处理**:将 `uiEditorRoute` 纳入 wheel effect 依赖,使进入/退出 UI 编辑器时先清理旧节点监听,再给返回后的新 manager 绑定同一处理器。
- **验证**`npx vitest run apps/ai-game-creator-shell/tests/appSurface.test.ts -t "restores resource canvas panning"`;回归用例覆盖打开栏目、wheel 平移、进入 UI 编辑器、返回并再次 wheel 平移。
- **关联**`apps/ai-game-creator-shell/src/view/project-development/index.tsx``apps/ai-game-creator-shell/tests/appSurface/project-development.suite.ts`
## 2026-09-14 AGC 壳 Rust 套件按「一片一 job」拆分,且分片必须自校验覆盖
- **现象**`AI game creator shell Rust tests` 一直是客户端 CI 的关键路径。run 2097 实测 15 分 27 秒,其中 `apps/ai-game-creator-shell/src-tauri` 的 bin target 单测(2466 条)一条 `cargo test -- --test-threads=1` 串行占 507 秒。