"use client"; // One shared IIOS message socket for the whole dashboard, so the messenger tab AND the app-wide // notification center use a single connection (not one each). Opened at the dashboard level and // kept alive across tab switches; the messenger tab reuses it via useRealtime(). import { createContext, useContext, useEffect, useState, type ReactNode } from "react"; import { useQuery } from "@abe-kap/appshell-sdk/react"; import { MessageSocket } from "@insignia/iios-kernel-client"; import { isShellConfigured } from "./appshell"; const RealtimeContext = createContext(null); interface RealtimeDTO { url: string; audience: string; token?: string } const SHELL = isShellConfigured(); function LiveRealtimeProvider({ children }: { children: ReactNode }) { const rt = useQuery("crm.messenger.realtime", {}); const [socket, setSocket] = useState(null); const url = rt.data?.url; const token = rt.data?.token; useEffect(() => { if (!url || !token) return; const s = new MessageSocket({ serviceUrl: url, token, autoConnect: false }); s.connect(); setSocket(s); return () => { s.disconnect(); setSocket(null); }; }, [url, token]); return {children}; } export function RealtimeProvider({ children }: { children: ReactNode }) { // SHELL is a build-time constant, so the same branch runs every render (Rules-of-Hooks safe). if (!SHELL) return <>{children}; return {children}; } /** The shared socket, or null (demo mode / not yet connected). */ export function useRealtime(): MessageSocket | null { return useContext(RealtimeContext); }