| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- '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<signalR.HubConnection|null>(null);
- const [connected, setConnected] = useState<boolean>(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 (
- <SignalRContext.Provider value={{ connection: connection.current, connected, stopConnection, reConnection }}>
- {children}
- </SignalRContext.Provider>
- )
- }
- export function useSignalRContext() {
- return useContext(SignalRContext);
- }
|