import { ref, onMounted, onBeforeUnmount, watch } from "vue"; import { connectWebSocket, disconnectWebSocket, sendEvent, sendEventAndWait, onEvent, isWebSocketConnected, setDefaultHandler, } from "@/services/ws"; import { useIngame } from "@/composables/useIngame"; function defaultEventHandler(data: (data: T) => void) { setDefaultHandler(data); } export function useWebSocket() { const isConnected = ref(isWebSocketConnected()); const lastMessage = ref(null); const lastError = ref(null); // Get ingame store to sync connection state const ig = useIngame(); // Watch the ingame store's connection state and keep this composable in sync watch(() => ig.isWsConnected, (connected) => { isConnected.value = connected; }); // Also update this composable's state when connecting/disconnecting const updateConnectionState = (connected: boolean) => { isConnected.value = connected; }; async function safeConnect(url?: string) { return connectWebSocket(url) .then(() => { updateConnectionState(true); }) .catch((err) => { updateConnectionState(false); lastError.value = err?.message ?? "Unknown WS error"; throw err; }); } function useEvent(event: string, handler: (data: T) => void) { const wrapped = (data: T) => { lastMessage.value = { event, data }; handler(data); }; onMounted(() => { console.log("Registering event handler for " + event); onEvent(event, wrapped); }); onBeforeUnmount(() => { console.log("Unregistering event handler for " + event); onEvent(event, () => {}); }); } return { isConnected, lastMessage, lastError, connect: safeConnect, disconnect: disconnectWebSocket, send: sendEvent, sendAndWait: sendEventAndWait, useEvent, defaultEventHandler }; }