diff options
| author | Andrej Mihajlov <and@codeispoetry.ru> | 2017-03-21 18:09:25 +0000 |
|---|---|---|
| committer | Andrej Mihajlov <and@codeispoetry.ru> | 2017-03-21 18:09:25 +0000 |
| commit | fca751a517b2b35b8316b5c1f5dab8f7a130953d (patch) | |
| tree | 0be3f24c4add055ebeca9d9c6f6e4106b6a4cc49 | |
| parent | e0b13a670f0e21fcca057b19afe45dc9d5312219 (diff) | |
| download | mullvadvpn-fca751a517b2b35b8316b5c1f5dab8f7a130953d.tar.xz mullvadvpn-fca751a517b2b35b8316b5c1f5dab8f7a130953d.zip | |
Add reachability and display offline screen automatically based on it
| -rw-r--r-- | app/components/Connect.js | 22 | ||||
| -rw-r--r-- | app/lib/backend-redux-actions.js | 5 | ||||
| -rw-r--r-- | app/lib/backend.js | 50 | ||||
| -rw-r--r-- | app/reducers/connect.js | 1 |
4 files changed, 63 insertions, 15 deletions
diff --git a/app/components/Connect.js b/app/components/Connect.js index 9c5a2c0075..c5d435823e 100644 --- a/app/components/Connect.js +++ b/app/components/Connect.js @@ -47,12 +47,22 @@ export default class Connect extends Component { } render() { + let error = null; + + if(this.props.connect.status === ConnectionState.failed) { + error = this.props.connect.error; + } + + if(this.props.connect.isOnline === false) { + error = new Backend.Error(Backend.ErrorType.noInternetConnection); + } + return ( <Layout> <Header style={ this.headerStyle() } showSettings={ true } onSettings={ this.props.onSettings } /> <Container> - <If condition={ this.props.connect.status === ConnectionState.failed }> - <Then>{ ::this.renderError }</Then> + <If condition={ error !== null }> + <Then>{ () => this.renderError(error) }</Then> <Else>{ ::this.renderMap }</Else> </If> </Container> @@ -60,7 +70,7 @@ export default class Connect extends Component { ); } - renderError() { + renderError(error) { return ( <div className="connect"> <div className="connect__status"> @@ -68,12 +78,12 @@ export default class Connect extends Component { <img src="./assets/images/icon-fail.svg" alt="" /> </div> <div className="connect__error-title"> - { this.props.connect.error.title } + { error.title } </div> <div className="connect__error-message"> - { this.props.connect.error.message } + { error.message } </div> - <If condition={ this.props.connect.error.code === Backend.ErrorType.noCredit }> + <If condition={ error.code === Backend.ErrorType.noCredit }> <Then> <div> <button className="button button--positive" onClick={ this.onExternalLink.bind(this, 'purchase') }> diff --git a/app/lib/backend-redux-actions.js b/app/lib/backend-redux-actions.js index 2760d09bab..ad95a71396 100644 --- a/app/lib/backend-redux-actions.js +++ b/app/lib/backend-redux-actions.js @@ -62,6 +62,10 @@ export default function mapBackendEventsToReduxActions(backend, store) { })); }; + const onReachability = (isOnline) => { + store.dispatch(connectActions.connectionChange({ isOnline })); + }; + backend.on(Backend.EventType.updatedIp, onUpdateIp); backend.on(Backend.EventType.updatedLocation, onUpdateLocation); backend.on(Backend.EventType.connecting, onConnecting); @@ -70,4 +74,5 @@ export default function mapBackendEventsToReduxActions(backend, store) { backend.on(Backend.EventType.logging, onLoggingIn); backend.on(Backend.EventType.login, onLogin); backend.on(Backend.EventType.logout, onLogout); + backend.on(Backend.EventType.updatedReachability, onReachability); } diff --git a/app/lib/backend.js b/app/lib/backend.js index 242deabe9e..400e2bdfc9 100644 --- a/app/lib/backend.js +++ b/app/lib/backend.js @@ -72,6 +72,13 @@ import { ConnectionState as ReduxConnectionState } from '../enums'; * @param {object} location data */ +/** + * Updated reachability + * + * @event Backend.EventType.updatedReachability + * @param {bool} true if online, otherwise false + */ + class BackendError extends Error { constructor(code) { @@ -113,6 +120,15 @@ class BackendError extends Error { export default class Backend extends EventEmitter { /** + * BackendError type + * + * @static + * + * @memberOf Backend + */ + static Error = BackendError; + + /** * Backend error enum * * @static @@ -138,8 +154,9 @@ export default class Backend extends EventEmitter { * @property {string} logout * @property {string} updatedIp * @property {string} updatedLocation + * @property {string} updatedReachability */ - static EventType = new Enum('connect', 'connecting', 'disconnect', 'login', 'logging', 'logout', 'updatedIp', 'updatedLocation'); + static EventType = new Enum('connect', 'connecting', 'disconnect', 'login', 'logging', 'logout', 'updatedIp', 'updatedLocation', 'updatedReachability'); /** * Connection state enum @@ -167,6 +184,9 @@ export default class Backend extends EventEmitter { // update IP in background setTimeout(::this._refreshIp, 0); + + // check for network reachability + this._startReachability(); } // Accessors @@ -332,11 +352,11 @@ export default class Backend extends EventEmitter { let res = { account }; if(account.startsWith('1111')) { // accounts starting with 1111 expire in one month - res.paidUntil = moment().startOf('day').add(15, 'days').toISOString(); + this._paidUntil = res.paidUntil = moment().startOf('day').add(15, 'days').toISOString(); } else if(account.startsWith('2222')) { // expired in 2013 - res.paidUntil = moment('2013-01-01').toISOString(); + this._paidUntil = res.paidUntil = moment('2013-01-01').toISOString(); } else if(account.startsWith('3333')) { // expire in 2038 - res.paidUntil = moment('2038-01-01').toISOString(); + this._paidUntil = res.paidUntil = moment('2038-01-01').toISOString(); } else { err = new BackendError(Backend.ErrorType.invalidAccount); } @@ -389,11 +409,6 @@ export default class Backend extends EventEmitter { timer = setTimeout(() => { let err = null; - // Prototype: Swedish servers will throw error during connect - if(/se\d+\.mullvad\.net/.test(addr)) { - err = new BackendError(Backend.ErrorType.noInternetConnection); - } - // Prototype: the US servers will throw error during connect if(/us\d+\.mullvad\.net/.test(addr)) { err = new BackendError(Backend.ErrorType.noCredit); @@ -491,4 +506,21 @@ export default class Backend extends EventEmitter { this.emit(Backend.EventType.updatedIp, ip.join('.')); } + + _startReachability() { + // update online status in background + setTimeout(() => { + this.emit(Backend.EventType.updatedReachability, navigator.onLine); + }, 0); + + window.addEventListener('online', () => { + this.emit(Backend.EventType.updatedReachability, true); + }); + + window.addEventListener('offline', () => { + // force disconnect since there is no real connection anyway. + this.disconnect(); + this.emit(Backend.EventType.updatedReachability, false); + }); + } } diff --git a/app/reducers/connect.js b/app/reducers/connect.js index b5571fca5e..6ed98501bf 100644 --- a/app/reducers/connect.js +++ b/app/reducers/connect.js @@ -4,6 +4,7 @@ import actions from '../actions/connect'; const initialState = { status: ConnectionState.disconnected, + isOnline: true, serverAddress: null, clientIp: null }; |
