From fbd30d7c6658deba671825dd906664c4f6aa1af1 Mon Sep 17 00:00:00 2001 From: kdletters <61648117+kdletters@users.noreply.github.com> Date: Fri, 2 Oct 2026 11:17:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20UI=20=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E5=99=A8=E5=BE=AA=E7=8E=AF=E6=B8=B8=E6=A0=87=E4=B8=8E=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=E6=80=81=E8=A2=AB=E5=BB=B6=E8=BF=9F=20effect=20?= =?UTF-8?q?=E8=A6=86=E7=9B=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 界面树循环游标改为渲染期换算有效游标,不再用被动 effect 事后重置 复制路径按钮把复制态绑定到具体路径,去掉延迟重置的 effect 复制态断言改为等待异步落盘,避免同步断言抢跑 新增 useUiTreeNodeCycle 循环顺序与界面树替换重置用例 --- .../components/UiEditorCopyPathButton.tsx | 27 +++--- .../src/view/ui-editor/useUiTreeNodeCycle.ts | 24 ++++- .../tests/uiEditorPage.test.ts | 3 +- .../tests/uiTreeNodeCycle.test.ts | 96 +++++++++++++++++++ 4 files changed, 133 insertions(+), 17 deletions(-) create mode 100644 apps/ai-game-creator-shell/tests/uiTreeNodeCycle.test.ts diff --git a/apps/ai-game-creator-shell/src/view/ui-editor/components/UiEditorCopyPathButton.tsx b/apps/ai-game-creator-shell/src/view/ui-editor/components/UiEditorCopyPathButton.tsx index ea19e48bf..b33d9e62a 100644 --- a/apps/ai-game-creator-shell/src/view/ui-editor/components/UiEditorCopyPathButton.tsx +++ b/apps/ai-game-creator-shell/src/view/ui-editor/components/UiEditorCopyPathButton.tsx @@ -1,31 +1,36 @@ import { writeText } from '@tauri-apps/plugin-clipboard-manager'; import { Copy } from 'lucide-react'; -import { useEffect, useState } from 'react'; +import { useState } from 'react'; + +type CopyState = 'idle' | 'copied' | 'failed'; export function UiEditorCopyPathButton({ relativePath, }: { relativePath: string; }) { - const [copyState, setCopyState] = useState<'idle' | 'copied' | 'failed'>( - 'idle', - ); - - useEffect(() => setCopyState('idle'), [relativePath]); + // 复制态跟着具体路径走:路径变了就等于回到未复制。这里不用 effect 事后重置, + // 因为延迟执行的 effect 会晚于复制结果落盘,把「已复制」覆盖回未复制。 + const [copyState, setCopyState] = useState<{ + relativePath: string; + value: CopyState; + }>({ relativePath, value: 'idle' }); + const value = + copyState.relativePath === relativePath ? copyState.value : 'idle'; async function copyPath() { - setCopyState('idle'); + setCopyState({ relativePath, value: 'idle' }); try { await writeText(relativePath); - setCopyState('copied'); + setCopyState({ relativePath, value: 'copied' }); } catch { - setCopyState('failed'); + setCopyState({ relativePath, value: 'failed' }); } } return ( <> - {copyState === 'failed' ? ( + {value === 'failed' ? (

复制失败,请手动复制路径。

@@ -36,7 +41,7 @@ export function UiEditorCopyPathButton({ onClick={() => void copyPath()} >