* wip * wip * wip * format * wip(mobile): lint and format * cleanup * nits * nits * idiomatic react * nit * format all root files
72 lines
1.7 KiB
TypeScript
72 lines
1.7 KiB
TypeScript
import {
|
|
createContext,
|
|
useContext,
|
|
useEffect,
|
|
useMemo,
|
|
useState,
|
|
type ReactNode,
|
|
} from 'react';
|
|
import { PusherClient, type ConnectionState } from './pusher-client';
|
|
import { useSessionStore } from '@/stores/session-store';
|
|
import { appConfig } from '@/config/env';
|
|
|
|
const PusherContext = createContext<PusherClient | null>(null);
|
|
const PusherStateContext = createContext<ConnectionState>('disconnected');
|
|
|
|
export function PusherProvider({ children }: { children: ReactNode }) {
|
|
const token = useSessionStore((s) => s.token);
|
|
const [connectionState, setConnectionState] =
|
|
useState<ConnectionState>('disconnected');
|
|
|
|
const client = useMemo(() => {
|
|
if (!token) {
|
|
return null;
|
|
}
|
|
|
|
return new PusherClient({
|
|
url: appConfig.pusherUrl,
|
|
getToken: () => useSessionStore.getState().token,
|
|
});
|
|
}, [token]);
|
|
|
|
useEffect(() => {
|
|
if (!client) {
|
|
return;
|
|
}
|
|
|
|
const unsubscribeState = client.onStateChange((state) => {
|
|
setConnectionState(state);
|
|
});
|
|
|
|
client.connect();
|
|
|
|
return () => {
|
|
unsubscribeState();
|
|
client.disconnect();
|
|
setConnectionState('disconnected');
|
|
};
|
|
}, [client]);
|
|
|
|
return (
|
|
<PusherContext.Provider value={client}>
|
|
<PusherStateContext.Provider value={connectionState}>
|
|
{children}
|
|
</PusherStateContext.Provider>
|
|
</PusherContext.Provider>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns the PusherClient instance, or null if not connected.
|
|
*/
|
|
export function usePusherClient(): PusherClient | null {
|
|
return useContext(PusherContext);
|
|
}
|
|
|
|
/**
|
|
* Returns the current WebSocket connection state.
|
|
*/
|
|
export function usePusherConnectionState(): ConnectionState {
|
|
return useContext(PusherStateContext);
|
|
}
|