import { ChatbotUIContext } from "@/context/context" import { getFileFromStorage } from "@/db/storage/files" import useHotkey from "@/lib/hooks/use-hotkey" import { cn } from "@/lib/utils" import { ChatFile, MessageImage } from "@/types" import { IconCircleFilled, IconFileFilled, IconFileTypeCsv, IconFileTypeDocx, IconFileTypePdf, IconFileTypeTxt, IconJson, IconLoader2, IconMarkdown, IconX } from "@tabler/icons-react" import Image from "next/image" import { FC, useContext, useState } from "react" import { Button } from "../ui/button" import { FilePreview } from "../ui/file-preview" import { WithTooltip } from "../ui/with-tooltip" import { ChatRetrievalSettings } from "./chat-retrieval-settings" interface ChatFilesDisplayProps {} export const ChatFilesDisplay: FC = ({}) => { useHotkey("f", () => setShowFilesDisplay(prev => !prev)) useHotkey("e", () => setUseRetrieval(prev => !prev)) const { files, newMessageImages, setNewMessageImages, newMessageFiles, setNewMessageFiles, setShowFilesDisplay, showFilesDisplay, chatFiles, chatImages, setChatImages, setChatFiles, setUseRetrieval } = useContext(ChatbotUIContext) const [selectedFile, setSelectedFile] = useState(null) const [selectedImage, setSelectedImage] = useState(null) const [showPreview, setShowPreview] = useState(false) const messageImages = [ ...newMessageImages.filter( image => !chatImages.some(chatImage => chatImage.messageId === image.messageId) ) ] const combinedChatFiles = [ ...newMessageFiles.filter( file => !chatFiles.some(chatFile => chatFile.id === file.id) ), ...chatFiles ] const combinedMessageFiles = [...messageImages, ...combinedChatFiles] const getLinkAndView = async (file: ChatFile) => { const fileRecord = files.find(f => f.id === file.id) if (!fileRecord) return const link = await getFileFromStorage(fileRecord.file_path) window.open(link, "_blank") } return showFilesDisplay && combinedMessageFiles.length > 0 ? ( <> {showPreview && selectedImage && ( { setShowPreview(isOpen) setSelectedImage(null) }} /> )} {showPreview && selectedFile && ( { setShowPreview(isOpen) setSelectedFile(null) }} /> )}
{messageImages.map((image, index) => (
File image { setSelectedImage(image) setShowPreview(true) }} /> { e.stopPropagation() setNewMessageImages( newMessageImages.filter( f => f.messageId !== image.messageId ) ) setChatImages( chatImages.filter(f => f.messageId !== image.messageId) ) }} />
))} {combinedChatFiles.map((file, index) => file.id === "loading" ? (
{file.name}
{file.type}
) : (
getLinkAndView(file)} >
{(() => { let fileExtension = file.type.includes("/") ? file.type.split("/")[1] : file.type switch (fileExtension) { case "pdf": return case "markdown": return case "txt": return case "json": return case "csv": return case "docx": return default: return } })()}
{file.name}
{ e.stopPropagation() setNewMessageFiles( newMessageFiles.filter(f => f.id !== file.id) ) setChatFiles(chatFiles.filter(f => f.id !== file.id)) }} />
) )}
) : ( combinedMessageFiles.length > 0 && (
) ) } const RetrievalToggle = ({}) => { const { useRetrieval, setUseRetrieval } = useContext(ChatbotUIContext) return (
{useRetrieval ? "File retrieval is enabled on the selected files for this message. Click the indicator to disable." : "Click the indicator to enable file retrieval for this message."}
} trigger={ { e.stopPropagation() setUseRetrieval(prev => !prev) }} /> } /> ) }