import { useState, useCallback, useRef, useEffect } from 'react';
import type { Face, FaceDetectionOptions, UseFaceDetectionResult } from '../types';
/**
* Options for useFaceDetection hook
*/
export interface UseFaceDetectionOptions extends FaceDetectionOptions {
/** Whether detection is enabled. Default: true */
enabled?: boolean;
/** Maximum number of faces to track. Default: 5 */
maxFaces?: number;
/** Callback when faces change */
onFacesChanged?: (faces: Face[]) => void;
}
/**
* Hook for managing face detection state
*
* Use this hook to get face detection results outside of the SmartCamera component.
*
* @param options - Face detection options
* @returns Face detection state
*
* @example
* ```tsx
* function FaceTracker() {
* const { faces, isDetecting } = useFaceDetection({
* performanceMode: 'fast',
* classificationMode: 'all',
* onFacesChanged: (faces) => {
* console.log('Detected faces:', faces.length);
* },
* });
*
* return (
*
* Faces detected: {faces.length}
* {faces.map((face, i) => (
*
* Smiling: {(face.smilingProbability ?? 0) * 100}%
*
* ))}
*
* );
* }
* ```
*/
export function useFaceDetection(options: UseFaceDetectionOptions = {}): UseFaceDetectionResult {
const { enabled = true, maxFaces = 5, onFacesChanged } = options;
const [faces, setFaces] = useState([]);
const [isDetecting, setIsDetecting] = useState(false);
const facesRef = useRef([]);
const callbackRef = useRef(onFacesChanged);
// Keep callback ref updated
useEffect(() => {
callbackRef.current = onFacesChanged;
}, [onFacesChanged]);
// Update faces (called from frame processor via native bridge)
const updateFaces = useCallback((newFaces: Face[]) => {
// Limit number of faces
const limitedFaces = newFaces.slice(0, maxFaces);
// Only update if faces changed
const facesChanged =
limitedFaces.length !== facesRef.current.length ||
limitedFaces.some((face, i) => face.trackingId !== facesRef.current[i]?.trackingId);
if (facesChanged) {
facesRef.current = limitedFaces;
setFaces(limitedFaces);
callbackRef.current?.(limitedFaces);
}
}, [maxFaces]);
// Detection state management
const startDetecting = useCallback(() => {
setIsDetecting(true);
}, []);
const stopDetecting = useCallback(() => {
setIsDetecting(false);
setFaces([]);
facesRef.current = [];
}, []);
// Effect to manage detection state based on enabled prop
useEffect(() => {
if (enabled) {
startDetecting();
} else {
stopDetecting();
}
}, [enabled, startDetecting, stopDetecting]);
return {
faces,
isDetecting,
};
}