Add adaptive per-vehicle layouts, full-panel dragging, source controls and automatic preview recovery for RealSense, Insta360 X4 and XGRIDS K1 observation views. Integrate cached Cesium map layers through the private NAS gateway link, retain bounded sensor command receipts, and document validation and operational handoff.
25 lines
1.4 KiB
TypeScript
25 lines
1.4 KiB
TypeScript
import {useCallback,useEffect,useRef,useState} from 'react';
|
|
import type {Sensor} from './contracts';
|
|
import {observationSession} from './observationStart';
|
|
|
|
/** One automatic activation per mounted view/session; failures require explicit retry. */
|
|
export function useObservationStart(device:Sensor,enabled:boolean,active:boolean,start:()=>Promise<unknown>){
|
|
const scope=observationSession(device),latest=useRef({scope,enabled,start});latest.current={scope,enabled,start};
|
|
const mounted=useRef(false),attempted=useRef(''),running=useRef(false);
|
|
const [pending,setPending]=useState(false),[error,setError]=useState('');
|
|
useEffect(()=>{mounted.current=true;return()=>{mounted.current=false;};},[]);
|
|
useEffect(()=>{setError('');},[scope]);
|
|
const retry=useCallback(async()=>{
|
|
const value=latest.current;if(!value.enabled||running.current)return;
|
|
attempted.current=value.scope;running.current=true;setPending(true);setError('');
|
|
try{await value.start();}catch(reason){if(mounted.current&&latest.current.scope===value.scope)setError(reason instanceof Error?reason.message:'Не удалось начать просмотр.');}
|
|
finally{running.current=false;if(mounted.current)setPending(false);}
|
|
},[]);
|
|
useEffect(()=>{
|
|
if(!enabled){attempted.current='';return;}
|
|
if(active){attempted.current=scope;setError('');return;}
|
|
if(attempted.current!==scope)void retry();
|
|
},[scope,enabled,active,retry,pending]);
|
|
return {pending,error,retry};
|
|
}
|