summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@codeispoetry.ru>2017-02-24 15:20:52 +0000
committerAndrej Mihajlov <and@codeispoetry.ru>2017-02-24 15:20:52 +0000
commite2c417059216d983c3e7d9560cfad02d82297aba (patch)
treee6683b6616db131e3a4f1823cf9403f82c1909c1
parent040c1ef18fec5ab1aac5bfef4fc596f0c4591e9f (diff)
downloadmullvadvpn-e2c417059216d983c3e7d9560cfad02d82297aba.tar.xz
mullvadvpn-e2c417059216d983c3e7d9560cfad02d82297aba.zip
- Move serverInfo configuration to backend
- Update settings - Reconnect when switching location
-rw-r--r--app/components/Connect.css2
-rw-r--r--app/components/Connect.js45
-rw-r--r--app/components/SelectLocation.js8
-rw-r--r--app/components/Settings.css7
-rw-r--r--app/components/Settings.js65
-rw-r--r--app/constants.js43
-rw-r--r--app/containers/ConnectPage.js3
-rw-r--r--app/containers/SelectLocationPage.js12
-rw-r--r--app/containers/SettingsPage.js3
-rw-r--r--app/lib/backend.js31
10 files changed, 141 insertions, 78 deletions
diff --git a/app/components/Connect.css b/app/components/Connect.css
index 4c7bdd9027..6a100006bc 100644
--- a/app/components/Connect.css
+++ b/app/components/Connect.css
@@ -111,7 +111,7 @@
.connect__status-location {
font-family: DINPro;
- font-size: 40px;
+ font-size: 38px;
font-weight: 900;
line-height: 44px;
letter-spacing: -1px;
diff --git a/app/components/Connect.js b/app/components/Connect.js
index 7eeec2eac9..b8c193ab2f 100644
--- a/app/components/Connect.js
+++ b/app/components/Connect.js
@@ -10,7 +10,8 @@ export default class Connect extends Component {
static propTypes = {
settings: PropTypes.object.isRequired,
onConnect: PropTypes.func.isRequired,
- onDisconnect: PropTypes.func.isRequired
+ onDisconnect: PropTypes.func.isRequired,
+ getServerInfo: PropTypes.func.isRequired
};
constructor() {
@@ -18,7 +19,7 @@ export default class Connect extends Component {
this.state = {
userLocation: {
- coordinate: [40.706213526877455, -74.0044641494751],
+ location: [40.706213526877455, -74.0044641494751],
city: 'New York',
country: 'USA'
}
@@ -35,33 +36,14 @@ export default class Connect extends Component {
onConnect() {
const server = this.props.settings.preferredServer;
- this.props.onConnect(server);
+ const serverInfo = this.props.getServerInfo(server);
+ this.props.onConnect(serverInfo.address);
}
onDisconnect() {
this.props.onDisconnect();
}
- serverInfo(key) {
- switch(key) {
- case 'fastest':
- return {
- name: 'Fastest',
- city: 'New York',
- country: 'USA',
- location: [40.7127837, -74.0059413]
- };
- case 'nearest':
- return {
- name: 'Nearest',
- city: 'New York',
- country: 'USA',
- location: [40.7127837, -74.0059413]
- };
- default: return servers[key] || {};
- }
- }
-
headerStyle() {
const S = Header.Style;
switch(this.props.connect.status) {
@@ -92,13 +74,11 @@ export default class Connect extends Component {
displayLocation() {
if(this.props.connect.status === ConnectionState.disconnected) {
- return this.state.userLocation.coordinate;
+ return this.state.userLocation;
}
const preferredServer = this.props.settings.preferredServer;
- const serverInfo = this.serverInfo(preferredServer);
-
- return serverInfo.location;
+ return this.props.getServerInfo(preferredServer);
}
getBounds(center) {
@@ -117,7 +97,7 @@ export default class Connect extends Component {
}
componentWillMount() {
- const loc = this.displayLocation();
+ const loc = this.displayLocation().location;
// we need this to override default center
// see: https://github.com/alex3165/react-mapbox-gl/issues/134
@@ -130,9 +110,10 @@ export default class Connect extends Component {
render() {
const preferredServer = this.props.settings.preferredServer;
- const serverInfo = this.serverInfo(preferredServer);
+ const serverInfo = this.props.getServerInfo(preferredServer);
const displayLocation = this.displayLocation(); // <lat>, <lng>
- const markerLocation = [ displayLocation[1], displayLocation[0] ]; // <lng>, <lat>
+ const loc = displayLocation.location;
+ const markerLocation = [ loc[1], loc[0] ]; // <lng>, <lat>
const isConnecting = this.props.connect.status === ConnectionState.connecting;
const isConnected = this.props.connect.status === ConnectionState.connected;
@@ -151,7 +132,7 @@ export default class Connect extends Component {
accessToken={ accessToken }
containerStyle={{ height: '100%' }}
interactive={ false }
- fitBounds={ this.getBounds(displayLocation) }
+ fitBounds={ this.getBounds(displayLocation.location) }
fitBoundsOptions={ {offset: [0, -100]} }>
<Marker coordinates={ markerLocation } offset={ [0, -10] }>
<img src={ this.markerImage() } />
@@ -171,7 +152,7 @@ export default class Connect extends Component {
</If>
<div className={ this.networkSecurityClass() }>{ this.networkSecurityMessage() }</div>
- <div className="connect__status-location">{ serverInfo.city }<br/>{ serverInfo.country }</div>
+ <div className="connect__status-location">{ displayLocation.city }<br/>{ displayLocation.country }</div>
<div className="connect__status-ipaddress">{ this.props.connect.clientIp }</div>
</div>
diff --git a/app/components/SelectLocation.js b/app/components/SelectLocation.js
index 66acd2af19..0720a983d6 100644
--- a/app/components/SelectLocation.js
+++ b/app/components/SelectLocation.js
@@ -7,7 +7,7 @@ import CustomScrollbars from './CustomScrollbars';
export default class SelectLocation extends Component {
static propTypes = {
- updateSettings: PropTypes.func.isRequired
+ onChangeLocation: PropTypes.func.isRequired
}
onClose() {
@@ -15,17 +15,17 @@ export default class SelectLocation extends Component {
}
handleSelection(name) {
- this.props.updateSettings({ preferredServer: name });
+ this.props.onChangeLocation(name);
this.props.router.push('/connect');
}
handleFastest() {
- this.props.updateSettings({ preferredServer: 'fastest' });
+ this.props.onChangeLocation('fastest');
this.props.router.push('/connect');
}
handleNearest() {
- this.props.updateSettings({ preferredServer: 'nearest' });
+ this.props.onChangeLocation('nearest');
this.props.router.push('/connect');
}
diff --git a/app/components/Settings.css b/app/components/Settings.css
index ff1c937a4b..c19b8e9d5f 100644
--- a/app/components/Settings.css
+++ b/app/components/Settings.css
@@ -53,6 +53,7 @@
font-weight: 600;
line-height: 20px;
color: rgba(255,255,255,0.8);
+ padding: 0 24px;
}
.settings__account-label {
@@ -65,6 +66,10 @@
margin-left: 4px;
}
+.settings__main {
+ margin-bottom: 24px;
+}
+
.settings__cell {
background-color:rgba(41,71,115,1);
padding: 15px 16px 15px 24px;
@@ -113,3 +118,5 @@
.settings__footer {
padding: 24px;
}
+
+.settings__footer .button + .button { margin-top: 16px; }
diff --git a/app/components/Settings.js b/app/components/Settings.js
index 8bb467e715..c2a77da34f 100644
--- a/app/components/Settings.js
+++ b/app/components/Settings.js
@@ -1,6 +1,7 @@
import React, { Component, PropTypes } from 'react';
import { Layout, Container, Header } from './Layout';
import Switch from './Switch';
+import CustomScrollbars from './CustomScrollbars';
import { formatAccount } from '../lib/formatters';
import { links } from '../constants';
import { shell } from 'electron';
@@ -9,6 +10,7 @@ export default class Settings extends Component {
static propTypes = {
logout: PropTypes.func.isRequired,
+ buyTime: PropTypes.func.isRequired,
updateSettings: PropTypes.func.isRequired
}
@@ -24,6 +26,10 @@ export default class Settings extends Component {
shell.openExternal(links[key]);
}
+ handleBuy() {
+ this.props.buyTime();
+ }
+
handleLogout() {
this.props.logout();
}
@@ -38,37 +44,46 @@ export default class Settings extends Component {
<div className="settings__container">
<div className="settings__header">
<h2 className="settings__title">Settings</h2>
- <div className="settings__account">
- <div className="settings__account-label">Account ID</div>
- <div className="settings__account-id">{ formatAccount(this.props.user.account) }</div>
- </div>
</div>
- <div className="settings__content">
- <div>
- <div className="settings__cell">
- <div className="settings__cell-label">Auto-secure</div>
- <div className="settings__cell-value">
- <Switch onChange={ ::this.handleAutoSecure } isOn={ this.props.settings.autoSecure } />
+ <CustomScrollbars autoHide={ true }>
+ <div className="settings__content">
+ <div className="settings__main">
+ <div className="settings__cell">
+ <div className="settings__cell-label">Auto-secure</div>
+ <div className="settings__cell-value">
+ <Switch onChange={ ::this.handleAutoSecure } isOn={ this.props.settings.autoSecure } />
+ </div>
+ </div>
+ <div className="settings__cell-footer">
+ When this device connects to the internet it will automatically connect to a secure server
+ </div>
+ <div className="settings__cell settings__cell--active" onClick={ () => this.handleLink('faq') }>
+ <div className="settings__cell-label">FAQs</div>
+ </div>
+ <div className="settings__cell settings__cell--active" onClick={ () => this.handleLink('guides') }>
+ <div className="settings__cell-label">Guides</div>
+ </div>
+ <div className="settings__cell settings__cell--active" onClick={ () => this.handleLink('supportEmail') }>
+ <img className="settings__cell-icon" src="./assets/images/icon-email.svg" />
+ <div className="settings__cell-label">Contact support</div>
</div>
</div>
- <div className="settings__cell-footer">
- When this device connects to the internet it will automatically connect to a secure server
- </div>
- <div className="settings__cell settings__cell--active" onClick={ () => this.handleLink('faq') }>
- <div className="settings__cell-label">FAQs</div>
- </div>
- <div className="settings__cell settings__cell--active" onClick={ () => this.handleLink('guides') }>
- <div className="settings__cell-label">Guides</div>
+ <div className="settings__account">
+ <div className="settings__account-row">
+ <div className="settings__account-label">Account ID</div>
+ <div className="settings__account-id">{ formatAccount(this.props.user.account) }</div>
+ </div>
+ <div className="settings__account-row">
+ <div className="settings__account-label">Time remaining</div>
+ <div className="settings__account-id">12 days</div>
+ </div>
</div>
- <div className="settings__cell settings__cell--active" onClick={ () => this.handleLink('supportEmail') }>
- <img className="settings__cell-icon" src="./assets/images/icon-email.svg" />
- <div className="settings__cell-label">Contact support</div>
+ <div className="settings__footer">
+ <button className="button button--neutral" onClick={ ::this.handleBuy }>Buy more time</button>
+ <button className="button button--negative" onClick={ ::this.handleLogout }>Logout</button>
</div>
</div>
- <div className="settings__footer">
- <button className="button button--negative" onClick={ ::this.handleLogout }>Logout</button>
- </div>
- </div>
+ </CustomScrollbars>
</div>
</div>
</Container>
diff --git a/app/constants.js b/app/constants.js
index 10dfea6526..6c969aabc7 100644
--- a/app/constants.js
+++ b/app/constants.js
@@ -6,90 +6,105 @@ const ConnectionState = Enum('disconnected', 'connecting', 'connected', 'failed'
module.exports = {
links: {
createAccount: 'https://mullvad.net/account/create/',
+ purchase: 'https://mullvad.net/account/',
faq: 'https://mullvad.net/faq/',
guides: 'https://mullvad.net/guides/',
supportEmail: 'mailto:support@mullvad.net'
},
servers: {
- 'ca1.mullvad.net': {
+ 'ca1.mullvad.net': {
+ address: 'ca1.mullvad.net',
name: 'Canada',
city: 'Ottawa',
country: 'Canada',
location: [45.421530, -75.697193]
},
- 'ca2.mullvad.net': {
+ 'ca2.mullvad.net': {
+ address: 'ca2.mullvad.net',
name: 'Canada (Quebec)',
city: 'Quebec',
country: 'Canada',
location: [46.810811, -71.215439]
},
- 'da.mullvad.net': {
+ 'da.mullvad.net': {
+ address: 'da.mullvad.net',
name: 'Denmark',
city: '‎Copenhagen',
country: 'Denmark',
location: [55.6760968, 12.5683371]
},
- 'de.mullvad.net': {
+ 'de.mullvad.net': {
+ address: 'de.mullvad.net',
name: 'Germany',
city: 'Berlin',
country: 'Germany',
location: [52.52000659999999, 13.404954]
},
- 'lt.mullvad.net': {
+ 'lt.mullvad.net': {
+ address: 'lt.mullvad.net',
name: 'Lithuania',
city: 'Vilnius',
country: 'Lithuania',
location: [54.6871555, 25.2796514]
},
- 'nl.mullvad.net': {
+ 'nl.mullvad.net': {
+ address: 'nl.mullvad.net',
name: 'The Netherlands',
city: 'Amsterdam',
country: 'The Netherlands',
location: [52.3702157, 4.895167900000001]
},
- 'no.mullvad.net': {
+ 'no.mullvad.net': {
+ address: 'no.mullvad.net',
name: 'Norway',
city: 'Oslo',
country: 'Norway',
location: [59.9138688, 10.7522454]
},
- 'ro.mullvad.net': {
+ 'ro.mullvad.net': {
+ address: 'ro.mullvad.net',
name: 'Romania',
city: 'Bucharest',
country: 'Canada',
location: [44.4267674, 26.1025384]
},
- 'sg.mullvad.net': {
+ 'sg.mullvad.net': {
+ address: 'sg.mullvad.net',
name: 'Singapore',
city: 'Singapore',
country: 'Singapore',
location: [1.352083, 103.819836]
},
- 'es.mullvad.net': {
+ 'es.mullvad.net': {
+ address: 'es.mullvad.net',
name: 'Spain',
city: 'Madrid',
country: 'Spain',
location: [40.4167754, -3.7037902]
},
- 'se1.mullvad.net': {
+ 'se1.mullvad.net': {
+ address: 'se1.mullvad.net',
name: 'Sweden',
city: 'Stockholm',
country: 'Sweden',
location: [59.32932349999999, 18.0685808]
},
- 'ch.mullvad.net': {
+ 'ch.mullvad.net': {
+ address: 'ch.mullvad.net',
name: 'Switzerland',
city: 'Zürich',
country: 'Switzerland',
location: [47.3768866, 8.541694]
},
- 'uk.mullvad.net': {
+ 'uk.mullvad.net': {
+ address: 'uk.mullvad.net',
name: 'United Kingdom',
city: 'London',
country: 'United Kingdom',
location: [51.5073509, -0.1277583]
},
- 'us1.mullvad.net': {
+ 'us1.mullvad.net': {
+ address: 'us1.mullvad.net',
name: 'USA',
city: 'New York',
country: 'USA',
diff --git a/app/containers/ConnectPage.js b/app/containers/ConnectPage.js
index 7fdd570a69..54a4b8d4d0 100644
--- a/app/containers/ConnectPage.js
+++ b/app/containers/ConnectPage.js
@@ -12,7 +12,8 @@ const mapDispatchToProps = (dispatch, props) => {
const { backend } = props;
return {
onConnect: (addr) => connect(backend, addr),
- onDisconnect: () => disconnect(backend)
+ onDisconnect: () => disconnect(backend),
+ getServerInfo: (key) => backend.serverInfo(key)
};
};
diff --git a/app/containers/SelectLocationPage.js b/app/containers/SelectLocationPage.js
index 114ec5ffd5..37892d508e 100644
--- a/app/containers/SelectLocationPage.js
+++ b/app/containers/SelectLocationPage.js
@@ -4,6 +4,16 @@ import SelectLocation from '../components/SelectLocation';
import settingsActions from '../actions/settings';
const mapStateToProps = (state) => state;
-const mapDispatchToProps = (dispatch) => bindActionCreators(settingsActions, dispatch);
+const mapDispatchToProps = (dispatch, props) => {
+ const { backend } = props;
+ const settings = bindActionCreators(settingsActions, dispatch);
+ return {
+ onChangeLocation: (preferredServer) => {
+ const server = backend.serverInfo(preferredServer);
+ settings.updateSettings({ preferredServer });
+ backend.connect(server.address);
+ }
+ };
+};
export default connect(mapStateToProps, mapDispatchToProps)(SelectLocation);
diff --git a/app/containers/SettingsPage.js b/app/containers/SettingsPage.js
index 3b014886e1..4369240928 100644
--- a/app/containers/SettingsPage.js
+++ b/app/containers/SettingsPage.js
@@ -3,6 +3,8 @@ import { bindActionCreators } from 'redux';
import Settings from '../components/Settings';
import userActions from '../actions/user';
import settingsActions from '../actions/settings';
+import { shell } from 'electron';
+import { links } from '../constants';
const mapStateToProps = (state) => {
return state;
@@ -13,6 +15,7 @@ const mapDispatchToProps = (dispatch, props) => {
const { updateSettings } = bindActionCreators(settingsActions, dispatch);
return {
logout: () => logout(props.backend),
+ buyTime: () => shell.openExternal(links.purchase),
updateSettings
};
};
diff --git a/app/lib/backend.js b/app/lib/backend.js
index 0add43f24f..abc6e56aba 100644
--- a/app/lib/backend.js
+++ b/app/lib/backend.js
@@ -1,5 +1,6 @@
import Enum from './enum';
import { EventEmitter } from 'events';
+import { servers } from '../constants';
const EventType = Enum('connect', 'connecting', 'disconnect', 'login', 'logging', 'logout', 'updatedIp');
@@ -31,6 +32,34 @@ export default class Backend extends EventEmitter {
// Public methods
+ serverInfo(key) {
+ switch(key) {
+ case 'fastest': return this.fastestServer();
+ case 'nearest': return this.nearestServer();
+ default: return servers[key] || {};
+ }
+ }
+
+ fastestServer() {
+ return {
+ address: 'uk.mullvad.net',
+ name: 'Fastest',
+ city: 'London',
+ country: 'United Kingdom',
+ location: [51.5073509, -0.1277583]
+ };
+ }
+
+ nearestServer() {
+ return {
+ address: 'es.mullvad.net',
+ name: 'Nearest',
+ city: 'Madrid',
+ country: 'Spain',
+ location: [40.4167754, -3.7037902]
+ };
+ }
+
login(account) {
this._account = account;
@@ -58,6 +87,8 @@ export default class Backend extends EventEmitter {
}
connect(addr) {
+ this.disconnect();
+
this._serverAddress = addr;
// emit: connecting