Adds the core project structure, including configuration files, a basic HTML page, and the main application component. It also lays the groundwork for the canvas, color palette, and configuration modal functionalities. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 0385ea33-cde8-4bbd-8fce-8d192d30eb41 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/870d08ce-da3b-4822-9874-c2fe2b7628b1/0385ea33-cde8-4bbd-8fce-8d192d30eb41/Vuy7IOw
50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
import { useEffect, useRef, useState } from "react";
|
|
import { WSMessage } from "@shared/schema";
|
|
|
|
export function useWebSocket(onMessage: (message: WSMessage) => void) {
|
|
const [isConnected, setIsConnected] = useState(false);
|
|
const [userCount, setUserCount] = useState(0);
|
|
const ws = useRef<WebSocket | null>(null);
|
|
|
|
useEffect(() => {
|
|
const protocol = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
const wsUrl = `${protocol}//${window.location.host}/ws`;
|
|
|
|
ws.current = new WebSocket(wsUrl);
|
|
|
|
ws.current.onopen = () => {
|
|
setIsConnected(true);
|
|
};
|
|
|
|
ws.current.onmessage = (event) => {
|
|
try {
|
|
const message: WSMessage = JSON.parse(event.data);
|
|
|
|
if (message.type === "user_count") {
|
|
setUserCount(message.data.count);
|
|
}
|
|
|
|
onMessage(message);
|
|
} catch (error) {
|
|
console.error("Failed to parse WebSocket message:", error);
|
|
}
|
|
};
|
|
|
|
ws.current.onclose = () => {
|
|
setIsConnected(false);
|
|
};
|
|
|
|
ws.current.onerror = () => {
|
|
setIsConnected(false);
|
|
};
|
|
|
|
return () => {
|
|
if (ws.current) {
|
|
ws.current.close();
|
|
}
|
|
};
|
|
}, [onMessage]);
|
|
|
|
return { isConnected, userCount };
|
|
}
|