diff options
| author | Andrej Mihajlov <and@codeispoetry.ru> | 2017-02-24 15:20:52 +0000 |
|---|---|---|
| committer | Andrej Mihajlov <and@codeispoetry.ru> | 2017-02-24 15:20:52 +0000 |
| commit | e2c417059216d983c3e7d9560cfad02d82297aba (patch) | |
| tree | e6683b6616db131e3a4f1823cf9403f82c1909c1 | |
| parent | 040c1ef18fec5ab1aac5bfef4fc596f0c4591e9f (diff) | |
| download | mullvadvpn-e2c417059216d983c3e7d9560cfad02d82297aba.tar.xz mullvadvpn-e2c417059216d983c3e7d9560cfad02d82297aba.zip | |
- Move serverInfo configuration to backend
- Update settings
- Reconnect when switching location
| -rw-r--r-- | app/components/Connect.css | 2 | ||||
| -rw-r--r-- | app/components/Connect.js | 45 | ||||
| -rw-r--r-- | app/components/SelectLocation.js | 8 | ||||
| -rw-r--r-- | app/components/Settings.css | 7 | ||||
| -rw-r--r-- | app/components/Settings.js | 65 | ||||
| -rw-r--r-- | app/constants.js | 43 | ||||
| -rw-r--r-- | app/containers/ConnectPage.js | 3 | ||||
| -rw-r--r-- | app/containers/SelectLocationPage.js | 12 | ||||
| -rw-r--r-- | app/containers/SettingsPage.js | 3 | ||||
| -rw-r--r-- | app/lib/backend.js | 31 |
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 |
