Skip to content

Commit

Permalink
Merge pull request #4 from Expensify/master
Browse files Browse the repository at this point in the history
Merge
  • Loading branch information
tugbadogan authored Feb 17, 2021
2 parents a851d91 + 88a0c5e commit f4d4ab4
Show file tree
Hide file tree
Showing 16 changed files with 146 additions and 134 deletions.
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ android {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
multiDexEnabled rootProject.ext.multiDexEnabled
versionCode 438
versionName "1.0.1-439"
versionCode 443
versionName "1.0.1-444"
}
splits {
abi {
Expand Down
2 changes: 1 addition & 1 deletion ios/ExpensifyCash/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>438</string>
<string>443</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false />
<key>LSRequiresIPhoneOS</key>
Expand Down
2 changes: 1 addition & 1 deletion ios/ExpensifyCashTests/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>438</string>
<string>443</string>
</dict>
</plist>
2 changes: 1 addition & 1 deletion package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "expensify.cash",
"version": "1.0.1-439",
"version": "1.0.1-444",
"author": "Expensify, Inc.",
"homepage": "https://expensify.cash",
"description": "Expensify.cash is the next generation of Expensify: a reimagination of payments based atop a foundation of chat.",
Expand Down
2 changes: 1 addition & 1 deletion src/Expensify.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ class Expensify extends PureComponent {

<Route path={[ROUTES.SET_PASSWORD]} component={SetPasswordPage} />
<Route path={[ROUTES.NOT_FOUND]} component={NotFoundPage} />
<Route path={[ROUTES.SIGNIN_WITH_EXITTO, ROUTES.SIGNIN]} component={SignInPage} />
<Route path={[ROUTES.SIGNIN]} component={SignInPage} />
<Route
path={[ROUTES.HOME, ROUTES.ROOT]}
render={() => (
Expand Down
2 changes: 0 additions & 2 deletions src/ROUTES.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,5 @@ export default {
SEARCH: '/search',
SET_PASSWORD: '/setpassword/:validateCode',
SIGNIN: '/signin',
SIGNIN_WITH_EXITTO: '/signIn/exitTo/:exitTo*',
getSigninWithExitToRoute: exitTo => `/signin/exitTo${exitTo}`,
NOT_FOUND: '/404',
};
6 changes: 6 additions & 0 deletions src/libs/API.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ function getAuthToken() {
* @param {String} parameters.partnerUserID
* @param {String} parameters.partnerUserSecret
* @param {String} [parameters.twoFactorAuthCode]
* @param {String} [parameters.email]
* @returns {Promise}
*/
function Authenticate(parameters) {
Expand Down Expand Up @@ -214,6 +215,9 @@ function Authenticate(parameters) {

// Force this request to be made because the network queue is paused when re-authentication is happening
forceNetworkRequest: true,

// Add email param so the first Authenticate request is logged on the server w/ this email
email: parameters.email,
})
.then((response) => {
// If we didn't get a 200 response from Authenticate we either failed to Authenticate with
Expand Down Expand Up @@ -323,6 +327,8 @@ function User_SignUp(parameters) {
* @param {String} parameters.partnerPassword
* @param {String} parameters.partnerUserID
* @param {String} parameters.partnerUserSecret
* @param {Boolean} [parameters.doNotRetry]
* @param {String} [parameters.email]
* @returns {Promise}
*/
function CreateLogin(parameters) {
Expand Down
22 changes: 5 additions & 17 deletions src/libs/Log.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import Logger from 'expensify-common/lib/Logger';
import Onyx from 'react-native-onyx';
import * as API from './API';
import CONFIG from '../CONFIG';
import getPlatform from './getPlatform';
import {version} from '../../package.json';
import ONYXKEYS from '../ONYXKEYS';

let email;
Onyx.connect({
key: ONYXKEYS.SESSION,
callback: val => email = val ? val.email : null,
});
import NetworkConnection from './NetworkConnection';

/**
* Network interface for logger.
Expand All @@ -26,25 +19,20 @@ function serverLoggingCallback(params) {
expensifyCashAppVersion: `expensifyCash[${getPlatform()}]${version}`,
};

// If we are logging something and have no email
// then we do not want to include this. If we pass
// this as null or undefined that will literally
// appear in the logs instead of we@dont.know
if (email) {
requestParams.email = email;
}

API.Log(requestParams);
}

// Note: We are importing Logger from expensify-common because it is
// used by other platforms. The server and client logging
// callback methods are passed in here so we can decouple
// the logging library from the logging methods.
export default new Logger({
const Log = new Logger({
serverLoggingCallback,
clientLoggingCallback: (message) => {
console.debug(message);
},
isDebug: !CONFIG.IS_IN_PRODUCTION,
});

NetworkConnection.registerLogInfoCallback(Log.info);
export default Log;
25 changes: 22 additions & 3 deletions src/libs/Network.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ Onyx.connect({
callback: val => isOffline = val && val.isOffline,
});

// Subscribe to the user's session so we can include their email in every request and include it in the server logs
let email;
Onyx.connect({
key: ONYXKEYS.SESSION,
callback: val => email = val ? val.email : null,
});

/**
* Process the networkRequestQueue by looping through the queue and attempting to make the requests
*/
Expand All @@ -32,8 +39,15 @@ function processNetworkRequestQueue() {
// 2. Getting a 200 response back from the API (happens right below)
// 3. NetInfo triggering an event that the network is back online

const data = {
doNotRetry: true,
};
if (email) {
data.email = email;
}

// Make a simple request every second to see if the API is online again
HttpUtils.xhr('Get', {doNotRetry: true})
HttpUtils.xhr('Get', data)
.then(() => NetworkConnection.setOfflineStatus(false))
.catch(e => console.debug('[Ping] failed', e));
return;
Expand All @@ -53,9 +67,14 @@ function processNetworkRequestQueue() {
return;
}

const requestData = queuedRequest.data;
if (email) {
requestData.email = email;
}

const finalParameters = _.isFunction(enhanceParameters)
? enhanceParameters(queuedRequest.command, queuedRequest.data)
: queuedRequest.data;
? enhanceParameters(queuedRequest.command, requestData)
: requestData;

// Check to see if the queue has paused again. It's possible that a call to enhanceParameters()
// has paused the queue and if this is the case we must return.
Expand Down
42 changes: 35 additions & 7 deletions src/libs/NetworkConnection.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import _ from 'underscore';
import {AppState} from 'react-native';
import NetInfo from '@react-native-community/netinfo';
import Onyx from 'react-native-onyx';
import ONYXKEYS from '../ONYXKEYS';
Expand All @@ -9,15 +10,17 @@ let unsubscribeFromNetInfo;
let sleepTimer;
let lastTime;
let isOffline = false;
let listeningForAppStateChanges = false;
let logInfo = () => {};

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

/**
* Loop over all reconnection callbacks and fire each one
*/
const triggerReconnectionCallbacks = _.throttle(() => {
console.debug('[Reconnection]: Firing reconnection callbacks');
const triggerReconnectionCallbacks = _.throttle((reason) => {
logInfo(`[NetworkConnection] Firing reconnection callbacks because ${reason}`, true);
_.each(reconnectionCallbacks, callback => callback());
}, 5000, {trailing: false});

Expand All @@ -33,34 +36,46 @@ function setOfflineStatus(isCurrentlyOffline) {
// When reconnecting, ie, going from offline to online, all the reconnection callbacks
// are triggered (this is usually Actions that need to re-download data from the server)
if (isOffline && !isCurrentlyOffline) {
triggerReconnectionCallbacks();
triggerReconnectionCallbacks('offline status changed');
}

isOffline = isCurrentlyOffline;
}

function logAppStateChange(state) {
logInfo('[NetworkConnection] AppState change event', true, {state});
}

/**
* Set up the event listener for NetInfo to tell whether the user has
* internet connectivity or not. This is more reliable than the Pusher
* `disconnected` event which takes about 10-15 seconds to emit.
*/
function listenForReconnect() {
logInfo('[NetworkConnection] listenForReconnect called', true);

if (!listeningForAppStateChanges) {
AppState.addEventListener('change', logAppStateChange);
listeningForAppStateChanges = true;
}

// Subscribe to the state change event via NetInfo so we can update
// whether a user has internet connectivity or not.
unsubscribeFromNetInfo = NetInfo.addEventListener((state) => {
console.debug('[NetInfo] isConnected:', state && state.isConnected);
logInfo(`[NetworkConnection] NetInfo isConnected: ${state && state.isConnected}`);
setOfflineStatus(!state.isConnected);
});

// When a device is put to sleep, NetInfo is not always able to detect
// when connectivity has been lost. As a failsafe we will capture the time
// every two seconds and if the last time recorded is greater than 20 seconds
// every two seconds and if the last time recorded is greater than 4 seconds
// we know that the computer has been asleep.
lastTime = (new Date()).getTime();
sleepTimer = setInterval(() => {
const currentTime = (new Date()).getTime();
if (currentTime > (lastTime + 20000)) {
triggerReconnectionCallbacks();
const isSkewed = currentTime > (lastTime + 4000);
if (isSkewed) {
triggerReconnectionCallbacks('sleep timer clock skewed');
}
lastTime = currentTime;
}, 2000);
Expand All @@ -70,11 +85,16 @@ function listenForReconnect() {
* Tear down the event listeners when we are finished with them.
*/
function stopListeningForReconnect() {
logInfo('[NetworkConnection] stopListeningForReconnect called', true);
clearInterval(sleepTimer);
if (unsubscribeFromNetInfo) {
unsubscribeFromNetInfo();
unsubscribeFromNetInfo = undefined;
}
if (listeningForAppStateChanges) {
AppState.removeEventListener('change', logAppStateChange);
listeningForAppStateChanges = false;
}
}

/**
Expand All @@ -86,10 +106,18 @@ function onReconnect(callback) {
reconnectionCallbacks.push(callback);
}

/**
* @param {Function} callback
*/
function registerLogInfoCallback(callback) {
logInfo = callback;
}

export default {
setOfflineStatus,
listenForReconnect,
stopListeningForReconnect,
onReconnect,
triggerReconnectionCallbacks,
registerLogInfoCallback,
};
17 changes: 14 additions & 3 deletions src/libs/PusherConnectionManager.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as Pusher from './Pusher/pusher';
import * as API from './API';
import Log from './Log';

function init() {
/**
Expand All @@ -10,7 +11,7 @@ function init() {
*/
Pusher.registerCustomAuthorizer(channel => ({
authorize: (socketID, callback) => {
console.debug('[Network] Attempting to authorize Pusher');
Log.info('[PusherConnectionManager] Attempting to authorize Pusher', true);

API.Push_Authenticate({
socket_id: socketID,
Expand All @@ -26,7 +27,7 @@ function init() {
return;
}

console.debug('[Pusher] Pusher authenticated successfully');
Log.info('[PusherConnectionManager] Pusher authenticated successfully', true);
callback(null, data);
});
},
Expand All @@ -38,11 +39,21 @@ function init() {
*
* @params {string} eventName
*/
Pusher.registerSocketEventCallback((eventName) => {
Pusher.registerSocketEventCallback((eventName, data) => {
switch (eventName) {
case 'error':
Log.info('[PusherConnectionManager] error event', true, {error: data});
Pusher.reconnect();
break;
case 'connected':
Log.info('[PusherConnectionManager] connected event', true);
break;
case 'disconnected':
Log.info('[PusherConnectionManager] disconnected event', true);
break;
case 'state_change':
Log.info('[PusherConnectionManager] state_change event', true, {states: data});
break;
default:
break;
}
Expand Down
Loading

0 comments on commit f4d4ab4

Please sign in to comment.