diff --git a/apps/ai-game-creator-shell/src/view/ui-editor/index.tsx b/apps/ai-game-creator-shell/src/view/ui-editor/index.tsx index 84267aad5..26cd2ba1f 100644 --- a/apps/ai-game-creator-shell/src/view/ui-editor/index.tsx +++ b/apps/ai-game-creator-shell/src/view/ui-editor/index.tsx @@ -1,4 +1,4 @@ -import { ChevronLeft } from 'lucide-react'; +import { ChevronLeft, Redo2, Undo2 } from 'lucide-react'; import { type ReactNode, useEffect, useMemo, useState } from 'react'; import { ThemedModal } from '../../components/modal/ThemedModal'; @@ -82,6 +82,37 @@ export default function UiEditorPage({ if (session.save.isDirty) setGenerateSuccess(null); }, [session.save.isDirty]); + useEffect(() => { + const isEditableTarget = (target: EventTarget | null) => { + const element = target instanceof HTMLElement ? target : null; + return Boolean( + element?.isContentEditable || + element?.closest( + 'input, textarea, select, button, a, [contenteditable="true"], [role="button"]', + ), + ); + }; + const onKeyDown = (event: KeyboardEvent) => { + if ( + isEditableTarget(event.target) || + (!event.ctrlKey && !event.metaKey) + ) { + return; + } + const isUndo = event.key.toLowerCase() === 'z' && !event.shiftKey; + const isRedo = + (event.key.toLowerCase() === 'z' && event.shiftKey) || + (event.ctrlKey && event.key.toLowerCase() === 'y'); + if (isUndo && session.history.undo()) { + event.preventDefault(); + } else if (isRedo && session.history.redo()) { + event.preventDefault(); + } + }; + window.addEventListener('keydown', onKeyDown); + return () => window.removeEventListener('keydown', onKeyDown); + }, [session.history]); + async function save(afterReturn = false) { if (await session.save.save()) { if (afterReturn) { @@ -155,6 +186,26 @@ export default function UiEditorPage({ {resourceLabel ?? 'UI 设计'}
+ + {walletEntry ? (
{walletEntry}
) : null}