Skip to content

Commit

Permalink
Merge pull request #23 from joebochill/tutorials
Browse files Browse the repository at this point in the history
Tutorials
  • Loading branch information
joebochill authored Nov 2, 2018
2 parents f9da977 + ffee957 commit 80d43b6
Show file tree
Hide file tree
Showing 43 changed files with 1,041 additions and 631 deletions.
16 changes: 15 additions & 1 deletion App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { AppRegistry, StatusBar } from 'react-native';
import { AsyncStorage, AppRegistry, StatusBar } from 'react-native';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';

Expand All @@ -11,6 +11,10 @@ import thunk from 'redux-thunk';
import SplashScreen from 'react-native-splash-screen';
import { PermissionsAndroid } from 'react-native';

import {ASYNC_PREFIX} from './src/constants/index';
import {setToken} from './src/actions/LoginActions';
import { loadTutorials } from './src/utils/tutorials';

async function requestPermissions() {
try {
const cameragranted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.CAMERA);
Expand All @@ -28,10 +32,20 @@ const store = createStore(
);

class SwingEssentialsApp extends React.Component {
constructor(props){
super(props);
AsyncStorage.getItem(ASYNC_PREFIX+'token')
.then((token)=>{
if(token){store.dispatch(setToken(token));}
});
loadTutorials(store.dispatch);
}

componentDidMount(){
SplashScreen.hide();
requestPermissions();
}

render() {
StatusBar.setBarStyle('light-content', true);
return (
Expand Down
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ android {
applicationId "com.swingessentials.app"
minSdkVersion 23
targetSdkVersion 26
versionCode 25
versionName "2.1.0"
versionCode 28
versionName "2.1.4"
ndk {
abiFilters "armeabi-v7a", "x86"
}
Expand Down
4 changes: 2 additions & 2 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.swingessentials.app"
android:versionCode="24"
android:versionName="2.1.0">
android:versionCode="28"
android:versionName="2.1.4">

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Expand Down
2 changes: 1 addition & 1 deletion ios/swingessentialsapp/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.1</string>
<string>2.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleURLTypes</key>
Expand Down
35 changes: 35 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
"react-native-iap": "^0.3.24",
"react-native-image-picker": "^0.26.10",
"react-native-keychain": "^3.0.0",
"react-native-modal": "^6.5.0",
"react-native-snap-carousel": "^3.7.5",
"react-native-splash-screen": "3.0.9",
"react-native-touch-id": "^4.0.4",
"react-native-vector-icons": "^4.6.0",
Expand Down
2 changes: 1 addition & 1 deletion src/actions/BlogActions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncStorage } from 'react-native';
// import { AsyncStorage } from 'react-native';

/* Constants */
import {BASEURL, AUTH, failure, success, checkTimeout} from './actions.js';
Expand Down
15 changes: 14 additions & 1 deletion src/actions/LoginActions.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {AsyncStorage} from 'react-native';
/* Constants */
import {BASEURL, AUTH, failure, success, checkTimeout} from './actions';
import {getUserData, getSettings} from './UserDataActions';
Expand All @@ -8,25 +9,34 @@ import * as Keychain from 'react-native-keychain';

export const LOGIN = {SUCCESS: 'LOGIN_SUCCESS', FAIL: 'LOGIN_FAIL'};
export const LOGOUT = {SUCCESS: 'LOGOUT_SUCCESS', FAIL: 'LOGOUT_FAIL'};
export const SET_TOKEN = {REQUEST: 'SET_TOKEN_REQUEST'};
export const REFRESH_TOKEN = {REQUEST: 'REFRESH_TOKEN', SUCCESS: 'REFRESH_TOKEN_SUCCESS', FAIL: 'REFRESH_TOKEN_FAIL'};
export const CHECK_TOKEN = {REQUEST: 'CHECK_TOKEN', SUCCESS: 'CHECK_TOKEN_SUCCESS', FAIL: 'CHECK_TOKEN_FAIL'};
export const DATA_FROM_TOKEN = {REQUEST: 'DATA_FROM_TOKEN', SUCCESS: 'DATA_FROM_TOKEN_SUCCESS', FAIL: 'DATA_FROM_TOKEN_FAIL'};


import {btoa} from '../utils/base64.js';
import { ASYNC_PREFIX } from '../constants';

/* requests application data from a token after returning from background */
export function requestDataFromToken(token){
return (dispatch) => {
dispatch({type:DATA_FROM_TOKEN.REQUEST});
// dispatch(getUserData(token));
dispatch(getUserData(token));
dispatch(getLessons(token));
dispatch(getCredits(token));
// dispatch(getTips(token));
// dispatch(getSettings(token));
}
}

export function setToken(token){
return (dispatch) => {
dispatch({type:SET_TOKEN.REQUEST, data: token});
dispatch(requestDataFromToken(token));
}
}

/* submit username/pass credentials to get a auth token */
export function requestLogin(userCredentials){
return (dispatch) => {
Expand All @@ -42,6 +52,7 @@ export function requestLogin(userCredentials){
const token = response.headers.get('Token');
response.json()
.then((json) => dispatch(success(LOGIN.SUCCESS, {...json,token:token})));
AsyncStorage.setItem(ASYNC_PREFIX+'token', token);
dispatch(getLessons(token));
dispatch(getCredits(token));
dispatch(getSettings(token));
Expand Down Expand Up @@ -70,6 +81,7 @@ export function requestLogout(token){
switch(response.status) {
case 200:
dispatch(success(LOGOUT.SUCCESS));
AsyncStorage.removeItem(ASYNC_PREFIX+'token');
break;
default:
checkTimeout(response, dispatch);
Expand All @@ -95,6 +107,7 @@ export function refreshToken(token){
const token = response.headers.get('Token');
//localStorage.setItem('token', token);
dispatch(success(REFRESH_TOKEN.SUCCESS, {token: token}));
AsyncStorage.setItem(ASYNC_PREFIX+'token', token);
break;
default:
checkTimeout(response, dispatch);
Expand Down
8 changes: 2 additions & 6 deletions src/actions/PackageActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@ import {BASEURL, AUTH, failure, success, checkTimeout} from './actions.js';
export const GET_PACKAGES = {REQUEST: 'GET_PACKAGES', SUCCESS: 'GET_PACKAGES_SUCCESS', FAIL: 'GET_PACKAGES_FAIL'};

/* Retrieves List of available lesson packages and prices */
export function getPackages(token){
export function getPackages(token = null){
return (dispatch) => {
dispatch({type:GET_PACKAGES.REQUEST});

return fetch(BASEURL+'packages', {
headers: {
[AUTH]: 'Bearer ' + token
}
})
return fetch(BASEURL+'packages')
.then((response) => {
switch(response.status) {
case 200:
Expand Down
2 changes: 1 addition & 1 deletion src/actions/TipActions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncStorage } from 'react-native';
// import { AsyncStorage } from 'react-native';

/* Constants */
import {BASEURL, AUTH, failure, success, checkTimeout} from './actions.js';
Expand Down
22 changes: 22 additions & 0 deletions src/actions/TutorialActions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { AsyncStorage } from 'react-native';
import {APP_VERSION, ASYNC_PREFIX} from '../constants/index';

/* Constants */
// import {BASEURL, AUTH, failure, success, checkTimeout} from './actions.js';
export const MARK_TUTORIAL = {VIEWED: 'MARK_TUTORIAL_VIEWED', NEW: 'MARK_TUTORIAL_NEW'};


/* Updates the store and AsyncStorage so that a tutorial is only shown once */
export function tutorialViewed(tutorial){
return (dispatch) => {
dispatch({type: MARK_TUTORIAL.VIEWED, data: tutorial});
AsyncStorage.setItem(ASYNC_PREFIX+tutorial, APP_VERSION);
}
}

/* Sets the specified tutorial to show */
export function tutorialNew(tutorial){
return (dispatch) => {
dispatch({type: MARK_TUTORIAL.NEW, data: tutorial});
}
}
8 changes: 0 additions & 8 deletions src/actions/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
export const LOCATION_CHANGE = '@@router/LOCATION_CHANGE';
export const TOKEN_TIMEOUT = 'TOKEN_TIMEOUT';
export const GET_PACKAGES = {REQUEST: 'GET_PACKAGES', SUCCESS: 'GET_PACKAGES_SUCCESS', FAIL: 'GET_PACKAGES_FAIL'};
export const SET_TARGET_ROUTE = {REQUEST: 'SET_TARGET_ROUTE', SUCCESS: 'SET_TARGET_ROUTE_SUCCESS', FAIL: 'SET_TARGET_ROUTE_FAIL'};

/* Base URL for fetch commands */
// export const BASEURL = 'http://www.josephpboyle.com/api/swingessentialsapi.php/';
Expand All @@ -28,13 +27,6 @@ export function checkTimeout(response, dispatch){
}
}

/* Sets the page to go to after navigating into the application from an external link. App will navigate
to that page after the user has authenticated */
export function setTargetRoute(loc, extra = null){
return (dispatch) => {
dispatch({type: SET_TARGET_ROUTE.REQUEST, data: {loc: loc, extra: extra}});
}
}

/* Dispatch a failure action for the supplied action type */
export function failure(type, response){
Expand Down
2 changes: 1 addition & 1 deletion src/components/Card/CardRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class CardRow extends React.Component {
<Text style={{fontSize: scale(14), color: colors.purple, flex: 0, opacity: this.props.disabled ? 0.7 : 1}}>{this.props.secondary}</Text>
}
{this.props.secondaryInput}
{this.props.action && !this.props.menuItem &&
{(this.props.action || this.props.nav) && !this.props.menuItem &&
<MaterialIcons name="ios-arrow-forward"
size={scale(16)}
style={{ fontSize: scale(14), color: colors.purple, paddingLeft: spacing.small, flex: 0, opacity: this.props.disabled ? 0.7 : 1 }}
Expand Down
36 changes: 18 additions & 18 deletions src/components/CustomDrawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {requestLogout,
requestDataFromToken} from '../actions/LoginActions';
import {getTips} from '../actions/TipActions';
import {getBlogs} from '../actions/BlogActions';
import {getPackages} from '../actions/PackageActions';
import { setTargetRoute} from '../actions/actions';
import LogoutWarning from './Modal/TokenExpire';

Expand All @@ -25,9 +26,7 @@ function mapStateToProps(state){
username: state.userData.username,
token: state.login.token,
lessons: state.lessons,
modalWarning: state.login.modalWarning,
targetRoute: state.links.targetRoute,
// tips: state.tips.tipList
modalWarning: state.login.modalWarning
};
}

Expand All @@ -38,7 +37,8 @@ function mapDispatchToProps(dispatch){
showLogoutWarning: (show) => dispatch(showLogoutWarning(show)),
setTargetRoute: (loc, extra) => dispatch(setTargetRoute(loc, extra)),
getTips: (token = null) => dispatch(getTips(token)),
getBlogs: (token = null) => dispatch(getBlogs(token))
getBlogs: (token = null) => dispatch(getBlogs(token)),
getPackages: (token = null) => dispatch(getPackages(token))
}
}

Expand All @@ -48,15 +48,11 @@ class CustomDrawer extends React.Component {
this.state={
appState: AppState.currentState
}
// TODO: load all data from the saved token
// const token = localStorage.getItem('token');
// if(token){
// store.dispatch(requestDataFromToken(token));
// }

// load the tips of the month and blogs as soon as we load the app
this.props.getTips();
this.props.getBlogs();
this.props.getPackages();
}
componentDidMount(){
AppState.addEventListener('change', this._handleAppStateChange);
Expand Down Expand Up @@ -95,15 +91,15 @@ class CustomDrawer extends React.Component {
let path = event.url.split('/').filter((el) => el.length > 0);

if(event.url.match(/\/lessons\/[A-Z0-9]+\/?$/gi)){
this.props.setTargetRoute('Lesson', path[path.length - 1]);
if(this.props.token) {this.props.navigation.navigate('Lesson')}
if(this.props.token) {this.props.navigation.navigate('Lesson',{url: path[path.length - 1]})}
}
else if(event.url.match(/\/lessons\/?$/gi)){
this.props.setTargetRoute('Lessons', null);
if(this.props.token) {this.props.navigation.navigate('Lessons')}
}
else if(event.url.match(/\/register\/[A-Z0-9]+\/?$/gi)){
this.props.setTargetRoute('Register', path[path.length - 1]);
this.props.navigation.navigate('Register', {code: path[path.length - 1]});
}
else if(event.url.match(/\/register\/?$/gi)){
this.props.navigation.navigate('Register');
}
}
Expand Down Expand Up @@ -135,7 +131,6 @@ class CustomDrawer extends React.Component {
<Text style={{fontSize: scale(14), color:colors.white, marginTop:scale(-14)}}>{this.props.username ? 'Welcome, ' + this.props.username + '!' : ''}</Text>
</View>
<ScrollView contentContainerStyle={{flexGrow: 1, justifyContent:'space-between'}}>
{this.props.token &&
<View style={{marginTop: spacing.normal}}>
<CardRow menuItem primary="Your Lessons"
customStyle={{borderTopWidth: scale(1)}}
Expand All @@ -157,19 +152,24 @@ class CustomDrawer extends React.Component {
<CardRow menuItem primary="Order Lessons"
action={() => this.props.navigation.navigate('Order')}/>
</View>
}
{!this.props.token && <View></View>}
<View>
<CardRow menuItem primary="Tips of the Month"
<CardRow menuItem primary="Tip of the Month"
customStyle={{borderTopWidth: scale(1)}}
action={() => this.props.navigation.navigate('Tips')}/>
<CardRow menuItem primary="The 19th Hole"
action={() => this.props.navigation.navigate('Blogs')}/>
</View>
<View style={{marginBottom: spacing.normal}}>
<CardRow menuItem primary="Sign Out"
{this.props.token &&
<CardRow menuItem primary="Sign Out"
customStyle={{borderTopWidth: scale(1)}}
action={() => this.props.requestLogout(this.props.token)}/>
}
{!this.props.token &&
<CardRow menuItem primary="Sign In / Register"
customStyle={{borderTopWidth: scale(1)}}
action={() => this.props.navigation.push('Auth')}/>
}
<CardRow menuItem primary="Help"
action={() => this.props.navigation.navigate('Help')}/>
<CardRow menuItem primary="About" secondary={`v${APP_VERSION}`}
Expand Down
Loading

0 comments on commit 80d43b6

Please sign in to comment.