From e49f89d7274e2c9cb04ee76bcdd4690272b9504a Mon Sep 17 00:00:00 2001 From: Chris Duarte Date: Tue, 24 Oct 2017 15:43:22 -0700 Subject: [PATCH] Add better network detection (#1054) * Add better network detection * Mock NetInfo for store --- app/screens/channel/channel.js | 8 ++++---- app/store/index.js | 2 ++ app/utils/network.js | 34 ++++++++++++++++++++++++++++++++++ test/setup.js | 8 +++++++- 4 files changed, 47 insertions(+), 5 deletions(-) create mode 100644 app/utils/network.js diff --git a/app/screens/channel/channel.js b/app/screens/channel/channel.js index 1c238e7c3..c4463b0a3 100644 --- a/app/screens/channel/channel.js +++ b/app/screens/channel/channel.js @@ -5,7 +5,6 @@ import React, {PureComponent} from 'react'; import PropTypes from 'prop-types'; import {injectIntl, intlShape} from 'react-intl'; import { - NetInfo, Platform, View } from 'react-native'; @@ -22,6 +21,7 @@ import StatusBar from 'app/components/status_bar'; import {wrapWithPreventDoubleTap} from 'app/utils/tap'; import {makeStyleSheetFromTheme} from 'app/utils/theme'; import PostTextbox from 'app/components/post_textbox'; +import networkConnectionListener from 'app/utils/network'; import ChannelDrawerButton from './channel_drawer_button'; import ChannelPostList from './channel_post_list'; @@ -53,8 +53,8 @@ class Channel extends PureComponent { componentWillMount() { EventEmitter.on('leave_team', this.handleLeaveTeam); - NetInfo.isConnected.addEventListener('connectionChange', this.handleConnectionChange); - NetInfo.isConnected.fetch().then(this.handleConnectionChange); + + this.networkListener = networkConnectionListener(this.handleConnectionChange); if (this.props.currentTeamId) { this.loadChannels(this.props.currentTeamId); @@ -79,7 +79,7 @@ class Channel extends PureComponent { const {closeWebSocket, stopPeriodicStatusUpdates} = this.props.actions; EventEmitter.off('leave_team', this.handleLeaveTeam); - NetInfo.isConnected.removeEventListener('connectionChange', this.handleConnectionChange); + this.networkListener.removeEventListener(); closeWebSocket(); stopPeriodicStatusUpdates(); diff --git a/app/store/index.js b/app/store/index.js index b641fc97f..25416ff94 100644 --- a/app/store/index.js +++ b/app/store/index.js @@ -13,6 +13,7 @@ import EventEmitter from 'mattermost-redux/utils/event_emitter'; import {NavigationTypes, ViewTypes} from 'app/constants'; import appReducer from 'app/reducers'; +import networkConnectionListener from 'app/utils/network'; import {createSentryMiddleware} from 'app/utils/sentry/middleware'; import {transformSet} from './utils'; @@ -100,6 +101,7 @@ export default function configureAppStore(initialState) { ); const offlineOptions = { + detectNetwork: (callback) => networkConnectionListener(callback), persist: (store, options) => { const persistor = persistStore(store, {storage: AsyncStorage, ...options}, () => { store.dispatch({ diff --git a/app/utils/network.js b/app/utils/network.js new file mode 100644 index 000000000..9d5d6c6db --- /dev/null +++ b/app/utils/network.js @@ -0,0 +1,34 @@ +import {NetInfo} from 'react-native'; + +import {Client4} from 'mattermost-redux/client'; + +export async function checkConnection() { + const server = Client4.getUrl() || 'https://www.google.com'; + + try { + await fetch(server); + return true; + } catch (error) { + return false; + } +} + +function handleConnectionChange(onChange) { + return async () => { + const result = await checkConnection(); + onChange(result); + }; +} + +export default function networkConnectionListener(onChange) { + const connectionChanged = handleConnectionChange(onChange); + + NetInfo.isConnected.addEventListener('change', connectionChanged); + NetInfo.isConnected.fetch().then(connectionChanged); + + const removeEventListener = () => NetInfo.isConnected.removeEventListener('change', connectionChanged); // eslint-disable-line + + return { + removeEventListener + }; +} \ No newline at end of file diff --git a/test/setup.js b/test/setup.js index 9464a8e50..bb1a074cc 100644 --- a/test/setup.js +++ b/test/setup.js @@ -21,7 +21,13 @@ mockery.registerMock('react-native', { return {width: 0, height: 0} } }, - NativeModules: {} + NativeModules: {}, + NetInfo: { + isConnected: { + addEventListener: () => true, + fetch: () => Promise.resolve(true) + } + } }); mockery.registerMock('react-native-device-info', { getDeviceLocale() {