Skip to content

Commit

Permalink
Merge pull request #299 from backbonelabs/how-to-video
Browse files Browse the repository at this point in the history
How to video
  • Loading branch information
kevhuang authored May 13, 2017
2 parents 3aaee67 + 79b291f commit 908f8d3
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 13 deletions.
8 changes: 8 additions & 0 deletions app/actions/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
HIDE_FULL_MODAL,
SHOW_PARTIAL_MODAL,
HIDE_PARTIAL_MODAL,
ONBOARDING_NEXT_STEP,
REMOVE_ONBOARDING_NEXT_STEP,
} from './types';

export default {
Expand Down Expand Up @@ -31,4 +33,10 @@ export default {
hidePartialModal() {
return { type: HIDE_PARTIAL_MODAL };
},
nextStep() {
return { type: ONBOARDING_NEXT_STEP };
},
removeNextStep() {
return { type: REMOVE_ONBOARDING_NEXT_STEP };
},
};
2 changes: 2 additions & 0 deletions app/actions/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export const HIDE_FULL_MODAL = 'HIDE_FULL_MODAL';
export const SHOW_PARTIAL_MODAL = 'SHOW_PARTIAL_MODAL';
export const HIDE_PARTIAL_MODAL = 'HIDE_PARTIAL_MODAL';
export const UPDATE_BLUETOOTH_STATE = 'UPDATE_BLUETOOTH_STATE';
export const ONBOARDING_NEXT_STEP = 'ONBOARDING_NEXT_STEP';
export const REMOVE_ONBOARDING_NEXT_STEP = 'REMOVE_ONBOARDING_NEXT_STEP';

// auth actions
export const LOGIN = 'LOGIN';
Expand Down
29 changes: 29 additions & 0 deletions app/components/HowTo.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@ import {
View,
Image,
ScrollView,
Linking,
Alert,
} from 'react-native';
import EStyleSheet from 'react-native-extended-stylesheet';
import styles from '../styles/howTo';
import HeadingText from '../components/HeadingText';
import Button from '../components/Button';
import howToUseBackbone from '../images/howTo/howToUseBackbone.png';
import howToStartSession from '../images/howTo/howToStartSession.png';
import howToGetBestResults from '../images/howTo/howToGetBestResults.png';
import relativeDimensions from '../utils/relativeDimensions';
import Mixpanel from '../utils/Mixpanel';

const { applyWidthDifference } = relativeDimensions;
const howToContent = [{
Expand All @@ -30,11 +34,36 @@ const howToContent = [{
height: applyWidthDifference(517),
}];

const openHowToVideo = () => {
Mixpanel.track('openHowToVideo');

const url = 'https://www.youtube.com/embed/Uo27rJAjriw?rel=0&autoplay=0&showinfo=0&controls=0';
Linking.canOpenURL(url)
.then(supported => {
if (supported) {
return Linking.openURL(url);
}
throw new Error();
})
.catch(() => {
// This catch handler will handle rejections from Linking.openURL as well
// as when the user's phone doesn't have any apps to open the URL
Alert.alert(
'How to video',
`${'We could not launch your browser. You can watch the video' +
'by visiting '}https://youtu.be/Uo27rJAjriw.`,
);
});
};

const HowTo = () => (
<ScrollView
removeClippedSubviews={false}
contentContainerStyle={styles.scrollView}
>
<View style={styles.videoLinkContainer}>
<Button text="Watch Video" onPress={openHowToVideo} />
</View>
{
howToContent.map((value, key) => (
<View
Expand Down
31 changes: 23 additions & 8 deletions app/containers/OnBoarding.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import onBoardingFlow from './onBoardingFlow';
import styles from '../styles/onboarding';
import authActions from '../actions/auth';
import userActions from '../actions/user';
import appActions from '../actions/app';
import routes from '../routes';
import Mixpanel from '../utils/Mixpanel';

Expand All @@ -34,6 +35,9 @@ class OnBoarding extends Component {
hasOnboarded: PropTypes.bool,
nickname: PropTypes.string,
}),
app: PropTypes.shape({
nextStep: PropTypes.bool,
}),
isUpdating: PropTypes.bool,
};

Expand Down Expand Up @@ -91,6 +95,12 @@ class OnBoarding extends Component {
Alert.alert('Error', 'Unable to save, please try again');
}
}

// if nextStep is truthy, go to next step
if (nextProps.app.nextStep) {
this.nextStep();
this.props.dispatch(appActions.removeNextStep());
}
}

// componentWillUnmount() {
Expand All @@ -99,16 +109,21 @@ class OnBoarding extends Component {
// }

onClose() {
// check if user already completed step 1
if (this.props.user.hasOnboarded) {
return this.props.navigator.replace(routes.postureDashboard);
}

return Alert.alert(
// If on step 0 (profile), return alert
// If on step 1 (device), return next step
// (default) If last step, redirect to dashboard
switch (this.state.step) {
case 0:
return Alert.alert(
'Are you sure?',
'\nExiting will log you out and can cause you to lose your information',
[{ text: 'Cancel' }, { text: 'Logout', onPress: this.exitOnboarding }]
);
case 1:
return this.nextStep();
default:
this.props.navigator.replace(routes.postureDashboard);
}
}

/**
Expand Down Expand Up @@ -305,8 +320,8 @@ class OnBoarding extends Component {
}

const mapStateToProps = (state) => {
const { user } = state;
return user;
const { user, app } = state;
return { ...user, app };
};

export default connect(mapStateToProps)(OnBoarding);
5 changes: 5 additions & 0 deletions app/containers/device/DeviceConnect.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import styles from '../../styles/device/deviceConnect';
import deviceActions from '../../actions/device';
import Spinner from '../../components/Spinner';
import HeadingText from '../../components/HeadingText';
import appActions from '../../actions/app';

const { BluetoothService } = NativeModules;
const { bluetoothStates, storageKeys } = constants;
Expand Down Expand Up @@ -122,6 +123,7 @@ class DeviceConnect extends Component {

goBackToScene() {
const routebackScenes = {
onboarding: 'onboarding',
device: 'device',
postureDashboard: 'postureDashboard',
};
Expand All @@ -134,6 +136,9 @@ class DeviceConnect extends Component {
// Route to the last route before DeviceScan / DeviceConnect
// If it matches device or postureDashboard in that order
if (routebackScenes[routeName]) {
if (routebackScenes[routeName] === 'onboarding') {
this.props.dispatch(appActions.nextStep());
}
return this.props.navigator.popToRoute(routeStack[i]);
}
}
Expand Down
4 changes: 2 additions & 2 deletions app/containers/onBoardingFlow/Device.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const Device = props => (
primary
style={styles._button}
text="CONNECT"
onPress={() => props.navigator.replace(routes.deviceScan)}
onPress={() => props.navigator.push(routes.deviceScan)}
/>
<View style={{ paddingTop: 15 }}>
<Button
Expand All @@ -38,7 +38,7 @@ const Device = props => (
Device.propTypes = {
key: PropTypes.number,
navigator: PropTypes.shape({
replace: PropTypes.func,
push: PropTypes.func,
}),
previousStep: PropTypes.func,
};
Expand Down
56 changes: 56 additions & 0 deletions app/containers/onBoardingFlow/HowToVideo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React, { PropTypes } from 'react';
import { WebView, View } from 'react-native';
import BodyText from '../../components/BodyText';
import Button from '../../components/Button';
import Spinner from '../../components/Spinner';
import styles from '../../styles/onBoarding/device';
import HeadingText from '../../components/HeadingText';

import routes from '../../routes';

const showSpinner = () => <Spinner />;
const showErrorMessage = () => (
<BodyText>An error has occur, Please try again later</BodyText>
);

const HowToVideo = (props) => (
<View key={props.key} style={styles.container}>
<View style={styles.headerTextContainer}>
<HeadingText size={2}>Tutorial</HeadingText>
</View>
{props.step === 2 ? <WebView
source={{
uri: 'https://www.youtube.com/embed/Uo27rJAjriw?rel=0&autoplay=0&showinfo=0&controls=0' }}
javaScriptEnabled
startInLoadingState
renderLoading={showSpinner}
renderError={showErrorMessage}
/> : null}
<View style={styles.buttonContainer}>
<Button
primary
style={styles._button}
text="DONE"
onPress={() => props.navigator.replace(routes.postureDashboard)}
/>
<View style={{ paddingTop: 15 }}>
<Button
style={styles._button}
text="BACK"
onPress={props.previousStep}
/>
</View>
</View>
</View>
);

HowToVideo.propTypes = {
key: PropTypes.number,
step: PropTypes.number,
navigator: PropTypes.shape({
replace: PropTypes.func,
}),
previousStep: PropTypes.func,
};

export default HowToVideo;
3 changes: 2 additions & 1 deletion app/containers/onBoardingFlow/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Profile from './Profile';
import Device from './Device';
import HowToVideo from './HowToVideo';

export default [Profile, Device];
export default [Profile, Device, HowToVideo];
15 changes: 15 additions & 0 deletions app/reducers/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
HIDE_FULL_MODAL,
SHOW_PARTIAL_MODAL,
HIDE_PARTIAL_MODAL,
ONBOARDING_NEXT_STEP,
REMOVE_ONBOARDING_NEXT_STEP,
} from '../actions/types';

export default (state = {
Expand All @@ -17,6 +19,7 @@ export default (state = {
content: null,
onClose: null,
},
nextStep: false,
}, action) => {
switch (action.type) {
case UPDATE_BLUETOOTH_STATE: {
Expand Down Expand Up @@ -86,6 +89,18 @@ export default (state = {
},
};
}
case ONBOARDING_NEXT_STEP: {
return {
...state,
nextStep: true,
};
}
case REMOVE_ONBOARDING_NEXT_STEP: {
return {
...state,
nextStep: false,
};
}
default:
return state;
}
Expand Down
17 changes: 15 additions & 2 deletions app/routes/device/deviceScan.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import { connect } from 'react-redux';
import React, { PropTypes } from 'react';
import { TouchableOpacity } from 'react-native';
import routes from '../../routes';
import DeviceScan from '../../containers/device/DeviceScan';
import BodyText from '../../components/BodyText';
import routes from '../../routes';
import Mixpanel from '../../utils/Mixpanel';

const DeviceScanSkipButton = props => (
<TouchableOpacity
style={{ padding: 5 }}
onPress={() => {
Mixpanel.track('skipScanForDevices');
props.navigator.replace(routes.postureDashboard);
// Loop through routeStack starting with the most recent route
const routeStack = props.navigator.getCurrentRoutes().reverse();

for (let i = 0; i < routeStack.length; i++) {
// if onboarding is in the stack, use pop() to redirect
if (routeStack[i].name === routes.onboarding.name) {
return props.navigator.pop();
}
}

// Else redirect to dashboard
return props.navigator.replace(routes.postureDashboard);
}}
>
<BodyText style={{ color: '#FFFFFF' }}>Skip</BodyText>
Expand All @@ -20,7 +31,9 @@ const DeviceScanSkipButton = props => (

DeviceScanSkipButton.propTypes = {
navigator: PropTypes.shape({
pop: PropTypes.func,
replace: PropTypes.func,
getCurrentRoutes: PropTypes.func,
}),
};

Expand Down
6 changes: 6 additions & 0 deletions app/styles/howTo.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,10 @@ export default EStyleSheet.create({
paddingVertical: applyWidthDifference(10),
...absoluteCenter,
},
videoLinkContainer: {
paddingVertical: applyWidthDifference(16),
...absoluteCenter,
width: '100%',
backgroundColor: '#eee',
},
});

0 comments on commit 908f8d3

Please sign in to comment.