From 3a843cd4aa68eb4141816bd7cd439e77863ba5fa Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 8 Aug 2022 15:49:06 -0700 Subject: [PATCH 1/6] Call listenForReconnect on App init --- src/libs/actions/App.js | 1 + src/pages/signin/LoginForm.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js index 99abe499d7e1..8b08aead3735 100644 --- a/src/libs/actions/App.js +++ b/src/libs/actions/App.js @@ -252,6 +252,7 @@ function openProfile() { } // When the app reconnects from being offline, fetch all initialization data +NetworkConnection.listenForReconnect(); NetworkConnection.onReconnect(() => { getAppData(); reconnectApp(); diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index dec680d100bb..e9c54afe73ae 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -18,6 +18,7 @@ import * as ValidationUtils from '../../libs/ValidationUtils'; import * as LoginUtils from '../../libs/LoginUtils'; import withToggleVisibilityView, {toggleVisibilityViewPropTypes} from '../../components/withToggleVisibilityView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; +import OfflineIndicator from "../../components/OfflineIndicator"; const propTypes = { /** Should we dismiss the keyboard when transitioning away from the page? */ @@ -181,6 +182,7 @@ class LoginForm extends React.Component { containerStyles={[styles.mh0]} /> + ); } From e1788975be62592cec9b85571be6500ad78f02fc Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Mon, 8 Aug 2022 21:02:24 -0700 Subject: [PATCH 2/6] singlequotes --- src/pages/signin/LoginForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index e9c54afe73ae..c30f3459da82 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -18,7 +18,7 @@ import * as ValidationUtils from '../../libs/ValidationUtils'; import * as LoginUtils from '../../libs/LoginUtils'; import withToggleVisibilityView, {toggleVisibilityViewPropTypes} from '../../components/withToggleVisibilityView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; -import OfflineIndicator from "../../components/OfflineIndicator"; +import OfflineIndicator from '../../components/OfflineIndicator'; const propTypes = { /** Should we dismiss the keyboard when transitioning away from the page? */ From 0d131842da3d73cd0ea9c92d2bff66bf35759c39 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 9 Aug 2022 12:27:31 -0700 Subject: [PATCH 3/6] Subscribe to NetInfo in Expensify constructor and have the reconnect listeners sit behind AuthScreens --- src/Expensify.js | 4 ++++ src/libs/Navigation/AppNavigator/AuthScreens.js | 4 ++++ src/libs/NetworkConnection.js | 3 +-- src/libs/actions/App.js | 8 +------- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Expensify.js b/src/Expensify.js index 1f0e249eb244..488711c37b99 100644 --- a/src/Expensify.js +++ b/src/Expensify.js @@ -21,6 +21,7 @@ import ConfirmModal from './components/ConfirmModal'; import compose from './libs/compose'; import withLocalize, {withLocalizePropTypes} from './components/withLocalize'; import * as User from './libs/actions/User'; +import NetworkConnection from './libs/NetworkConnection'; Onyx.registerLogger(({level, message}) => { if (level === 'alert') { @@ -91,6 +92,9 @@ class Expensify extends PureComponent { isOnyxMigrated: false, isSplashShown: true, }; + + // Used for the offline indicator appearing when someone is offline + NetworkConnection.subscribeToNetInfo(); } componentDidMount() { diff --git a/src/libs/Navigation/AppNavigator/AuthScreens.js b/src/libs/Navigation/AppNavigator/AuthScreens.js index aa6a9324845f..b1b8e9b8ccad 100644 --- a/src/libs/Navigation/AppNavigator/AuthScreens.js +++ b/src/libs/Navigation/AppNavigator/AuthScreens.js @@ -102,6 +102,10 @@ class AuthScreens extends React.Component { componentDidMount() { NetworkConnection.listenForReconnect(); + NetworkConnection.onReconnect(() => { + App.getAppData(); + App.reconnectApp(); + }); PusherConnectionManager.init(); Pusher.init({ appKey: CONFIG.PUSHER.APP_KEY, diff --git a/src/libs/NetworkConnection.js b/src/libs/NetworkConnection.js index 300839bf204b..cda405943da2 100644 --- a/src/libs/NetworkConnection.js +++ b/src/libs/NetworkConnection.js @@ -81,8 +81,6 @@ function listenForReconnect() { unsubscribeFromAppState = AppStateMonitor.addBecameActiveListener(() => { triggerReconnectionCallbacks('app became active'); }); - - subscribeToNetInfo(); } /** @@ -130,4 +128,5 @@ export default { onReconnect, triggerReconnectionCallbacks, recheckNetworkConnection, + subscribeToNetInfo, }; diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js index 8b08aead3735..859a2eea8852 100644 --- a/src/libs/actions/App.js +++ b/src/libs/actions/App.js @@ -251,13 +251,6 @@ function openProfile() { Navigation.navigate(ROUTES.SETTINGS_PROFILE); } -// When the app reconnects from being offline, fetch all initialization data -NetworkConnection.listenForReconnect(); -NetworkConnection.onReconnect(() => { - getAppData(); - reconnectApp(); -}); - export { setLocale, setSidebarLoaded, @@ -266,4 +259,5 @@ export { setUpPoliciesAndNavigate, openProfile, openApp, + reconnectApp, }; From cee7e58091f30a651a16e044044ae311ef81c9eb Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 9 Aug 2022 12:34:31 -0700 Subject: [PATCH 4/6] Remove unused import --- src/libs/actions/App.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/actions/App.js b/src/libs/actions/App.js index 859a2eea8852..2db1983fca8a 100644 --- a/src/libs/actions/App.js +++ b/src/libs/actions/App.js @@ -14,7 +14,6 @@ import Timing from './Timing'; import * as Report from './Report'; import * as BankAccounts from './BankAccounts'; import * as Policy from './Policy'; -import NetworkConnection from '../NetworkConnection'; import Navigation from '../Navigation/Navigation'; import ROUTES from '../../ROUTES'; import * as SessionUtils from '../SessionUtils'; From 75d70d9b59dc9d93b1c218cc7c52649c0f1d9ec2 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Tue, 9 Aug 2022 21:04:07 -0700 Subject: [PATCH 5/6] Preserve isOffline state when calling clearStorageAndRedirect --- src/libs/actions/SignInRedirect.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libs/actions/SignInRedirect.js b/src/libs/actions/SignInRedirect.js index ffde6f2f9557..597de6d2ecd8 100644 --- a/src/libs/actions/SignInRedirect.js +++ b/src/libs/actions/SignInRedirect.js @@ -16,12 +16,19 @@ Onyx.connect({ callback: val => currentPreferredLocale = val, }); +let currentIsOffline; +Onyx.connect({ + key: ONYXKEYS.NETWORK, + callback: val => currentIsOffline = val.isOffline, +}); + /** * @param {String} errorMessage */ function clearStorageAndRedirect(errorMessage) { const activeClients = currentActiveClients; const preferredLocale = currentPreferredLocale; + const isOffline = currentIsOffline; // Clearing storage discards the authToken. This causes a redirect to the SignIn screen Onyx.clear() @@ -32,6 +39,9 @@ function clearStorageAndRedirect(errorMessage) { if (activeClients && activeClients.length > 0) { Onyx.set(ONYXKEYS.ACTIVE_CLIENTS, activeClients); } + if (isOffline) { + Onyx.set(ONYXKEYS.NETWORK, {isOffline}); + } // `Onyx.clear` reinitialize the Onyx instance with initial values so use `Onyx.merge` instead of `Onyx.set`. Onyx.merge(ONYXKEYS.SESSION, {error: errorMessage}); From 757ff0cc58565af7198c3503f88b916277cce840 Mon Sep 17 00:00:00 2001 From: Yuwen Memon Date: Wed, 10 Aug 2022 10:46:45 -0700 Subject: [PATCH 6/6] return early on form submission if we're offline --- src/pages/signin/LoginForm.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/pages/signin/LoginForm.js b/src/pages/signin/LoginForm.js index c30f3459da82..04ce5c7cc04f 100755 --- a/src/pages/signin/LoginForm.js +++ b/src/pages/signin/LoginForm.js @@ -19,6 +19,8 @@ import * as LoginUtils from '../../libs/LoginUtils'; import withToggleVisibilityView, {toggleVisibilityViewPropTypes} from '../../components/withToggleVisibilityView'; import FormAlertWithSubmitButton from '../../components/FormAlertWithSubmitButton'; import OfflineIndicator from '../../components/OfflineIndicator'; +import {withNetwork} from '../../components/OnyxProvider'; +import networkPropTypes from '../../components/networkPropTypes'; const propTypes = { /** Should we dismiss the keyboard when transitioning away from the page? */ @@ -38,6 +40,9 @@ const propTypes = { isLoading: PropTypes.bool, }), + /** Props to detect online status */ + network: networkPropTypes.isRequired, + ...windowDimensionsPropTypes, ...withLocalizePropTypes, @@ -114,6 +119,10 @@ class LoginForm extends React.Component { * Check that all the form fields are valid, then trigger the submit callback */ validateAndSubmitForm() { + if (this.props.network.isOffline) { + return; + } + const login = this.state.login.trim(); if (!login) { this.setState({formError: 'common.pleaseEnterEmailOrPhoneNumber'}); @@ -198,4 +207,5 @@ export default compose( withWindowDimensions, withLocalize, withToggleVisibilityView, + withNetwork(), )(LoginForm);