Spaces:
Sleeping
Sleeping
| import React, { useState, useEffect } from "react"; | |
| const ChatBox = ({ activeThread }) => { | |
| const [messages, setMessages] = useState([]); | |
| const [userInput, setUserInput] = useState(""); | |
| const [isStreaming, setIsStreaming] = useState(false); | |
| const FLASK_API_URL = process.env.FLASK_API_URL; | |
| // useEffect(() => { | |
| // // Fetch existing messages for the active thread | |
| // fetch(`http://127.0.0.1:5000/api/chat/${activeThread}`) | |
| // .then((response) => response.json()) | |
| // .then((data) => setMessages(data)); | |
| // }, [activeThread]); | |
| const sendMessage = async () => { | |
| if (!userInput.trim()) return; | |
| const newMessage = { sender: "user", message: userInput }; | |
| setMessages((prevMessages) => [...prevMessages, newMessage]); | |
| setUserInput(""); | |
| try { | |
| setIsStreaming(true); | |
| const response = await fetch(FLASK_API_URL, { | |
| method: "POST", | |
| headers: { "Content-Type": "application/json" }, | |
| body: JSON.stringify({ thread_id: activeThread, prompt: userInput }), | |
| }); | |
| if (!response.ok) { | |
| console.error("Failed to stream response"); | |
| setIsStreaming(false); | |
| return; | |
| } | |
| const reader = response.body.getReader(); | |
| const decoder = new TextDecoder("utf-8"); | |
| let streamingMessage = ""; | |
| while (true) { | |
| const { done, value } = await reader.read(); | |
| if (done) break; | |
| const chunk = decoder.decode(value, { stream: true }); | |
| streamingMessage += chunk; | |
| setMessages((prevMessages) => { | |
| const updatedMessages = [...prevMessages]; | |
| const lastMessage = updatedMessages[updatedMessages.length - 1]; | |
| if (lastMessage && lastMessage.sender === "bot") { | |
| lastMessage.message = streamingMessage; | |
| } else { | |
| updatedMessages.push({ sender: "bot", message: streamingMessage }); | |
| } | |
| return updatedMessages; | |
| }); | |
| } | |
| setIsStreaming(false); | |
| } catch (error) { | |
| console.error("Error during streaming:", error); | |
| setIsStreaming(false); | |
| } | |
| }; | |
| const renderMessage = (message) => { | |
| if (message.message.includes("```")) { | |
| // Handle code block | |
| const parts = message.message.split(/```/g); | |
| return parts.map((part, index) => ( | |
| <div key={index}> | |
| {index % 2 === 0 ? ( | |
| <p style={{ whiteSpace: "pre-wrap", margin: "5px 0" }}>{part}</p> | |
| ) : ( | |
| <pre | |
| style={{ | |
| backgroundColor: "#333", | |
| color: "#f5f5f5", | |
| padding: "10px", | |
| borderRadius: "5px", | |
| margin: "5px 0", | |
| overflowX: "auto", | |
| }} | |
| > | |
| <code>{part}</code> | |
| </pre> | |
| )} | |
| </div> | |
| )); | |
| } | |
| // Plain text message | |
| return <p style={{ whiteSpace: "pre-wrap", margin: "5px 0" }}>{message.message}</p>; | |
| }; | |
| const handleKeyDown = (event) => { | |
| if (event.key === "Enter") { | |
| sendMessage(); | |
| } | |
| }; | |
| return ( | |
| <div | |
| style={{ | |
| width: "80%", | |
| display: "flex", | |
| flexDirection: "column", | |
| padding: "10px", | |
| backgroundColor: "#1e1e1e", | |
| color: "#f5f5f5", | |
| }} | |
| > | |
| <div | |
| style={{ | |
| flex: 1, | |
| overflowY: "auto", | |
| border: "1px solid #333", | |
| borderRadius: "5px", | |
| marginBottom: "10px", | |
| padding: "10px", | |
| backgroundColor: "#121212", | |
| }} | |
| > | |
| {messages.map((msg, index) => ( | |
| <div | |
| key={index} | |
| style={{ | |
| display: "flex", | |
| justifyContent: msg.sender === "user" ? "flex-end" : "flex-start", | |
| marginBottom: "10px", | |
| }} | |
| > | |
| <div | |
| style={{ | |
| maxWidth: "70%", | |
| padding: "10px", | |
| backgroundColor: msg.sender === "user" ? "#333" : "#444", | |
| color: msg.sender === "user" ? "#ffa726" : "#f5f5f5", | |
| borderRadius: "10px", | |
| textAlign: "left", | |
| }} | |
| > | |
| {renderMessage(msg)} | |
| </div> | |
| </div> | |
| ))} | |
| {isStreaming && ( | |
| <div style={{ color: "#64b5f6" }}> | |
| <em>Bot is typing...</em> | |
| </div> | |
| )} | |
| </div> | |
| <div style={{ display: "flex" }}> | |
| <input | |
| type="text" | |
| value={userInput} | |
| onChange={(e) => setUserInput(e.target.value)} | |
| onKeyDown={handleKeyDown} | |
| placeholder="Type your message..." | |
| style={{ | |
| flex: 1, | |
| padding: "10px", | |
| border: "1px solid #333", | |
| borderRadius: "5px", | |
| backgroundColor: "#333", | |
| color: "#f5f5f5", | |
| }} | |
| /> | |
| <button | |
| onClick={sendMessage} | |
| style={{ | |
| marginLeft: "10px", | |
| padding: "10px", | |
| backgroundColor: "#333", | |
| color: "#f5f5f5", | |
| border: "none", | |
| borderRadius: "5px", | |
| cursor: "pointer", | |
| }} | |
| > | |
| Send | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default ChatBox; | |