5bfe2a0331
* feat: add file manager module - Complete file manager implementation with UI/UX - Add drive management functionality - Add file upload/download with progress tracking - Add stamp integration and handling - Add bulk operations and context menus Co-authored-by: Roland Seres <roland.seres90@gmail.com> Co-authored-by: nidishk <nidishkrishnan45@gmail.com>
92 lines
2.6 KiB
TypeScript
92 lines
2.6 KiB
TypeScript
import { useCallback, useRef, useState } from 'react'
|
|
import { DriveInfo } from '@solarpunkltd/file-manager-lib'
|
|
|
|
interface UseDragAndDropProps {
|
|
onFilesDropped: (files: FileList) => void
|
|
currentDrive: DriveInfo | null
|
|
}
|
|
|
|
interface UseDragAndDropReturn {
|
|
isDragging: boolean
|
|
handleDragEnter: (e: React.DragEvent<HTMLDivElement>) => void
|
|
handleDragOver: (e: React.DragEvent<HTMLDivElement>) => void
|
|
handleDragLeave: (e: React.DragEvent<HTMLDivElement>) => void
|
|
handleDrop: (e: React.DragEvent<HTMLDivElement>) => void
|
|
handleOverlayDrop: (e: React.DragEvent<HTMLDivElement>) => void
|
|
}
|
|
|
|
export function useDragAndDrop({ onFilesDropped, currentDrive }: UseDragAndDropProps): UseDragAndDropReturn {
|
|
const [isDragging, setIsDragging] = useState(false)
|
|
const dragCounter = useRef(0)
|
|
|
|
const hasFilesDT = (dt: DataTransfer | null): boolean => {
|
|
if (!dt) return false
|
|
|
|
if (dt.types && Array.from(dt.types).includes('Files')) return true
|
|
|
|
if (dt.items && Array.from(dt.items).some(i => i.kind === 'file')) return true
|
|
|
|
return false
|
|
}
|
|
|
|
const handleDragEnter = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
|
if (!hasFilesDT(e.dataTransfer)) return
|
|
e.preventDefault()
|
|
|
|
if (dragCounter.current++ === 0) setIsDragging(true)
|
|
}, [])
|
|
|
|
const handleDragOver = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
|
if (!hasFilesDT(e.dataTransfer)) return
|
|
e.preventDefault()
|
|
e.dataTransfer.dropEffect = 'copy'
|
|
}, [])
|
|
|
|
const handleDragLeave = useCallback((e: React.DragEvent<HTMLDivElement>) => {
|
|
if (!hasFilesDT(e.dataTransfer)) return
|
|
e.preventDefault()
|
|
dragCounter.current = Math.max(0, dragCounter.current - 1)
|
|
|
|
if (dragCounter.current === 0) setIsDragging(false)
|
|
}, [])
|
|
|
|
const handleDrop = useCallback(
|
|
(e: React.DragEvent<HTMLDivElement>) => {
|
|
if (!hasFilesDT(e.dataTransfer)) return
|
|
e.preventDefault()
|
|
const droppedFiles = e.dataTransfer?.files ?? null
|
|
dragCounter.current = 0
|
|
setIsDragging(false)
|
|
|
|
if (droppedFiles && droppedFiles.length) {
|
|
onFilesDropped(droppedFiles)
|
|
}
|
|
},
|
|
[onFilesDropped],
|
|
)
|
|
|
|
const handleOverlayDrop = useCallback(
|
|
(e: React.DragEvent<HTMLDivElement>) => {
|
|
e.preventDefault()
|
|
e.stopPropagation()
|
|
setIsDragging(false)
|
|
dragCounter.current = 0
|
|
const dropped = e.dataTransfer?.files
|
|
|
|
if (dropped && dropped.length) {
|
|
onFilesDropped(dropped)
|
|
}
|
|
},
|
|
[onFilesDropped],
|
|
)
|
|
|
|
return {
|
|
isDragging,
|
|
handleDragEnter,
|
|
handleDragOver,
|
|
handleDragLeave,
|
|
handleDrop,
|
|
handleOverlayDrop,
|
|
}
|
|
}
|