/* eslint-disable @typescript-eslint/naming-convention */ import React, { useContext, useEffect, useState } from 'react' import { useDropzone } from 'react-dropzone' import { useAtomValue, useSetAtom } from 'jotai' import { UploadCloudIcon } from 'lucide-react' import { twMerge } from 'tailwind-merge' import GenerateResponse from '@/containers/Loader/GenerateResponse' import ModelReload from '@/containers/Loader/ModelReload' import ModelStart from '@/containers/Loader/ModelStart' import { currentPromptAtom, fileUploadAtom } from '@/containers/Providers/Jotai' import { showLeftSideBarAtom } from '@/containers/Providers/KeyListener' import { snackbar } from '@/containers/Toast' import { FeatureToggleContext } from '@/context/FeatureToggle' import { activeModelAtom, loadModelErrorAtom } from '@/hooks/useActiveModel' import { queuedMessageAtom, reloadModelAtom } from '@/hooks/useSendChatMessage' import ChatBody from '@/screens/Chat/ChatBody' import ThreadList from '@/screens/Chat/ThreadList' import ChatInput from './ChatInput' import LoadModelErrorMessage from './LoadModelErrorMessage' import RequestDownloadModel from './RequestDownloadModel' import Sidebar from './Sidebar' import { activeThreadAtom, engineParamsUpdateAtom, isGeneratingResponseAtom, } from '@/helpers/atoms/Thread.atom' const renderError = (code: string) => { switch (code) { case 'multiple-upload': return 'Currently, we only support 1 attachment at the same time' case 'retrieval-off': return 'Turn on Retrieval in Assistant Settings to use this feature' case 'file-invalid-type': return 'We do not support this file type' default: return 'Oops, something error, please try again.' } } const ChatScreen: React.FC = () => { const setCurrentPrompt = useSetAtom(currentPromptAtom) const activeThread = useAtomValue(activeThreadAtom) const showLeftSideBar = useAtomValue(showLeftSideBarAtom) const engineParamsUpdate = useAtomValue(engineParamsUpdateAtom) const [dragOver, setDragOver] = useState(false) const queuedMessage = useAtomValue(queuedMessageAtom) const reloadModel = useAtomValue(reloadModelAtom) const [dragRejected, setDragRejected] = useState({ code: '' }) const setFileUpload = useSetAtom(fileUploadAtom) const { experimentalFeature } = useContext(FeatureToggleContext) const activeModel = useAtomValue(activeModelAtom) const isGeneratingResponse = useAtomValue(isGeneratingResponseAtom) const loadModelError = useAtomValue(loadModelErrorAtom) const { getRootProps, isDragReject } = useDropzone({ noClick: true, multiple: false, accept: { 'application/pdf': ['.pdf'], }, onDragOver: (e) => { // Retrieval file drag and drop is experimental feature if (!experimentalFeature) return if ( e.dataTransfer.items.length === 1 && activeThread?.assistants[0].tools && activeThread?.assistants[0].tools[0]?.enabled ) { setDragOver(true) } else if ( activeThread?.assistants[0].tools && !activeThread?.assistants[0].tools[0]?.enabled ) { setDragRejected({ code: 'retrieval-off' }) } else { setDragRejected({ code: 'multiple-upload' }) } }, onDragLeave: () => setDragOver(false), onDrop: (files, rejectFiles) => { // Retrieval file drag and drop is experimental feature if (!experimentalFeature) return if ( !files || files.length !== 1 || rejectFiles.length !== 0 || (activeThread?.assistants[0].tools && !activeThread?.assistants[0].tools[0]?.enabled) ) return const imageType = files[0]?.type.includes('image') setFileUpload([{ file: files[0], type: imageType ? 'image' : 'pdf' }]) setDragOver(false) if (imageType) { setCurrentPrompt('What do you see in this image?') } else { setCurrentPrompt('Summarize this for me') } }, onDropRejected: (e) => { if ( activeThread?.assistants[0].tools && !activeThread?.assistants[0].tools[0]?.enabled ) { setDragRejected({ code: 'retrieval-off' }) } else { setDragRejected({ code: e[0].errors[0].code }) } setDragOver(false) }, }) useEffect(() => { if (dragRejected.code) { snackbar({ description: renderError(dragRejected.code), type: 'error', }) } setTimeout(() => { if (dragRejected.code) { setDragRejected({ code: '' }) } }, 2000) }, [dragRejected.code]) return (
(PDF)
}