ultisuite-client/lib/hooks/use-drive-grid-selection.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

108 lines
3.2 KiB
TypeScript

"use client"
import { useCallback, useEffect } from "react"
import type { DriveFileInfo } from "@/lib/api/types"
import { isFromDriveMenu, isCardOpenSuppressed } from "@/lib/drive/drive-menu-guard"
import { useDriveUIStore } from "@/lib/stores/drive-ui-store"
export function useDriveGridSelection(items: DriveFileInfo[], enabled: boolean) {
const selectedPaths = useDriveUIStore((s) => s.selectedPaths)
const selectionAnchorPath = useDriveUIStore((s) => s.selectionAnchorPath)
const setSelectedPaths = useDriveUIStore((s) => s.setSelectedPaths)
const setSelectionAnchor = useDriveUIStore((s) => s.setSelectionAnchor)
const clearSelection = useDriveUIStore((s) => s.clearSelection)
const toggleSelect = useDriveUIStore((s) => s.toggleSelect)
const orderedPaths = items.map((i) => i.path)
const selectOnly = useCallback(
(path: string) => {
setSelectedPaths([path])
setSelectionAnchor(path)
},
[setSelectedPaths, setSelectionAnchor]
)
const selectRangeTo = useCallback(
(path: string) => {
const anchor = selectionAnchorPath ?? path
const from = orderedPaths.indexOf(anchor)
const to = orderedPaths.indexOf(path)
if (from < 0 || to < 0) {
selectOnly(path)
return
}
const lo = Math.min(from, to)
const hi = Math.max(from, to)
setSelectedPaths(orderedPaths.slice(lo, hi + 1))
},
[orderedPaths, selectOnly, selectionAnchorPath, setSelectedPaths]
)
const handleItemClick = useCallback(
(file: DriveFileInfo, e: React.MouseEvent) => {
if (isFromDriveMenu(e.target) || isCardOpenSuppressed()) {
e.stopPropagation()
e.preventDefault()
return
}
if (e.shiftKey) {
e.preventDefault()
selectRangeTo(file.path)
setSelectionAnchor(file.path)
return
}
if (e.ctrlKey || e.metaKey) {
e.preventDefault()
toggleSelect(file.path, !selectedPaths.has(file.path))
setSelectionAnchor(file.path)
return
}
selectOnly(file.path)
},
[
selectOnly,
selectRangeTo,
selectedPaths,
setSelectionAnchor,
toggleSelect,
]
)
const selectAll = useCallback(() => {
setSelectedPaths(orderedPaths)
if (orderedPaths[0]) setSelectionAnchor(orderedPaths[0])
}, [orderedPaths, setSelectedPaths, setSelectionAnchor])
useEffect(() => {
if (!enabled) return
const onKeyDown = (e: KeyboardEvent) => {
if (!(e.ctrlKey || e.metaKey) || e.key.toLowerCase() !== "a") return
const target = e.target as HTMLElement | null
if (!target) return
if (
target.closest(
'input, textarea, select, [contenteditable="true"], [data-drive-search], [data-drive-header]'
)
) {
return
}
if (!target.closest("[data-drive-marquee-surface], [data-drive-browser-main]")) {
return
}
e.preventDefault()
selectAll()
}
window.addEventListener("keydown", onKeyDown)
return () => window.removeEventListener("keydown", onKeyDown)
}, [enabled, selectAll])
return {
selectedPaths,
selectOnly,
handleItemClick,
selectAll,
clearSelection,
}
}