Files
dify/web/app/components/workflow/skill/hooks/use-sync-tree-with-active-tab.ts
yyh aa3cc9b9a0 fix(skill-editor): add START_TAB_ID guards to prevent invalid metadata operations
- Add guards in tool-block component to skip metadata read/write when Start tab is active
- Add guard in tool-picker-block to prevent writing tool config to Start tab
- Add guard in use-sync-tree-with-active-tab to skip tree sync for Start tab
2026-01-23 13:15:39 +08:00

56 lines
1.4 KiB
TypeScript

'use client'
import type { TreeApi } from 'react-arborist'
import type { TreeNodeData } from '../type'
import { useEffect } from 'react'
import { START_TAB_ID } from '@/app/components/workflow/skill/constants'
import { useWorkflowStore } from '@/app/components/workflow/store'
type UseSyncTreeWithActiveTabOptions = {
treeRef: React.RefObject<TreeApi<TreeNodeData> | null>
activeTabId: string | null
}
/**
* Hook that synchronizes the file tree with the active tab.
* Expands ancestor folders and scrolls to the active node.
*
* Uses node.parent chain for efficient ancestor traversal instead of
* re-traversing the tree data structure.
*/
export function useSyncTreeWithActiveTab({
treeRef,
activeTabId,
}: UseSyncTreeWithActiveTabOptions): void {
const storeApi = useWorkflowStore()
useEffect(() => {
if (!activeTabId || activeTabId === START_TAB_ID)
return
const tree = treeRef.current
if (!tree)
return
requestAnimationFrame(() => {
const node = tree.get(activeTabId)
if (!node)
return
const ancestors: string[] = []
let current = node.parent
while (current && !current.isRoot) {
ancestors.push(current.id)
current = current.parent
}
if (ancestors.length > 0)
storeApi.getState().revealFile(ancestors)
tree.openParents(node)
tree.select(activeTabId)
tree.scrollTo(activeTabId)
})
}, [activeTabId, treeRef, storeApi])
}