Componentize message send, and send message when clicking nudges

This commit is contained in:
Lucas Oliveira 2025-09-05 10:20:17 -03:00
parent 382df1064e
commit 06b3850057

View file

@ -23,6 +23,7 @@ import {
} from "lucide-react"; } from "lucide-react";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useGetNudgesQuery } from "../api/queries/useGetNudgesQuery"; import { useGetNudgesQuery } from "../api/queries/useGetNudgesQuery";
import Nudges from "./nudges";
interface Message { interface Message {
role: "user" | "assistant"; role: "user" | "assistant";
@ -128,7 +129,6 @@ function ChatPage() {
const [dropdownDismissed, setDropdownDismissed] = useState(false); const [dropdownDismissed, setDropdownDismissed] = useState(false);
const [isUserInteracting, setIsUserInteracting] = useState(false); const [isUserInteracting, setIsUserInteracting] = useState(false);
const [isForkingInProgress, setIsForkingInProgress] = useState(false); const [isForkingInProgress, setIsForkingInProgress] = useState(false);
const [lastForkTimestamp, setLastForkTimestamp] = useState<number>(0);
const dragCounterRef = useRef(0); const dragCounterRef = useRef(0);
const messagesEndRef = useRef<HTMLDivElement>(null); const messagesEndRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLTextAreaElement>(null); const inputRef = useRef<HTMLTextAreaElement>(null);
@ -472,7 +472,12 @@ function ChatPage() {
[conversationData.endpoint]: conversationData.response_id, [conversationData.endpoint]: conversationData.response_id,
})); }));
} }
}, [conversationData, isUserInteracting, isForkingInProgress]); }, [
conversationData,
isUserInteracting,
isForkingInProgress,
setPreviousResponseIds,
]);
// Handle new conversation creation - only reset messages when placeholderConversation is set // Handle new conversation creation - only reset messages when placeholderConversation is set
useEffect(() => { useEffect(() => {
@ -1312,13 +1317,12 @@ function ChatPage() {
} }
}; };
const handleSubmit = async (e: React.FormEvent) => { const handleSendMessage = async (inputMessage: string) => {
e.preventDefault(); if (!inputMessage.trim() || loading) return;
if (!input.trim() || loading) return;
const userMessage: Message = { const userMessage: Message = {
role: "user", role: "user",
content: input.trim(), content: inputMessage.trim(),
timestamp: new Date(), timestamp: new Date(),
}; };
@ -1433,6 +1437,11 @@ function ChatPage() {
setLoading(false); setLoading(false);
}; };
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
handleSendMessage(input);
};
const toggleFunctionCall = (functionCallId: string) => { const toggleFunctionCall = (functionCallId: string) => {
setExpandedFunctionCalls((prev) => { setExpandedFunctionCalls((prev) => {
const newSet = new Set(prev); const newSet = new Set(prev);
@ -1456,10 +1465,8 @@ function ChatPage() {
} }
// Set interaction state to prevent auto-scroll interference // Set interaction state to prevent auto-scroll interference
const forkTimestamp = Date.now();
setIsUserInteracting(true); setIsUserInteracting(true);
setIsForkingInProgress(true); setIsForkingInProgress(true);
setLastForkTimestamp(forkTimestamp);
console.log("Fork conversation called for message index:", messageIndex); console.log("Fork conversation called for message index:", messageIndex);
@ -1472,7 +1479,6 @@ function ChatPage() {
console.error("Fork button should only be on assistant messages"); console.error("Fork button should only be on assistant messages");
setIsUserInteracting(false); setIsUserInteracting(false);
setIsForkingInProgress(false); setIsForkingInProgress(false);
setLastForkTimestamp(0);
return; return;
} }
@ -1745,8 +1751,7 @@ function ChatPage() {
}; };
const handleSuggestionClick = (suggestion: string) => { const handleSuggestionClick = (suggestion: string) => {
setInput(suggestion); handleSendMessage(suggestion);
inputRef.current?.focus();
}; };
return ( return (
@ -1962,27 +1967,14 @@ function ChatPage() {
{/* Suggestion chips - always show unless streaming */} {/* Suggestion chips - always show unless streaming */}
{!streamingMessage && ( {!streamingMessage && (
<div className="flex-shrink-0 p-6 pb-4 flex justify-center"> <Nudges
<div className="w-full max-w-[75%] relative"> nudges={nudges as string[]}
<div className="flex gap-2 justify-start overflow-x-auto scrollbar-hide"> handleSuggestionClick={handleSuggestionClick}
{(nudges as string[]).map((suggestion: string, index: number) => ( />
<button
key={index}
onClick={() => handleSuggestionClick(suggestion)}
className="px-4 py-2 bg-muted/30 hover:bg-muted/50 rounded-lg text-sm text-muted-foreground hover:text-foreground transition-colors whitespace-nowrap"
>
{suggestion}
</button>
))}
</div>
{/* Fade out gradient on the right */}
<div className="absolute right-0 top-0 bottom-0 w-8 bg-gradient-to-l from-background to-transparent pointer-events-none"></div>
</div>
</div>
)} )}
{/* Input Area - Fixed at bottom */} {/* Input Area - Fixed at bottom */}
<div className="flex-shrink-0 p-6 pb-8 flex justify-center"> <div className="flex-shrink-0 p-6 pb-8 pt-4 flex justify-center">
<div className="w-full max-w-[75%]"> <div className="w-full max-w-[75%]">
<form onSubmit={handleSubmit} className="relative"> <form onSubmit={handleSubmit} className="relative">
<div className="relative w-full bg-muted/20 rounded-lg border border-border/50 focus-within:ring-1 focus-within:ring-ring"> <div className="relative w-full bg-muted/20 rounded-lg border border-border/50 focus-within:ring-1 focus-within:ring-ring">