1import { H2 } from '@expo/html-elements'; 2import { Pedometer } from 'expo-sensors'; 3import * as React from 'react'; 4import { ScrollView, Text, View } from 'react-native'; 5 6import ListButton from '../components/ListButton'; 7import { useResolvedValue } from '../utilities/useResolvedValue'; 8 9function usePedometer({ isActive }: { isActive: boolean }): Pedometer.PedometerResult | null { 10 const [data, setData] = React.useState<Pedometer.PedometerResult | null>(null); 11 const listener = React.useRef<Pedometer.PedometerListener | null>(null); 12 13 React.useEffect(() => { 14 return () => { 15 listener.current?.remove(); 16 }; 17 }, []); 18 19 React.useEffect(() => { 20 if (isActive) { 21 listener.current = Pedometer.watchStepCount(setData); 22 } else { 23 listener.current?.remove(); 24 } 25 }, [isActive]); 26 27 return data; 28} 29 30function usePedometerHistory({ 31 start, 32 end, 33}: { 34 start: Date; 35 end: Date; 36}): Pedometer.PedometerResult | null { 37 const [data, setData] = React.useState<Pedometer.PedometerResult | null>(null); 38 const isMounted = React.useRef(true); 39 40 React.useEffect(() => { 41 return () => { 42 isMounted.current = false; 43 }; 44 }, []); 45 46 React.useEffect(() => { 47 Pedometer.getStepCountAsync(start, end).then(data => { 48 if (isMounted.current) { 49 setData(data); 50 } 51 }); 52 }, [start, end]); 53 54 return data; 55} 56 57function StepTrackerView() { 58 const [isActive, setActive] = React.useState(false); 59 const data = usePedometer({ isActive }); 60 const message = data?.steps ? `Total steps ${data.steps}` : `Waiting...`; 61 return ( 62 <View style={{ padding: 10 }}> 63 <H2>Step Tracker</H2> 64 <ListButton onPress={() => setActive(true)} disabled={isActive} title="Start" /> 65 <ListButton onPress={() => setActive(false)} disabled={!isActive} title="Stop" /> 66 <Text style={{ paddingTop: 10, fontWeight: 'bold' }}>{message}</Text> 67 </View> 68 ); 69} 70 71function StepHistoryMessage() { 72 const today = React.useMemo(() => { 73 return new Date(); 74 }, []); 75 const yesterday = React.useMemo(() => { 76 const yesterday = new Date(); 77 yesterday.setDate(today.getDate() - 1); 78 return yesterday; 79 }, [today]); 80 81 const data = usePedometerHistory({ start: yesterday, end: today }); 82 83 const message = data ? `Steps in the last day: ${data.steps}` : `Loading health data...`; 84 return ( 85 <View style={{ padding: 10 }}> 86 <H2>Step History</H2> 87 <Text>{message}</Text> 88 </View> 89 ); 90} 91 92export default function PedometerScreen() { 93 const [value] = useResolvedValue(Pedometer.isAvailableAsync); 94 95 if (value === null) { 96 return null; 97 } else if (value === false) { 98 return ( 99 <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> 100 <Text>Pedometer is not available on this platform</Text> 101 </View> 102 ); 103 } 104 return ( 105 <ScrollView> 106 <StepTrackerView /> 107 <StepHistoryMessage /> 108 </ScrollView> 109 ); 110} 111 112PedometerScreen.navigationOptions = { 113 title: 'Pedometer', 114}; 115