import { useEffect, useRef, useState } from 'react' import { createBluetoothDiscovery } from '../discovery' // 工厂回调 → React state 的映射产物 export interface BleUiState { searching: boolean connected: boolean deviceList: Array<{ deviceId: string; name?: string; RSSI?: number }> profileId: string stage: string deviceInfo: Record | null authResult: unknown } export function useBle() { const [state, setState] = useState({ searching: false, connected: false, deviceList: [], profileId: 'UNKNOWN', stage: 'IDLE', deviceInfo: null, authResult: null }) // discovery 实例在整个组件生命周期内只创建一次; // 回调里读最新 state 用 setState 函数式更新,不闭包旧值 const discoveryRef = useRef | null>(null) if (discoveryRef.current === null) { discoveryRef.current = createBluetoothDiscovery({ onSearchingChange: (searching) => setState((s) => ({ ...s, searching })), onConnectedChange: (connected) => setState((s) => ({ ...s, connected })), onDeviceListChange: (deviceList) => setState((s) => ({ ...s, deviceList })), onProfileChange: (profileId) => setState((s) => ({ ...s, profileId })), onStageChange: (stage) => setState((s) => ({ ...s, stage })), onDeviceInfoChange: (deviceInfo) => setState((s) => ({ ...s, deviceInfo })), onAuthChange: (authResult) => setState((s) => ({ ...s, authResult })) // onError / onRadarData / onProtocolState / onProtocolMsg 按页面需要接入 }) } // 卸载时统一清理(停扫描、断连接、解绑事件) useEffect(() => { const discovery = discoveryRef.current return () => { discovery?.cleanupDiscovery() discoveryRef.current = null } }, []) const discovery = discoveryRef.current! return { state, discovery } }