index.js 5.84 KB
Newer Older
1 2 3 4 5 6 7 8 9
/**
 * Created by greg on 2016-06-30.
 */

import React, { Component } from 'react';
import {
    Navigator,
    TouchableOpacity,
    ScrollView,
10
    Image,
11
    Text,
12 13
    View,
    NativeAppEventEmitter,
14
} from 'react-native';
15

16
import AppleHealthKit from 'react-native-apple-healthkit';
17
import styles from '../../styles/styles';
18 19
import History from './history';

20
// setup the HealthKit initialization options
21
const HKPERMS = AppleHealthKit.Constants.Permissions;
22 23
const HKOPTIONS = {
    permissions: {
24
        read:  [
25 26 27 28
            HKPERMS.StepCount,
            HKPERMS.DistanceWalkingRunning,
            HKPERMS.FlightsClimbed,
            HKPERMS.Height,
29 30
            HKPERMS.DateOfBirth,
            HKPERMS.BiologicalSex,
31
        ],
32
        write: [
33
            HKPERMS.StepCount
34
        ],
35 36 37
    }
};

38 39 40
/**
 * React Component
 */
41 42 43 44 45 46 47 48 49 50
class Home extends Component {

    constructor(props) {
        super(props);
        this.state = {
            stepsToday: 0,
            stepHistory: [],
        };
    }

51 52 53 54 55
    /**
     * if HealthKit is available on the device then initialize it
     * with the permissions set above in HKOPTIONS. on successful
     * initialization fetch today's steps and the step history
     */
56 57 58 59 60 61 62
    componentDidMount() {
        AppleHealthKit.isAvailable((err,available) => {
            if(available){
                AppleHealthKit.initHealthKit(HKOPTIONS, (err, res) => {
                    if(this._handleHKError(err, 'initHealthKit')){
                        return;
                    }
63 64 65 66 67 68 69 70 71 72 73 74 75

                    AppleHealthKit.initStepCountObserver({}, () => {});

                    var subscription = NativeAppEventEmitter.addListener(
                        'change:steps',
                        (evt) => {
                            console.log('change:steps EVENT!! : ', evt);
                            this._fetchStepsToday();
                        }
                    );

                    this.sub = subscription;

76 77 78 79 80 81 82
                    this._fetchStepsToday();
                    this._fetchStepsHistory();
                });
            }
        });
    }

83 84 85 86
    componentWillUnmount() {
        this.sub.remove();
    }

87 88 89 90 91
    /**
     * get today's step count from HealthKit. on success update
     * the component state
     * @private
     */
92
    _fetchStepsToday() {
93
        AppleHealthKit.getStepCount(null, (err, res) => {
94
            if(this._handleHKError(err, 'getStepCount')){
95 96
                return;
            }
97
            this.setState({stepsToday: res.value});
98 99 100
        });
    }

101 102 103 104 105
    /**
     * get the step history from options.startDate through the
     * current time. on success update the component state
     * @private
     */
106 107 108 109
    _fetchStepsHistory() {
        let options = {
            startDate: (new Date(2016,4,1)).toISOString(),
        };
110 111
        AppleHealthKit.getDailyStepCountSamples(options, (err, res) => {
            if(this._handleHKError(err, 'getDailyStepCountSamples')){
112 113 114 115 116 117
                return;
            }
            this.setState({stepHistory: res});
        });
    }

118 119 120 121 122
    /**
     * render the Navigator which will render the navigation
     * bar and the scene
     * @returns {XML}
     */
123 124 125 126 127 128 129 130 131 132 133 134
    render() {
        return (
            <Navigator
                renderScene={this.renderScene.bind(this)}
                navigator={this.props.navigator}
                navigationBar={
                    <Navigator.NavigationBar style={styles.navigationBar}
                                             routeMapper={NavigationBarRouteMapper} />
                }/>
        );
    }

135 136 137 138 139 140
    /**
     * render the scene
     * @param route
     * @param navigator
     * @returns {XML}
     */
141 142 143 144 145
    renderScene(route, navigator) {
        return (
            <View style={styles.sceneContainerWithNavbar}>

                <View style={styles.stepsContainer}>
146 147 148 149 150 151 152 153 154
                    <Image style={styles.stepsIcon}
                           source={require('../../assets/images/steps.png')}>

                    </Image>
                    <Text style={styles.stepsLabel}>
                        Today's Steps
                    </Text>
                    <Text style={styles.stepsValue}>
                        {this.state.stepsToday}
155 156 157 158
                    </Text>
                </View>

                <View style={styles.historyContainer}>
159 160 161 162 163
                    <View style={styles.titleRow}>
                        <Text>
                            History
                        </Text>
                    </View>
164 165 166 167 168 169 170
                    <History data={this.state.stepHistory} />
                </View>

            </View>
        );
    }

171 172 173 174 175 176 177 178
    /**
     * if 'err' is truthy then log the error message and
     * return true indicating an error has occurred
     * @param err
     * @param method
     * @returns {boolean}
     * @private
     */
179 180 181
    _handleHKError(err, method) : boolean {
        if(err){
            let errStr = 'HealthKit_ERROR['+method+'] : ';
182
            errStr += (err && err.message) ? err.message : err;
183 184 185 186 187 188 189 190 191 192 193 194 195
            console.log(errStr);
            return true;
        }
        return false;
    }
}


var NavigationBarRouteMapper = {
    LeftButton(route, navigator, index, nextState) {
        return null;
    },
    RightButton(route, navigator, index, nextState) {
196 197 198 199 200 201 202 203
        return (
            <TouchableOpacity style={styles.navbarTitleTouchable}
                              onPress={() => { navigator.parentNavigator.push({name: 'Add'})}}>
                <Text style={styles.navbarPlusButton}>
                    +
                </Text>
            </TouchableOpacity>
        );
204 205 206 207 208 209 210 211 212 213 214 215 216 217
    },
    Title(route, navigator, index, nextState) {
        return (
            <TouchableOpacity style={styles.navbarTitleTouchable}>
                <Text style={styles.navbarTitle}>
                    HealthKit Steps
                </Text>
            </TouchableOpacity>
        );
    }
};

module.exports = Home;
export default Home;