diff options
| author | Andrej Mihajlov <and@codeispoetry.ru> | 2017-06-21 14:11:49 +0300 |
|---|---|---|
| committer | Andrej Mihajlov <and@codeispoetry.ru> | 2017-06-21 14:11:49 +0300 |
| commit | 5ae8eda0075ec72424c478fdf1ff731db43b0ff5 (patch) | |
| tree | c642e59864520408cbe8c1f7967cf814fdee43e8 | |
| parent | 7950d83c2d70c72bb08415d8ecf823d85ce7bd35 (diff) | |
| parent | 00c6ccf614bc92b72262e4ac57e8d602573ffc65 (diff) | |
| download | mullvadvpn-5ae8eda0075ec72424c478fdf1ff731db43b0ff5.tar.xz mullvadvpn-5ae8eda0075ec72424c478fdf1ff731db43b0ff5.zip | |
Merge branch 'feature/flow-typed/enums-migration'
| -rw-r--r-- | .eslintrc | 3 | ||||
| -rw-r--r-- | .flowconfig | 2 | ||||
| -rw-r--r-- | .vscode/settings.json | 7 | ||||
| -rw-r--r-- | app/app.js | 17 | ||||
| -rw-r--r-- | app/components/Connect.js | 27 | ||||
| -rw-r--r-- | app/components/Login.js | 29 | ||||
| -rw-r--r-- | app/components/Settings.js | 3 | ||||
| -rw-r--r-- | app/containers/LoginPage.js | 3 | ||||
| -rw-r--r-- | app/enums.js | 23 | ||||
| -rw-r--r-- | app/lib/backend-redux-actions.js | 13 | ||||
| -rw-r--r-- | app/reducers/connect.js | 3 | ||||
| -rw-r--r-- | app/reducers/user.js | 3 | ||||
| -rw-r--r-- | app/routes.js | 5 | ||||
| -rw-r--r-- | package.json | 2 | ||||
| -rw-r--r-- | test/actions.spec.js | 9 | ||||
| -rw-r--r-- | test/mocks/redux.js | 5 | ||||
| -rw-r--r-- | test/reducers.spec.js | 5 | ||||
| -rw-r--r-- | test/routing.spec.js | 3 | ||||
| -rw-r--r-- | yarn.lock | 18 |
19 files changed, 77 insertions, 103 deletions
@@ -26,7 +26,8 @@ "no-unused-expressions" : [ 0 ], // until fixed https://github.com/babel/babel-eslint/issues/158 "no-unused-vars": ["error", {"args": all, "argsIgnorePattern": "_.*"}], "block-scoped-var": [ 0 ], // until fixed https://github.com/eslint/eslint/issues/2253 - "react/prop-types": [ 0 ] + "react/prop-types": [ 0 ], + "flowtype/define-flow-type": 1 }, "env": { "es6": true, diff --git a/.flowconfig b/.flowconfig index 6d8e2c3c6e..e08fa5ecae 100644 --- a/.flowconfig +++ b/.flowconfig @@ -10,5 +10,7 @@ flow-libs/ [options] +emoji=true +suppress_comment= \\(.\\|\n\\)*\\$FlowFixMe munge_underscores=true unsafe.enable_getters_and_setters=true diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index 1a1f9a53e7..0000000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "search.exclude": { - "build/": true, - "dist/": true, - "docs/": true - } -}
\ No newline at end of file diff --git a/app/app.js b/app/app.js index 7eef8f3685..86084202af 100644 --- a/app/app.js +++ b/app/app.js @@ -13,7 +13,8 @@ import connectActions from './actions/connect'; import Backend from './lib/backend'; import mapBackendEventsToReduxActions from './lib/backend-redux-actions'; import mapBackendEventsToRouter from './lib/backend-routing'; -import { LoginState, ConnectionState } from './enums'; + +import type { LoginState, ConnectionState } from './enums'; import type { TrayIconType } from './lib/tray-icon-manager'; const initialState = {}; @@ -22,16 +23,16 @@ const store = configureStore(initialState, memoryHistory); const backend = new Backend(); // reset login state if user quit the app during login -if([LoginState.connecting, LoginState.failed].includes(store.getState().user.status)) { +if((['connecting', 'failed']: Array<LoginState>).includes(store.getState().user.status)) { store.dispatch(userActions.loginChange({ - status: LoginState.none + status: 'none' })); } // reset connection state if user quit the app when connecting -if(store.getState().connect.status === ConnectionState.connecting) { +if(store.getState().connect.status === 'connecting') { store.dispatch(connectActions.connectionChange({ - status: ConnectionState.disconnected + status: 'disconnected' })); } @@ -40,10 +41,10 @@ if(store.getState().connect.status === ConnectionState.connecting) { /** * Get tray icon type based on connection state */ -const getIconType = (s: string): TrayIconType => { +const getIconType = (s: ConnectionState): TrayIconType => { switch(s) { - case ConnectionState.connected: return 'secured'; - case ConnectionState.connecting: return 'securing'; + case 'connected': return 'secured'; + case 'connecting': return 'securing'; default: return 'unsecured'; } }; diff --git a/app/components/Connect.js b/app/components/Connect.js index c060986af3..0a3bd761a9 100644 --- a/app/components/Connect.js +++ b/app/components/Connect.js @@ -7,7 +7,6 @@ import cheapRuler from 'cheap-ruler'; import { Layout, Container, Header } from './Layout'; import { mapbox as mapboxConfig } from '../config'; import Backend from '../lib/backend'; -import { ConnectionState } from '../enums'; import ExternalLinkSVG from '../assets/images/icon-extLink.svg'; import type HeaderBarStyle from './HeaderBar'; @@ -109,9 +108,9 @@ export default class Connect extends Component { const preferredServer = this.props.settings.preferredServer; const serverInfo = this.props.getServerInfo(preferredServer); - const isConnecting = this.props.connect.status === ConnectionState.connecting; - const isConnected = this.props.connect.status === ConnectionState.connected; - const isDisconnected = this.props.connect.status === ConnectionState.disconnected; + const isConnecting = this.props.connect.status === 'connecting'; + const isConnected = this.props.connect.status === 'connected'; + const isDisconnected = this.props.connect.status === 'disconnected'; const altitude = (isConnecting ? 300 : 100) * 1000; @@ -338,19 +337,19 @@ export default class Connect extends Component { headerStyle(): HeaderBarStyle { switch(this.props.connect.status) { - case ConnectionState.connecting: - case ConnectionState.disconnected: + case 'connecting': + case 'disconnected': return 'error'; - case ConnectionState.connected: + case 'connected': return 'success'; } } networkSecurityClass() { let classes = ['connect__status-security']; - if(this.props.connect.status === ConnectionState.connected) { + if(this.props.connect.status === 'connected') { classes.push('connect__status-security--secure'); - } else if(this.props.connect.status === ConnectionState.disconnected) { + } else if(this.props.connect.status === 'disconnected') { classes.push('connect__status-security--unsecured'); } @@ -359,15 +358,15 @@ export default class Connect extends Component { networkSecurityMessage() { switch(this.props.connect.status) { - case ConnectionState.connected: return 'Secure connection'; - case ConnectionState.connecting: return 'Creating secure connection'; + case 'connected': return 'Secure connection'; + case 'connecting': return 'Creating secure connection'; default: return 'Unsecured connection'; } } spinnerClass() { var classes = ['connect__status-icon']; - if(this.props.connect.status !== ConnectionState.connecting) { + if(this.props.connect.status !== 'connecting') { classes.push('connect__status-icon--hidden'); } return classes.join(' '); @@ -375,14 +374,14 @@ export default class Connect extends Component { ipAddressClass() { var classes = ['connect__status-ipaddress']; - if(this.props.connect.status === ConnectionState.connecting) { + if(this.props.connect.status === 'connecting') { classes.push('connect__status-ipaddress--invisible'); } return classes.join(' '); } displayLocation() { - if(this.props.connect.status === ConnectionState.disconnected) { + if(this.props.connect.status === 'disconnected') { const { location, country, city } = this.props.user; return { location, country, city }; } diff --git a/app/components/Login.js b/app/components/Login.js index 3e841e096f..2bcf40950e 100644 --- a/app/components/Login.js +++ b/app/components/Login.js @@ -1,7 +1,6 @@ import React, { Component, PropTypes } from 'react'; import { If, Then } from 'react-if'; import { Layout, Container, Header } from './Layout'; -import { LoginState } from '../enums'; import AccountInput from './AccountInput'; import ExternalLinkSVG from '../assets/images/icon-extLink.svg'; import LoginArrowSVG from '../assets/images/icon-arrow.svg'; @@ -28,7 +27,7 @@ export default class Login extends Component { const prev = this.props.user || {}; const next = nextProps.user || {}; - if(prev.status !== next.status && next.status === LoginState.failed) { + if(prev.status !== next.status && next.status === 'failed') { this.setState({ notifyOnFirstChangeAfterFailure: true }); } } @@ -63,17 +62,17 @@ export default class Login extends Component { formTitle(s) { switch(s) { - case LoginState.connecting: return 'Logging in...'; - case LoginState.failed: return 'Login failed'; - case LoginState.ok: return 'Login successful'; + case 'connecting': return 'Logging in...'; + case 'failed': return 'Login failed'; + case 'ok': return 'Login successful'; default: return 'Login'; } } formSubtitle(s, e) { switch(s) { - case LoginState.failed: return e.message; - case LoginState.connecting: return 'Checking account number'; + case 'failed': return e.message; + case 'connecting': return 'Checking account number'; default: return 'Enter your account number'; } } @@ -86,10 +85,10 @@ export default class Login extends Component { } switch(user.status) { - case LoginState.connecting: + case 'connecting': classes.push('login-form__input-wrap--inactive'); break; - case LoginState.failed: + case 'failed': classes.push('login-form__input-wrap--error'); break; } @@ -100,8 +99,8 @@ export default class Login extends Component { footerClass(user) { const classes = ['login-footer']; switch(user.status) { - case LoginState.ok: - case LoginState.connecting: + case 'ok': + case 'connecting': classes.push('login-footer--invisible'); break; } @@ -115,7 +114,7 @@ export default class Login extends Component { classes.push('login-form__submit--active'); } - if(user.status === LoginState.connecting) { + if(user.status === 'connecting') { classes.push('login-form__submit--invisible'); } @@ -126,9 +125,9 @@ export default class Login extends Component { const { account, status, error } = this.props.user; const title = this.formTitle(status); const subtitle = this.formSubtitle(status, error); - const isConnecting = status === LoginState.connecting; - const isFailed = status === LoginState.failed; - const isLoggedIn = status === LoginState.ok; + const isConnecting = status === 'connecting'; + const isFailed = status === 'failed'; + const isLoggedIn = status === 'ok'; const inputWrapClass = this.inputWrapClass(this.props.user); const footerClass = this.footerClass(this.props.user); diff --git a/app/components/Settings.js b/app/components/Settings.js index 08a9af441b..cc8dc24f25 100644 --- a/app/components/Settings.js +++ b/app/components/Settings.js @@ -4,7 +4,6 @@ import { If, Then, Else } from 'react-if'; import { Layout, Container, Header } from './Layout'; import Switch from './Switch'; import CustomScrollbars from './CustomScrollbars'; -import { LoginState } from '../enums'; export default class Settings extends Component { @@ -34,7 +33,7 @@ export default class Settings extends Component { } render() { - const isLoggedIn = this.props.user.status === LoginState.ok; + const isLoggedIn = this.props.user.status === 'ok'; let isOutOfTime = false, formattedPaidUntil = ''; let paidUntilIso = this.props.user.paidUntil; diff --git a/app/containers/LoginPage.js b/app/containers/LoginPage.js index f5a75ca989..163e55f145 100644 --- a/app/containers/LoginPage.js +++ b/app/containers/LoginPage.js @@ -4,7 +4,6 @@ import { bindActionCreators } from 'redux'; import { push } from 'react-router-redux'; import Login from '../components/Login'; import userActions from '../actions/user'; -import { LoginState } from '../enums'; import { links } from '../config'; const mapStateToProps = (state) => state; @@ -15,7 +14,7 @@ const mapDispatchToProps = (dispatch, props) => { onSettings: () => dispatch(push('/settings')), onLogin: (account) => login(backend, account), onChange: (account) => loginChange({ account }), - onFirstChangeAfterFailure: () => loginChange({ status: LoginState.none, error: null }), + onFirstChangeAfterFailure: () => loginChange({ status: 'none', error: null }), onExternalLink: (type) => shell.openExternal(links[type]) }; }; diff --git a/app/enums.js b/app/enums.js index 8613b52bf8..6f4647efa6 100644 --- a/app/enums.js +++ b/app/enums.js @@ -1,20 +1,3 @@ -import Enum from './lib/enum'; - -/** - * Login state enum used for React components - * @type {LoginState} - * @property {string} none Initial state (not logged in) - * @property {string} connecting Attempting to log in - * @property {string} failed Failed to log in - * @property {string} ok Logged in - */ -export const LoginState = new Enum('none', 'connecting', 'failed', 'ok'); - -/** - * Connection state enum used for React components - * @type {ConnectionState} - * @property {string} disconnected Initial state (disconnected) - * @property {string} connecting Connecting - * @property {string} connected Connected - */ -export const ConnectionState = new Enum('disconnected', 'connecting', 'connected'); +// @flow +export type LoginState = 'none' | 'connecting' | 'failed' | 'ok'; +export type ConnectionState = 'disconnected' | 'connecting' | 'connected'; diff --git a/app/lib/backend-redux-actions.js b/app/lib/backend-redux-actions.js index 4e3dd63323..50bfd22943 100644 --- a/app/lib/backend-redux-actions.js +++ b/app/lib/backend-redux-actions.js @@ -1,7 +1,6 @@ import userActions from '../actions/user'; import connectActions from '../actions/connect'; import Backend from './backend'; -import { LoginState, ConnectionState } from '../enums'; import log from 'electron-log'; /** @@ -22,7 +21,7 @@ export default function mapBackendEventsToReduxActions(backend, store) { const onConnecting = (serverAddress) => { store.dispatch(connectActions.connectionChange({ - status: ConnectionState.connecting, + status: 'connecting', serverAddress })); }; @@ -31,33 +30,33 @@ export default function mapBackendEventsToReduxActions(backend, store) { if (error) { log.error('Unable to connect to', serverAddress, error); } else { - store.dispatch(connectActions.connectionChange({ status: ConnectionState.connected })); + store.dispatch(connectActions.connectionChange({ status: 'connected' })); } }; const onDisconnect = () => { store.dispatch(connectActions.connectionChange({ - status: ConnectionState.disconnected, + status: 'disconnected', serverAddress: null })); }; const onLoggingIn = (info) => { store.dispatch(userActions.loginChange(Object.assign({ - status: LoginState.connecting, + status: 'connecting', error: null }, info))); }; const onLogin = (info, error) => { - const status = error ? LoginState.failed : LoginState.ok; + const status = error ? 'failed' : 'ok'; const paidUntil = info.paidUntil ? info.paidUntil : null; store.dispatch(userActions.loginChange({ paidUntil, status, error })); }; const onLogout = () => { store.dispatch(userActions.loginChange({ - status: LoginState.none, + status: 'none', account: '', paidUntil: null, error: null diff --git a/app/reducers/connect.js b/app/reducers/connect.js index 35af5e888b..cf3dc35906 100644 --- a/app/reducers/connect.js +++ b/app/reducers/connect.js @@ -1,9 +1,8 @@ import { handleActions } from 'redux-actions'; -import { ConnectionState } from '../enums'; import actions from '../actions/connect'; const initialState = { - status: ConnectionState.disconnected, + status: 'disconnected', isOnline: true, serverAddress: null, clientIp: null diff --git a/app/reducers/user.js b/app/reducers/user.js index 15685034b8..1409c77a4e 100644 --- a/app/reducers/user.js +++ b/app/reducers/user.js @@ -1,6 +1,5 @@ import { handleActions } from 'redux-actions'; import actions from '../actions/user'; -import { LoginState } from '../enums'; const initialState = { account: null, @@ -8,7 +7,7 @@ const initialState = { location: [0, 0], country: null, city: null, - status: LoginState.none, + status: 'none', error: null }; diff --git a/app/routes.js b/app/routes.js index e61782f5f1..d815d12100 100644 --- a/app/routes.js +++ b/app/routes.js @@ -7,7 +7,6 @@ import ConnectPage from './containers/ConnectPage'; import SettingsPage from './containers/SettingsPage'; import AccountPage from './containers/AccountPage'; import SelectLocationPage from './containers/SelectLocationPage'; -import { LoginState } from './enums'; import { getTransitionProps } from './transitions'; /** @@ -55,7 +54,7 @@ export default function makeRoutes(getState, componentProps) { return ( <Route {...rest} render={ (routeProps) => { const { user } = getState(); - const isLoggedIn = user.status === LoginState.ok; + const isLoggedIn = user.status === 'ok'; if(isLoggedIn) { return renderMergedProps(component, routeProps, ...rest); @@ -76,7 +75,7 @@ export default function makeRoutes(getState, componentProps) { return ( <Route {...rest} render={ (routeProps) => { const { user } = getState(); - const isLoggedIn = user.status === LoginState.ok; + const isLoggedIn = user.status === 'ok'; if(isLoggedIn) { return (<Redirect to={ '/connect' } />); diff --git a/package.json b/package.json index 615dfde17c..9b16195226 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "eslint": "^3.14.1", "eslint-plugin-flowtype": "^2.34.0", "eslint-plugin-react": "^6.9.0", - "flow-bin": "^0.46.0", + "flow-bin": "^0.48.0", "flow-typed": "^2.1.2", "isomorphic-fetch": "^2.2.1", "jsdom": "^9.11.0", diff --git a/test/actions.spec.js b/test/actions.spec.js index e1420e92d2..914483161e 100644 --- a/test/actions.spec.js +++ b/test/actions.spec.js @@ -7,7 +7,6 @@ import { newMockIpc } from './mocks/ipc'; import userActions from '../app/actions/user'; import connectActions from '../app/actions/connect'; import mapBackendEventsToReduxActions from '../app/lib/backend-redux-actions'; -import { LoginState, ConnectionState } from '../app/enums'; describe('actions', function() { this.timeout(10000); @@ -100,11 +99,11 @@ describe('actions', function() { user: { account: '3333234567890', paidUntil: '2038-01-01T00:00:00.000Z', - status: LoginState.ok + status: 'ok' }, connect: { serverAddress: '1.2.3.4', - status: ConnectionState.connected + status: 'connected' } }); @@ -132,11 +131,11 @@ describe('actions', function() { user: { account: '3333234567890', paidUntil: '2038-01-01T00:00:00.000Z', - status: LoginState.ok + status: 'ok' }, connect: { serverAddress: '1.2.3.4', - status: ConnectionState.connected + status: 'connected' } }); diff --git a/test/mocks/redux.js b/test/mocks/redux.js index 6855274296..0d4d73518f 100644 --- a/test/mocks/redux.js +++ b/test/mocks/redux.js @@ -1,7 +1,6 @@ import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { defaultServer } from '../../app/config'; -import { LoginState, ConnectionState } from '../../app/enums'; // fetch is absent in node environment // this will automatically import it into global scope @@ -13,11 +12,11 @@ export const mockState = () => { return { user: { account: null, - status: LoginState.none, + status: 'none', error: null }, connect: { - status: ConnectionState.disconnected, + status: 'disconnected', serverAddress: null, clientIp: null }, diff --git a/test/reducers.spec.js b/test/reducers.spec.js index 8a5402c3e8..7a5470e930 100644 --- a/test/reducers.spec.js +++ b/test/reducers.spec.js @@ -3,7 +3,6 @@ import userReducer from '../app/reducers/user'; import connectReducer from '../app/reducers/connect'; import settingsReducer from '../app/reducers/settings'; import { defaultServer } from '../app/config'; -import { LoginState, ConnectionState } from '../app/enums'; describe('reducers', () => { @@ -12,7 +11,7 @@ describe('reducers', () => { type: 'USER_LOGIN_CHANGE', payload: { account: '1111', - status: LoginState.failed, + status: 'failed', error: new Error('Something went wrong') } }; @@ -24,7 +23,7 @@ describe('reducers', () => { const action = { type: 'CONNECTION_CHANGE', payload: { - status: ConnectionState.connected, + status: 'connected', serverAddress: '2.1.1.2', clientIp: '2.1.1.1' } diff --git a/test/routing.spec.js b/test/routing.spec.js index 2ce33e73c2..e728ca59a6 100644 --- a/test/routing.spec.js +++ b/test/routing.spec.js @@ -3,7 +3,6 @@ import { expect } from 'chai'; import { filterMinorActions, mockState, mockStore } from './mocks/redux'; import userActions from '../app/actions/user'; import mapBackendEventsToRouter from '../app/lib/backend-routing'; -import { LoginState } from '../app/enums'; import Backend from '../app/lib/backend'; import { newMockIpc } from './mocks/ipc'; @@ -18,7 +17,7 @@ describe('routing', function() { let state = Object.assign(mockState(), { user: { account: '1111234567890', - status: LoginState.ok + status: 'ok' } }); @@ -2292,6 +2292,12 @@ esdoc@^0.5.2: minimist "1.2.0" taffydb "2.7.2" +eslint-plugin-flowtype@^2.34.0: + version "2.34.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-2.34.0.tgz#b9875f314652e5081623c9d2b18a346bbb759c09" + dependencies: + lodash "^4.15.0" + eslint-plugin-react@^6.9.0: version "6.10.3" resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz#c5435beb06774e12c7db2f6abaddcbf900cd3f78" @@ -2583,9 +2589,9 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" -flow-bin@^0.46.0: - version "0.46.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.46.0.tgz#06ad7fe19dddb1042264438064a2a32fee12b872" +flow-bin@^0.48.0: + version "0.48.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.48.0.tgz#72d075143524358db8901525e3c784dc13a7c7ee" flow-remove-types@^1.1.2: version "1.2.1" @@ -3667,7 +3673,7 @@ lodash@^3.10.1: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" -lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0: +lodash@^4.0.0, lodash@^4.1.0, lodash@^4.13.1, lodash@^4.15.0, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" @@ -4016,8 +4022,8 @@ npmlog@^4.0.2: set-blocking "~2.0.0" "nseventmonitor@git+https://github.com/pronebird/NSEventMonitor.git": - version "0.0.2" - resolved "git+https://github.com/pronebird/NSEventMonitor.git#f6af316e7a92c1d50872ef3552271fdd4d8d4459" + version "0.0.3" + resolved "git+https://github.com/pronebird/NSEventMonitor.git#2707370d46748c2e4de99f0f762daf6d3b28b431" dependencies: bindings "^1.2.1" |
