From 075f04f6eb01f75284a7d9165f95965699e045db Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 25 Oct 2022 14:58:27 -0700 Subject: [PATCH 01/25] Add a dev only switch to force offline mode --- src/components/TestToolMenu.js | 8 ++++++++ src/libs/actions/Network.js | 9 +++++++++ 2 files changed, 17 insertions(+) diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index 908c0a8db8a1..764d51e9be27 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -47,6 +47,14 @@ const TestToolMenu = props => ( /> + {/* When toggled the app will be forced offline. */} + + Network.setShouldForceOffline(!props.network.shouldForceOffline)} + /> + + {/* When toggled all network requests will fail. */} Date: Tue, 25 Oct 2022 15:34:32 -0700 Subject: [PATCH 02/25] Force offline if needed when the app mounts --- src/Expensify.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Expensify.js b/src/Expensify.js index 93224dfd9321..bf51a3f92aec 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -20,9 +20,14 @@ import Log from './libs/Log'; import ConfirmModal from './components/ConfirmModal'; import compose from './libs/compose'; import withLocalize, {withLocalizePropTypes} from './components/withLocalize'; +import withEnvironment, {environmentPropTypes} from './components/withEnvironment'; +import {withNetwork} from './components/OnyxProvider'; +import networkPropTypes from './components/networkPropTypes'; import * as User from './libs/actions/User'; import NetworkConnection from './libs/NetworkConnection'; import Navigation from './libs/Navigation/Navigation'; +import * as Network from './libs/actions/Network'; +import CONST from './CONST'; Onyx.registerLogger(({level, message}) => { if (level === 'alert') { @@ -63,6 +68,8 @@ const propTypes = { }), ...withLocalizePropTypes, + ...environmentPropTypes, + ...networkPropTypes, }; const defaultProps = { @@ -109,6 +116,11 @@ class Expensify extends PureComponent { PushNotification.clearNotifications(); } + // Force offline mode on staging or dev if needed + if (_.contains([CONST.ENVIRONMENT.STAGING, CONST.ENVIRONMENT.DEV], this.props.environment)) { + Network.setIsOffline(this.props.network.shouldForceOffline); + } + this.setState({isOnyxMigrated: true}); }); @@ -218,6 +230,8 @@ Expensify.propTypes = propTypes; Expensify.defaultProps = defaultProps; export default compose( withLocalize, + withEnvironment, + withNetwork(), withOnyx({ session: { key: ONYXKEYS.SESSION, From 510189296a99f2fed49edf32f37bea1f5b7d0e96 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 25 Oct 2022 16:15:03 -0700 Subject: [PATCH 03/25] Ignore network state change when forcing offline --- src/libs/NetworkConnection.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index 972c3dcd5179..0cb31fe210b3 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -1,10 +1,19 @@ import _ from 'underscore'; +import Onyx from 'react-native-onyx'; import NetInfo from '@react-native-community/netinfo'; import AppStateMonitor from './AppStateMonitor'; import Log from './Log'; import * as NetworkActions from './actions/Network'; import CONFIG from '../CONFIG'; import CONST from '../CONST'; +import ONYXKEYS from '../ONYXKEYS'; + +let shouldForceOffline; +Onyx.connect({ + key: ONYXKEYS.NETWORK, + waitForCollectionCallback: true, + callback: val => shouldForceOffline = val.network.shouldForceOffline, +}); let isOffline = false; let hasPendingNetworkCheck = false; @@ -65,6 +74,10 @@ function subscribeToNetInfo() { // whether a user has internet connectivity or not. NetInfo.addEventListener((state) => { Log.info('[NetworkConnection] NetInfo state change', false, state); + if (shouldForceOffline) { + Log.info('[NetworkConnection] Not setting offline status because shouldForceOffline', false, shouldForceOffline); + return; + } setOfflineStatus(state.isInternetReachable === false); }); } From 587955a68d7d6a2b442cfc7f054e1304e14d71bf Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 31 Oct 2022 14:51:38 -0700 Subject: [PATCH 04/25] Default to false for shouldForceOffline connection --- src/libs/NetworkConnection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index 0cb31fe210b3..15a394193022 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -12,7 +12,7 @@ let shouldForceOffline; Onyx.connect({ key: ONYXKEYS.NETWORK, waitForCollectionCallback: true, - callback: val => shouldForceOffline = val.network.shouldForceOffline, + callback: val => shouldForceOffline = (val.network && val.network.shouldForceOffline) || false, }); let isOffline = false; From 294101e22008dfebdd01db6c1e9355cf475c2b39 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 31 Oct 2022 14:52:13 -0700 Subject: [PATCH 05/25] Fix network prop types --- src/Expensify.js | 4 +++- src/components/networkPropTypes.js | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Expensify.js b/src/Expensify.js index bf51a3f92aec..081281665cb9 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -67,9 +67,11 @@ const propTypes = { roomName: PropTypes.string, }), + /** Information about the network */ + network: networkPropTypes.isRequired, + ...withLocalizePropTypes, ...environmentPropTypes, - ...networkPropTypes, }; const defaultProps = { diff --git a/src/components/networkPropTypes.js b/src/components/networkPropTypes.js index ecfcc3b601cb..40cbf990d81f 100644 --- a/src/components/networkPropTypes.js +++ b/src/components/networkPropTypes.js @@ -4,6 +4,9 @@ export default PropTypes.shape({ /** Is the network currently offline or not */ isOffline: PropTypes.bool, + /** Should the network be forced offline */ + shouldForceOffline: PropTypes.bool, + /** Whether we should fail all network requests */ shouldFailAllRequests: PropTypes.bool, }); From 3b7930145e8dff1cfca3625747890590d58f12c8 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 31 Oct 2022 15:14:00 -0700 Subject: [PATCH 06/25] Fix shouldForceOffline again --- src/libs/NetworkConnection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index 15a394193022..6188b95673de 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -12,7 +12,7 @@ let shouldForceOffline; Onyx.connect({ key: ONYXKEYS.NETWORK, waitForCollectionCallback: true, - callback: val => shouldForceOffline = (val.network && val.network.shouldForceOffline) || false, + callback: val => shouldForceOffline = val.shouldForceOffline || false, }); let isOffline = false; From 036b7185a51ebb0b02f8b2c7191626192c34fef5 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 31 Oct 2022 15:54:43 -0700 Subject: [PATCH 07/25] Ignore shouldForceOffline while signed out --- src/libs/actions/SignInRedirect.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index d221ba62f6be..8e7a79b67d63 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -19,9 +19,13 @@ Onyx.connect({ }); let currentIsOffline; +let currentShouldForceOffline; Onyx.connect({ key: ONYXKEYS.NETWORK, - callback: val => currentIsOffline = val.isOffline, + callback: (val) => { + currentIsOffline = val.isOffline; + currentShouldForceOffline = val.shouldForceOffline || false; + }, }); /** @@ -31,6 +35,7 @@ function clearStorageAndRedirect(errorMessage) { const activeClients = currentActiveClients; const preferredLocale = currentPreferredLocale; const isOffline = currentIsOffline; + const shouldForceOffline = currentShouldForceOffline; // Clearing storage discards the authToken. This causes a redirect to the SignIn screen Onyx.clear() @@ -41,7 +46,10 @@ function clearStorageAndRedirect(errorMessage) { if (activeClients && activeClients.length > 0) { Onyx.set(ONYXKEYS.ACTIVE_CLIENTS, activeClients); } - if (isOffline) { + + // After sigining out set ourselves as offline if we were offline before logging out and we are not forcing it. + // If we are forcing offline, ignore it while signed out, otherwise it would require a refresh because there's no way to toggle the switch, to go back online, while signed out. + if (isOffline && !shouldForceOffline) { Onyx.set(ONYXKEYS.NETWORK, {isOffline}); } From 14bbfd8273727b3008aed8a8ad242f02b652d258 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 21 Nov 2022 17:31:47 -0800 Subject: [PATCH 08/25] Clean up log line and a comment --- src/libs/NetworkConnection.js | 2 +- src/libs/actions/SignInRedirect.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index 6188b95673de..d71ebf2ce1eb 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -75,7 +75,7 @@ function subscribeToNetInfo() { NetInfo.addEventListener((state) => { Log.info('[NetworkConnection] NetInfo state change', false, state); if (shouldForceOffline) { - Log.info('[NetworkConnection] Not setting offline status because shouldForceOffline', false, shouldForceOffline); + Log.info('[NetworkConnection] Not setting offline status because shouldForceOffline = true'); return; } setOfflineStatus(state.isInternetReachable === false); diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index 8e7a79b67d63..a6d4e3554e4e 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -47,8 +47,8 @@ function clearStorageAndRedirect(errorMessage) { Onyx.set(ONYXKEYS.ACTIVE_CLIENTS, activeClients); } - // After sigining out set ourselves as offline if we were offline before logging out and we are not forcing it. - // If we are forcing offline, ignore it while signed out, otherwise it would require a refresh because there's no way to toggle the switch, to go back online, while signed out. + // After signing out, set ourselves as offline if we were offline before logging out and we are not forcing it. + // If we are forcing offline, ignore it while signed out, otherwise it would require a refresh because there's no way to toggle the switch to go back online while signed out. if (isOffline && !shouldForceOffline) { Onyx.set(ONYXKEYS.NETWORK, {isOffline}); } From b6db0a765528c1a8301c7a57deebd6e760d71380 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 21 Nov 2022 18:15:39 -0800 Subject: [PATCH 09/25] Network store is also offline when forcing it --- src/libs/Network/NetworkStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Network/NetworkStore.js b/src/libs/Network/NetworkStore.js index 67b57f966974..4227ca164de0 100644 --- a/src/libs/Network/NetworkStore.js +++ b/src/libs/Network/NetworkStore.js @@ -80,7 +80,7 @@ Onyx.connect({ triggerReconnectCallback(); } - offline = network.isOffline; + offline = network.isOffline || network.shouldForceOffline; }, }); From a16d31afd71870945c89b9a834b767071e0a7001 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 22 Nov 2022 13:43:00 -0800 Subject: [PATCH 10/25] Fail to fetch if forcing offline --- src/libs/HttpUtils.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index 4c8fe2ee6b30..f18a6def4665 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -13,9 +13,16 @@ Onyx.connect({ }); let shouldFailAllRequests = false; +let shouldForceOffline = false; Onyx.connect({ key: ONYXKEYS.NETWORK, - callback: val => shouldFailAllRequests = (val && _.isBoolean(val.shouldFailAllRequests)) ? val.shouldFailAllRequests : false, + callback: (network) => { + if (!network) { + return; + } + shouldFailAllRequests = _.isBoolean(network.shouldFailAllRequests) ? network.shouldFailAllRequests : false; + shouldForceOffline = network.shouldForceOffline; + }, }); // We use the AbortController API to terminate pending request in `cancelPendingRequests` @@ -40,7 +47,7 @@ function processHTTPRequest(url, method = 'get', body = null, canCancel = true) }) .then((response) => { // Test mode where all requests will succeed in the server, but fail to return a response - if (shouldFailAllRequests) { + if (shouldFailAllRequests || shouldForceOffline) { throw new HttpsError({ message: CONST.ERROR.FAILED_TO_FETCH, }); From 6ba03a9adb87270bc2003719172926e6ea9ba57e Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Tue, 22 Nov 2022 13:56:31 -0800 Subject: [PATCH 11/25] Convert shouldForceOffline to boolean if undefined --- src/libs/HttpUtils.js | 2 +- src/libs/Network/NetworkStore.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index f18a6def4665..5436a01a967f 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -21,7 +21,7 @@ Onyx.connect({ return; } shouldFailAllRequests = _.isBoolean(network.shouldFailAllRequests) ? network.shouldFailAllRequests : false; - shouldForceOffline = network.shouldForceOffline; + shouldForceOffline = Boolean(network.shouldForceOffline); }, }); diff --git a/src/libs/Network/NetworkStore.js b/src/libs/Network/NetworkStore.js index 4227ca164de0..1e7b6d583fc4 100644 --- a/src/libs/Network/NetworkStore.js +++ b/src/libs/Network/NetworkStore.js @@ -80,7 +80,7 @@ Onyx.connect({ triggerReconnectCallback(); } - offline = network.isOffline || network.shouldForceOffline; + offline = network.isOffline || Boolean(network.shouldForceOffline); }, }); From db4ce83e559df9305fb57e60e2474f272620c7e8 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 23 Nov 2022 12:07:29 -0800 Subject: [PATCH 12/25] Force offline mode in the Expensify constructor --- src/Expensify.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Expensify.js b/src/Expensify.js index 081281665cb9..9feb1dd6a2f4 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -99,6 +99,12 @@ class Expensify extends PureComponent { isSplashShown: true, }; + // Force offline mode on staging or dev if needed + if (_.contains([CONST.ENVIRONMENT.STAGING, CONST.ENVIRONMENT.DEV], this.props.environment)) { + // network.isOffline is always initialized to false, so set its value based on shouldForceOffline + Network.setIsOffline(this.props.network.shouldForceOffline); + } + // Used for the offline indicator appearing when someone is offline NetworkConnection.subscribeToNetInfo(); } @@ -118,11 +124,6 @@ class Expensify extends PureComponent { PushNotification.clearNotifications(); } - // Force offline mode on staging or dev if needed - if (_.contains([CONST.ENVIRONMENT.STAGING, CONST.ENVIRONMENT.DEV], this.props.environment)) { - Network.setIsOffline(this.props.network.shouldForceOffline); - } - this.setState({isOnyxMigrated: true}); }); From a96133bf75c05e4fd3a92b7b39586c233223198a Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 23 Nov 2022 12:24:40 -0800 Subject: [PATCH 13/25] Boolean constructor for clarity and consistency --- src/libs/HttpUtils.js | 2 +- src/libs/NetworkConnection.js | 2 +- src/libs/actions/SignInRedirect.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libs/HttpUtils.js b/src/libs/HttpUtils.js index 5436a01a967f..60971fe1b0b3 100644 --- a/src/libs/HttpUtils.js +++ b/src/libs/HttpUtils.js @@ -20,7 +20,7 @@ Onyx.connect({ if (!network) { return; } - shouldFailAllRequests = _.isBoolean(network.shouldFailAllRequests) ? network.shouldFailAllRequests : false; + shouldFailAllRequests = Boolean(network.shouldFailAllRequests); shouldForceOffline = Boolean(network.shouldForceOffline); }, }); diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index d71ebf2ce1eb..0d4fd300c929 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -12,7 +12,7 @@ let shouldForceOffline; Onyx.connect({ key: ONYXKEYS.NETWORK, waitForCollectionCallback: true, - callback: val => shouldForceOffline = val.shouldForceOffline || false, + callback: val => shouldForceOffline = Boolean(val.shouldForceOffline), }); let isOffline = false; diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index a6d4e3554e4e..8cbae3d1296d 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -24,7 +24,7 @@ Onyx.connect({ key: ONYXKEYS.NETWORK, callback: (val) => { currentIsOffline = val.isOffline; - currentShouldForceOffline = val.shouldForceOffline || false; + currentShouldForceOffline = Boolean(val.shouldForceOffline); }, }); From 6fada1a5bdb1e03281390fb8cf0597c7a6f0013c Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 23 Nov 2022 12:25:58 -0800 Subject: [PATCH 14/25] Remove redundant default --- src/components/TestToolMenu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index 764d51e9be27..0ef8a92255bf 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -50,7 +50,7 @@ const TestToolMenu = props => ( {/* When toggled the app will be forced offline. */} Network.setShouldForceOffline(!props.network.shouldForceOffline)} /> From 1bbe8aea89daf7a8805b9bfd6ec753ca0278f7ae Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 23 Nov 2022 12:31:22 -0800 Subject: [PATCH 15/25] Evaluate shouldForceOffline first --- src/libs/Network/NetworkStore.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/Network/NetworkStore.js b/src/libs/Network/NetworkStore.js index 1e7b6d583fc4..6d4a9dd8856f 100644 --- a/src/libs/Network/NetworkStore.js +++ b/src/libs/Network/NetworkStore.js @@ -80,7 +80,7 @@ Onyx.connect({ triggerReconnectCallback(); } - offline = network.isOffline || Boolean(network.shouldForceOffline); + offline = Boolean(network.shouldForceOffline) || network.isOffline; }, }); From 3608ff48bae755a35a3cc32c2b47e319250aaa18 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 23 Nov 2022 14:10:47 -0800 Subject: [PATCH 16/25] Clean up Onyx network connections --- src/libs/NetworkConnection.js | 8 ++++++-- src/libs/actions/SignInRedirect.js | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index 0d4fd300c929..65058a0cf2cc 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -11,8 +11,12 @@ import ONYXKEYS from '../ONYXKEYS'; let shouldForceOffline; Onyx.connect({ key: ONYXKEYS.NETWORK, - waitForCollectionCallback: true, - callback: val => shouldForceOffline = Boolean(val.shouldForceOffline), + callback: (network) => { + if (!network) { + return; + } + shouldForceOffline = Boolean(network.shouldForceOffline); + }, }); let isOffline = false; diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index 8cbae3d1296d..9dc63952b5dd 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -22,9 +22,12 @@ let currentIsOffline; let currentShouldForceOffline; Onyx.connect({ key: ONYXKEYS.NETWORK, - callback: (val) => { - currentIsOffline = val.isOffline; - currentShouldForceOffline = Boolean(val.shouldForceOffline); + callback: (network) => { + if (!network) { + return; + } + currentIsOffline = network.isOffline; + currentShouldForceOffline = Boolean(network.shouldForceOffline); }, }); From 16802f09cda3550677da3337ad65e198a84af78a Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 23 Nov 2022 14:45:08 -0800 Subject: [PATCH 17/25] Set real isOffline value after force offline --- src/libs/actions/Network.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/Network.js b/src/libs/actions/Network.js index bb70a3e0dc9f..1b56bbf9d7e8 100644 --- a/src/libs/actions/Network.js +++ b/src/libs/actions/Network.js @@ -1,4 +1,5 @@ import Onyx from 'react-native-onyx'; +import NetInfo from '@react-native-community/netinfo'; import ONYXKEYS from '../../ONYXKEYS'; /** @@ -13,7 +14,14 @@ function setIsOffline(isOffline) { * @param {Boolean} shouldForceOffline */ function setShouldForceOffline(shouldForceOffline) { - Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline, isOffline: shouldForceOffline}); + if (shouldForceOffline) { + Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline, isOffline: shouldForceOffline}); + } else { + Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline}); + + // If we are no longer forcing offline, refresh the NetInfo to trigger a state change which will set isOffline appropriately + NetInfo.refresh(); + } } /** From 2d1c45fa18552e86be3038636534c77297c85376 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Wed, 23 Nov 2022 15:14:49 -0800 Subject: [PATCH 18/25] Fetch net info when no longer forcing offline --- src/libs/actions/Network.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libs/actions/Network.js b/src/libs/actions/Network.js index 1b56bbf9d7e8..1de80a5f69a4 100644 --- a/src/libs/actions/Network.js +++ b/src/libs/actions/Network.js @@ -19,8 +19,9 @@ function setShouldForceOffline(shouldForceOffline) { } else { Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline}); - // If we are no longer forcing offline, refresh the NetInfo to trigger a state change which will set isOffline appropriately - NetInfo.refresh(); + // If we are no longer forcing offline fetch the NetInfo to set isOffline appropriately + NetInfo.fetch() + .then(state => setIsOffline(state.isInternetReachable === false)); } } From 6d86036226f1e47d022eccfd04410bc30486e635 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Fri, 25 Nov 2022 11:39:55 -0800 Subject: [PATCH 19/25] Always provide boolean isOn to switches --- src/components/TestToolMenu.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/TestToolMenu.js b/src/components/TestToolMenu.js index 0ef8a92255bf..10f12bac71d0 100644 --- a/src/components/TestToolMenu.js +++ b/src/components/TestToolMenu.js @@ -50,7 +50,7 @@ const TestToolMenu = props => ( {/* When toggled the app will be forced offline. */} Network.setShouldForceOffline(!props.network.shouldForceOffline)} /> @@ -58,7 +58,7 @@ const TestToolMenu = props => ( {/* When toggled all network requests will fail. */} Network.setShouldFailAllRequests(!props.network.shouldFailAllRequests)} /> From 41fa6c1aa3f6feb5a2aa599b2cd85b76dd475242 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 28 Nov 2022 11:34:17 -0800 Subject: [PATCH 20/25] Ignore all Pusher events when forcing offline --- src/libs/Pusher/pusher.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libs/Pusher/pusher.js b/src/libs/Pusher/pusher.js index 5fd1e7fa6d26..2483a0c5e3f3 100644 --- a/src/libs/Pusher/pusher.js +++ b/src/libs/Pusher/pusher.js @@ -1,8 +1,21 @@ +import Onyx from 'react-native-onyx'; import _ from 'underscore'; +import ONYXKEYS from '../../ONYXKEYS'; import Pusher from './library'; import TYPE from './EventType'; import Log from '../Log'; +let shouldForceOffline = false; +Onyx.connect({ + key: ONYXKEYS.NETWORK, + callback: (network) => { + if (!network) { + return; + } + shouldForceOffline = Boolean(network.shouldForceOffline); + }, +}); + let socket; const socketEventCallbacks = []; let customAuthorizer; @@ -112,6 +125,11 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}) { const chunkedDataEvents = {}; const callback = (eventData) => { + if (shouldForceOffline) { + Log.info('[Pusher] Ignoring a Push event because shouldForceOffline = true'); + return; + } + let data; try { data = _.isObject(eventData) ? eventData : JSON.parse(eventData); From e4d0e3f76fd61c522f0a792340f4e2495d320f38 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 28 Nov 2022 11:38:21 -0800 Subject: [PATCH 21/25] Ignore Push events when offline with devtools --- src/libs/Pusher/pusher.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/Pusher/pusher.js b/src/libs/Pusher/pusher.js index 2483a0c5e3f3..b563de6da721 100644 --- a/src/libs/Pusher/pusher.js +++ b/src/libs/Pusher/pusher.js @@ -5,14 +5,14 @@ import Pusher from './library'; import TYPE from './EventType'; import Log from '../Log'; -let shouldForceOffline = false; +let isOffline = false; Onyx.connect({ key: ONYXKEYS.NETWORK, callback: (network) => { if (!network) { return; } - shouldForceOffline = Boolean(network.shouldForceOffline); + isOffline = Boolean(network.shouldForceOffline) || network.isOffline; }, }); @@ -125,8 +125,8 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}) { const chunkedDataEvents = {}; const callback = (eventData) => { - if (shouldForceOffline) { - Log.info('[Pusher] Ignoring a Push event because shouldForceOffline = true'); + if (isOffline) { + Log.info('[Pusher] Ignoring Push event because isOffline = true'); return; } From 09007c1d875656d6a6a1be2923600a0410959be5 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 28 Nov 2022 12:17:18 -0800 Subject: [PATCH 22/25] trigger app reconnect after forcing offline --- src/libs/NetworkConnection.js | 30 +++++++++++++++++++----------- src/libs/actions/Network.js | 11 +---------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index 65058a0cf2cc..1d89d7ea8a3c 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -8,17 +8,6 @@ import CONFIG from '../CONFIG'; import CONST from '../CONST'; import ONYXKEYS from '../ONYXKEYS'; -let shouldForceOffline; -Onyx.connect({ - key: ONYXKEYS.NETWORK, - callback: (network) => { - if (!network) { - return; - } - shouldForceOffline = Boolean(network.shouldForceOffline); - }, -}); - let isOffline = false; let hasPendingNetworkCheck = false; @@ -52,6 +41,25 @@ function setOfflineStatus(isCurrentlyOffline) { isOffline = isCurrentlyOffline; } +// Update the offline status in response to changes in shouldForceOffline +let shouldForceOffline; +Onyx.connect({ + key: ONYXKEYS.NETWORK, + callback: (network) => { + if (!network) { + return; + } + shouldForceOffline = Boolean(network.shouldForceOffline); + if (shouldForceOffline) { + setOfflineStatus(true); + } else { + // If we are no longer forcing offline fetch the NetInfo to set isOffline appropriately + NetInfo.fetch() + .then(state => setOfflineStatus(state.isInternetReachable === false)); + } + }, +}); + /** * Set up the event listener for NetInfo to tell whether the user has * internet connectivity or not. This is more reliable than the Pusher diff --git a/src/libs/actions/Network.js b/src/libs/actions/Network.js index 1de80a5f69a4..43f6303d20db 100644 --- a/src/libs/actions/Network.js +++ b/src/libs/actions/Network.js @@ -1,5 +1,4 @@ import Onyx from 'react-native-onyx'; -import NetInfo from '@react-native-community/netinfo'; import ONYXKEYS from '../../ONYXKEYS'; /** @@ -14,15 +13,7 @@ function setIsOffline(isOffline) { * @param {Boolean} shouldForceOffline */ function setShouldForceOffline(shouldForceOffline) { - if (shouldForceOffline) { - Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline, isOffline: shouldForceOffline}); - } else { - Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline}); - - // If we are no longer forcing offline fetch the NetInfo to set isOffline appropriately - NetInfo.fetch() - .then(state => setIsOffline(state.isInternetReachable === false)); - } + Onyx.merge(ONYXKEYS.NETWORK, {shouldForceOffline}); } /** From 3104a7e3fbf81523d6b7b3d17f7d715bbcdb6920 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 28 Nov 2022 13:22:59 -0800 Subject: [PATCH 23/25] Revert "Ignore Push events when offline with devtools" This reverts commit e4d0e3f76fd61c522f0a792340f4e2495d320f38. --- src/libs/Pusher/pusher.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libs/Pusher/pusher.js b/src/libs/Pusher/pusher.js index b563de6da721..2483a0c5e3f3 100644 --- a/src/libs/Pusher/pusher.js +++ b/src/libs/Pusher/pusher.js @@ -5,14 +5,14 @@ import Pusher from './library'; import TYPE from './EventType'; import Log from '../Log'; -let isOffline = false; +let shouldForceOffline = false; Onyx.connect({ key: ONYXKEYS.NETWORK, callback: (network) => { if (!network) { return; } - isOffline = Boolean(network.shouldForceOffline) || network.isOffline; + shouldForceOffline = Boolean(network.shouldForceOffline); }, }); @@ -125,8 +125,8 @@ function bindEventToChannel(channel, eventName, eventCallback = () => {}) { const chunkedDataEvents = {}; const callback = (eventData) => { - if (isOffline) { - Log.info('[Pusher] Ignoring Push event because isOffline = true'); + if (shouldForceOffline) { + Log.info('[Pusher] Ignoring a Push event because shouldForceOffline = true'); return; } From 5d44b69c78ccbbf1e7978c67da069e43e5e4a025 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 28 Nov 2022 13:34:41 -0800 Subject: [PATCH 24/25] Ignore changes irrelevant to shouldForceOffline --- src/libs/NetworkConnection.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index 1d89d7ea8a3c..d6c7932f2a47 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -42,14 +42,18 @@ function setOfflineStatus(isCurrentlyOffline) { } // Update the offline status in response to changes in shouldForceOffline -let shouldForceOffline; +let shouldForceOffline = false; Onyx.connect({ key: ONYXKEYS.NETWORK, callback: (network) => { if (!network) { return; } - shouldForceOffline = Boolean(network.shouldForceOffline); + const currentShouldForceOffline = Boolean(network.shouldForceOffline); + if (currentShouldForceOffline === shouldForceOffline) { + return; + } + shouldForceOffline = currentShouldForceOffline; if (shouldForceOffline) { setOfflineStatus(true); } else { From a467667c85b3b5cdd9428a1e227924deb2bdc3e4 Mon Sep 17 00:00:00 2001 From: neil-marcellini Date: Mon, 28 Nov 2022 13:51:21 -0800 Subject: [PATCH 25/25] Remove duplicate setup based on shouldForceOffline --- src/Expensify.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/Expensify.js b/src/Expensify.js index 9feb1dd6a2f4..93224dfd9321 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -20,14 +20,9 @@ import Log from './libs/Log'; import ConfirmModal from './components/ConfirmModal'; import compose from './libs/compose'; import withLocalize, {withLocalizePropTypes} from './components/withLocalize'; -import withEnvironment, {environmentPropTypes} from './components/withEnvironment'; -import {withNetwork} from './components/OnyxProvider'; -import networkPropTypes from './components/networkPropTypes'; import * as User from './libs/actions/User'; import NetworkConnection from './libs/NetworkConnection'; import Navigation from './libs/Navigation/Navigation'; -import * as Network from './libs/actions/Network'; -import CONST from './CONST'; Onyx.registerLogger(({level, message}) => { if (level === 'alert') { @@ -67,11 +62,7 @@ const propTypes = { roomName: PropTypes.string, }), - /** Information about the network */ - network: networkPropTypes.isRequired, - ...withLocalizePropTypes, - ...environmentPropTypes, }; const defaultProps = { @@ -99,12 +90,6 @@ class Expensify extends PureComponent { isSplashShown: true, }; - // Force offline mode on staging or dev if needed - if (_.contains([CONST.ENVIRONMENT.STAGING, CONST.ENVIRONMENT.DEV], this.props.environment)) { - // network.isOffline is always initialized to false, so set its value based on shouldForceOffline - Network.setIsOffline(this.props.network.shouldForceOffline); - } - // Used for the offline indicator appearing when someone is offline NetworkConnection.subscribeToNetInfo(); } @@ -233,8 +218,6 @@ Expensify.propTypes = propTypes; Expensify.defaultProps = defaultProps; export default compose( withLocalize, - withEnvironment, - withNetwork(), withOnyx({ session: { key: ONYXKEYS.SESSION,