'use client'; import { createContext, useContext, useEffect, useState, useRef } from 'react'; import * as signalR from '@microsoft/signalr'; import useAuth from '@/hooks/useAuth'; const SignalRContext = createContext<{ connection: signalR.HubConnection | null; connected: boolean; stopConnection: () => void; reConnection: () => void; }>({ connection: null, connected: false, stopConnection: () => {}, reConnection: () => {} }); type Props = { children: React.ReactNode; accessToken: string|null; signalRUrl: string; } export function SignalRProvider({ children, accessToken, signalRUrl }: Props) { const connection = useRef(null); const [connected, setConnected] = useState(false); const { logout } = useAuth(); useEffect(() => { initConnection(); return () => { if (connection.current) { stopConnection(); } }; }, []); useEffect(() => { if (connected) { console.info('SignalR Connected'); } else if(connection.current) { console.info('SignalR Disconnected'); } else { console.info('SignalR Waiting...'); } }, [connected]); const initConnection = async () => { try { if (connection.current && connection.current.state !== signalR.HubConnectionState.Disconnected) { return; } console.log('SignalR Connecting...'); const connectionOptions = accessToken ? { accessTokenFactory: async () => accessToken, withCredentials: true } : {}; const conn = new signalR.HubConnectionBuilder().withUrl(signalRUrl, connectionOptions).build(); if (conn.state === signalR.HubConnectionState.Disconnected) { console.warn('SignalR Connection is already disconnected'); return; } await conn.start(); setConnected(true); conn.on('Connected', (message) => { console.info(message); }); conn.on('Logout', (message) => { console.info(message); }); conn.on('Kick', async () => { await logout(); }); connection.current = conn; } catch (error) { console.error('SignalR Connect Failed:', error); } }; const stopConnection = async () => { if (connection.current && connection.current.state === signalR.HubConnectionState.Connected) { try { await connection.current.invoke('Logout'); setConnected(false); } catch (error) { console.error('SignalR Disconnect Failed:', error); } } }; const reConnection = async () => { if (connection.current && connection.current.state === signalR.HubConnectionState.Connected) { try { console.log('SignalR ReConnecting...'); await connection.current.stop(); await initConnection(); console.log('SignalR ReConnected'); } catch (error) { console.error("SignalR ReConnection Failed:", error); } } }; return ( {children} ) } export function useSignalRContext() { return useContext(SignalRContext); }