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" />
); } 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); } }