({ messages, sources, newsResults, imageResults, followUpQuestions, searchStatus, isLoading, input, handleInputChange, handleSubmit, messageData, currentTicker }: ChatInterfaceProps)
| 47 | } |
| 48 | |
| 49 | export function ChatInterface({ messages, sources, newsResults, imageResults, followUpQuestions, searchStatus, isLoading, input, handleInputChange, handleSubmit, messageData, currentTicker }: ChatInterfaceProps) { |
| 50 | const messagesEndRef = useRef<HTMLDivElement>(null) |
| 51 | const formRef = useRef<HTMLFormElement>(null) |
| 52 | const [copiedMessageId, setCopiedMessageId] = useState<string | null>(null) |
| 53 | |
| 54 | // Simple theme detection based on document class |
| 55 | const theme = typeof window !== 'undefined' && document.documentElement.classList.contains('dark') ? 'dark' : 'light' |
| 56 | |
| 57 | // Extract the current query and check if we're waiting for response |
| 58 | let query = '' |
| 59 | let isWaitingForResponse = false |
| 60 | |
| 61 | if (messages.length > 0) { |
| 62 | const lastMessage = messages[messages.length - 1] |
| 63 | const secondLastMessage = messages[messages.length - 2] |
| 64 | |
| 65 | if (lastMessage.role === 'user') { |
| 66 | // Waiting for response to this user message |
| 67 | query = getMessageContent(lastMessage) |
| 68 | isWaitingForResponse = true |
| 69 | } else if (secondLastMessage?.role === 'user' && lastMessage.role === 'assistant') { |
| 70 | // Current conversation pair |
| 71 | query = getMessageContent(secondLastMessage) |
| 72 | isWaitingForResponse = false |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | const scrollContainerRef = useRef<HTMLDivElement>(null) |
| 77 | |
| 78 | // Auto-scroll to bottom when new content appears |
| 79 | useEffect(() => { |
| 80 | if (!scrollContainerRef.current) return |
| 81 | |
| 82 | const container = scrollContainerRef.current |
| 83 | |
| 84 | // Always scroll to bottom when new messages arrive |
| 85 | setTimeout(() => { |
| 86 | container.scrollTo({ |
| 87 | top: container.scrollHeight, |
| 88 | behavior: 'smooth' |
| 89 | }) |
| 90 | }, 100) |
| 91 | }, [messages, sources, followUpQuestions]) |
| 92 | |
| 93 | const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => { |
| 94 | e.preventDefault() |
| 95 | if (!input.trim() || isLoading) return |
| 96 | handleSubmit(e) |
| 97 | |
| 98 | // Scroll to bottom after submitting |
| 99 | setTimeout(() => { |
| 100 | if (scrollContainerRef.current) { |
| 101 | scrollContainerRef.current.scrollTo({ |
| 102 | top: scrollContainerRef.current.scrollHeight, |
| 103 | behavior: 'smooth' |
| 104 | }) |
| 105 | } |
| 106 | }, 100) |
nothing calls this directly
no test coverage detected