import { FolderFill, FolderSymlinkFill, FileEarmark, FiletypeExe, FileEarmarkBinary, } from "react-bootstrap-icons"; import { ScrollArea } from "@/components/ui/scroll-area"; import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger, ContextMenuSeparator, ContextMenuLabel, } from "@/components/ui/context-menu"; import { TextTooltip } from "./text-tooltip"; export enum FolderElementType { Folder = 0, File, } export interface FolderElement { name: string; type: FolderElementType; } type ClickHandler = (element: FolderElement) => void; type CreateFolderHandler = () => void; type RemoveElementHandler = (element: FolderElement) => void; type RenameElementHandler = (element: FolderElement) => void; type DownloadElementHandler = (element: FolderElement) => void; type AddFilesHandler = () => void; type IconReader = (element: FolderElement) => string | null; export interface FolderProps { elements: FolderElement[]; iconReader: IconReader; clickHandler: ClickHandler; createFolderHandler: CreateFolderHandler; removeElementHandler: RemoveElementHandler; renameElementHandler: RenameElementHandler; downloadElementHandler: DownloadElementHandler; addFilesHandler: AddFilesHandler; } function elementComparator(e1: FolderElement, e2: FolderElement) { if (e1.type != e2.type) { return e1.type - e2.type; } return e1.name.localeCompare(e2.name); } function getIcon( element: FolderElement, iconReader: IconReader, className: string = "", ) { const icon = iconReader(element); if (icon) { return (
); } switch (element.type) { case FolderElementType.File: if (element.name.endsWith(".dll")) { return ; } if (element.name.endsWith(".exe")) { return ; } return ; case FolderElementType.Folder: return element.name == ".." ? ( ) : ( ); default: return <>; } } function renderIcon(element: FolderElement, iconReader: IconReader) { let className = "w-11 h-11 flex-1"; return getIcon(element, iconReader, className); } function renderElement(element: FolderElement, props: FolderProps) { return (
props.clickHandler(element)} className="folder-element cursor-default select-none flex flex-col gap-2 items-center text-center text-xs p-2 m-2 w-27 h-25 rounded-lg border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50" > {renderIcon(element, props.iconReader)} {element.name}
); } export function trimFilename(filename: string, limit = 25) { if (limit < 4) { limit = 4; } if (filename.length < limit) { return filename; } return filename.substring(0, limit - 3) + "..."; } function renderElementWithContext(element: FolderElement, props: FolderProps) { if (element.name == "..") { return renderElement(element, props); } return ( {renderElement(element, props)} {trimFilename(element.name)} {element.type != FolderElementType.File ? ( <> ) : ( props.downloadElementHandler(element)} > Download )} props.renameElementHandler(element)}> Rename props.removeElementHandler(element)}> Delete ); } function renderElementWrapper(element: FolderElement, props: FolderProps) { return (
{renderElementWithContext(element, props)}
); } export function Folder(props: FolderProps) { return (
{props.elements .sort(elementComparator) .map((e) => renderElementWrapper(e, props))}
Create new Folder Add Files
); }