refactor(web): remove redundant useUnifiedDrag abstraction layer

Simplify file drop hooks by removing the unnecessary useUnifiedDrag
wrapper that became redundant after internal node drag was migrated
to react-arborist's built-in system. Now useFolderFileDrop and
useRootFileDrop directly use useFileDrop, reducing code complexity
and eliminating unused treeChildren prop drilling.
This commit is contained in:
yyh 2026-01-20 18:04:30 +08:00
parent 2151676db1
commit ee91c9d5f1
No known key found for this signature in database
5 changed files with 19 additions and 68 deletions

View File

@ -72,7 +72,7 @@ const FileTree: React.FC<FileTreeProps> = ({ className }) => {
handleRootDragOver, handleRootDragOver,
handleRootDrop, handleRootDrop,
resetRootDragCounter, resetRootDragCounter,
} = useRootFileDrop({ treeChildren }) } = useRootFileDrop()
// Root dropzone highlight (when dragging to root, not to a specific folder) // Root dropzone highlight (when dragging to root, not to a specific folder)
const isRootDropzone = dragOverFolderId === ROOT_ID const isRootDropzone = dragOverFolderId === ROOT_ID
@ -200,8 +200,8 @@ const FileTree: React.FC<FileTreeProps> = ({ className }) => {
}, [treeChildren]) }, [treeChildren])
const renderTreeNode = useCallback((props: NodeRendererProps<TreeNodeData>) => { const renderTreeNode = useCallback((props: NodeRendererProps<TreeNodeData>) => {
return <TreeNode {...props} treeChildren={treeChildren} /> return <TreeNode {...props} />
}, [treeChildren]) }, [])
useSyncTreeWithActiveTab({ useSyncTreeWithActiveTab({
treeRef, treeRef,

View File

@ -20,11 +20,9 @@ import TreeEditInput from './tree-edit-input'
import TreeGuideLines from './tree-guide-lines' import TreeGuideLines from './tree-guide-lines'
import { TreeNodeIcon } from './tree-node-icon' import { TreeNodeIcon } from './tree-node-icon'
type TreeNodeProps = NodeRendererProps<TreeNodeData> & { type TreeNodeProps = NodeRendererProps<TreeNodeData>
treeChildren: TreeNodeData[]
}
const TreeNode = ({ node, style, dragHandle, treeChildren }: TreeNodeProps) => { const TreeNode = ({ node, style, dragHandle }: TreeNodeProps) => {
const { t } = useTranslation('workflow') const { t } = useTranslation('workflow')
const isFolder = node.data.node_type === 'folder' const isFolder = node.data.node_type === 'folder'
const isSelected = node.isSelected const isSelected = node.isSelected
@ -77,7 +75,7 @@ const TreeNode = ({ node, style, dragHandle, treeChildren }: TreeNodeProps) => {
} = useTreeNodeHandlers({ node }) } = useTreeNodeHandlers({ node })
// Get file drop visual state (for external file uploads) // Get file drop visual state (for external file uploads)
const { isDragOver: isFileDragOver, isBlinking, dragHandlers } = useFolderFileDrop({ node, treeChildren }) const { isDragOver: isFileDragOver, isBlinking, dragHandlers } = useFolderFileDrop({ node })
// Combine internal drag target (willReceiveDrop) with external file drag (isFileDragOver) // Combine internal drag target (willReceiveDrop) with external file drag (isFileDragOver)
const isDragOver = isFileDragOver || (isFolder && node.willReceiveDrop) const isDragOver = isFileDragOver || (isFolder && node.willReceiveDrop)

View File

@ -4,11 +4,10 @@
import type { NodeApi } from 'react-arborist' import type { NodeApi } from 'react-arborist'
import type { TreeNodeData } from '../type' import type { TreeNodeData } from '../type'
import type { AppAssetTreeView } from '@/types/app-asset'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useStore } from '@/app/components/workflow/store' import { useStore } from '@/app/components/workflow/store'
import { isDragEvent } from '../utils/drag-utils' import { isFileDrag } from '../utils/drag-utils'
import { useUnifiedDrag } from './use-unified-drag' import { useFileDrop } from './use-file-drop'
type UseFolderFileDropReturn = { type UseFolderFileDropReturn = {
isDragOver: boolean isDragOver: boolean
@ -27,15 +26,14 @@ const AUTO_EXPAND_DELAY_MS = 2000
type UseFolderFileDropOptions = { type UseFolderFileDropOptions = {
node: NodeApi<TreeNodeData> node: NodeApi<TreeNodeData>
treeChildren: AppAssetTreeView[]
} }
export function useFolderFileDrop({ node, treeChildren: _treeChildren }: UseFolderFileDropOptions): UseFolderFileDropReturn { export function useFolderFileDrop({ node }: UseFolderFileDropOptions): UseFolderFileDropReturn {
const isFolder = node.data.node_type === 'folder' const isFolder = node.data.node_type === 'folder'
const dragOverFolderId = useStore(s => s.dragOverFolderId) const dragOverFolderId = useStore(s => s.dragOverFolderId)
const isDragOver = isFolder && dragOverFolderId === node.data.id const isDragOver = isFolder && dragOverFolderId === node.data.id
const { handleDragOver, handleDrop } = useUnifiedDrag() const { handleDragOver, handleDrop } = useFileDrop()
const expandTimerRef = useRef<NodeJS.Timeout | null>(null) const expandTimerRef = useRef<NodeJS.Timeout | null>(null)
const blinkTimerRef = useRef<NodeJS.Timeout | null>(null) const blinkTimerRef = useRef<NodeJS.Timeout | null>(null)
@ -86,7 +84,7 @@ export function useFolderFileDrop({ node, treeChildren: _treeChildren }: UseFold
}, [clearExpandTimer]) }, [clearExpandTimer])
const handleFolderDragEnter = useCallback((e: React.DragEvent) => { const handleFolderDragEnter = useCallback((e: React.DragEvent) => {
if (!isFolder || !isDragEvent(e)) if (!isFolder || !isFileDrag(e))
return return
dragCounterRef.current += 1 dragCounterRef.current += 1
if (dragCounterRef.current === 1) if (dragCounterRef.current === 1)
@ -94,13 +92,13 @@ export function useFolderFileDrop({ node, treeChildren: _treeChildren }: UseFold
}, [isFolder, scheduleAutoExpand]) }, [isFolder, scheduleAutoExpand])
const handleFolderDragOver = useCallback((e: React.DragEvent) => { const handleFolderDragOver = useCallback((e: React.DragEvent) => {
if (!isFolder || !isDragEvent(e)) if (!isFolder || !isFileDrag(e))
return return
handleDragOver(e, { folderId: node.data.id, isFolder: true }) handleDragOver(e, { folderId: node.data.id, isFolder: true })
}, [handleDragOver, isFolder, node.data.id]) }, [handleDragOver, isFolder, node.data.id])
const handleFolderDragLeave = useCallback((e: React.DragEvent) => { const handleFolderDragLeave = useCallback((e: React.DragEvent) => {
if (!isFolder || !isDragEvent(e)) if (!isFolder || !isFileDrag(e))
return return
dragCounterRef.current = Math.max(dragCounterRef.current - 1, 0) dragCounterRef.current = Math.max(dragCounterRef.current - 1, 0)
if (dragCounterRef.current === 0) if (dragCounterRef.current === 0)

View File

@ -2,10 +2,9 @@
// Root-level file drop handler with drag counter to handle nested DOM events // Root-level file drop handler with drag counter to handle nested DOM events
import type { AppAssetTreeView } from '@/types/app-asset'
import { useCallback, useRef } from 'react' import { useCallback, useRef } from 'react'
import { isDragEvent } from '../utils/drag-utils' import { isFileDrag } from '../utils/drag-utils'
import { useUnifiedDrag } from './use-unified-drag' import { useFileDrop } from './use-file-drop'
type UseRootFileDropReturn = { type UseRootFileDropReturn = {
handleRootDragEnter: (e: React.DragEvent) => void handleRootDragEnter: (e: React.DragEvent) => void
@ -15,16 +14,12 @@ type UseRootFileDropReturn = {
resetRootDragCounter: () => void resetRootDragCounter: () => void
} }
type UseRootFileDropOptions = { export function useRootFileDrop(): UseRootFileDropReturn {
treeChildren: AppAssetTreeView[] const { handleDragOver, handleDragLeave, handleDrop } = useFileDrop()
}
export function useRootFileDrop({ treeChildren: _treeChildren }: UseRootFileDropOptions): UseRootFileDropReturn {
const { handleDragOver, handleDragLeave, handleDrop } = useUnifiedDrag()
const dragCounterRef = useRef(0) const dragCounterRef = useRef(0)
const handleRootDragEnter = useCallback((e: React.DragEvent) => { const handleRootDragEnter = useCallback((e: React.DragEvent) => {
if (!isDragEvent(e)) if (!isFileDrag(e))
return return
dragCounterRef.current += 1 dragCounterRef.current += 1
}, []) }, [])
@ -34,7 +29,7 @@ export function useRootFileDrop({ treeChildren: _treeChildren }: UseRootFileDrop
}, [handleDragOver]) }, [handleDragOver])
const handleRootDragLeave = useCallback((e: React.DragEvent) => { const handleRootDragLeave = useCallback((e: React.DragEvent) => {
if (!isDragEvent(e)) if (!isFileDrag(e))
return return
dragCounterRef.current = Math.max(dragCounterRef.current - 1, 0) dragCounterRef.current = Math.max(dragCounterRef.current - 1, 0)
if (dragCounterRef.current === 0) if (dragCounterRef.current === 0)

View File

@ -1,40 +0,0 @@
'use client'
// Unified drag handler for external file uploads
// Internal node drag-move is now handled by react-arborist's built-in drag system
import { useCallback } from 'react'
import { isFileDrag } from '../utils/drag-utils'
import { useFileDrop } from './use-file-drop'
type DragTarget = {
folderId: string | null
isFolder: boolean
}
export function useUnifiedDrag() {
const fileDrop = useFileDrop()
// Only handle external file drags - internal node drags are handled by react-arborist
const handleDragOver = useCallback((e: React.DragEvent, target: DragTarget) => {
if (isFileDrag(e))
fileDrop.handleDragOver(e, target)
}, [fileDrop])
const handleDragLeave = useCallback((e: React.DragEvent) => {
if (isFileDrag(e))
fileDrop.handleDragLeave(e)
}, [fileDrop])
const handleDrop = useCallback((e: React.DragEvent, targetFolderId: string | null) => {
if (isFileDrag(e))
return fileDrop.handleDrop(e, targetFolderId)
}, [fileDrop])
return {
handleDragOver,
handleDragLeave,
handleDrop,
isUploading: fileDrop.isUploading,
}
}