import { useEffect, useRef, useState } from "react" import { BaseBoxShapeUtil, TLBaseShape } from "tldraw" export type IChatBoxShape = TLBaseShape< "ChatBox", { w: number h: number roomId: string userName: string } > export class ChatBoxShape extends BaseBoxShapeUtil { static override type = "ChatBox" getDefaultProps(): IChatBoxShape["props"] { return { roomId: "default-room", w: 100, h: 100, userName: "", } } indicator(shape: IChatBoxShape) { return } component(shape: IChatBoxShape) { return ( ) } } interface Message { id: string username: string content: string timestamp: Date } // Update the ChatBox component to accept userName export const ChatBox: React.FC = ({ roomId, w, h, userName, }) => { const [messages, setMessages] = useState([]) const [inputMessage, setInputMessage] = useState("") const [username, setUsername] = useState(userName) const messagesEndRef = useRef(null) useEffect(() => { const storedUsername = localStorage.getItem("chatUsername") if (storedUsername) { setUsername(storedUsername) } else { const newUsername = `User${Math.floor(Math.random() * 1000)}` setUsername(newUsername) localStorage.setItem("chatUsername", newUsername) } fetchMessages(roomId) const interval = setInterval(() => fetchMessages(roomId), 2000) return () => clearInterval(interval) }, [roomId]) useEffect(() => { if (messagesEndRef.current) { ;(messagesEndRef.current as HTMLElement).scrollIntoView({ behavior: "smooth", }) } }, [messages]) const fetchMessages = async (roomId: string) => { try { const response = await fetch( `https://jeffemmett-realtimechatappwithpolling.web.val.run?action=getMessages&roomId=${roomId}`, ) if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`) } const newMessages = (await response.json()) as Message[] setMessages( newMessages.map((msg) => ({ ...msg, timestamp: new Date(msg.timestamp), })), ) } catch (error) { console.error("Error fetching messages:", error) } } const sendMessage = async (e: React.FormEvent) => { e.preventDefault() if (!inputMessage.trim()) return await sendMessageToChat(roomId, username, inputMessage) setInputMessage("") fetchMessages(roomId) } return (
{messages.map((msg) => (
{msg.username} {new Date(msg.timestamp).toLocaleTimeString()}
{msg.content}
))}
setInputMessage(e.target.value)} placeholder="Type a message..." className="message-input" style={{ touchAction: "manipulation" }} />
) } async function sendMessageToChat( roomId: string, username: string, content: string, ): Promise { const apiUrl = "https://jeffemmett-realtimechatappwithpolling.web.val.run" // Replace with your actual Val Town URL try { const response = await fetch(`${apiUrl}?action=sendMessage`, { method: "POST", mode: "no-cors", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ roomId, username, content, }), }) const result = await response.text() //console.log("Message sent successfully:", result) } catch (error) { console.error("Error sending message:", error) } }