import { useRef } from "react"; import useWebSocket from "react-use-websocket"; import { useHandleWebsocketMessages } from "../livestream-store/use-store"; import { useUrl } from "../streamplace-store"; export function useLivestreamWebsocket(src: string) { const url = useUrl(); const handleWebSocketMessages = useHandleWebsocketMessages(); let wsUrl = url.replace(/^http\:/, "ws:"); wsUrl = wsUrl.replace(/^https\:/, "wss:"); const ref = useRef([]); const handle = useRef(null); const hasReceivedMessage = useRef(false); const hasErrored = useRef(false); const { readyState } = useWebSocket(`${wsUrl}/api/websocket/${src}`, { reconnectInterval: 1000, shouldReconnect: () => !hasErrored.current, onOpen: () => { ref.current = []; hasReceivedMessage.current = false; }, onError: (e) => { console.log("onError", e); if (!hasReceivedMessage.current) { hasErrored.current = true; handleWebSocketMessages([ { $type: "place.stream.error", code: "user_not_found", message: "this stream doesn't exist or is unavailable", }, ]); } }, // spamming the redux store with messages causes a zillion re-renders, // so we batch them up a bit onMessage: (msg) => { try { const data = JSON.parse(msg.data); hasReceivedMessage.current = true; ref.current.push(data); if (handle.current) { return; } handle.current = setTimeout(() => { handleWebSocketMessages(ref.current); ref.current = []; handle.current = null; }, 250); } catch (e) { console.log("onMessage parse error", e); } }, }); }