Files
fusion/packages/dashboard/app/hooks/useRemoteNodeEvents.ts
Fusion 0433ce5dd8 fix(FN-2024): gate task SSE subscriptions by active view
- Add an sseEnabled option to useTasks and skip SSE subscription setup when disabled
- Compute taskSseEnabled in App based on board/list views and pass it through to useTasks
- Migrate useRemoteNodeEvents from raw EventSource management to shared subscribeSse bus usage
- Update App, useTasks, and useRemoteNodeEvents tests to cover SSE gating and bus-based event wiring
2026-04-17 15:21:15 -07:00

65 lines
1.8 KiB
TypeScript

/**
* useRemoteNodeEvents hook - subscribes to SSE events from a remote node via the proxy.
*/
import { useEffect, useState } from "react";
import { subscribeSse } from "../sse-bus";
export interface RemoteNodeEvent {
type: string;
data: unknown;
}
export interface UseRemoteNodeEventsResult {
/** Whether the SSE connection is currently active */
isConnected: boolean;
/** The last received event, or null if no events received */
lastEvent: RemoteNodeEvent | null;
}
/**
* Hook for subscribing to SSE events from a remote node via the proxy.
* Uses the shared SSE bus for connection multiplexing, heartbeat, and reconnection.
*/
export function useRemoteNodeEvents(nodeId: string | null): UseRemoteNodeEventsResult {
const [isConnected, setIsConnected] = useState(false);
const [lastEvent, setLastEvent] = useState<RemoteNodeEvent | null>(null);
useEffect(() => {
if (!nodeId) {
setIsConnected(false);
setLastEvent(null);
return;
}
const url = `/api/proxy/${encodeURIComponent(nodeId)}/events`;
return subscribeSse(url, {
events: {
"task:created": (e: MessageEvent) => {
setLastEvent({ type: "task:created", data: e.data });
},
"task:moved": (e: MessageEvent) => {
setLastEvent({ type: "task:moved", data: e.data });
},
"task:updated": (e: MessageEvent) => {
setLastEvent({ type: "task:updated", data: e.data });
},
"task:deleted": (e: MessageEvent) => {
setLastEvent({ type: "task:deleted", data: e.data });
},
"task:merged": (e: MessageEvent) => {
setLastEvent({ type: "task:merged", data: e.data });
},
},
onOpen: () => setIsConnected(true),
onError: () => setIsConnected(false),
});
}, [nodeId]);
return {
isConnected,
lastEvent,
};
}