ultisuite-client/components/drive/file-browser.tsx
R3D347HR4Y d6d18f911b
Some checks failed
E2E / Playwright e2e (push) Has been cancelled
Lots of stuff and mobile app
2026-06-17 00:13:28 +02:00

173 lines
5.7 KiB
TypeScript

"use client"
import { useRouter } from "next/navigation"
import { FileThumbnail } from "@/components/drive/file-thumbnail"
import { DriveGridView } from "@/components/drive/drive-grid-view"
import { DriveListModified } from "@/components/drive/drive-list-modified"
import { DriveFileContextMenu } from "@/components/drive/drive-file-context-menu"
import type { DriveFileInfo } from "@/lib/api/types"
import { useDriveSettingsStore } from "@/lib/stores/drive-settings-store"
import { openDriveItem } from "@/lib/drive/drive-open-item"
import { useDriveMutations } from "@/lib/api/hooks/use-drive-queries"
import { pathRefFromRoute, type DrivePathRef } from "@/lib/api/drive-roots"
import type { DriveView } from "@/lib/drive/drive-url"
import type { PublicShareThumbContext } from "@/lib/api/hooks/use-public-share-preview-thumb"
import { useDriveUIStore } from "@/lib/stores/drive-ui-store"
import {
displayFileBaseName,
displayFileFormatLabel,
} from "@/lib/drive/display-file-name"
import { useDriveGridSelection } from "@/lib/hooks/use-drive-grid-selection"
import { DRIVE_CARD_PAD_X } from "@/lib/drive/drive-chrome-classes"
import { useDriveRouteRoot } from "@/lib/drive/drive-route-context"
import { cn } from "@/lib/utils"
function formatSize(n: number) {
if (n < 1024) return `${n} o`
if (n < 1024 ** 2) return `${(n / 1024).toFixed(1)} Ko`
return `${(n / 1024 ** 2).toFixed(1)} Mo`
}
export function FileBrowser({
items,
view = "files",
rootId,
pathRef: pathRefProp,
isTrash,
onOpenItem,
mutations: mutationsProp,
allowShare: allowShareProp,
writable = true,
hideFavorite = false,
disableDnd = false,
onDownloadItem,
gridClassName,
publicShare,
}: {
items: DriveFileInfo[]
view?: DriveView
rootId?: string | null
pathRef?: DrivePathRef
isTrash?: boolean
onOpenItem?: (file: DriveFileInfo) => void
mutations?: ReturnType<typeof useDriveMutations>
allowShare?: boolean
writable?: boolean
hideFavorite?: boolean
disableDnd?: boolean
onDownloadItem?: (file: DriveFileInfo) => void
gridClassName?: string
publicShare?: PublicShareThumbContext
}) {
const router = useRouter()
const routeRoot = useDriveRouteRoot()
const viewMode = useDriveSettingsStore((s) => s.viewMode)
const openPreview = useDriveUIStore((s) => s.openPreview)
const pathRef = pathRefProp ?? pathRefFromRoute(view, rootId ?? null, "/")
const mutationsDefault = useDriveMutations(pathRef)
const mutations = mutationsProp ?? mutationsDefault
const openItem = (file: DriveFileInfo) => {
if (onOpenItem) {
onOpenItem(file)
return
}
openDriveItem(file, {
router,
openPreview,
view,
contextItems: items,
isTrash: Boolean(isTrash),
routeRoot,
})
}
const allowShare = allowShareProp ?? view !== "shared"
const { handleItemClick } = useDriveGridSelection(items, true)
if (viewMode === "grid") {
return (
<DriveGridView
items={items}
isTrash={isTrash}
inSharedView={view === "shared"}
allowShare={allowShare}
writable={writable}
hideFavorite={hideFavorite}
disableDnd={disableDnd}
mutations={mutations}
onDownloadItem={onDownloadItem}
gridClassName={gridClassName}
publicShare={publicShare}
onOpen={openItem}
onItemClick={handleItemClick}
/>
)
}
return (
<div>
<div
className={cn(
"sticky top-0 z-10 hidden items-center gap-3 border-b border-border bg-mail-surface pb-2 pt-1 text-xs font-medium text-muted-foreground sm:flex",
DRIVE_CARD_PAD_X
)}
aria-hidden
>
<span className="size-10 shrink-0" />
<span className="min-w-0 flex-1">Nom</span>
<span className="hidden w-16 shrink-0 text-right sm:block">Type</span>
<span className="hidden w-20 shrink-0 text-right sm:block">Taille</span>
<span className="hidden w-36 shrink-0 text-right md:block">Modifié</span>
</div>
<div className="divide-y divide-border">
{items.map((file) => (
<DriveFileContextMenu
key={file.path}
file={file}
allItems={items}
isTrash={isTrash}
allowShare={allowShare}
writable={writable}
hideFavorite={hideFavorite}
disableDnd={disableDnd}
mutations={mutations}
onDownloadRequest={
onDownloadItem ? () => onDownloadItem(file) : undefined
}
onOpen={() => openItem(file)}
onItemClick={handleItemClick}
>
<div
className={cn(
"flex w-full cursor-pointer items-center gap-3 py-2.5 text-left hover:bg-accent/50",
DRIVE_CARD_PAD_X
)}
>
<FileThumbnail
file={file}
variant="list"
inSharedView={view === "shared"}
publicShare={publicShare}
/>
<span className="min-w-0 flex-1 truncate font-medium text-[#3c4043] dark:text-[#e8eaed]">
{displayFileBaseName(file.name, file.type === "directory")}
</span>
<span className="hidden w-16 shrink-0 truncate text-right text-sm text-muted-foreground sm:block">
{displayFileFormatLabel(file.name, file.type === "directory")}
</span>
<span className="hidden w-20 shrink-0 text-right text-sm text-muted-foreground sm:block">
{file.type === "directory" ? "—" : formatSize(file.size)}
</span>
<DriveListModified
iso={file.last_modified}
className="hidden w-36 shrink-0 truncate text-right md:block"
/>
</div>
</DriveFileContextMenu>
))}
</div>
</div>
)
}