Files
dify/web/app/components/workflow/skill/hooks/use-file-node-view-state.ts
yyh dc213ca76c refactor(skill)!: add file node view-state flow and mode-based file data hook
- introduce resolving/ready/missing node view-state to avoid unsupported flicker

- switch useSkillFileData to explicit mode: none/content/download

- add hook tests for view-state transitions and mode query gating

BREAKING CHANGE: useSkillFileData signature changed from (appId, nodeId, isEditable) to (appId, nodeId, mode).
2026-02-06 15:39:00 +08:00

74 lines
1.8 KiB
TypeScript

import { useRef } from 'react'
export type FileNodeViewState = 'resolving' | 'ready' | 'missing'
type ResolveFileNodeViewStateParams = {
hasFileTabId: boolean
hasCurrentFileNode: boolean
isNodeMapLoading: boolean
isNodeMapFetching: boolean
isNodeMapFetched: boolean
isNodeResolutionPending: boolean
}
type UseFileNodeViewStateParams = {
fileTabId: string | null
hasCurrentFileNode: boolean
isNodeMapLoading: boolean
isNodeMapFetching: boolean
isNodeMapFetched: boolean
}
export const resolveFileNodeViewState = ({
hasFileTabId,
hasCurrentFileNode,
isNodeMapLoading,
isNodeMapFetching,
isNodeMapFetched,
isNodeResolutionPending,
}: ResolveFileNodeViewStateParams): FileNodeViewState => {
if (!hasFileTabId || hasCurrentFileNode)
return 'ready'
if (isNodeResolutionPending && (!isNodeMapFetched || isNodeMapLoading || isNodeMapFetching))
return 'resolving'
return 'missing'
}
export function useFileNodeViewState({
fileTabId,
hasCurrentFileNode,
isNodeMapLoading,
isNodeMapFetching,
isNodeMapFetched,
}: UseFileNodeViewStateParams): FileNodeViewState {
const hasFileTabId = Boolean(fileTabId)
const resolutionRef = useRef<{ tabId: string | null, pending: boolean }>({
tabId: fileTabId,
pending: hasFileTabId,
})
if (resolutionRef.current.tabId !== fileTabId) {
resolutionRef.current = {
tabId: fileTabId,
pending: hasFileTabId,
}
}
if (fileTabId && resolutionRef.current.pending) {
const isQuerySettled = isNodeMapFetched && !isNodeMapLoading && !isNodeMapFetching
if (hasCurrentFileNode || isQuerySettled)
resolutionRef.current.pending = false
}
return resolveFileNodeViewState({
hasFileTabId,
hasCurrentFileNode,
isNodeMapLoading,
isNodeMapFetching,
isNodeMapFetched,
isNodeResolutionPending: resolutionRef.current.pending,
})
}