diff --git a/apps/ai-game-creator-shell/scripts/check-config.mjs b/apps/ai-game-creator-shell/scripts/check-config.mjs index 9833f1251..da4523c06 100644 --- a/apps/ai-game-creator-shell/scripts/check-config.mjs +++ b/apps/ai-game-creator-shell/scripts/check-config.mjs @@ -1754,8 +1754,6 @@ for (const snippet of [ "'write_game_creator_app_config'", 'aria-label="运行时配置"', 'LLM API Key', - 'External Editor Base URL', - 'External Editor API Key', 'runtime_config.save', "'/run:运行自检,启动本地 HTTP 预览并载入客户端运行视图'", "'activate_local_game_preview'", @@ -1791,6 +1789,19 @@ for (const snippet of [ } } +for (const snippet of [ + "label: '连接与工具'", + "id: 'connections'", + "activeSection === 'connections'", + 'aria-label="外部连接"', +]) { + if (appSource.includes(snippet)) { + throw new Error( + `AI game creator shell removed settings page was reintroduced: ${snippet}`, + ); + } +} + for (const script of [ 'ai-game-creator-shell:dev', 'ai-game-creator-shell:dev-server', diff --git a/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx b/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx index 0ff7f445c..44f47ffb7 100644 --- a/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx +++ b/apps/ai-game-creator-shell/src/features/runtime-config/RuntimeConfigDialog.tsx @@ -1,6 +1,5 @@ import { Bot, - Cable, CheckCircle2, CircleAlert, Info, @@ -91,7 +90,6 @@ const defaultRuntimeConfigDraft: GameCreatorAppConfig = { type RuntimeSettingsSection = | 'general' | 'agents' - | 'connections' | 'extensions' | 'advanced' | 'about'; @@ -116,12 +114,6 @@ const runtimeSettingsSections = [ description: '按角色覆盖默认模型', icon: Bot, }, - { - id: 'connections', - label: '连接与工具', - description: '外部服务', - icon: Cable, - }, { id: 'extensions', label: '扩展', @@ -1452,57 +1444,6 @@ export function RuntimeConfigDialog({ })} ) : null} - {activeSection === 'connections' ? ( - - - - 外部连接 - 配置图片编辑器使用的外部服务 - - - {allowAdvancedExternalEditorConfig ? ( - - - External Editor Base URL - - setRuntimeConfigDraft((current) => ({ - ...current, - editorApi: { - ...current.editorApi, - baseUrl: event.currentTarget.value, - }, - })) - } - /> - - - External Editor API Key - - setRuntimeConfigDraft((current) => ({ - ...current, - editorApi: { - ...current.editorApi, - apiKey: event.currentTarget.value, - }, - })) - } - /> - - - ) : null} - - ) : null} {activeSection === 'extensions' ? ( ( { + if ( + event.target instanceof Element && + event.target.closest('button') + ) { + event.preventDefault(); + } + }} > { window.removeEventListener('keydown', listener); }); - it('keeps node deletion available when the zoom slider has focus', () => { - const slider = document.createElement('input'); - slider.type = 'range'; - document.body.append(slider); - const deleteNode = vi.fn(() => ({ ok: true })); - const listener = (event: KeyboardEvent) => - handleUiEditorKeyDown(event, { - selectedNodeId: 'node-1', - activeImageId: 'page-1', - deleteNode, - historyUndo: vi.fn(() => true), - historyRedo: vi.fn(() => true), - }); - window.addEventListener('keydown', listener); + it.each(['Delete', 'Backspace'])( + 'does not delete a node when the zoom slider has focus (%s)', + (key) => { + const slider = document.createElement('input'); + slider.type = 'range'; + document.body.append(slider); + const deleteNode = vi.fn(() => ({ ok: true })); + const listener = (event: KeyboardEvent) => + handleUiEditorKeyDown(event, { + selectedNodeId: 'node-1', + activeImageId: 'page-1', + deleteNode, + historyUndo: vi.fn(() => true), + historyRedo: vi.fn(() => true), + }); + window.addEventListener('keydown', listener); - fireEvent.keyDown(slider, { key: 'Delete' }); + fireEvent.keyDown(slider, { key }); - expect(deleteNode).toHaveBeenCalledWith('node-1', 'page-1'); - window.removeEventListener('keydown', listener); - }); + expect(deleteNode).not.toHaveBeenCalled(); + window.removeEventListener('keydown', listener); + }, + ); - it('keeps node deletion available after a zoom button is clicked', () => { + it('keeps node deletion available after zoom button focus is released', () => { const zoomControls = document.createElement('div'); - zoomControls.setAttribute('data-ui-editor-zoom-controls', ''); const zoomIn = document.createElement('button'); zoomControls.append(zoomIn); document.body.append(zoomControls); @@ -99,7 +101,7 @@ describe('ui editor keyboard shortcuts', () => { window.addEventListener('keydown', listener); fireEvent.click(zoomIn); - fireEvent.keyDown(zoomIn, { key: 'Delete' }); + fireEvent.keyDown(window, { key: 'Delete' }); expect(deleteNode).toHaveBeenCalledWith('node-1', 'page-1'); window.removeEventListener('keydown', listener); diff --git a/docs/【交互设计】预览画布缩放滑杆-2026-09-05.md b/docs/【交互设计】预览画布缩放滑杆-2026-09-05.md index eb518c538..cd57f23ee 100644 --- a/docs/【交互设计】预览画布缩放滑杆-2026-09-05.md +++ b/docs/【交互设计】预览画布缩放滑杆-2026-09-05.md @@ -11,7 +11,7 @@ - 保留 `−` 与 `+` 按钮。点击轨道可跳转,拖动滑块实时更新画布和百分比。 - 缩放以视口中心为中心,继续支持 Ctrl/Cmd + 滚轮缩放。 - 滑杆支持方向键、Home、End;百分比文本可点击编辑并在失焦时限制到有效范围。 -- 缩放滑杆即使处于焦点,也不得拦截 UI 节点的 Delete/Backspace 快捷删除。 +- 缩放滑杆获得焦点时,Delete/Backspace 不触发 UI 节点快捷删除;缩放按钮鼠标点击不改变快捷键焦点。 - Windows/Linux 使用 `Ctrl`,macOS 使用 `Cmd`;`+`、`=` 与 `NumpadAdd` 放大,`-` 与 `NumpadSubtract` 缩小,允许按键重复时连续缩放。 - 快捷键直接复用现有 `+`/`−` 按钮动作:以视口中心为锚点,按 `×1.16`/`×0.86` 改变缩放。 - 鼠标悬停在预览画布上,或预览画布已获得键盘焦点时,快捷键生效。预览画布需提供可聚焦语义与无障碍名称。
配置图片编辑器使用的外部服务