From 5947e04226df2921bc481157282ace1728e71811 Mon Sep 17 00:00:00 2001 From: yyh Date: Mon, 19 Jan 2026 14:09:37 +0800 Subject: [PATCH] feat: decouple create target from tab selection --- web/app/components/workflow/skill/file-tree/index.tsx | 1 + .../workflow/skill/hooks/use-tree-node-handlers.ts | 4 +++- web/app/components/workflow/skill/sidebar-search-add.tsx | 6 +++--- .../workflow/store/workflow/skill-editor/file-tree-slice.ts | 5 +++++ .../workflow/store/workflow/skill-editor/index.ts | 1 + .../workflow/store/workflow/skill-editor/types.ts | 2 ++ 6 files changed, 15 insertions(+), 4 deletions(-) diff --git a/web/app/components/workflow/skill/file-tree/index.tsx b/web/app/components/workflow/skill/file-tree/index.tsx index 46984d0a4a..ae4593e687 100644 --- a/web/app/components/workflow/skill/file-tree/index.tsx +++ b/web/app/components/workflow/skill/file-tree/index.tsx @@ -87,6 +87,7 @@ const FileTree: React.FC = ({ className, searchTerm = '' }) => { } const selectedId = nodes[0]?.id ?? null storeApi.getState().setSelectedTreeNodeId(selectedId) + storeApi.getState().setCreateTargetNodeId(selectedId) }, [activeTabId, storeApi]) const handleBlankAreaContextMenu = useCallback((e: React.MouseEvent) => { diff --git a/web/app/components/workflow/skill/hooks/use-tree-node-handlers.ts b/web/app/components/workflow/skill/hooks/use-tree-node-handlers.ts index a1265d6a36..74eaae857c 100644 --- a/web/app/components/workflow/skill/hooks/use-tree-node-handlers.ts +++ b/web/app/components/workflow/skill/hooks/use-tree-node-handlers.ts @@ -49,12 +49,13 @@ export function useTreeNodeHandlers({ const handleClick = useCallback((e: React.MouseEvent) => { e.stopPropagation() + storeApi.getState().setCreateTargetNodeId(node.data.id) node.select() if (isFolder) throttledToggle() else handleFileClick() - }, [isFolder, node, throttledToggle, handleFileClick]) + }, [handleFileClick, isFolder, node, storeApi, throttledToggle]) const handleDoubleClick = useCallback((e: React.MouseEvent) => { e.stopPropagation() @@ -73,6 +74,7 @@ export function useTreeNodeHandlers({ e.preventDefault() e.stopPropagation() + storeApi.getState().setCreateTargetNodeId(node.data.id) storeApi.getState().setContextMenu({ top: e.clientY, left: e.clientX, diff --git a/web/app/components/workflow/skill/sidebar-search-add.tsx b/web/app/components/workflow/skill/sidebar-search-add.tsx index d745b18360..6607a4198c 100644 --- a/web/app/components/workflow/skill/sidebar-search-add.tsx +++ b/web/app/components/workflow/skill/sidebar-search-add.tsx @@ -66,14 +66,14 @@ const SidebarSearchAdd: FC = ({ onSearchChange }) => { const { data: treeData } = useSkillAssetTreeData() const activeTabId = useStore(s => s.activeTabId) - const selectedTreeNodeId = useStore(s => s.selectedTreeNodeId) + const createTargetNodeId = useStore(s => s.createTargetNodeId) const treeChildren = treeData?.children const targetFolderId = useMemo(() => { if (!treeChildren) return 'root' - return getTargetFolderIdFromSelection(activeTabId ?? selectedTreeNodeId, treeChildren) - }, [activeTabId, selectedTreeNodeId, treeChildren]) + return getTargetFolderIdFromSelection(createTargetNodeId ?? activeTabId, treeChildren) + }, [activeTabId, createTargetNodeId, treeChildren]) const menuOffset = useMemo(() => ({ mainAxis: 4 }), []) const { diff --git a/web/app/components/workflow/store/workflow/skill-editor/file-tree-slice.ts b/web/app/components/workflow/store/workflow/skill-editor/file-tree-slice.ts index ddb4aeb96e..d134df518b 100644 --- a/web/app/components/workflow/store/workflow/skill-editor/file-tree-slice.ts +++ b/web/app/components/workflow/store/workflow/skill-editor/file-tree-slice.ts @@ -17,6 +17,7 @@ export const createFileTreeSlice: StateCreator< > = (set, get) => ({ expandedFolderIds: new Set(), selectedTreeNodeId: null, + createTargetNodeId: null, pendingCreateNode: null, setExpandedFolderIds: (ids: Set) => { @@ -61,6 +62,10 @@ export const createFileTreeSlice: StateCreator< set({ selectedTreeNodeId: nodeId }) }, + setCreateTargetNodeId: (nodeId) => { + set({ createTargetNodeId: nodeId }) + }, + startCreateNode: (nodeType, parentId) => { set({ pendingCreateNode: { diff --git a/web/app/components/workflow/store/workflow/skill-editor/index.ts b/web/app/components/workflow/store/workflow/skill-editor/index.ts index 909f71dc64..4d08d524bb 100644 --- a/web/app/components/workflow/store/workflow/skill-editor/index.ts +++ b/web/app/components/workflow/store/workflow/skill-editor/index.ts @@ -28,6 +28,7 @@ export const createSkillEditorSlice: StateCreator = (...a previewTabId: null, expandedFolderIds: new Set(), selectedTreeNodeId: null, + createTargetNodeId: null, pendingCreateNode: null, dirtyContents: new Map(), fileMetadata: new Map>(), diff --git a/web/app/components/workflow/store/workflow/skill-editor/types.ts b/web/app/components/workflow/store/workflow/skill-editor/types.ts index 4ed9f908fc..b5b85a7395 100644 --- a/web/app/components/workflow/store/workflow/skill-editor/types.ts +++ b/web/app/components/workflow/store/workflow/skill-editor/types.ts @@ -30,6 +30,8 @@ export type FileTreeSliceShape = { getOpensObject: () => OpensObject selectedTreeNodeId: string | null setSelectedTreeNodeId: (nodeId: string | null) => void + createTargetNodeId: string | null + setCreateTargetNodeId: (nodeId: string | null) => void pendingCreateNode: PendingCreateNode | null startCreateNode: (nodeType: PendingCreateNode['nodeType'], parentId: PendingCreateNode['parentId']) => void clearCreateNode: () => void