Skip to content

Commit

Permalink
fix conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
marcaaron committed Aug 24, 2020
2 parents d28867f + fb03397 commit 458b646
Show file tree
Hide file tree
Showing 15 changed files with 102 additions and 56 deletions.
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@
* Rename this file to `.env` and put your local config in here
*/
REPORT_IDS=1,2,3
EXPENSIFY_API_ROOT=https://www.expensify.com.dev/api?
EXPENSIFY_PARTNER_NAME=android
EXPENSIFY_PARTNER_PASSWORD=c3a9ac418ea3f152aae2
PUSHER_APP_KEY=ac6d22b891daae55283a
PUSHER_AUTH_URL=https://www.expensify.com.dev
5 changes: 5 additions & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
REPORT_IDS=63212778,63212795,63212764,63212607,63699490
EXPENSIFY_API_ROOT=https://www.expensify.com/api?
EXPENSIFY_PARTNER_NAME=chat-expensify-com
EXPENSIFY_PARTNER_PASSWORD=e21965746fd75f82bb66
PUSHER_APP_KEY=268df511a204fbb60884
PUSHER_AUTH_URL=https://www.expensify.com
16 changes: 7 additions & 9 deletions src/CONFIG.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import {Platform} from 'react-native';
import Config from 'react-native-config';

// eslint-disable-next-line no-undef
const IS_IN_PRODUCTION = Platform.OS === 'web' ? process.env.NODE_ENV === 'production' : !__DEV__;

export default {
AUTH_TOKEN_EXPIRATION_TIME: 1000 * 60 * 90,
EXPENSIFY: {
API_ROOT: IS_IN_PRODUCTION ? 'https://www.expensify.com/api?' : 'https://www.expensify.com.dev/api?',
PARTNER_NAME: IS_IN_PRODUCTION ? 'chat-expensify-com' : 'android',
PARTNER_PASSWORD: IS_IN_PRODUCTION ? 'e21965746fd75f82bb66' : 'c3a9ac418ea3f152aae2',
API_ROOT: Config.EXPENSIFY_API_ROOT,
PARTNER_NAME: Config.EXPENSIFY_PARTNER_NAME,
PARTNER_PASSWORD: Config.EXPENSIFY_PARTNER_PASSWORD,
},
IS_IN_PRODUCTION,
// eslint-disable-next-line no-undef
IS_IN_PRODUCTION: Platform.OS === 'web' ? process.env.NODE_ENV === 'production' : !__DEV__,
PUSHER: {
APP_KEY: IS_IN_PRODUCTION ? '268df511a204fbb60884' : 'ac6d22b891daae55283a',
AUTH_URL: IS_IN_PRODUCTION ? 'https://www.expensify.com' : 'https://www.expensify.com.dev',
APP_KEY: Config.PUSHER_APP_KEY,
AUTH_URL: Config.PUSHER_AUTH_URL,
CLUSTER: 'mt1',
},
REPORT_IDS: Config.REPORT_IDS,
Expand Down
2 changes: 1 addition & 1 deletion src/Expensify.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import SignInPage from './page/SignInPage';
import HomePage from './page/HomePage/HomePage';
import Ion from './lib/Ion';
import * as ActiveClientManager from './lib/ActiveClientManager';
import {verifyAuthToken} from './lib/actions/ActionsSession';
import {verifyAuthToken} from './lib/actions/Session';
import IONKEYS from './IONKEYS';
import WithIon from './components/WithIon';
import styles from './style/StyleSheet';
Expand Down
90 changes: 59 additions & 31 deletions src/lib/Network.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ import ROUTES from '../ROUTES';
import Str from './Str';
import Guid from './Guid';
import {registerSocketEventCallback} from './Pusher/pusher';
import redirectToSignIn from './actions/ActionsSignInRedirect';

let isAppOffline = false;
import redirectToSignIn from './actions/SignInRedirect';

// Indicates if we're in the process of re-authenticating. When an API call returns jsonCode 407 indicating that the
// authToken expired, we set this to true, pause all API calls, re-authenticate, and then use the authToken fromm the
Expand All @@ -19,11 +17,30 @@ let reauthenticating = false;
// Queue for network requests so we don't lose actions done by the user while offline
const networkRequestQueue = [];

// Holds all of the callbacks that need to be triggered when the network reconnects
const reconnectionCallbacks = [];

/**
* Called when the offline status of the app changes and if the network is "reconnecting" (going from offline to online)
* then all of the reconnection callbacks are triggered
*
* @param {boolean} isCurrentlyOffline
*/
function setNewOfflineStatus(isCurrentlyOffline) {
Ion.get(IONKEYS.NETWORK, 'isOffline')
.then((prevWasOffline) => {
Ion.merge(IONKEYS.NETWORK, {isOffline: isCurrentlyOffline});
if (prevWasOffline && !isCurrentlyOffline) {
_.each(reconnectionCallbacks, cb => cb());
}
});
}

// Subscribe to the state change event via NetInfo so we can update
// whether a user has internet connectivity or not. This is more reliable
// than the Pusher `disconnected` event which takes about 10-15 seconds to emit
NetInfo.addEventListener((state) => {
Ion.merge(IONKEYS.NETWORK, {isOffline: !state.isConnected});
setNewOfflineStatus(!state.isConnected);
});

/**
Expand All @@ -50,8 +67,7 @@ registerSocketEventCallback((eventName, data) => {
default:
break;
}
isAppOffline = isCurrentlyOffline;
Ion.merge(IONKEYS.NETWORK, {isOffline: isCurrentlyOffline});
setNewOfflineStatus(isCurrentlyOffline);
});

/**
Expand Down Expand Up @@ -115,14 +131,13 @@ function xhr(command, data, type = 'post') {
.then(formData => fetch(`${CONFIG.EXPENSIFY.API_ROOT}command=${command}`, {
method: type,
body: formData,
})
.then(response => response.json()))
}))
.then(response => response.json())

// This will catch any HTTP network errors (like 404s and such), not to be confused with jsonCode which this
// does NOT catch
.catch(() => {
isAppOffline = true;
Ion.merge(IONKEYS.NETWORK, {isOffline: true});
setNewOfflineStatus(true);

// If the request failed, we need to put the request object back into the queue as long as there is no
// doNotRetry option set in the data
Expand Down Expand Up @@ -238,35 +253,48 @@ function request(command, data, type = 'post') {
* Process the networkRequestQueue by looping through the queue and attempting to make the requests
*/
function processNetworkRequestQueue() {
if (isAppOffline) {
// Two things will bring the app online again...
// 1. Pusher reconnecting (see registerSocketEventCallback at the top of this file)
// 2. Getting a 200 response back from the API (happens right below)
Ion.get(IONKEYS.NETWORK, 'isOffline')
.then((isOffline) => {
if (isOffline) {
// Two things will bring the app online again...
// 1. Pusher reconnecting (see registerSocketEventCallback at the top of this file)
// 2. Getting a 200 response back from the API (happens right below)

// Make a simple request every second to see if the API is online again
request('Get', {doNotRetry: true})
.then(() => Ion.merge(IONKEYS.NETWORK, {isOffline: false}))
.then(() => isAppOffline = false);
return;
}
// Make a simple request every second to see if the API is online again
xhr('Get', {doNotRetry: true})
.then(() => setNewOfflineStatus(false));
return;
}

// Don't make any requests until we're done re-authenticating since we'll use the new authToken
// from that response for the subsequent network requests
if (reauthenticating || networkRequestQueue.length === 0) {
return;
}
for (let i = 0; i < networkRequestQueue.length; i++) {
// Take the request object out of the queue and make the request
const queuedRequest = networkRequestQueue.shift();
request(queuedRequest.command, queuedRequest.data)
.then(queuedRequest.callback);
}
// Don't make any requests until we're done re-authenticating since we'll use the new authToken
// from that response for the subsequent network requests
if (reauthenticating || networkRequestQueue.length === 0) {
return;
}
for (let i = 0; i < networkRequestQueue.length; i++) {
// Take the request object out of the queue and make the request
const queuedRequest = networkRequestQueue.shift();
request(queuedRequest.command, queuedRequest.data)
.then(queuedRequest.callback);
}
});
}

// Process our write queue very often
setInterval(processNetworkRequestQueue, 1000);

/**
* Register a callback function to be called when the network reconnects
*
* @public
* @param {function} cb
*/
function onReconnect(cb) {
reconnectionCallbacks.push(cb);
}

export {
request,
queueRequest,
onReconnect,
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import _ from 'underscore';
import Ion from '../Ion';
import {queueRequest} from '../Network';
import {onReconnect, queueRequest} from '../Network';
import IONKEYS from '../../IONKEYS';
import md5 from '../md5';
import CONST from '../../CONST';
Expand Down Expand Up @@ -106,6 +106,9 @@ function fetchTimezone() {
return requestPromise;
}

// When the app reconnects from being offline, fetch all of the personal details
onReconnect(fetch);

export {
fetch,
fetchTimezone,
Expand Down
10 changes: 8 additions & 2 deletions src/lib/actions/ActionsReport.js → src/lib/actions/Report.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import moment from 'moment';
import _ from 'underscore';
import lodashGet from 'lodash.get';
import Ion from '../Ion';
import {queueRequest} from '../Network';
import {queueRequest, onReconnect} from '../Network';
import IONKEYS from '../../IONKEYS';
import CONFIG from '../../CONFIG';
import * as pusher from '../Pusher/pusher';
Expand Down Expand Up @@ -134,7 +134,8 @@ function fetchAll() {
});

return promiseAllSettled(ionPromises);
});
})
.then(() => fetchedReports);
}

/**
Expand Down Expand Up @@ -244,6 +245,11 @@ function updateLastReadActionID(accountID, reportID, sequenceNumber) {
}));
}

// When the app reconnects from being offline, fetch all of the reports and their history
onReconnect(() => {
fetchAll().then(reports => _.each(reports, report => fetchHistory(report.reportID)));
});

export {
fetchAll,
fetchHistory,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Ion from '../Ion';
import {request} from '../Network';
import IONKEYS from '../../IONKEYS';
import CONFIG from '../../CONFIG';
import redirectToSignIn from './ActionsSignInRedirect';
import redirectToSignIn from './SignInRedirect';

/**
* Sign in with the API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import ROUTES from '../../ROUTES';

/**
* Redirects to the sign in page and handles adding any exitTo params to the URL.
* Normally this method would live in ActionsSession.js, but that would cause a circular dependency with Network.js.
* Normally this method would live in Session.js, but that would cause a circular dependency with Network.js.
*
* @returns {Promise}
*/
Expand Down
2 changes: 1 addition & 1 deletion src/page/HomePage/HomePage.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import Sidebar from './SidebarView';
import Main from './MainView';
import Ion from '../../lib/Ion';
import IONKEYS from '../../IONKEYS';
import {initPusher} from '../../lib/actions/ActionsReport';
import {initPusher} from '../../lib/actions/Report';
import * as pusher from '../../lib/Pusher/pusher';

const windowSize = Dimensions.get('window');
Expand Down
7 changes: 4 additions & 3 deletions src/page/HomePage/Report/ReportHistoryItem.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import {View} from 'react-native';
import PropTypes from 'prop-types';
import _ from 'underscore';
import ReportHistoryItemSingle from './ReportHistoryItemSingle';
import ReportHistoryPropsTypes from './ReportHistoryPropsTypes';
import ReportHistoryItemGrouped from './ReportHistoryItemGrouped';
Expand All @@ -19,9 +20,9 @@ const propTypes = {
class ReportHistoryItem extends React.Component {
shouldComponentUpdate(nextProps) {
// This component should only render if the history item's sequenceNumber or displayAsGroup props change
return nextProps.historyItem.sequenceNumber !== this.props.historyItem.sequenceNumber
|| nextProps.displayAsGroup !== this.props.displayAsGroup
|| nextProps.authToken !== this.props.authToken;
return nextProps.displayAsGroup !== this.props.displayAsGroup
|| nextProps.authToken !== this.props.authToken
|| !_.isEqual(nextProps.historyItem, this.props.historyItem);
}

render() {
Expand Down
2 changes: 1 addition & 1 deletion src/page/HomePage/Report/ReportHistoryView.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import _ from 'underscore';
import lodashGet from 'lodash.get';
import Text from '../../../components/Text';
import Ion from '../../../lib/Ion';
import {fetchHistory, updateLastReadActionID} from '../../../lib/actions/ActionsReport';
import {fetchHistory, updateLastReadActionID} from '../../../lib/actions/Report';
import WithIon from '../../../components/WithIon';
import IONKEYS from '../../../IONKEYS';
import ReportHistoryItem from './ReportHistoryItem';
Expand Down
2 changes: 1 addition & 1 deletion src/page/HomePage/Report/ReportView.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {View} from 'react-native';
import PropTypes from 'prop-types';
import ReportHistoryView from './ReportHistoryView';
import ReportHistoryCompose from './ReportHistoryCompose';
import {addHistoryItem} from '../../../lib/actions/ActionsReport';
import {addHistoryItem} from '../../../lib/actions/Report';
import KeyboardSpacer from '../../../components/KeyboardSpacer';
import styles from '../../../style/StyleSheet';

Expand Down
6 changes: 3 additions & 3 deletions src/page/HomePage/SidebarView.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import {
} from 'react-native';
import PropTypes from 'prop-types';
import Text from '../../components/Text';
import {signOut} from '../../lib/actions/ActionsSession';
import {fetch as getPersonalDetails} from '../../lib/actions/ActionsPersonalDetails';
import {signOut} from '../../lib/actions/Session';
import {fetch as getPersonalDetails} from '../../lib/actions/PersonalDetails';
import styles, {getSafeAreaMargins} from '../../style/StyleSheet';
import WithIon from '../../components/WithIon';
import IONKEYS from '../../IONKEYS';
import {fetchAll} from '../../lib/actions/ActionsReport';
import {fetchAll} from '../../lib/actions/Report';
import SidebarLink from './SidebarLink';
import logo from '../../../assets/images/expensify-logo_reversed.png';
import PageTitleUpdater from '../../lib/PageTitleUpdater';
Expand Down
2 changes: 1 addition & 1 deletion src/page/SignInPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from 'react-native';
import PropTypes from 'prop-types';
import {withRouter} from '../lib/Router';
import {signIn} from '../lib/actions/ActionsSession';
import {signIn} from '../lib/actions/Session';
import IONKEYS from '../IONKEYS';
import WithIon from '../components/WithIon';
import styles from '../style/StyleSheet';
Expand Down

0 comments on commit 458b646

Please sign in to comment.