ultisuite-client/lib/drive/drive-file-icon.tsx
R3D347HR4Y 918ce6e348
Some checks are pending
E2E / Playwright e2e (push) Waiting to run
feat(cloud-integration): add external URL handling for mounted cloud files
- Introduced `driveMountExternalURLApiPath` function to generate API paths for external file URLs.
- Enhanced `DriveFileInfo` interface with new properties for cloud mount providers and external URLs.
- Implemented functions to determine if a mounted file should open externally and to resolve external URLs.
- Updated existing components to utilize the new external URL functionality for improved user experience when opening cloud documents.
2026-06-13 13:44:37 +02:00

145 lines
3.9 KiB
TypeScript

import { Icon } from "@iconify/react"
import type { DriveFileInfo } from "@/lib/api/types"
import { classifyDriveFile, type DriveMimeCategory } from "@/lib/drive/drive-filters"
import { mountCloudSuiteIcon } from "@/lib/drive/cloud-native-open"
import { cn } from "@/lib/utils"
export type DriveIconSize = "sm" | "md" | "lg"
const SIZE_CLASS: Record<DriveIconSize, string> = {
sm: "h-4 w-4",
md: "h-5 w-5",
lg: "h-10 w-10",
}
const FOLDER_COLOR = "text-amber-500"
const MIME_ICON: Record<DriveMimeCategory, { icon: string; color: string }> = {
folder: { icon: "mdi:folder", color: FOLDER_COLOR },
document: { icon: "mdi:file-document", color: "text-blue-600" },
spreadsheet: { icon: "mdi:file-excel", color: "text-green-600" },
presentation: { icon: "mdi:file-powerpoint", color: "text-amber-600" },
image: { icon: "mdi:file-image", color: "text-rose-500" },
pdf: { icon: "mdi:file-pdf-box", color: "text-red-600" },
video: { icon: "mdi:file-video", color: "text-red-500" },
audio: { icon: "mdi:file-music", color: "text-red-500" },
archive: { icon: "mdi:folder-zip", color: "text-[#5f6368]" },
other: { icon: "mdi:file", color: "text-blue-500" },
}
const SHARED_FOLDER_ICON = { icon: "mdi:folder-account", color: FOLDER_COLOR }
export type DriveFolderIconOptions = {
/** True when browsing the “Partagés avec moi” tree or a folder inside it. */
inSharedView?: boolean
}
export function isDriveSharedFolder(
file: DriveFileInfo,
options?: DriveFolderIconOptions
): boolean {
if (file.type !== "directory") return false
return Boolean(file.is_shared || options?.inSharedView)
}
export function driveMimeCategoryFor(file: DriveFileInfo): DriveMimeCategory {
return classifyDriveFile(file)
}
export function driveFolderIconMeta(file: DriveFileInfo, options?: DriveFolderIconOptions) {
return isDriveSharedFolder(file, options) ? SHARED_FOLDER_ICON : MIME_ICON.folder
}
export function driveMimeIconMeta(category: DriveMimeCategory) {
return MIME_ICON[category]
}
export function driveIconColor(file: DriveFileInfo, options?: DriveFolderIconOptions) {
const category = driveMimeCategoryFor(file)
if (category === "folder") {
return driveFolderIconMeta(file, options).color
}
return driveMimeIconMeta(category).color
}
export function DriveFolderIcon({
file,
inSharedView,
size = "sm",
className,
}: {
file: DriveFileInfo
inSharedView?: boolean
size?: DriveIconSize
className?: string
}) {
const { icon, color } = driveFolderIconMeta(file, { inSharedView })
return (
<span data-drive-type-icon className="inline-flex shrink-0">
<Icon
icon={icon}
className={cn(SIZE_CLASS[size], "shrink-0", color, className)}
aria-hidden
/>
</span>
)
}
export function DriveMimeCategoryIcon({
category,
size = "sm",
className,
}: {
category: DriveMimeCategory
size?: DriveIconSize
className?: string
}) {
const { icon, color } = driveMimeIconMeta(category)
return (
<span data-drive-type-icon className="inline-flex shrink-0">
<Icon
icon={icon}
className={cn(SIZE_CLASS[size], "shrink-0", color, className)}
aria-hidden
/>
</span>
)
}
export function DriveFileTypeIcon({
file,
inSharedView,
size = "sm",
className,
}: {
file: DriveFileInfo
inSharedView?: boolean
size?: DriveIconSize
className?: string
}) {
const category = driveMimeCategoryFor(file)
if (category === "folder") {
return (
<DriveFolderIcon
file={file}
inSharedView={inSharedView}
size={size}
className={className}
/>
)
}
const suiteIcon = mountCloudSuiteIcon(file)
if (suiteIcon) {
return (
<span data-drive-type-icon className="inline-flex shrink-0">
<Icon
icon={suiteIcon}
className={cn(SIZE_CLASS[size], "shrink-0", className)}
aria-hidden
/>
</span>
)
}
return <DriveMimeCategoryIcon category={category} size={size} className={className} />
}