diff --git a/android/app/build.gradle b/android/app/build.gradle index 6dd642e9..ccb4a195 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -175,6 +175,7 @@ android { } dependencies { + compile project(':react-native-device-info') compile project(':react-native-paypal') compile project(':react-native-localization') compile project(':react-native-vector-icons') diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 72e7684b..b6bb68eb 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -7,6 +7,8 @@ android:launchMode="singleTop"> + + diff --git a/android/app/src/main/assets/crashlytics-build.properties b/android/app/src/main/assets/crashlytics-build.properties deleted file mode 100644 index f4c950f1..00000000 --- a/android/app/src/main/assets/crashlytics-build.properties +++ /dev/null @@ -1,11 +0,0 @@ -#This file is automatically generated by Crashlytics to uniquely -#identify individual builds of your Android application. -# -#Do NOT modify, delete, or commit to source control! -# -#Sun Oct 15 19:54:12 WIB 2017 -version_name=1.0 -package_name=io.devsummit.app.android -build_id=45307a6a-7e0b-4335-9bc4-c6dc9fd23086 -version_code=1 -app_name=DevSummit diff --git a/android/app/src/main/java/io/devsummit/app/android/MainApplication.java b/android/app/src/main/java/io/devsummit/app/android/MainApplication.java index 2f3c0e89..17e88e71 100644 --- a/android/app/src/main/java/io/devsummit/app/android/MainApplication.java +++ b/android/app/src/main/java/io/devsummit/app/android/MainApplication.java @@ -3,6 +3,7 @@ import android.app.Application; import com.facebook.react.ReactApplication; +import com.learnium.RNDeviceInfo.RNDeviceInfo; import br.com.vizir.rn.paypal.PayPalPackage; import com.babisoft.ReactNativeLocalization.ReactNativeLocalizationPackage; import com.oblador.vectoricons.VectorIconsPackage; @@ -54,6 +55,7 @@ protected List getPackages() { MainApplication.paypalPackage = new PayPalPackage(PAY_PAL_REQUEST_ID); return Arrays.asList( new MainReactPackage(), + new RNDeviceInfo(), new ReactNativeLocalizationPackage(), MainApplication.getPaypalPackage(), new VectorIconsPackage(), diff --git a/android/app/src/main/res/values/com_crashlytics_export_strings.xml b/android/app/src/main/res/values/com_crashlytics_export_strings.xml deleted file mode 100644 index a091ae6f..00000000 --- a/android/app/src/main/res/values/com_crashlytics_export_strings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - -45307a6a-7e0b-4335-9bc4-c6dc9fd23086 - diff --git a/android/settings.gradle b/android/settings.gradle index 891ced56..91285420 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,6 @@ rootProject.name = 'DevSummit' +include ':react-native-device-info' +project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android') include ':react-native-paypal' project(':react-native-paypal').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-paypal/android') include ':react-native-localization' diff --git a/app/components/Splash/index.js b/app/components/Splash/index.js index 52244947..23adf14b 100644 --- a/app/components/Splash/index.js +++ b/app/components/Splash/index.js @@ -4,6 +4,7 @@ import { createTransition, Fade } from 'react-native-transition'; import { Actions } from 'react-native-router-flux'; import { getAccessToken } from '../../helpers'; import SplashScreen from './SplashScreen'; +import { createStructuredSelector } from 'reselect'; const Transition = createTransition(Fade); @@ -16,13 +17,6 @@ export default class Splash extends Component { } componentDidMount() { - getAccessToken().then((accessToken) => { - if (accessToken) { - Actions.mainTabs(); - } else { - Actions.main(); - } - }); } render() { diff --git a/app/containers/Feed/actions.js b/app/containers/Feed/actions.js index aa764bb6..73963be3 100644 --- a/app/containers/Feed/actions.js +++ b/app/containers/Feed/actions.js @@ -56,15 +56,6 @@ export function isFetchingMoreFeeds(status) { }; } -export function setTokenHeader(currentpage) { - return (dispatch) => { - getAccessToken().then((accessToken) => { - Api.setAuthorizationToken(accessToken); - dispatch(fetchFeeds(currentpage)); - }); - }; -} - export function fetchFeeds(currentpage) { return (dispatch) => { dispatch(isFetchingFeeds(true)); diff --git a/app/containers/Feed/index.js b/app/containers/Feed/index.js index a401b929..579f9569 100644 --- a/app/containers/Feed/index.js +++ b/app/containers/Feed/index.js @@ -50,6 +50,7 @@ import strings from '../../localization'; import HeaderPoint from '../../components/Header'; import * as actions from './actions'; import * as selectors from './selectors'; +import { getProfileData } from '../Main/selectors'; import OrderList from '../OrderList'; import Redeem from '../Redeem'; import { PRIMARYCOLOR } from '../../constants'; @@ -132,7 +133,8 @@ const mapStateToProps = () => imagesData: selectors.getUpdateImage(), textData: selectors.getUpdateText(), currentPage: selectors.getCurrentPage(), - isRemoving: selectors.getIsRemoveFeed() + isRemoving: selectors.getIsRemoveFeed(), + profileData: getProfileData(), }); class Feed extends Component { @@ -170,16 +172,12 @@ class Feed extends Component { } componentWillMount() { - this.props.setTokenHeader(this.props.currentPage); - - AsyncStorage.getItem('profile_data').then((profile) => { - const data = JSON.parse(profile); - const firstName = data.first_name; - const lastName = data.last_name; - const url = data.photos[0].url; - const id = data.id; - this.setState({ firstName, lastName, profileUrl: url, userId: id }); - }); + // const data = this.props.profileData; + // const firstName = data.first_name; + // const lastName = data.last_name; + // const url = data.photos[0].url; + // const id = data.id; + // this.setState({ firstName, lastName, profileUrl: url, userId: id }); } setModalVisible = (visible, image) => { diff --git a/app/containers/Main/actions.js b/app/containers/Main/actions.js index 61a92c04..d4031473 100644 --- a/app/containers/Main/actions.js +++ b/app/containers/Main/actions.js @@ -5,6 +5,7 @@ import { Actions } from 'react-native-router-flux'; import axios from 'axios'; import { DevSummitAxios } from '../../helpers'; +import api from '../../services/api'; /* * import constants @@ -23,7 +24,9 @@ import { GOOGLE_CLIENT_SECRET, TWITTER_CALLBACK, TWITTER_CONSUMER_KEY, - TWITTER_CONSUMER_KEY_SECRET + TWITTER_CONSUMER_KEY_SECRET, + SET_TOKEN, + RESET_TOKEN } from './constants'; /* @@ -74,6 +77,13 @@ export function updateisLoading(status) { }; } +export function setToken(token) { + return { + type: SET_TOKEN, + token + } +} + /* * Log user in * save access_token & refresh_token to asyncstorage @@ -93,17 +103,19 @@ export function login() { .then(async (response) => { if (response && response.data && response.data.meta.success) { const resData = response.data.data; - const roleId = JSON.stringify(response.data.included.role_id); - const profileData = JSON.stringify(response.data.included); - const boothData = JSON.stringify(response.data.included.booth); + const roleId = response.data.included.role_id; + const profileData = response.data.included; + const boothData = response.data.included.booth; try { if (profileData || boothData) { - await AsyncStorage.multiSet([ - [ 'access_token', resData.access_token ], - [ 'refresh_token', resData.refresh_token ], - [ 'role_id', roleId ], - [ 'profile_data', profileData ] - ]); + dispatch(setToken({ + accessToken: resData.access_token, + refreshToken: resData.refresh_token, + roleId, + profileData, + boothData + })) + api.setAuthorizationToken(resData.access_token); } } catch (error) { console.log(error, 'error caught'); @@ -225,15 +237,14 @@ export function loginGoogle() { .then(async (response) => { if (response && response.data && response.data.meta.success) { const resData = response.data.data; - const roleId = JSON.stringify(response.data.included.role_id); - const profileData = JSON.stringify(response.data.included); try { - await AsyncStorage.multiSet([ - [ 'access_token', resData.access_token ], - [ 'refresh_token', resData.refresh_token ], - [ 'role_id', roleId ], - [ 'profile_data', profileData ] - ]); + dispatch(setToken({ + accessToken: resData.access_token, + refreshToken: resData.refresh_token, + roleId: response.data.included.role_id, + profileData: response.data.included, + })) + api.setAuthorizationToken(resData.access_token); } catch (error) { console.log(error, 'error caught'); } @@ -423,3 +434,9 @@ export function subscribeNewsletter() { }); }; } + +export function resetToken() { + return { + type: RESET_TOKEN + } +} diff --git a/app/containers/Main/constants.js b/app/containers/Main/constants.js index ec256cef..acc34323 100644 --- a/app/containers/Main/constants.js +++ b/app/containers/Main/constants.js @@ -15,3 +15,6 @@ export const UPDATE_SINGLE_FIELD = 'app/containers/Main/UPDATE_FIELD'; export const UPDATE_IS_LOGGED_IN = 'app/containers/Main/CHECK_IS_LOGGED_IN'; export const UPDATE_IS_SUBSCRIBED = 'app/containers/Main/UPDATE_IS_SUBSCRIBED'; export const UPDATE_IS_LOADING = 'app/containers/Main/UPDATE_IS_LOADING'; + +export const SET_TOKEN = 'app/containers/Main/SET_TOKEN'; +export const RESET_TOKEN = 'app/containers/Main/RESET_TOKEN'; diff --git a/app/containers/Main/reducer.js b/app/containers/Main/reducer.js index 8920462b..a630d97e 100644 --- a/app/containers/Main/reducer.js +++ b/app/containers/Main/reducer.js @@ -10,7 +10,9 @@ import { UPDATE_IS_SUBSCRIBED, UPDATE_IS_NOT_REGISTERED, UPDATE_IS_LOADING, - FETCH_PROFILE_DATA + FETCH_PROFILE_DATA, + SET_TOKEN, + RESET_TOKEN } from './constants'; /* @@ -24,7 +26,11 @@ const initialState = fromJS({ }, isLoading: false, isLoggedIn: false, - isSubscribed: false + isSubscribed: false, + accessToken: '', + refreshToken: '', + roleId: null, + profileData: null, }); function mainReducer(state = initialState, action) { @@ -37,6 +43,17 @@ function mainReducer(state = initialState, action) { return state.setIn([ 'fields', action.field ], action.value); case UPDATE_IS_LOADING: return state.set('isLoading', action.status); + case SET_TOKEN: + const token = action.token; + return state.set('accessToken', token.accessToken) + .set('refreshToken', token.refreshToken) + .set('roleId', token.roleId) + .set('profileData', token.profileData) + case RESET_TOKEN: + return state.set('accessToken', '') + .set('refreshToken', '') + .set('roleId', null) + .set('profileData', null) default: return state; } diff --git a/app/containers/Main/selectors.js b/app/containers/Main/selectors.js index eefea1a6..e5447779 100644 --- a/app/containers/Main/selectors.js +++ b/app/containers/Main/selectors.js @@ -43,3 +43,21 @@ export const getIsLoading = () => createSelector( selectMainReducer(), state => state.get('isLoading') ); + +/** + * Get access token + * @return boolean + */ +export const getAccessToken = () => createSelector( + selectMainReducer(), + state => state.get('accessToken') +); + +/** + * Get profile data + * @return boolean + */ +export const getProfileData = () => createSelector( + selectMainReducer(), + state => state.get('profileData') +); diff --git a/app/containers/MainTabs/PushNotification.js b/app/containers/MainTabs/PushNotification.js index 1f81c223..51b70a0a 100644 --- a/app/containers/MainTabs/PushNotification.js +++ b/app/containers/MainTabs/PushNotification.js @@ -7,6 +7,7 @@ import Toast from 'react-native-simple-toast'; import FCM, { FCMEvent, RemoteNotificationResult, WillPresentNotificationResult, NotificationType } from 'react-native-fcm'; import { getAccessToken, DevSummitAxios } from '../../helpers'; +import auth from '../../services/auth'; // this shall be called regardless of app state: running, background or not running. @@ -53,20 +54,15 @@ FCM.on(FCMEvent.Notification, async (notif) => { }); FCM.on(FCMEvent.RefreshToken, (token) => { - getAccessToken().then((usertoken) => { - const headers = { Authorization: usertoken }; - DevSummitAxios.patch('auth/me/updatefcmtoken', { token }, { headers }) - .then(async (response) => { - if (response.meta && response.meta.success) { - await AsyncStorage.setItem('fcmtoken', token); - } - }) - .catch((err) => { - console.log(err); - }); - }).catch((err) => { - console.log(err); - }); + auth.updateFcmToken(token) + .then(async (response) => { + if (response.meta && response.meta.success) { + await AsyncStorage.setItem('fcmtoken', token); + } + }) + .catch((err) => { + console.log(err); + }); // fcm token may not be available on first load, catch it here }); @@ -88,20 +84,15 @@ export default class PushNotification extends Component { FCM.getFCMToken().then((token) => { this.setState({ fcm_token: token }); // update your fcm token on server. - getAccessToken().then((usertoken) => { - const headers = { Authorization: usertoken }; - DevSummitAxios.patch('auth/me/updatefcmtoken', { token }, { headers }) - .then(async (response) => { - if (response.meta && response.meta.success) { - await AsyncStorage.setItem('fcmtoken', token); - } - }) - .catch((err) => { - console.log(err); - }); - }).catch((err) => { - console.log(err); - }); + auth.updateFcmToken(token) + .then(async (response) => { + if (response.meta && response.meta.success) { + await AsyncStorage.setItem('fcmtoken', token); + } + }) + .catch((err) => { + console.log(err); + }); }); this.notificationListener = FCM.on(FCMEvent.Notification, async (notif) => { // do some component related stuff diff --git a/app/containers/Settings/actions.js b/app/containers/Settings/actions.js index 56315d06..1e1168f7 100644 --- a/app/containers/Settings/actions.js +++ b/app/containers/Settings/actions.js @@ -12,6 +12,7 @@ import { UPDATE_IS_DISABLED } from './constants'; import { restoreCurrentPage } from '../Feed/actions'; +import { resetToken } from '../Main/actions'; import local from '../../../config/local'; /* @@ -162,6 +163,7 @@ export function logOut() { const keys = [ 'access_token', 'refresh_token', 'role_id', 'profile_data' ]; await AsyncStorage.multiRemove(keys); + dispatch(resetToken()); dispatch(restoreCurrentPage()); dispatch(isLoadingLogout(false)); dispatch(updateIsLogOut(true)); diff --git a/app/containers/Splash/index.js b/app/containers/Splash/index.js new file mode 100644 index 00000000..ac056afa --- /dev/null +++ b/app/containers/Splash/index.js @@ -0,0 +1,41 @@ +import React, { Component } from 'react'; + +import { createTransition, Fade } from 'react-native-transition'; +import { Actions } from 'react-native-router-flux'; +import { connect } from 'react-redux'; +import { createStructuredSelector } from 'reselect'; +import { getAccessToken } from '../Main/selectors'; +import SplashScreen from '../../components/Splash/SplashScreen'; +import Api from '../../services/api'; + +const Transition = createTransition(Fade); + +class Splash extends Component { + constructor() { + super(); + this.state = { + isActive: true + }; + } + + componentDidMount() { + console.log('token', this.props.accessToken); + if (this.props.accessToken && this.props.accessToken !== '') { + Api.setAuthorizationToken(this.props.accessToken); + Actions.mainTabs({ type: 'replace' }); + } else { + Actions.main({ type: 'replace' }); + } + } + + render() { + return ; + } +} + + +const mapStateToProps = () => createStructuredSelector({ + accessToken: getAccessToken() +}); + +export default connect(mapStateToProps, null)(Splash); diff --git a/app/index.js b/app/index.js index 8220c203..6f75156c 100644 --- a/app/index.js +++ b/app/index.js @@ -1,14 +1,16 @@ import React, { Component } from 'react'; import { Router, Scene, Actions } from 'react-native-router-flux'; -import { View, AsyncStorage } from 'react-native'; +import { View, AsyncStorage, NetInfo, StatusBar, Platform } from 'react-native'; import { Container, Content, Spinner } from 'native-base'; import BusyIndicator from 'react-native-busy-indicator'; +import { MessageBar as MessageBarAlert, MessageBarManager } from 'react-native-message-bar'; // Redux imports import { Provider, connect } from 'react-redux'; -import { createStore, applyMiddleware } from 'redux'; +import { createStore, applyMiddleware, compose } from 'redux'; +import { persistStore, autoRehydrate } from 'redux-persist-immutable'; import ReduxThunk from 'redux-thunk'; -import logger from 'redux-logger' +import logger from 'redux-logger'; import reducers from './reducers'; // Style imports @@ -22,6 +24,8 @@ import RegisterPhone from './containers/RegisterPhone'; import Schedule from './containers/Schedule'; import ScheduleDetail from './containers/ScheduleDetail'; import Main from './containers/Main'; +import { setToken } from './containers/Main/actions'; +import { setIsOnline, setConnectionType } from './modules/net/actions'; import ChangePassword from './containers/ChangePassword'; import OrderList from './containers/OrderList'; import TicketList from './containers/TicketList'; @@ -30,7 +34,7 @@ import MainTabs from './containers/MainTabs'; import SpeakerDetail from './containers/SpeakerDetail'; import NewOrder from './containers/NewOrder'; import AttendeesList from './containers/AttendeesList'; -import Splash from './components/Splash'; +import Splash from './containers/Splash'; import Payment from './containers/Payment'; import PaymentDetail from './containers/PaymentDetail'; import BoothList from './containers/BoothList'; @@ -58,16 +62,97 @@ switch (lang) { } strings.setLanguage(setlang); + /** * Apply middlewares */ -export const createStoreWithMiddleware = applyMiddleware(ReduxThunk)(createStore); -const store = createStoreWithMiddleware(reducers); +const store = createStore( + reducers, + undefined, + compose( + applyMiddleware(ReduxThunk), + autoRehydrate(), + ) +); + +function handleConnectivity() { + const { online, connection } = store.getState().get('network').toJS(); + console.log({ online, connection }); + if (!online || [ 'unknown', 'none' ].indexOf(connection) >= 0) { + MessageBarManager.showAlert({ + title: 'Looking for network', + message: 'It seems we can\'t reach out the server at the moment.', + alertType: 'error', + shouldHideAfterDelay: false, + shouldHideOnTap: false, + + titleStyle: { fontSize: 16, fontWeight: 'normal', marginTop: 10, color: 'white' }, + messageStyle: {fontSize: 11, color: 'white'} + }); + } else { + MessageBarManager.hideAlert(); + } +} +function handleConnectivityChange(status) { + console.log('connection', status); + store.dispatch(setConnectionType(status)); + // no connection at all + NetInfo.removeEventListener('connectionChange', handleConnectivityChange); +} +function handleConnectivityStatusChange(status) { + console.log('status', status); + store.dispatch(setIsOnline(status)); + // no connection at all + NetInfo.isConnected.removeEventListener('connectionChange', handleConnectivityStatusChange); +} +const networkListener = () => { + setInterval(() => { + NetInfo.addEventListener('connectionChange', handleConnectivityChange); + NetInfo.isConnected.addEventListener('connectionChange', handleConnectivityStatusChange); + NetInfo.isConnectionExpensive().then(status => console.log(status)); + setTimeout(() => { + handleConnectivity(); + }, 5 * 100); + }, 5 * 1000); +}; + +const persistingStore = (callback = () => {}) => { + persistStore(store, { storage: AsyncStorage }, () => { + AsyncStorage + .multiGet([ 'access_token', 'refresh_token', 'role_id', 'profile_data' ]) + .then(([ accessToken, refreshToken, roleId, profileData ]) => { + const savedToken = store.getState().getIn([ 'main', 'accessToken' ]); + if (!savedToken || savedToken === '') { + store.dispatch(setToken({ + accessToken, + refreshToken, + roleId, + profileData: JSON.parse(profileData) + })); + } + callback(); + }).catch((err) => { + // it means no particular data saved on async storage or just new installation + callback(); + }); + }); +}; export default class App extends Component { constructor(props) { super(props); - this.state = {}; + this.state = { + rehydrated: false + }; + } + + componentWillMount() { + persistingStore(() => { + this.setState({ rehydrated: true }, () => { + MessageBarManager.registerMessageBar(this.messageBar); + networkListener(); + }); + }); } onBackPress = () => { @@ -80,45 +165,52 @@ export default class App extends Component { render() { return ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + {Platform.OS === 'ios' && } + + {this.state.rehydrated && + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + + + { this.messageBar = ref; }} /> + ); } } diff --git a/app/modules/net/actions.js b/app/modules/net/actions.js new file mode 100644 index 00000000..5122b807 --- /dev/null +++ b/app/modules/net/actions.js @@ -0,0 +1,17 @@ +import { + NETWORK_CHANGE, + NETWORK_STATUS_CHANGE, +} from './constants'; + +export const setIsOnline = (value) => { + return { + type: NETWORK_STATUS_CHANGE, + value + } +} +export const setConnectionType = (value) => { + return { + type: NETWORK_CHANGE, + value + } +} diff --git a/app/modules/net/constants.js b/app/modules/net/constants.js new file mode 100644 index 00000000..f507d3a6 --- /dev/null +++ b/app/modules/net/constants.js @@ -0,0 +1,2 @@ +export const NETWORK_CHANGE = 'modules/net/NETWORK_CHANGE'; +export const NETWORK_STATUS_CHANGE = 'modules/net/NETWORK_STATUS_CHANGE'; diff --git a/app/modules/net/reducer.js b/app/modules/net/reducer.js new file mode 100644 index 00000000..c552d045 --- /dev/null +++ b/app/modules/net/reducer.js @@ -0,0 +1,24 @@ +import { fromJS } from 'immutable'; + +import { + NETWORK_CHANGE, + NETWORK_STATUS_CHANGE +} from './constants'; + +const initialState = fromJS({ + online: true, + connection: 'wifi' +}); + +function netReducer(state = initialState, action) { + switch (action.type) { + case NETWORK_STATUS_CHANGE: + return state.set('online', action.value); + case NETWORK_CHANGE: + return state.set('connection', action.value); + default: + return state; + } +} + +export default netReducer; diff --git a/app/modules/net/selectors.js b/app/modules/net/selectors.js new file mode 100644 index 00000000..f4f23f31 --- /dev/null +++ b/app/modules/net/selectors.js @@ -0,0 +1,8 @@ +import { createSelector } from 'reselect'; + +const selectNetworkReducer = () => state => state.get('network'); + +export const isOnline = () => createSelector( + selectNetworkReducer(), + state => state.get('online') +); diff --git a/app/reducers.js b/app/reducers.js index 1a695e98..0f6ab010 100644 --- a/app/reducers.js +++ b/app/reducers.js @@ -22,6 +22,7 @@ import BoothInfoReducer from './containers/BoothInfo/reducer'; import codeRedeemReducer from './containers/Redeem/reducer'; import Notification from './containers/Notification/reducer'; import FeedReducer from './containers/Feed/reducer'; +import network from './modules/net/reducer'; const rootReducers = combineReducers({ main: MainReducer, @@ -44,7 +45,8 @@ const rootReducers = combineReducers({ boothInfo: BoothInfoReducer, code: codeRedeemReducer, notificationList: Notification, - feed: FeedReducer + feed: FeedReducer, + network }); export default rootReducers; diff --git a/app/services/api.js b/app/services/api.js index 1adf5da8..d18185c9 100644 --- a/app/services/api.js +++ b/app/services/api.js @@ -23,19 +23,19 @@ class Api { return this.id; } put(url, json, qs = {}, config) { - return this.sendRequest('PUT', url, { qs, json, config }); + return this.sendRequest('PUT', url, { qs, json, ...config }); } get(url, config = {}, qs) { - return this.sendRequest('GET', url, { qs, config }); + return this.sendRequest('GET', url, { qs, ...config }); } post(url, json, qs = {}, config = {}) { - return this.sendRequest('POST', url, { qs, json, config }); + return this.sendRequest('POST', url, { qs, json, ...config }); } patch(url, form, qs = {}, config = {}) { - return this.sendRequest('PATCH', url, { qs, form, config }); + return this.sendRequest('PATCH', url, { qs, form, ...config }); } delete(url, qs = {}, config = {}) { - return this.sendRequest('DELETE', url, { qs, config }); + return this.sendRequest('DELETE', url, { qs, ...config }); } setHeader(key, value) { this.config.headers[key] = value; @@ -44,7 +44,7 @@ class Api { this.setHeader('Authorization', `${token}`); } sendRequest(requestMethod, url, data = {}) { - let headers = data.config ? data.config.headers || {} : {}; + let headers = data.config ? data.headers || {} : {}; headers = Object.assign({}, this.client.defaults.headers.common, this.config.headers, headers); return this.client diff --git a/app/services/auth.js b/app/services/auth.js new file mode 100644 index 00000000..b7ea83bf --- /dev/null +++ b/app/services/auth.js @@ -0,0 +1,5 @@ +import Api from './api'; + +export default { + updateFcmToken: token => Api.patch(`auth/me/updatefcmtoken`, null, null, { json: {token}}), +}; diff --git a/config/development.js b/config/development.js index 797488da..c070e0d2 100644 --- a/config/development.js +++ b/config/development.js @@ -18,6 +18,6 @@ export default { PAYPAL_CLIENT_ID: 'Ac-Ikn76GlVB5tFLwMoFYEl9FGumrB7NYdkicE5bd7Q_QfWmnKDyK_ZlZ7mFB-MlENIQR1fTvcj1Ivdv', PAYPAL_CURRENCY: 'USD', - PAYPAL_RATE: Math.pow(10, 4), + PAYPAL_RATE: 10 ** 4, PAYPAL_ENV: Platform.OS === 'android' ? 'sandbox' : 0, }; diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 0de84b84..d800a0c9 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,31 +1,31 @@ PODS: - - Crashlytics (3.8.6): - - Fabric (~> 1.6.3) + - Crashlytics (3.9.0): + - Fabric (~> 1.7.0) - DCTAuth (3.0) - - Fabric (1.6.13) - - Firebase/Core (4.2.0): - - FirebaseAnalytics (= 4.0.3) - - FirebaseCore (= 4.0.7) - - FirebaseAnalytics (4.0.3): + - Fabric (1.7.0) + - Firebase/Core (4.3.0): + - FirebaseAnalytics (= 4.0.4) + - FirebaseCore (= 4.0.8) + - FirebaseAnalytics (4.0.4): - FirebaseCore (~> 4.0) - FirebaseInstanceID (~> 2.0) - GoogleToolboxForMac/NSData+zlib (~> 2.1) - nanopb (~> 0.3) - - FirebaseCore (4.0.7): + - FirebaseCore (4.0.8): - GoogleToolboxForMac/NSData+zlib (~> 2.1) - nanopb (~> 0.3) - - FirebaseInstanceID (2.0.3) - - FirebaseMessaging (2.0.3): + - FirebaseInstanceID (2.0.4) + - FirebaseMessaging (2.0.4): - FirebaseAnalytics (~> 4.0) - FirebaseCore (~> 4.0) - FirebaseInstanceID (~> 2.0) - GoogleToolboxForMac/Logger (~> 2.1) - Protobuf (~> 3.1) - - GoogleToolboxForMac/Defines (2.1.1) - - GoogleToolboxForMac/Logger (2.1.1): - - GoogleToolboxForMac/Defines (= 2.1.1) - - GoogleToolboxForMac/NSData+zlib (2.1.1): - - GoogleToolboxForMac/Defines (= 2.1.1) + - GoogleToolboxForMac/Defines (2.1.3) + - GoogleToolboxForMac/Logger (2.1.3): + - GoogleToolboxForMac/Defines (= 2.1.3) + - GoogleToolboxForMac/NSData+zlib (2.1.3): + - GoogleToolboxForMac/Defines (= 2.1.3) - nanopb (0.3.8): - nanopb/decode (= 0.3.8) - nanopb/encode (= 0.3.8) @@ -50,15 +50,15 @@ CHECKOUT OPTIONS: :git: https://github.com/danielctull/DCTAuth.git SPEC CHECKSUMS: - Crashlytics: 95d05f4e4c19a771250c4bd9ce344d996de32bbf + Crashlytics: 64aad5dd97249dd3ff94b979fea140144590cdd3 DCTAuth: 8add154decd00335d62917828896bba790ce47fd - Fabric: 2fb5676bc811af011a04513451f463dac6803206 - Firebase: 9548cae14d69718add12d75a5b312893f7ef89c7 - FirebaseAnalytics: 76f754d37ca5b04f36856729b6af3ca0152d1069 - FirebaseCore: 9a6cc1e3eaf75905390f9220596ad4fd8f92faee - FirebaseInstanceID: a4fc702b5a026f7322964376047f1a3f1f7cc6ff - FirebaseMessaging: eaf1bfff0193170c04ea3ba3bfe983f68f893118 - GoogleToolboxForMac: 8e329f1b599f2512c6b10676d45736bcc2cbbeb0 + Fabric: e6be012366472553807dada21243c5ab8d904151 + Firebase: 83283761a1ef6dc9846e03d08059f51421afbd65 + FirebaseAnalytics: 722b53c7b32bfc7806b06e0093a2f5180d4f2c5a + FirebaseCore: 69b1a5ac5f857ba6d5fd9d5fe794f4786dd5e579 + FirebaseInstanceID: 70c2b877e9338971b2429ea5a4293df6961aa44e + FirebaseMessaging: 3dd86bfda2acb680b05c97f3f8ac566e9bb87b2a + GoogleToolboxForMac: 2501e2ad72a52eb3dfe7bd9aee7dad11b858bd20 nanopb: 5601e6bca2dbf1ed831b519092ec110f66982ca3 Protobuf: 03eef2ee0b674770735cf79d9c4d3659cf6908e8 diff --git a/ios/app.xcodeproj/project.pbxproj b/ios/app.xcodeproj/project.pbxproj index 724eff30..b030fc83 100644 --- a/ios/app.xcodeproj/project.pbxproj +++ b/ios/app.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ 9C98CD9F1F7B681500139C4B /* libjschelpers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EAD1DF850E9000B6D8A /* libjschelpers.a */; }; 9C98CDA01F7B682800139C4B /* libthird-party.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9CF18CE11F711578009E4D56 /* libthird-party.a */; }; 9C98CDA11F7B682C00139C4B /* libyoga.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3DAD3EA51DF850E9000B6D8A /* libyoga.a */; }; + 9CAD63D51F951D94008E85FB /* libRNDeviceInfo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9CAD63D21F95162E008E85FB /* libRNDeviceInfo.a */; }; 9CB86CFB1F7E3A81009143CF /* QBImagePicker.framework in Embed Framework */ = {isa = PBXBuildFile; fileRef = 9CBF94431F7E2CA3001A8393 /* QBImagePicker.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9CB86CFC1F7E3A81009143CF /* RSKImageCropper.framework in Embed Framework */ = {isa = PBXBuildFile; fileRef = 9CBF94441F7E2CA3001A8393 /* RSKImageCropper.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9CBF8E481F75678700AFFF12 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 9CBF8E471F75678700AFFF12 /* Default-568h@2x.png */; }; @@ -301,6 +302,20 @@ remoteGlobalIDString = 7B5D9D0A1B6AD0EA00CF3A83; remoteInfo = ReactNativeLocalization; }; + 9CAD63D11F95162E008E85FB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 50EE28D3B0C84A679CC0542E /* RNDeviceInfo.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = DA5891D81BA9A9FC002B4DB2; + remoteInfo = RNDeviceInfo; + }; + 9CAD63D31F95162E008E85FB /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 50EE28D3B0C84A679CC0542E /* RNDeviceInfo.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = E72EC1401F7ABB5A0001BC90; + remoteInfo = "RNDeviceInfo-tvOS"; + }; 9CE392F81F7A16E80021C0F3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = F6EC7A164CC54E27B1EEDA3A /* RNShare.xcodeproj */; @@ -459,6 +474,7 @@ 365423E507D84F7FA53D5811 /* Roboto.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Roboto.ttf; path = "../node_modules/native-base/Fonts/Roboto.ttf"; sourceTree = ""; }; 4EC68CDBCC424FECBACF47F1 /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 4F82159FA2EC440195EB210F /* RNVectorIcons.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNVectorIcons.xcodeproj; path = "../node_modules/react-native-vector-icons/RNVectorIcons.xcodeproj"; sourceTree = ""; }; + 50EE28D3B0C84A679CC0542E /* RNDeviceInfo.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNDeviceInfo.xcodeproj; path = "../node_modules/react-native-device-info/RNDeviceInfo.xcodeproj"; sourceTree = ""; }; 51799398E8594CCF8CA86A93 /* SimpleLineIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = SimpleLineIcons.ttf; path = "../node_modules/native-base/Fonts/SimpleLineIcons.ttf"; sourceTree = ""; }; 54E45A76BFF891706A35FC1E /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Pods/Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = ""; }; 56489A250B984A028B94D923 /* ReactNativeLocalization.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = ReactNativeLocalization.xcodeproj; path = "../node_modules/react-native-localization/ReactNativeLocalization.xcodeproj"; sourceTree = ""; }; @@ -499,7 +515,9 @@ C44889F647634BC6838DB34F /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/native-base/Fonts/Ionicons.ttf"; sourceTree = ""; }; CCFC7D14F69E4DC5A3A6DDFA /* LRDRCTSimpleToast.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = LRDRCTSimpleToast.xcodeproj; path = "../node_modules/react-native-simple-toast/ios/LRDRCTSimpleToast.xcodeproj"; sourceTree = ""; }; CE15BE6BBAAA4B5BAC62171E /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = ""; }; + CF2CAD6C46F74C319930D4D7 /* libRNDeviceInfo-tvOS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = "libRNDeviceInfo-tvOS.a"; sourceTree = ""; }; CF57C351BC444B37887A25FE /* Montserrat-Bold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Montserrat-Bold.ttf"; path = "../assets/fonts/Montserrat-Bold.ttf"; sourceTree = ""; }; + DB7C12A93D3E4F63892E1BA2 /* libRNDeviceInfo.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNDeviceInfo.a; sourceTree = ""; }; DE8D3178DDE04773B6F95F3A /* OFL.txt */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = OFL.txt; path = "../node_modules/native-base/Fonts/OFL.txt"; sourceTree = ""; }; E018BC4CD4814AF487610BC6 /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialIcons.ttf"; sourceTree = ""; }; E22D7CC99A97DCDD8638412D /* libPods-appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -526,6 +544,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 9CAD63D51F951D94008E85FB /* libRNDeviceInfo.a in Frameworks */, 9CFFFF171F7BF48A00AAF527 /* libimageCropPicker.a in Frameworks */, 9CBF94461F7E2CA9001A8393 /* RSKImageCropper.framework in Frameworks */, 9CFFFF181F7BF48A00AAF527 /* libLRDRCTSimpleToast.a in Frameworks */, @@ -760,6 +779,7 @@ F6EC7A164CC54E27B1EEDA3A /* RNShare.xcodeproj */, 56489A250B984A028B94D923 /* ReactNativeLocalization.xcodeproj */, A34C580BD5764A3D8364D74B /* MFLReactNativePayPal.xcodeproj */, + 50EE28D3B0C84A679CC0542E /* RNDeviceInfo.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -817,11 +837,22 @@ name = Products; sourceTree = ""; }; + 9CAD63CD1F95162E008E85FB /* Products */ = { + isa = PBXGroup; + children = ( + 9CAD63D21F95162E008E85FB /* libRNDeviceInfo.a */, + 9CAD63D41F95162E008E85FB /* libRNDeviceInfo-tvOS.a */, + ); + name = Products; + sourceTree = ""; + }; 9CE392CD1F7A16E70021C0F3 /* Recovered References */ = { isa = PBXGroup; children = ( 4EC68CDBCC424FECBACF47F1 /* libz.tbd */, 7E4FDE8F0E7E4833A7F9E237 /* libMFLReactNativePayPal.a */, + DB7C12A93D3E4F63892E1BA2 /* libRNDeviceInfo.a */, + CF2CAD6C46F74C319930D4D7 /* libRNDeviceInfo-tvOS.a */, ); name = "Recovered References"; sourceTree = ""; @@ -1168,6 +1199,10 @@ ProductGroup = 9CF18CF21F711578009E4D56 /* Products */; ProjectRef = 7C77BA90E20947609A548199 /* RNAccountKit.xcodeproj */; }, + { + ProductGroup = 9CAD63CD1F95162E008E85FB /* Products */; + ProjectRef = 50EE28D3B0C84A679CC0542E /* RNDeviceInfo.xcodeproj */; + }, { ProductGroup = 9CF18CFC1F711579009E4D56 /* Products */; ProjectRef = BD0BC10FCDDF45309B5A4E07 /* RNDocumentPicker.xcodeproj */; @@ -1392,6 +1427,20 @@ remoteRef = 9C9131BE1F7B285A000D018E /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 9CAD63D21F95162E008E85FB /* libRNDeviceInfo.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = libRNDeviceInfo.a; + remoteRef = 9CAD63D11F95162E008E85FB /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 9CAD63D41F95162E008E85FB /* libRNDeviceInfo-tvOS.a */ = { + isa = PBXReferenceProxy; + fileType = archive.ar; + path = "libRNDeviceInfo-tvOS.a"; + remoteRef = 9CAD63D31F95162E008E85FB /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 9CE392F91F7A16E80021C0F3 /* libRNShare.a */ = { isa = PBXReferenceProxy; fileType = archive.ar; @@ -1869,6 +1918,7 @@ "$(SRCROOT)/../node_modules/react-native-share/ios", "$(SRCROOT)/../node_modules/react-native-localization", "$(SRCROOT)/../node_modules/react-native-paypal/ios/**", + "$(SRCROOT)/../node_modules/react-native-device-info/RNDeviceInfo", ); INFOPLIST_FILE = appTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1885,6 +1935,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1916,6 +1968,7 @@ "$(SRCROOT)/../node_modules/react-native-share/ios", "$(SRCROOT)/../node_modules/react-native-localization", "$(SRCROOT)/../node_modules/react-native-paypal/ios/**", + "$(SRCROOT)/../node_modules/react-native-device-info/RNDeviceInfo", ); INFOPLIST_FILE = appTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; @@ -1932,6 +1985,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1972,6 +2027,7 @@ "$(SRCROOT)/../node_modules/react-native-fcm/ios", "$(SRCROOT)/../node_modules/react-native-localization", "$(SRCROOT)/../node_modules/react-native-paypal/ios/**", + "$(SRCROOT)/../node_modules/react-native-device-info/RNDeviceInfo", ); INFOPLIST_FILE = app/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2026,6 +2082,7 @@ "$(SRCROOT)/../node_modules/react-native-fcm/ios", "$(SRCROOT)/../node_modules/react-native-localization", "$(SRCROOT)/../node_modules/react-native-paypal/ios/**", + "$(SRCROOT)/../node_modules/react-native-device-info/RNDeviceInfo", ); INFOPLIST_FILE = app/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2077,6 +2134,7 @@ "$(SRCROOT)/../node_modules/react-native-share/ios", "$(SRCROOT)/../node_modules/react-native-localization", "$(SRCROOT)/../node_modules/react-native-paypal/ios/**", + "$(SRCROOT)/../node_modules/react-native-device-info/RNDeviceInfo", ); INFOPLIST_FILE = "app-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2092,6 +2150,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -2131,6 +2191,7 @@ "$(SRCROOT)/../node_modules/react-native-share/ios", "$(SRCROOT)/../node_modules/react-native-localization", "$(SRCROOT)/../node_modules/react-native-paypal/ios/**", + "$(SRCROOT)/../node_modules/react-native-device-info/RNDeviceInfo", ); INFOPLIST_FILE = "app-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -2146,6 +2207,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -2185,6 +2248,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.app-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2220,6 +2285,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.REACT.app-tvOSTests"; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/package.json b/package.json index e3b623db..a5dae756 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "react-native": "0.46.4", "react-native-busy-indicator": "^1.1.0", "react-native-code-push": "^5.1.0-beta", + "react-native-device-info": "^0.12.0", "react-native-document-picker": "^2.0.0", "react-native-facebook-account-kit": "^0.7.0", "react-native-fcm": "^9.3.0", @@ -30,11 +31,12 @@ "react-native-image-crop-picker": "^0.16.0", "react-native-linear-gradient": "^2.2.0", "react-native-localization": "^0.1.32", + "react-native-message-bar": "git+https://github.com/refactory-id/react-native-message-bar#master", "react-native-oauth": "^2.2.0", "react-native-paypal": "git+https://github.com/refactory-id/react-native-paypal#master", "react-native-photo-grid": "0.0.2", - "react-native-qrcode": "^0.2.6", "react-native-progress": "^3.4.0", + "react-native-qrcode": "^0.2.6", "react-native-router-flux": "^4.0.0-beta.15", "react-native-share": "^1.0.21", "react-native-simple-auth": "^2.1.0", @@ -46,6 +48,8 @@ "redux": "^3.7.2", "redux-immutable": "^4.0.0", "redux-logger": "^3.0.6", + "redux-persist": "^4.10.1", + "redux-persist-immutable": "^4.3.1", "redux-thunk": "^2.2.0", "reselect": "^3.0.1", "socket.io-client": "^1.4.8" diff --git a/yarn.lock b/yarn.lock index 19c212f2..5bbaf3c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3145,7 +3145,7 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -3259,7 +3259,7 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash-es@^4.2.0, lodash-es@^4.2.1: +lodash-es@^4.17.4, lodash-es@^4.2.0, lodash-es@^4.2.1: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.4.tgz#dcc1d7552e150a0640073ba9cb31d70f032950e7" @@ -4223,6 +4223,10 @@ react-native-code-push@^5.1.0-beta: plist "1.2.0" xcode "0.9.2" +react-native-device-info@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-0.12.0.tgz#f534bf61b3da2ac612d9d715a3ac865bbe6482e6" + react-native-dismiss-keyboard@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/react-native-dismiss-keyboard/-/react-native-dismiss-keyboard-1.0.0.tgz#32886242b3f2317e121f3aeb9b0a585e2b879b49" @@ -4300,6 +4304,10 @@ react-native-localization@^0.1.32: version "0.1.32" resolved "https://registry.yarnpkg.com/react-native-localization/-/react-native-localization-0.1.32.tgz#623bf3359abdd0f0afff50951dcf06cffda01b2a" +"react-native-message-bar@git+https://github.com/refactory-id/react-native-message-bar#master": + version "1.6.0" + resolved "git+https://github.com/refactory-id/react-native-message-bar#cea0e2221696fcf2d2ac94c6f76de8c4423cda6f" + react-native-oauth@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/react-native-oauth/-/react-native-oauth-2.2.0.tgz#8aa7fad344b22cd29f24a4c3385244684dbcbe9e" @@ -4622,6 +4630,28 @@ redux-logger@^3.0.6: dependencies: deep-diff "^0.3.5" +redux-persist-immutable@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/redux-persist-immutable/-/redux-persist-immutable-4.3.1.tgz#fcef34a246f1c4ec0ae10ad14a27a614215fd0ee" + dependencies: + redux-persist "^4.0.0" + redux-persist-transform-immutable "^4.1.0" + +redux-persist-transform-immutable@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/redux-persist-transform-immutable/-/redux-persist-transform-immutable-4.3.0.tgz#24720c99f0707dd99e920b95f851ae3d1baa6ed8" + dependencies: + transit-immutable-js "^0.7.0" + transit-js "^0.8.846" + +redux-persist@^4.0.0, redux-persist@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/redux-persist/-/redux-persist-4.10.1.tgz#4fb2b789942f10f56d51cc7ad068d9d6beb46124" + dependencies: + json-stringify-safe "^5.0.1" + lodash "^4.17.4" + lodash-es "^4.17.4" + redux-thunk@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.2.0.tgz#e615a16e16b47a19a515766133d1e3e99b7852e5" @@ -5341,6 +5371,14 @@ tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" +transit-immutable-js@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/transit-immutable-js/-/transit-immutable-js-0.7.0.tgz#993e25089b6311ff402140f556276d6d253005d9" + +transit-js@^0.8.846: + version "0.8.846" + resolved "https://registry.yarnpkg.com/transit-js/-/transit-js-0.8.846.tgz#76e06e8f0e6be27675e3442112f5c9bb75343464" + traverse@0.6.6: version "0.6.6" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"