155 lines
6.4 KiB
TypeScript
155 lines
6.4 KiB
TypeScript
import { Download, ExternalLink, Maximize } from "lucide-react";
|
|
import { AspectRatio } from "~/components/ui/aspect-ratio"; // Shadcn UI AspectRatio
|
|
import { Button } from "~/components/ui/button"; // Shadcn UI Button
|
|
import {
|
|
Dialog,
|
|
DialogClose,
|
|
DialogContent,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "~/components/ui/dialog"; // Shadcn UI Dialog
|
|
import {
|
|
Tooltip,
|
|
TooltipContent,
|
|
TooltipProvider,
|
|
TooltipTrigger,
|
|
} from "~/components/ui/tooltip"; // Shadcn UI Tooltip
|
|
import type { UploadedFile } from "~/lib/api/types"; // Adjust path as needed
|
|
import { formatFileSize } from "~/lib/utils"; // Adjust path
|
|
import { FileIcon } from "./file-icon";
|
|
|
|
interface ChatMessageAttachmentProps {
|
|
file: UploadedFile;
|
|
}
|
|
|
|
export default function ChatMessageAttachment({
|
|
file,
|
|
}: ChatMessageAttachmentProps) {
|
|
if (file.contentType.startsWith("image/")) {
|
|
return <ImageAttachment file={file} />;
|
|
}
|
|
return <GenericFileAttachment file={file} />;
|
|
}
|
|
|
|
function GenericFileAttachment({ file }: ChatMessageAttachmentProps) {
|
|
return (
|
|
<TooltipProvider delayDuration={100}>
|
|
<div className="flex items-center gap-3 rounded-lg border bg-card p-3 shadow-sm ">
|
|
<div className="flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-md">
|
|
<FileIcon
|
|
className="h-8 w-8 text-muted-foreground"
|
|
contentType={file.contentType}
|
|
/>
|
|
</div>
|
|
<div className="flex-1 overflow-hidden">
|
|
<p className="truncate text-sm font-medium text-card-foreground">
|
|
{file.filename}
|
|
</p>
|
|
<p className="text-xs text-muted-foreground">
|
|
{formatFileSize(file.size)}
|
|
</p>
|
|
</div>
|
|
<div className="flex items-center gap-1">
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Button variant="ghost" size="icon" asChild>
|
|
<a
|
|
href={file.url}
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
download={file.filename}
|
|
>
|
|
<Download className="h-4 w-4" />
|
|
<span className="sr-only">Download</span>
|
|
</a>
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent>Download</TooltipContent>
|
|
</Tooltip>
|
|
<Tooltip>
|
|
<TooltipTrigger asChild>
|
|
<Button variant="ghost" size="icon" asChild>
|
|
<a
|
|
href={file.url}
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
>
|
|
<ExternalLink className="h-4 w-4" />
|
|
<span className="sr-only">
|
|
Open in new tab
|
|
</span>
|
|
</a>
|
|
</Button>
|
|
</TooltipTrigger>
|
|
<TooltipContent>Open in new tab</TooltipContent>
|
|
</Tooltip>
|
|
</div>
|
|
</div>
|
|
</TooltipProvider>
|
|
);
|
|
}
|
|
|
|
function ImageAttachment({ file }: ChatMessageAttachmentProps) {
|
|
return (
|
|
<Dialog>
|
|
<TooltipProvider delayDuration={100}>
|
|
<div className="group relative w-48 cursor-pointer sm:w-64">
|
|
<DialogTrigger asChild>
|
|
<AspectRatio
|
|
ratio={16 / 9}
|
|
className="overflow-hidden rounded-lg border bg-muted"
|
|
>
|
|
<img
|
|
src={file.url}
|
|
alt={file.filename}
|
|
className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
|
|
/>
|
|
<div className="absolute inset-0 flex items-center justify-center bg-black/30 opacity-0 transition-opacity group-hover:opacity-100">
|
|
<Maximize className="h-8 w-8 text-white" />
|
|
</div>
|
|
</AspectRatio>
|
|
</DialogTrigger>
|
|
<div className="mt-1">
|
|
<p className="truncate text-xs text-muted-foreground">
|
|
{file.filename} ({formatFileSize(file.size)})
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</TooltipProvider>
|
|
|
|
<DialogContent className="max-w-3xl p-0">
|
|
<DialogHeader className="p-4 pb-0">
|
|
<DialogTitle className="truncate">
|
|
{file.filename}
|
|
</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="p-4 pt-0 max-h-[70vh] overflow-y-auto">
|
|
<img
|
|
src={file.url}
|
|
alt={file.filename}
|
|
className="mx-auto max-h-full w-auto rounded-md object-contain"
|
|
/>
|
|
</div>
|
|
<DialogFooter className="flex-col items-stretch gap-2 border-t p-4 sm:flex-row sm:justify-end sm:space-x-2">
|
|
<Button variant="outline" asChild>
|
|
<a href={file.url} target="_blank" rel="noreferrer">
|
|
<ExternalLink className="mr-2 h-4 w-4" /> Open
|
|
original
|
|
</a>
|
|
</Button>
|
|
<Button asChild>
|
|
<a href={file.url} download={file.filename}>
|
|
<Download className="mr-2 h-4 w-4" /> Download
|
|
</a>
|
|
</Button>
|
|
<DialogClose asChild>
|
|
<Button variant="ghost">Close</Button>
|
|
</DialogClose>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|