import { HubConnectionState } from "@microsoft/signalr"; import { createContext, useContext, useEffect } from "react"; import { createSignalRContext } from "react-signalr"; import { Context } from "react-signalr/lib/signalr/types"; import { URLManager } from "../../../modules"; type MessageEvent = { stream: string; data: any; }; export const createSocketConnection = ( events: Partial, ) => { if (typeof window === "undefined") { return { Provider: ({ children }: { children: any }) => children, useEvent: () => null, SocketConnection: {} as Context, }; } const _events = new Map([]); const SocketConnection = createSignalRContext({ // key: "socket", shareConnectionBetweenTab: false, }); const HasProviderContext = createContext(false); const Provider = ({ children }: { children: any }) => { useEffect(() => { return () => { _events.clear(); }; }, []); return ( { if (connection.state === HubConnectionState.Disconnected) { await connection.start(); } await connection?.invoke("UNSUBSCRIBE", [...events]); if (connection?.state === HubConnectionState.Connected) { if (__DEV__ || __STAGE__) { connection.keepAliveIntervalInMilliseconds = 120000; } await connection?.invoke("SUBSCRIBE", [ ...events, ...Array.from(_events.keys()), ]); } }} onBeforeClose={async (connection) => { if (connection?.state === HubConnectionState.Connected) { await connection?.invoke("UNSUBSCRIBE", [ ...events, ...Array.from(_events.keys()), ]); } }} onReconnect={async (connection) => { if (connection.state === HubConnectionState.Disconnected) { await connection.start(); } await connection?.invoke("UNSUBSCRIBE", [...events]); if (connection?.state === HubConnectionState.Connected) { await connection?.invoke("SUBSCRIBE", [ ...events, ...Array.from(_events.keys()), ]); } }} dependencies={[]} > {children} ); }; const ProviderContainer = ({ children }: { children: any }) => { const hasProvider = useContext(HasProviderContext); return hasProvider ? children : {children}; }; const useEvent = ( event: T, callback: (message: any) => void, { enabled = true }: { enabled?: boolean } = {}, ) => { useEffect(() => { let timeout: any; if (enabled) { timeout = setInterval(() => { if (events.includes(event)) { return; } if ( SocketConnection.connection?.state === HubConnectionState.Connected && _events.get(event) !== "subscribed" ) { clearInterval(timeout); if (__DEV__ || __STAGE__) { SocketConnection.connection.keepAliveIntervalInMilliseconds = 120000; } SocketConnection.connection?.invoke("SUBSCRIBE", [event]); _events.set(event, "subscribed"); } else { _events.set(event, "notSubscribed"); } }, 1000); } return () => { clearInterval(timeout); if ( SocketConnection.connection?.state === HubConnectionState.Connected && _events.has(event) ) { SocketConnection.connection.invoke("UNSUBSCRIBE", [event]); _events.delete(event); } }; }, [event, enabled]); SocketConnection.useSignalREffect( event, (message: MessageEvent) => { callback(message); }, [event, enabled], ); }; return { SocketConnection, useEvent, Provider: ProviderContainer, }; };