summaryrefslogtreecommitdiffhomepage
path: root/app
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@codeispoetry.ru>2017-03-21 18:09:25 +0000
committerAndrej Mihajlov <and@codeispoetry.ru>2017-03-21 18:09:25 +0000
commitfca751a517b2b35b8316b5c1f5dab8f7a130953d (patch)
tree0be3f24c4add055ebeca9d9c6f6e4106b6a4cc49 /app
parente0b13a670f0e21fcca057b19afe45dc9d5312219 (diff)
downloadmullvadvpn-fca751a517b2b35b8316b5c1f5dab8f7a130953d.tar.xz
mullvadvpn-fca751a517b2b35b8316b5c1f5dab8f7a130953d.zip
Add reachability and display offline screen automatically based on it
Diffstat (limited to 'app')
-rw-r--r--app/components/Connect.js22
-rw-r--r--app/lib/backend-redux-actions.js5
-rw-r--r--app/lib/backend.js50
-rw-r--r--app/reducers/connect.js1
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
};