ultisuite-client/lib/hooks/use-drive-drop-target.ts
R3D347HR4Y 6ec95262af Add OnlyOffice integration and update project configurations
- Updated .env.example to include configuration for OnlyOffice Document Server.
- Modified the workspace configuration to remove the drive-suite path.
- Adjusted TypeScript environment imports for consistency.
- Enhanced Next.js configuration to disable canvas in Webpack.
- Updated package.json to include new dependencies for OnlyOffice and PDF.js.
- Added global styles for OnlyOffice theme integration in the CSS.
- Created new layout and page components for the Drive feature, including public sharing and editing functionalities.
- Updated metadata handling across various layouts to reflect the new app structure.
2026-06-07 15:49:21 +02:00

157 lines
4.2 KiB
TypeScript

"use client"
import { useCallback, useRef, useState } from "react"
import { toast } from "sonner"
import { useDriveMutations } from "@/lib/api/hooks/use-drive-queries"
import { getDriveDragData } from "@/lib/drive/drive-dnd"
import {
isMoveDestinationBlocked,
isMoveToSameFolder,
moveDriveItemsToFolder,
} from "@/lib/drive/drive-move-items"
import { useDriveUIStore } from "@/lib/stores/drive-ui-store"
const HOVER_EXPAND_MS = 700
export function useDriveDropTarget({
folderPath,
disabled,
hasChildFolders,
onExpandRequest,
}: {
folderPath: string
disabled?: boolean
hasChildFolders?: boolean
onExpandRequest?: () => void
}) {
const [isOver, setIsOver] = useState(false)
const [canDrop, setCanDrop] = useState(false)
const enterCountRef = useRef(0)
const expandTimerRef = useRef<number | null>(null)
const mutations = useDriveMutations()
const clearSelection = useDriveUIStore((s) => s.clearSelection)
const draggingItems = useDriveUIStore((s) => s.draggingItems)
const setDraggingItems = useDriveUIStore((s) => s.setDraggingItems)
const clearExpandTimer = useCallback(() => {
if (expandTimerRef.current !== null) {
window.clearTimeout(expandTimerRef.current)
expandTimerRef.current = null
}
}, [])
const resolveSources = useCallback(
(event: React.DragEvent) => {
return getDriveDragData(event.dataTransfer) ?? draggingItems
},
[draggingItems]
)
const evaluateDrop = useCallback(
(sources: ReturnType<typeof resolveSources>) => {
if (disabled || !sources || sources.length === 0) return false
if (isMoveDestinationBlocked(sources, folderPath)) return false
if (isMoveToSameFolder(sources, folderPath)) return false
return true
},
[disabled, folderPath]
)
const onDragOver = useCallback(
(event: React.DragEvent) => {
if (disabled) return
const sources = draggingItems
const allowed = evaluateDrop(sources)
if (!allowed) return
event.preventDefault()
event.dataTransfer.dropEffect = "move"
setCanDrop(true)
if (hasChildFolders && onExpandRequest && expandTimerRef.current === null) {
expandTimerRef.current = window.setTimeout(() => {
expandTimerRef.current = null
onExpandRequest()
}, HOVER_EXPAND_MS)
}
},
[disabled, draggingItems, evaluateDrop, hasChildFolders, onExpandRequest]
)
const onDragEnter = useCallback(
(event: React.DragEvent) => {
if (disabled) return
enterCountRef.current += 1
if (enterCountRef.current === 1) {
setIsOver(true)
setCanDrop(evaluateDrop(draggingItems))
}
},
[disabled, draggingItems, evaluateDrop]
)
const onDragLeave = useCallback(() => {
enterCountRef.current = Math.max(0, enterCountRef.current - 1)
if (enterCountRef.current === 0) {
setIsOver(false)
setCanDrop(false)
clearExpandTimer()
}
}, [clearExpandTimer])
const onDrop = useCallback(
(event: React.DragEvent) => {
event.preventDefault()
event.stopPropagation()
enterCountRef.current = 0
setIsOver(false)
setCanDrop(false)
clearExpandTimer()
if (disabled) return
const sources = resolveSources(event)
if (!sources) return
if (isMoveDestinationBlocked(sources, folderPath)) {
toast.error("Impossible de déplacer un dossier dans lui-même")
return
}
if (isMoveToSameFolder(sources, folderPath)) return
void (async () => {
try {
await moveDriveItemsToFolder(sources, folderPath, (body) =>
mutations.move.mutateAsync(body)
)
toast.success(sources.length > 1 ? "Éléments déplacés" : "Élément déplacé")
clearSelection()
} catch {
toast.error("Impossible de déplacer")
} finally {
setDraggingItems(null)
}
})()
},
[
clearExpandTimer,
clearSelection,
disabled,
folderPath,
mutations.move,
resolveSources,
setDraggingItems,
]
)
return {
isOver,
canDrop,
dropProps: disabled
? ({} as const)
: ({
onDragOver,
onDragEnter,
onDragLeave,
onDrop,
} as const),
}
}