UNPKG

react-native-healthkit-bridge

Version:

A comprehensive React Native bridge for Apple HealthKit with TypeScript support, advanced authorization, and flexible data queries

189 lines (162 loc) 5.26 kB
import { useCallback, useEffect, useState } from 'react'; import { HealthKitBridge } from '../core/HealthKitBridge'; import { HealthKitQuantity, HealthKitCategoryData, HealthKitWorkout } from '../core/types/HealthKitTypes'; // Singleton instance of HealthKitBridge with proper cleanup let healthKitInstance: HealthKitBridge | null = null; function getHealthKitBridge(): HealthKitBridge { if (!healthKitInstance) { healthKitInstance = new HealthKitBridge(); } return healthKitInstance; } // Cleanup function for testing and memory management export function cleanupHealthKitBridge(): void { healthKitInstance = null; } interface UseHealthKitResult<T> { data: T | null; loading: boolean; error: string | null; refetch: () => void; } // Generic hook for quantitative data export function useHealthKitQuantity( identifier: string, unit: string ): UseHealthKitResult<HealthKitQuantity[]> { const [data, setData] = useState<HealthKitQuantity[] | null>(null); const [loading, setLoading] = useState(false); const [error, setError] = useState<string | null>(null); const fetch = useCallback(async () => { setLoading(true); setError(null); try { const result = await getHealthKitBridge().getQuantitySamples(identifier, unit); // Convert to HealthKitQuantity format const formattedData = result.map((sample, index) => ({ value: sample.value, unit, startDate: Date.now() / 1000 - (index * 86400), endDate: Date.now() / 1000 - (index * 86400) + 86400 })); setData(formattedData); } catch (e: any) { setError(e?.message || 'Error fetching data'); } finally { setLoading(false); } }, [identifier, unit]); useEffect(() => { fetch(); }, [fetch]); return { data, loading, error, refetch: fetch }; } // Generic hook for categorical data export function useHealthKitCategory( identifier: string ): UseHealthKitResult<HealthKitCategoryData[]> { const [data, setData] = useState<HealthKitCategoryData[] | null>(null); const [loading, setLoading] = useState(false); const [error, setError] = useState<string | null>(null); const fetch = useCallback(async () => { setLoading(true); setError(null); try { const result = await getHealthKitBridge().getCategorySamples(identifier); setData(result); } catch (e: any) { setError(e?.message || 'Error fetching data'); } finally { setLoading(false); } }, [identifier]); useEffect(() => { fetch(); }, [fetch]); return { data, loading, error, refetch: fetch }; } // Hook for workouts export function useHealthKitWorkouts(): UseHealthKitResult<HealthKitWorkout[]> { const [data, setData] = useState<HealthKitWorkout[] | null>(null); const [loading, setLoading] = useState(false); const [error, setError] = useState<string | null>(null); const fetch = useCallback(async () => { setLoading(true); setError(null); try { const result = await getHealthKitBridge().getWorkoutsGeneric(); setData(result); } catch (e: any) { setError(e?.message || 'Error fetching data'); } finally { setLoading(false); } }, []); useEffect(() => { fetch(); }, [fetch]); return { data, loading, error, refetch: fetch }; } // Hook for available types export function useHealthKitTypes() { const [types, setTypes] = useState<any[] | null>(null); const [loading, setLoading] = useState(false); const [error, setError] = useState<string | null>(null); const fetchTypes = useCallback(async () => { setLoading(true); setError(null); try { const result = await getHealthKitBridge().getAvailableTypes(); setTypes(result); return result; } catch (e: any) { const errorMessage = e?.message || 'Error fetching available types'; setError(errorMessage); return []; } finally { setLoading(false); } }, []); const getTypeInfo = useCallback(async (identifier: string) => { setLoading(true); setError(null); try { const result = await getHealthKitBridge().getTypeInfo(identifier as any); return result; } catch (e: any) { const errorMessage = e?.message || 'Error fetching type information'; setError(errorMessage); return null; } finally { setLoading(false); } }, []); return { types, loading, error, fetchTypes, getTypeInfo }; } // Hook for provider information export function useHealthKitProvider() { const [providerInfo, setProviderInfo] = useState<any>(null); const [availableProviders, setAvailableProviders] = useState<string[]>([]); const [allProvidersInfo, setAllProvidersInfo] = useState<any[]>([]); const fetchProviderInfo = useCallback(() => { const info = getHealthKitBridge().getProviderInfo(); const available = getHealthKitBridge().getAvailableProviders(); const allInfo = getHealthKitBridge().getAllProvidersInfo(); setProviderInfo(info); setAvailableProviders(available); setAllProvidersInfo(allInfo); return { info, available, allInfo }; }, []); return { providerInfo, availableProviders, allProvidersInfo, fetchProviderInfo }; }