You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
memos/web/src/components/ResourceIcon.tsx

83 lines
2.7 KiB
TypeScript

import clsx from "clsx";
import {
BinaryIcon,
BookIcon,
FileArchiveIcon,
FileAudioIcon,
FileEditIcon,
FileIcon,
FileTextIcon,
FileVideo2Icon,
SheetIcon,
} from "lucide-react";
import React from "react";
import { Resource } from "@/types/proto/api/v1/resource_service";
import { getResourceType, getResourceUrl } from "@/utils/resource";
import showPreviewImageDialog from "./PreviewImageDialog";
import SquareDiv from "./kit/SquareDiv";
interface Props {
resource: Resource;
className?: string;
strokeWidth?: number;
}
const ResourceIcon = (props: Props) => {
const { resource } = props;
const resourceType = getResourceType(resource);
const resourceUrl = getResourceUrl(resource);
const className = clsx("w-full h-auto", props.className);
const strokeWidth = props.strokeWidth;
const previewResource = () => {
window.open(resourceUrl);
};
if (resourceType === "image/*") {
return (
<SquareDiv className={clsx(className, "flex items-center justify-center overflow-clip")}>
<img
className="min-w-full min-h-full object-cover"
src={resource.externalLink ? resourceUrl : resourceUrl + "?thumbnail=true"}
onClick={() => showPreviewImageDialog(resourceUrl)}
decoding="async"
loading="lazy"
/>
</SquareDiv>
);
}
const getResourceIcon = () => {
switch (resourceType) {
case "video/*":
return <FileVideo2Icon strokeWidth={strokeWidth} className="w-full h-auto" />;
case "audio/*":
return <FileAudioIcon strokeWidth={strokeWidth} className="w-full h-auto" />;
case "text/*":
return <FileTextIcon strokeWidth={strokeWidth} className="w-full h-auto" />;
case "application/epub+zip":
return <BookIcon strokeWidth={strokeWidth} className="w-full h-auto" />;
case "application/pdf":
return <BookIcon strokeWidth={strokeWidth} className="w-full h-auto" />;
case "application/msword":
return <FileEditIcon strokeWidth={strokeWidth} className="w-full h-auto" />;
case "application/msexcel":
return <SheetIcon strokeWidth={strokeWidth} className="w-full h-auto" />;
case "application/zip":
return <FileArchiveIcon onClick={previewResource} strokeWidth={strokeWidth} className="w-full h-auto" />;
case "application/x-java-archive":
return <BinaryIcon strokeWidth={strokeWidth} className="w-full h-auto" />;
default:
return <FileIcon strokeWidth={strokeWidth} className="w-full h-auto" />;
}
};
return (
<div onClick={previewResource} className={clsx(className, "max-w-[4rem] opacity-50")}>
{getResourceIcon()}
</div>
);
};
export default React.memo(ResourceIcon);