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 */}
{/* Bot Message (pre-stream with spinner) */}
openRightSidebar("tasks", blockId)}
>
{thoughtLabel}
) : (
// Render without spinner (user message only)
)
) : (
// Render Full Chat Message
{/* User Message */}
{/* Bot Message */}
{!isError && renderThoughtLabel() && (
openRightSidebar("tasks", blockId)}
>
{renderThoughtLabel()}
)}
{renderSourcesRead() !== null && (
Sources Read: {renderSourcesRead()}
)}
{!isStreaming && (
Copy
)}
{actions && actions.some(a => a.name === "evaluate") && (
openRightSidebar("evaluate", blockId)}>
Evaluate
)}
{actions && actions.some(a => a.name === "sources") && (
openRightSidebar("sources", blockId)}>
Sources
)}
{actions && actions.some(a => a.name === "graph") && (
setGraphDialogOpen(true)}>
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 && (
)}
}
/>
>
);
}
export default ChatWindow;