refactor chat component

This commit is contained in:
Ramnique Singh 2025-07-30 23:46:15 +05:30
parent ca3c80e96d
commit faef91f0a1

View file

@ -42,6 +42,7 @@ export function Chat({
const [showSuccessMessage, setShowSuccessMessage] = useState(false); const [showSuccessMessage, setShowSuccessMessage] = useState(false);
// Add state for explain (no modal needed, just direct trigger) // Add state for explain (no modal needed, just direct trigger)
const [showExplainSuccess, setShowExplainSuccess] = useState(false); const [showExplainSuccess, setShowExplainSuccess] = useState(false);
const [pendingFixIndex, setPendingFixIndex] = useState<number | null>(null);
// --- Scroll/auto-scroll/unread bubble logic --- // --- Scroll/auto-scroll/unread bubble logic ---
const scrollContainerRef = useRef<HTMLDivElement>(null); const scrollContainerRef = useRef<HTMLDivElement>(null);
@ -49,6 +50,15 @@ export function Chat({
const [autoScroll, setAutoScroll] = useState(true); const [autoScroll, setAutoScroll] = useState(true);
const [showUnreadBubble, setShowUnreadBubble] = useState(false); const [showUnreadBubble, setShowUnreadBubble] = useState(false);
// collect published tool call results
const toolCallResults: Record<string, z.infer<typeof ToolMessage>> = {};
optimisticMessages
.filter((message) => message.role == 'tool')
.forEach((message) => {
toolCallResults[message.toolCallId] = message;
});
const handleScroll = useCallback(() => { const handleScroll = useCallback(() => {
const container = scrollContainerRef.current; const container = scrollContainerRef.current;
if (!container) return; if (!container) return;
@ -58,18 +68,6 @@ export function Chat({
if (atBottom) setShowUnreadBubble(false); if (atBottom) setShowUnreadBubble(false);
}, []); }, []);
useEffect(() => {
const container = scrollContainerRef.current;
if (!container) return;
if (autoScroll) {
container.scrollTop = container.scrollHeight;
setShowUnreadBubble(false);
} else {
setShowUnreadBubble(true);
}
}, [optimisticMessages, loadingAssistantResponse, autoScroll]);
// --- End scroll/auto-scroll logic ---
const getCopyContent = useCallback(() => { const getCopyContent = useCallback(() => {
return JSON.stringify({ return JSON.stringify({
messages, messages,
@ -78,18 +76,7 @@ export function Chat({
}, null, 2); }, null, 2);
}, [messages, lastAgenticRequest, lastAgenticResponse]); }, [messages, lastAgenticRequest, lastAgenticResponse]);
// Expose copy function to parent
useEffect(() => {
onCopyClick(getCopyContent);
}, [getCopyContent, onCopyClick]);
// reset optimistic messages when messages change
useEffect(() => {
setOptimisticMessages(messages);
}, [messages]);
// Handle fix functionality // Handle fix functionality
const [pendingFixIndex, setPendingFixIndex] = useState<number | null>(null);
const handleFix = useCallback((message: string, index: number) => { const handleFix = useCallback((message: string, index: number) => {
setPendingFixMessage(message); setPendingFixMessage(message);
setPendingFixIndex(index); setPendingFixIndex(index);
@ -144,13 +131,14 @@ export function Chat({
} }
}, [projectId, triggerCopilotChat]); }, [projectId, triggerCopilotChat]);
// collect published tool call results // Add a stop handler function
const toolCallResults: Record<string, z.infer<typeof ToolMessage>> = {}; const handleStop = useCallback(() => {
optimisticMessages if (eventSourceRef.current) {
.filter((message) => message.role == 'tool') eventSourceRef.current.close();
.forEach((message) => { eventSourceRef.current = null;
toolCallResults[message.toolCallId] = message; setLoadingAssistantResponse(false);
}); }
}, []);
function handleUserMessage(prompt: string) { function handleUserMessage(prompt: string) {
const updatedMessages: z.infer<typeof Message>[] = [...messages, { const updatedMessages: z.infer<typeof Message>[] = [...messages, {
@ -162,6 +150,27 @@ export function Chat({
setIsLastInteracted(true); setIsLastInteracted(true);
} }
useEffect(() => {
const container = scrollContainerRef.current;
if (!container) return;
if (autoScroll) {
container.scrollTop = container.scrollHeight;
setShowUnreadBubble(false);
} else {
setShowUnreadBubble(true);
}
}, [optimisticMessages, loadingAssistantResponse, autoScroll]);
// Expose copy function to parent
useEffect(() => {
onCopyClick(getCopyContent);
}, [getCopyContent, onCopyClick]);
// reset optimistic messages when messages change
useEffect(() => {
setOptimisticMessages(messages);
}, [messages]);
// reset state when workflow changes // reset state when workflow changes
useEffect(() => { useEffect(() => {
setMessages([]); setMessages([]);
@ -187,7 +196,7 @@ export function Chat({
// Reset request/response state before making new request // Reset request/response state before making new request
setLastAgenticRequest(null); setLastAgenticRequest(null);
setLastAgenticResponse(null); setLastAgenticResponse(null);
let streamId: string | null = null; let streamId: string | null = null;
try { try {
const response = await getAssistantResponseStreamId( const response = await getAssistantResponseStreamId(
@ -202,7 +211,7 @@ export function Chat({
setBillingError(response.billingError); setBillingError(response.billingError);
setFetchResponseError(response.billingError); setFetchResponseError(response.billingError);
setLoadingAssistantResponse(false); setLoadingAssistantResponse(false);
console.log('returning from getAssistantResponseStreamId due to billing error'); console.log('returning from getAssistantResponseStreamId due to billing error');
return; return;
} }
streamId = response.streamId; streamId = response.streamId;
@ -313,15 +322,6 @@ export function Chat({
fetchResponseError, fetchResponseError,
]); ]);
// Add a stop handler function
const handleStop = useCallback(() => {
if (eventSourceRef.current) {
eventSourceRef.current.close();
eventSourceRef.current = null;
setLoadingAssistantResponse(false);
}
}, []);
return ( return (
<div className="w-11/12 max-w-6xl mx-auto h-full flex flex-col relative"> <div className="w-11/12 max-w-6xl mx-auto h-full flex flex-col relative">
<div className="sticky top-0 z-10 bg-white dark:bg-zinc-900 pt-4 pb-4"> <div className="sticky top-0 z-10 bg-white dark:bg-zinc-900 pt-4 pb-4">