import React, { useRef, useState, useEffect } from 'react'; import Box from '@mui/material/Box'; import Snackbar from '@mui/material/Snackbar'; import Slide from '@mui/material/Slide'; import IconButton from '@mui/material/IconButton'; import { FaTimes } from 'react-icons/fa'; import GraphDialog from './ChatComponents/Graph'; import Streaming from './ChatComponents/Streaming'; import './ChatWindow.css'; import bot from '../../Icons/bot.png'; import copy from '../../Icons/copy.png'; import evaluate from '../../Icons/evaluate.png'; import sourcesIcon from '../../Icons/sources.png'; import graphIcon from '../../Icons/graph.png'; import user from '../../Icons/user.png'; // SlideTransition function for both entry and exit transitions. function SlideTransition(props) { return ; } function ChatWindow({ blockId, userMessage, tokenChunks, aiAnswer, thinkingTime, thoughtLabel, sourcesRead, actions, tasks, openRightSidebar, // openLeftSidebar, isError, errorMessage }) { const answerRef = useRef(null); const [graphDialogOpen, setGraphDialogOpen] = useState(false); const [snackbarOpen, setSnackbarOpen] = useState(false); // Get the graph action from the actions prop. const graphAction = actions && actions.find(a => a.name === "graph"); // Handler for copying answer to clipboard. const handleCopy = () => { if (answerRef.current) { const textToCopy = answerRef.current.innerText || answerRef.current.textContent; navigator.clipboard.writeText(textToCopy) .then(() => { console.log('Copied to clipboard:', textToCopy); setSnackbarOpen(true); }) .catch((err) => console.error('Failed to copy text:', err)); } }; // Snackbar close handler const handleSnackbarClose = (event, reason) => { if (reason === 'clickaway') return; setSnackbarOpen(false); }; // Combine partial chunks (tokenChunks) if present; else fall back to the aiAnswer string. const combinedAnswer = (tokenChunks && tokenChunks.length > 0) ? tokenChunks.join("") : aiAnswer; const hasTokens = combinedAnswer && combinedAnswer.length > 0; // Assume streaming is in progress if thinkingTime is not set. const isStreaming = thinkingTime === null || thinkingTime === undefined; // Helper to render the thought label. const renderThoughtLabel = () => { if (!hasTokens) { return thoughtLabel; } else { if (thoughtLabel && thoughtLabel.startsWith("Thought and searched for")) { return thoughtLabel; } return null; } }; // Helper to render sources read. const renderSourcesRead = () => { if (!sourcesRead && sourcesRead !== 0) return null; return sourcesRead; }; // When tasks first appear, automatically open the sidebar. const prevTasksRef = useRef(tasks); useEffect(() => { if (prevTasksRef.current.length === 0 && tasks && tasks.length > 0) { openRightSidebar("tasks", blockId); } prevTasksRef.current = tasks; }, [tasks, blockId, openRightSidebar]); // Handle getting the reference to the content for copy functionality const handleContentRef = (ref) => { answerRef.current = ref; }; return ( <> { !hasTokens ? ( // If no tokens, render pre-stream UI. (!isError && thoughtLabel) ? (
{/* User Message */}

{userMessage}

user icon
{/* Bot Message (pre-stream with spinner) */}
openRightSidebar("tasks", blockId)} > {thoughtLabel}
) : ( // Render without spinner (user message only)

{userMessage}

user icon
) ) : ( // Render Full Chat Message
{/* User Message */}

{userMessage}

user icon
{/* Bot Message */}
{!isError && renderThoughtLabel() && (
openRightSidebar("tasks", blockId)} > {renderThoughtLabel()}
)} {renderSourcesRead() !== null && (

Sources Read: {renderSourcesRead()}

)}
bot icon
{!isStreaming && (
copy icon Copy
)} {actions && actions.some(a => a.name === "evaluate") && (
openRightSidebar("evaluate", blockId)}> evaluate icon Evaluate
)} {actions && actions.some(a => a.name === "sources") && (
openRightSidebar("sources", blockId)}> sources icon Sources
)} {actions && actions.some(a => a.name === "graph") && (
setGraphDialogOpen(true)}> graph icon View Graph
)}
{/* Render the GraphDialog when graphDialogOpen is true */} {graphDialogOpen && ( setGraphDialogOpen(false)} payload={graphAction ? graphAction.payload : { query: userMessage }} /> )}
)} {/* Render error container if there's an error */} {isError && (

Error

{errorMessage}

)} } /> ); } export default ChatWindow;