From 8fb88529a00cc9739e9a85091c2bda8900f2c803 Mon Sep 17 00:00:00 2001 From: Jori Lallo Date: Fri, 19 Aug 2016 08:02:56 -0700 Subject: [PATCH] Implemented offline indicator --- frontend/components/Layout/Layout.js | 13 ++++- frontend/components/Offline/Offline.js | 43 ++++++++++++++++ frontend/components/Offline/index.js | 7 +++ frontend/components/Offline/injectOffline.js | 19 +++++++ frontend/index.js | 53 +++++++++++--------- 5 files changed, 108 insertions(+), 27 deletions(-) create mode 100644 frontend/components/Offline/Offline.js create mode 100644 frontend/components/Offline/index.js create mode 100644 frontend/components/Offline/injectOffline.js diff --git a/frontend/components/Layout/Layout.js b/frontend/components/Layout/Layout.js index 33076f9b..44703b2b 100644 --- a/frontend/components/Layout/Layout.js +++ b/frontend/components/Layout/Layout.js @@ -2,6 +2,7 @@ import React from 'react'; import { browserHistory, Link } from 'react-router'; import Helmet from 'react-helmet'; import { observer } from 'mobx-react'; +import { injectOffline } from 'components/Offline'; import keydown from 'react-keydown'; import _ from 'lodash'; @@ -16,6 +17,7 @@ import classNames from 'classnames/bind'; const cx = classNames.bind(styles); @observer(['user']) +@injectOffline class Layout extends React.Component { static propTypes = { children: React.PropTypes.node, @@ -25,6 +27,7 @@ class Layout extends React.Component { loading: React.PropTypes.bool, user: React.PropTypes.object.isRequired, search: React.PropTypes.bool, + offline: React.PropTypes.bool, } static defaultProps = { @@ -54,9 +57,15 @@ class Layout extends React.Component { : 'Atlas' } /> - { this.props.loading ? ( + { this.props.loading && ( - ) : null } + ) } + + { this.props.offline && ( + + It looks like you're offline. Reconnect to restore access to all of your documents 📚 + + ) }
diff --git a/frontend/components/Offline/Offline.js b/frontend/components/Offline/Offline.js new file mode 100644 index 00000000..3d9eb795 --- /dev/null +++ b/frontend/components/Offline/Offline.js @@ -0,0 +1,43 @@ +import React from 'react'; + +class Offline extends React.Component { + static propTypes = { + children: React.PropTypes.node, + }; + + static childContextTypes = { + offline: React.PropTypes.bool, + }; + + state = { + offline: false, + } + + getChildContext() { + return { + offline: this.state.offline, + }; + } + + componentDidMount = () => { + window.addEventListener('offline', this.handleConnectionState); + window.addEventListener('online', this.handleConnectionState); + } + + componentWillUnmount = () => { + window.removeEventListener('offline', this.handleConnectionState); + window.removeEventListener('online', this.handleConnectionState); + }; + + handleConnectionState = () => { + this.setState({ + offline: !navigator.onLine, + }); + } + + render() { + return React.Children.only(this.props.children); + } +} + +export default Offline; diff --git a/frontend/components/Offline/index.js b/frontend/components/Offline/index.js new file mode 100644 index 00000000..5bc9f908 --- /dev/null +++ b/frontend/components/Offline/index.js @@ -0,0 +1,7 @@ +import Offline from './Offline'; +import injectOffline from './injectOffline'; + +export { + Offline, + injectOffline, +} diff --git a/frontend/components/Offline/injectOffline.js b/frontend/components/Offline/injectOffline.js new file mode 100644 index 00000000..5bb66509 --- /dev/null +++ b/frontend/components/Offline/injectOffline.js @@ -0,0 +1,19 @@ +import React from 'react'; + +const injectOffline = (WrappedComponent) => { + return class OfflineWrapper extends React.Component { + static contextTypes = { + offline: React.PropTypes.bool, + }; + + render() { + const newProps = { + offline: this.context.offline, + }; + + return (); + } + }; +}; + +export default injectOffline; diff --git a/frontend/index.js b/frontend/index.js index 83636a3f..14778eb0 100644 --- a/frontend/index.js +++ b/frontend/index.js @@ -6,6 +6,7 @@ import Route from 'react-router/lib/Route'; import IndexRoute from 'react-router/lib/IndexRoute'; import Redirect from 'react-router/lib/Redirect'; import History from 'utils/History'; +import { Offline } from 'components/Offline'; import stores from 'stores'; @@ -45,35 +46,37 @@ function requireAuth(nextState, replace) { render((
- - - + + + + - - - - - - + + + + + + - + - + - - - - + + + + + { __DEV__ && }