- 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.
83 lines
2.7 KiB
TypeScript
83 lines
2.7 KiB
TypeScript
"use client"
|
|
|
|
import { useCallback, useRef, useState } from "react"
|
|
import {
|
|
pathsInMarqueeRect,
|
|
shouldIgnoreDriveMarqueeStart,
|
|
type DriveMarqueeRect,
|
|
} from "@/lib/drive/drive-marquee"
|
|
import { useDriveUIStore } from "@/lib/stores/drive-ui-store"
|
|
|
|
export function useDriveMarqueeSelection(enabled: boolean) {
|
|
const selectedPaths = useDriveUIStore((s) => s.selectedPaths)
|
|
const setSelectedPaths = useDriveUIStore((s) => s.setSelectedPaths)
|
|
const clearSelection = useDriveUIStore((s) => s.clearSelection)
|
|
|
|
const cardRefs = useRef(new Map<string, HTMLDivElement>())
|
|
const dragRef = useRef<{
|
|
startX: number
|
|
startY: number
|
|
additive: boolean
|
|
baseSelection: Set<string>
|
|
} | null>(null)
|
|
const [marquee, setMarquee] = useState<DriveMarqueeRect | null>(null)
|
|
|
|
const registerCardRef = useCallback((path: string, el: HTMLDivElement | null) => {
|
|
if (el) cardRefs.current.set(path, el)
|
|
else cardRefs.current.delete(path)
|
|
}, [])
|
|
|
|
const onSurfacePointerDown = useCallback(
|
|
(e: React.PointerEvent) => {
|
|
if (!enabled || e.button !== 0) return
|
|
// Touch scroll on empty surface must not wipe mobile selection.
|
|
if (e.pointerType === "touch") return
|
|
const target = e.target as HTMLElement
|
|
if (shouldIgnoreDriveMarqueeStart(target)) return
|
|
|
|
const additive = e.ctrlKey || e.metaKey || e.shiftKey
|
|
const baseSelection = additive ? new Set(selectedPaths) : new Set<string>()
|
|
if (!additive) clearSelection()
|
|
|
|
dragRef.current = {
|
|
startX: e.clientX,
|
|
startY: e.clientY,
|
|
additive,
|
|
baseSelection,
|
|
}
|
|
|
|
const update = (clientX: number, clientY: number) => {
|
|
const state = dragRef.current
|
|
if (!state) return
|
|
const left = Math.min(state.startX, clientX)
|
|
const top = Math.min(state.startY, clientY)
|
|
const width = Math.abs(clientX - state.startX)
|
|
const height = Math.abs(clientY - state.startY)
|
|
const rect = { left, top, width, height }
|
|
setMarquee(rect)
|
|
const hit = pathsInMarqueeRect(cardRefs.current, rect)
|
|
if (state.additive) {
|
|
setSelectedPaths([...state.baseSelection, ...hit])
|
|
} else {
|
|
setSelectedPaths(hit)
|
|
}
|
|
}
|
|
|
|
update(e.clientX, e.clientY)
|
|
|
|
const onMove = (ev: PointerEvent) => update(ev.clientX, ev.clientY)
|
|
const onUp = () => {
|
|
dragRef.current = null
|
|
setMarquee(null)
|
|
window.removeEventListener("pointermove", onMove)
|
|
window.removeEventListener("pointerup", onUp)
|
|
}
|
|
window.addEventListener("pointermove", onMove)
|
|
window.addEventListener("pointerup", onUp)
|
|
},
|
|
[clearSelection, enabled, selectedPaths, setSelectedPaths]
|
|
)
|
|
|
|
return { registerCardRef, onSurfacePointerDown, marquee }
|
|
}
|