diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-08-02 22:27:45 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-08-20 12:45:56 -0300 |
| commit | 964e6e695352fc005c7c36008c4c072030938a99 (patch) | |
| tree | 19079f684542d01c84e23065b70eb88e71a41d2d | |
| parent | 006012a514385171f55a86bb80828e0f8fe4a67a (diff) | |
| download | mullvadvpn-964e6e695352fc005c7c36008c4c072030938a99.tar.xz mullvadvpn-964e6e695352fc005c7c36008c4c072030938a99.zip | |
Show exclamation icon if version is inconsistent
8 files changed, 89 insertions, 12 deletions
diff --git a/gui/packages/desktop/src/assets/images/icon-alert.svg b/gui/packages/desktop/src/assets/images/icon-alert.svg new file mode 100644 index 0000000000..c11507a4a5 --- /dev/null +++ b/gui/packages/desktop/src/assets/images/icon-alert.svg @@ -0,0 +1,4 @@ +<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> + <title>alert</title> + <path d="m12 24c-6.627417 0-12-5.372583-12-12s5.372583-12 12-12 12 5.372583 12 12-5.372583 12-12 12zm0-19.5c-.8284271 0-1.5.67157288-1.5 1.5v7.5c0 .8284271.6715729 1.5 1.5 1.5s1.5-.6715729 1.5-1.5v-7.5c0-.82842712-.6715729-1.5-1.5-1.5zm0 12c-.8284271 0-1.5.6715729-1.5 1.5s.6715729 1.5 1.5 1.5 1.5-.6715729 1.5-1.5-.6715729-1.5-1.5-1.5z" fill="currentColor" /> +</svg> diff --git a/gui/packages/desktop/src/renderer/app.js b/gui/packages/desktop/src/renderer/app.js index 82a717941d..2fd1bb6bbd 100644 --- a/gui/packages/desktop/src/renderer/app.js +++ b/gui/packages/desktop/src/renderer/app.js @@ -10,7 +10,7 @@ import { replace as replaceHistory, } from 'connected-react-router'; import { createMemoryHistory } from 'history'; -import { webFrame, ipcRenderer } from 'electron'; +import { remote, webFrame, ipcRenderer } from 'electron'; import makeRoutes from './routes'; import ReconnectionBackoff from './lib/reconnection-backoff'; @@ -23,6 +23,7 @@ import configureStore from './redux/store'; import accountActions from './redux/account/actions'; import connectionActions from './redux/connection/actions'; import settingsActions from './redux/settings/actions'; +import versionActions from './redux/version/actions'; import daemonActions from './redux/daemon/actions'; import type { RpcCredentials } from '../common/types'; @@ -57,6 +58,7 @@ export default class AppRenderer { account: bindActionCreators(accountActions, dispatch), connection: bindActionCreators(connectionActions, dispatch), settings: bindActionCreators(settingsActions, dispatch), + version: bindActionCreators(versionActions, dispatch), daemon: bindActionCreators(daemonActions, dispatch), history: bindActionCreators( { @@ -405,6 +407,17 @@ export default class AppRenderer { actions.settings.updateEnableIpv6(tunnelOptions.openvpn.enableIpv6); } + async _fetchVersionInfo() { + const actions = this._reduxActions; + const versionFromDaemon = await this._daemonRpc.getCurrentVersion(); + const versionFromGui = remote.app + .getVersion() + .replace('.0-', '-') // remove the .0 in yyyy.x.0-zzz + .replace(/\.0$/, ''); // remove the .0 in yyyy.x.0 + + actions.version.updateVersion(versionFromDaemon, versionFromDaemon === versionFromGui); + } + async _connectToDaemon(): Promise<void> { let credentials; try { @@ -536,6 +549,7 @@ export default class AppRenderer { this._fetchLocation(), this._fetchAccountHistory(), this._fetchTunnelOptions(), + this._fetchVersionInfo(), ]); } diff --git a/gui/packages/desktop/src/renderer/components/Settings.js b/gui/packages/desktop/src/renderer/components/Settings.js index 40c4c2e2de..7c077f03a9 100644 --- a/gui/packages/desktop/src/renderer/components/Settings.js +++ b/gui/packages/desktop/src/renderer/components/Settings.js @@ -5,12 +5,14 @@ import * as React from 'react'; import { Component, View } from 'reactxp'; import * as AppButton from './AppButton'; import * as Cell from './Cell'; +import Img from './Img'; import { Layout, Container } from './Layout'; import NavigationBar, { CloseBarItem } from './NavigationBar'; import SettingsHeader, { HeaderTitle } from './SettingsHeader'; import CustomScrollbars from './CustomScrollbars'; import styles from './SettingsStyles'; import WindowStateObserver from '../lib/window-state-observer'; +import { colors } from '../../config'; import type { LoginState } from '../redux/account/reducers'; @@ -18,6 +20,7 @@ type Props = { loginState: LoginState, accountExpiry: ?string, appVersion: string, + consistentVersion: boolean, onQuit: () => void, onClose: () => void, onViewAccount: () => void, @@ -133,13 +136,17 @@ export default class Settings extends Component<Props> { } _renderMiddleButtons() { + const icon = this.props.consistentVersion ? null : ( + <Img source="icon-alert" tintColor={colors.red} style={styles.settings__version_warning} /> + ); return ( <View> <Cell.CellButton onPress={this.props.onExternalLink.bind(this, 'download')} testName="settings__version"> + {icon} <Cell.Label>App version</Cell.Label> - <Cell.SubText>{this._formattedVersion()}</Cell.SubText> + <Cell.SubText>{this.props.appVersion}</Cell.SubText> <Cell.Img height={16} width={16} source="icon-extLink" /> </Cell.CellButton> <View style={styles.settings__cell_spacer} /> @@ -147,15 +154,6 @@ export default class Settings extends Component<Props> { ); } - _formattedVersion() { - // the version in package.json has to be semver, but we use a YEAR.release-channel - // version scheme. in package.json we thus have to write YEAR.release.X-channel and - // this function is responsible for removing .X part. - return this.props.appVersion - .replace('.0-', '-') // remove the .0 in 2018.1.0-beta9 - .replace(/\.0$/, ''); // remove the .0 in 2018.1.0 - } - _renderBottomButtons() { return ( <View> diff --git a/gui/packages/desktop/src/renderer/components/SettingsStyles.js b/gui/packages/desktop/src/renderer/components/SettingsStyles.js index 3f63d96b0f..8ffefcabdf 100644 --- a/gui/packages/desktop/src/renderer/components/SettingsStyles.js +++ b/gui/packages/desktop/src/renderer/components/SettingsStyles.js @@ -33,6 +33,9 @@ export default { paddingLeft: 24, paddingRight: 24, }), + settings__version_warning: Styles.createViewStyle({ + marginLeft: 8, + }), settings__account_paid_until_label__error: Styles.createTextStyle({ color: colors.red, diff --git a/gui/packages/desktop/src/renderer/containers/SettingsPage.js b/gui/packages/desktop/src/renderer/containers/SettingsPage.js index 68fc929342..51d50fdb03 100644 --- a/gui/packages/desktop/src/renderer/containers/SettingsPage.js +++ b/gui/packages/desktop/src/renderer/containers/SettingsPage.js @@ -13,7 +13,8 @@ import type { SharedRouteProps } from '../routes'; const mapStateToProps = (state: ReduxState) => ({ loginState: state.account.status, accountExpiry: state.account.expiry, - appVersion: remote.app.getVersion(), + appVersion: state.version.current, + consistentVersion: state.version.consistent, }); const mapDispatchToProps = (dispatch: ReduxDispatch, props: SharedRouteProps) => { const history = bindActionCreators({ push, goBack }, dispatch); diff --git a/gui/packages/desktop/src/renderer/redux/store.js b/gui/packages/desktop/src/renderer/redux/store.js index af2ebc1d5a..58c6645a45 100644 --- a/gui/packages/desktop/src/renderer/redux/store.js +++ b/gui/packages/desktop/src/renderer/redux/store.js @@ -11,6 +11,8 @@ import settings from './settings/reducers'; import settingsActions from './settings/actions'; import support from './support/reducers'; import supportActions from './support/actions'; +import version from './version/reducers'; +import versionActions from './version/actions'; import daemon from './daemon/reducers'; import daemonActions from './daemon/actions'; @@ -20,12 +22,14 @@ import type { AccountReduxState } from './account/reducers'; import type { ConnectionReduxState } from './connection/reducers'; import type { SettingsReduxState } from './settings/reducers'; import type { SupportReduxState } from './support/reducers'; +import type { VersionReduxState } from './version/reducers'; import type { DaemonReduxState } from './daemon/reducers'; import type { AccountAction } from './account/actions'; import type { ConnectionAction } from './connection/actions'; import type { SettingsAction } from './settings/actions'; import type { SupportAction } from './support/actions'; +import type { VersionAction } from './version/actions'; import type { DaemonAction } from './daemon/actions'; export type ReduxState = { @@ -33,6 +37,7 @@ export type ReduxState = { connection: ConnectionReduxState, settings: SettingsReduxState, support: SupportReduxState, + version: VersionReduxState, daemon: DaemonReduxState, }; @@ -41,6 +46,7 @@ export type ReduxAction = | ConnectionAction | SettingsAction | SupportAction + | VersionAction | DaemonAction; export type ReduxStore = Store<ReduxState, ReduxAction, ReduxDispatch>; export type ReduxGetState = () => ReduxState; @@ -57,6 +63,7 @@ export default function configureStore( ...connectionActions, ...settingsActions, ...supportActions, + ...versionActions, ...daemonActions, pushRoute: (route) => push(route), replaceRoute: (route) => replace(route), @@ -67,6 +74,7 @@ export default function configureStore( connection, settings, support, + version, daemon, }; diff --git a/gui/packages/desktop/src/renderer/redux/version/actions.js b/gui/packages/desktop/src/renderer/redux/version/actions.js new file mode 100644 index 0000000000..7edee16c03 --- /dev/null +++ b/gui/packages/desktop/src/renderer/redux/version/actions.js @@ -0,0 +1,19 @@ +// @flow + +export type UpdateVersionAction = { + type: 'UPDATE_VERSION', + version: string, + consistent: boolean, +}; + +export type VersionAction = UpdateVersionAction; + +function updateVersion(version: string, consistent: boolean): UpdateVersionAction { + return { + type: 'UPDATE_VERSION', + version, + consistent, + }; +} + +export default { updateVersion }; diff --git a/gui/packages/desktop/src/renderer/redux/version/reducers.js b/gui/packages/desktop/src/renderer/redux/version/reducers.js new file mode 100644 index 0000000000..160dbe569e --- /dev/null +++ b/gui/packages/desktop/src/renderer/redux/version/reducers.js @@ -0,0 +1,30 @@ +// @flow + +import type { ReduxAction } from '../store'; + +export type VersionReduxState = { + current: string, + consistent: boolean, +}; + +const initialState: VersionReduxState = { + current: '', + consistent: true, +}; + +export default function( + state: VersionReduxState = initialState, + action: ReduxAction, +): VersionReduxState { + switch (action.type) { + case 'UPDATE_VERSION': + return { + ...state, + current: action.version, + consistent: action.consistent, + }; + + default: + return state; + } +} |
