import type { FeatureCollection, Point } from "geojson"; import type { Map as MapLibreMap } from "maplibre-gl"; import type { ScadaDevice } from "../api/scada-client"; import { useEffect, useRef, useSyncExternalStore, type RefObject } from "react"; import { getResponsiveWorkbenchPadding } from "../map/camera"; import type { WaterNetworkSourceId } from "../map/sources"; import { WorkbenchMapController } from "../map/workbench-map-controller"; export function useWorkbenchMapController({ mapRef, geoserverWorkspace, mapReady, leftPanelOpen, rightPanelOpen, conditionPanelExpanded = false, agentPanelWidth, getScadaFeatures, availableSourceIds }: { geoserverWorkspace?: string; mapRef: RefObject; mapReady: boolean; leftPanelOpen: boolean; rightPanelOpen: boolean; conditionPanelExpanded?: boolean; agentPanelWidth?: number; getScadaFeatures?: (deviceIds?: string[], signal?: AbortSignal) => Promise>; availableSourceIds?: readonly WaterNetworkSourceId[]; }) { const valuesRef = useRef({ mapReady, leftPanelOpen, rightPanelOpen, conditionPanelExpanded, agentPanelWidth }); valuesRef.current = { mapReady, leftPanelOpen, rightPanelOpen, conditionPanelExpanded, agentPanelWidth }; const controllerRef = useRef(null); if (!controllerRef.current) { controllerRef.current = new WorkbenchMapController({ geoserverWorkspace, getMap: () => mapRef.current, isReady: () => valuesRef.current.mapReady, getPadding: () => { const map = mapRef.current; return map ? getResponsiveWorkbenchPadding( map, valuesRef.current.leftPanelOpen, valuesRef.current.rightPanelOpen, valuesRef.current.conditionPanelExpanded, valuesRef.current.agentPanelWidth ) : { top: 48, right: 48, bottom: 48, left: 48 }; }, getScadaFeatures }); } const controller = controllerRef.current; const state = useSyncExternalStore( controller.subscribe, controller.getSnapshot, controller.getSnapshot ); useEffect(() => { if (availableSourceIds) controller.syncAvailableSources(availableSourceIds); }, [availableSourceIds, controller]); useEffect(() => () => controller.destroy(), [controller]); return { controller, state }; }