UNPKG

@adventurelabs/scout-core

Version:

Core utilities and helpers for Adventure Labs Scout applications

85 lines (84 loc) 3.48 kB
"use client"; import { useSelector } from "react-redux"; import { useEffect, useRef, useCallback, useState, useMemo } from "react"; import { EnumRealtimeOperation } from "../types/realtime"; export function useScoutRealtimeConnectivity(scoutSupabase) { const channels = useRef([]); const [latestConnectivityUpdate, setLatestConnectivityUpdate] = useState(null); const activeHerdId = useSelector((state) => state.scout.active_herd_id); const herdModules = useSelector((state) => state.scout.herd_modules); // Create stable reference for GPS device IDs to prevent unnecessary refetching const gpsDeviceIds = useMemo(() => { if (!activeHerdId) return ""; const activeHerdModule = herdModules.find((hm) => hm.herd.id.toString() === activeHerdId); if (!activeHerdModule) return ""; const gpsDevices = activeHerdModule.devices.filter((device) => device.device_type && ["gps_tracker", "gps_tracker_vehicle", "gps_tracker_person"].includes(device.device_type)); return gpsDevices .map((d) => d.id) .filter(Boolean) .sort() .join(","); }, [activeHerdId, herdModules]); // Handle connectivity broadcasts const handleConnectivityBroadcast = useCallback((payload) => { const { event, payload: data } = payload; const connectivityData = data.record || data.old_record; // Only process GPS tracker data (no session_id) if (!connectivityData?.device_id || connectivityData.session_id) { return; } let operation; switch (data.operation) { case "INSERT": operation = EnumRealtimeOperation.INSERT; break; case "UPDATE": operation = EnumRealtimeOperation.UPDATE; break; case "DELETE": operation = EnumRealtimeOperation.DELETE; break; default: return; } console.log(`[scout-core realtime] CONNECTIVITY ${data.operation} received for device ${connectivityData.device_id}:`, JSON.stringify(connectivityData)); const realtimeData = { data: connectivityData, operation, }; setLatestConnectivityUpdate(realtimeData); }, []); // Clear latest update const clearLatestUpdate = useCallback(() => { setLatestConnectivityUpdate(null); }, []); useEffect(() => { if (!scoutSupabase || gpsDeviceIds === "") return; // Clean up existing channels channels.current.forEach((channel) => scoutSupabase.removeChannel(channel)); channels.current = []; // Clear previous update when switching herds clearLatestUpdate(); // Create connectivity channel const channel = scoutSupabase .channel(`${activeHerdId}-connectivity`, { config: { private: true } }) .on("broadcast", { event: "*" }, handleConnectivityBroadcast) .subscribe(); channels.current.push(channel); return () => { channels.current.forEach((ch) => scoutSupabase.removeChannel(ch)); channels.current = []; }; }, [ scoutSupabase, gpsDeviceIds, activeHerdId, handleConnectivityBroadcast, clearLatestUpdate, ]); return [latestConnectivityUpdate, clearLatestUpdate]; }