diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2020-02-21 15:31:52 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2020-02-21 15:31:52 +0100 |
| commit | a558bbbed062059dc778d78c4f179945deb5ef41 (patch) | |
| tree | b6a77e46fc0f3ee3aa4886d2d33ce147bfc8996b | |
| parent | af69985becd9a4fd8f2b80d57dc568a0cf7d0ce5 (diff) | |
| parent | e260455ac88de2c641d5df11af9d2fd38b047fe0 (diff) | |
| download | mullvadvpn-a558bbbed062059dc778d78c4f179945deb5ef41.tar.xz mullvadvpn-a558bbbed062059dc778d78c4f179945deb5ef41.zip | |
Merge branch 'eslint-add-promise-rules'
| -rw-r--r-- | gui/.eslintrc.js | 19 | ||||
| -rw-r--r-- | gui/package.json | 2 | ||||
| -rw-r--r-- | gui/src/main/account-data-cache.ts | 5 | ||||
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 4 | ||||
| -rw-r--r-- | gui/src/main/index.ts | 21 | ||||
| -rw-r--r-- | gui/src/main/notification-controller.ts | 3 | ||||
| -rw-r--r-- | gui/src/main/proc.ts | 2 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 9 | ||||
| -rw-r--r-- | gui/src/renderer/components/Accordion.tsx | 5 | ||||
| -rw-r--r-- | gui/src/renderer/components/AppButton.tsx | 9 | ||||
| -rw-r--r-- | gui/src/renderer/components/Login.tsx | 9 | ||||
| -rw-r--r-- | gui/src/renderer/components/Marquee.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/NotificationBanner.tsx | 5 | ||||
| -rw-r--r-- | gui/src/renderer/containers/AccountPage.tsx | 3 | ||||
| -rw-r--r-- | gui/src/renderer/containers/LoginPage.tsx | 3 | ||||
| -rw-r--r-- | gui/src/renderer/containers/PreferencesPage.tsx | 3 | ||||
| -rw-r--r-- | gui/src/shared/promise.ts | 6 | ||||
| -rw-r--r-- | gui/types/d3-geo-projection/index.d.ts | 1 |
18 files changed, 62 insertions, 49 deletions
diff --git a/gui/.eslintrc.js b/gui/.eslintrc.js index 01b47ee0d5..4a8eac1f15 100644 --- a/gui/.eslintrc.js +++ b/gui/.eslintrc.js @@ -18,10 +18,6 @@ module.exports = { 'eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react/recommended', - 'plugin:import/errors', - 'plugin:import/warnings', - 'plugin:import/typescript', - 'plugin:promise/recommended', ], settings: { react: { @@ -36,20 +32,19 @@ module.exports = { 'error', { argsIgnorePattern: '^_', ignoreRestSiblings: true }, ], - // TODO: Enable these - // 'require-await': 'error', - // '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/require-await': 'error', + '@typescript-eslint/no-floating-promises': 'error', + 'no-return-await': 'error', + 'no-unused-expressions': 'error', '@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/explicit-function-return-type': 'off', - // TODO: This should eventually be removed. - '@typescript-eslint/ban-types': 'warn', - '@typescript-eslint/no-non-null-assertion': 'warn', - '@typescript-eslint/no-explicit-any': 'warn', - 'react/no-find-dom-node': 'warn', + '@typescript-eslint/no-non-null-assertion': 'off', '@typescript-eslint/interface-name-prefix': 'off', + // TODO: The rules below should be enabled when move from ReactXP is completed. '@typescript-eslint/camelcase': 'off', '@typescript-eslint/ban-ts-ignore': 'off', + 'react/no-find-dom-node': 'off', }, }; diff --git a/gui/package.json b/gui/package.json index 2d4282249e..2d33a6af81 100644 --- a/gui/package.json +++ b/gui/package.json @@ -74,9 +74,7 @@ "enzyme": "^3.7.0", "enzyme-adapter-react-16": "^1.7.0", "eslint": "^6.8.0", - "eslint-plugin-import": "^2.20.1", "eslint-plugin-prettier": "^3.1.2", - "eslint-plugin-promise": "^4.2.1", "eslint-plugin-react": "^7.18.3", "gettext-extractor": "^3.5.1", "gulp": "^4.0.2", diff --git a/gui/src/main/account-data-cache.ts b/gui/src/main/account-data-cache.ts index 0c68f38729..58c6d41dbd 100644 --- a/gui/src/main/account-data-cache.ts +++ b/gui/src/main/account-data-cache.ts @@ -1,5 +1,6 @@ import log from 'electron-log'; import { AccountToken, IAccountData } from '../shared/daemon-rpc-types'; +import consumePromise from '../shared/promise'; export enum AccountFetchRetryAction { stop, @@ -37,7 +38,7 @@ export default class AccountDataCache { this.watchers.push(watcher); } - this.performFetch(accountToken); + consumePromise(this.performFetch(accountToken)); } else if (watcher) { watcher.onFinish(); } @@ -107,7 +108,7 @@ export default class AccountDataCache { this.fetchRetryTimeout = global.setTimeout(() => { this.fetchRetryTimeout = undefined; - this.performFetch(accountToken); + consumePromise(this.performFetch(accountToken)); }, delay); } diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index 31ac80f7e7..00201f7505 100644 --- a/gui/src/main/daemon-rpc.ts +++ b/gui/src/main/daemon-rpc.ts @@ -392,8 +392,8 @@ const NETWORK_CALL_TIMEOUT = 10000; export class DaemonRpc { private transport = new JsonRpcClient(new SocketTransport()); - public connect(connectionParams: { path: string }) { - this.transport.connect(connectionParams); + public connect(connectionParams: { path: string }): Promise<void> { + return this.transport.connect(connectionParams); } public disconnect() { diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index 6d146eb418..3b13231e69 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -34,6 +34,7 @@ import { getRendererLogFile, setupLogging, } from '../shared/logging'; +import consumePromise from '../shared/promise'; import AccountDataCache, { AccountFetchRetryAction } from './account-data-cache'; import { getOpenAtLogin, setOpenAtLogin } from './autostart'; import { @@ -379,7 +380,11 @@ class ApplicationMain { windowController.show(); } - window.loadFile(path.resolve(path.join(__dirname, '../renderer/index.html'))); + try { + await window.loadFile(path.resolve(path.join(__dirname, '../renderer/index.html'))); + } catch (error) { + log.error(`Failed to load index file: ${error.message}`); + } }; private onDaemonConnected = async () => { @@ -444,7 +449,7 @@ class ApplicationMain { } // fetch the latest version info in background - this.fetchLatestVersion(); + consumePromise(this.fetchLatestVersion()); // notify user about inconsistent version if ( @@ -502,7 +507,7 @@ class ApplicationMain { }; private connectToDaemon() { - this.daemonRpc.connect({ path: DAEMON_RPC_PATH }); + consumePromise(this.daemonRpc.connect({ path: DAEMON_RPC_PATH })); } private reconnectToDaemon() { @@ -585,7 +590,7 @@ class ApplicationMain { private setTunnelState(newState: TunnelState) { this.tunnelState = newState; this.updateTrayIcon(newState, this.settings.blockWhenDisconnected); - this.updateLocation(); + consumePromise(this.updateLocation()); if (!this.shouldSuppressNotifications(false)) { this.notificationController.notifyTunnelState(newState); @@ -610,8 +615,8 @@ class ApplicationMain { this.updateAccountDataOnAccountChange(oldSettings.accountToken, newSettings.accountToken); if (oldSettings.accountToken !== newSettings.accountToken) { - this.updateAccountHistory(); - this.fetchWireguardKey(); + consumePromise(this.updateAccountHistory()); + consumePromise(this.fetchWireguardKey()); } if (this.windowController) { @@ -975,7 +980,7 @@ class ApplicationMain { IpcMainEventChannel.accountHistory.handleRemoveItem(async (token: AccountToken) => { await this.daemonRpc.removeAccountFromHistory(token); - this.updateAccountHistory(); + consumePromise(this.updateAccountHistory()); }); IpcMainEventChannel.wireguardKeys.handleGenerateKey(async () => { @@ -1183,7 +1188,7 @@ class ApplicationMain { private updateDaemonsAutoConnect() { const daemonAutoConnect = this.guiSettings.autoConnect && getOpenAtLogin(); if (daemonAutoConnect !== this.settings.autoConnect) { - this.daemonRpc.setAutoConnect(daemonAutoConnect); + consumePromise(this.daemonRpc.setAutoConnect(daemonAutoConnect)); } } diff --git a/gui/src/main/notification-controller.ts b/gui/src/main/notification-controller.ts index 69c0f9ec30..4c542db3ea 100644 --- a/gui/src/main/notification-controller.ts +++ b/gui/src/main/notification-controller.ts @@ -6,6 +6,7 @@ import config from '../config.json'; import AccountExpiry from '../shared/account-expiry'; import { TunnelState } from '../shared/daemon-rpc-types'; import { messages } from '../shared/gettext'; +import consumePromise from '../shared/promise'; export default class NotificationController { private lastTunnelStateAnnouncement?: { body: string; notification: Notification }; @@ -140,7 +141,7 @@ export default class NotificationController { }); notification.on('click', () => { - shell.openExternal(config.links.download); + consumePromise(shell.openExternal(config.links.download)); }); this.scheduleNotification(notification); diff --git a/gui/src/main/proc.ts b/gui/src/main/proc.ts index 238c08c172..1e8118268d 100644 --- a/gui/src/main/proc.ts +++ b/gui/src/main/proc.ts @@ -10,7 +10,7 @@ function getBasePath(): string { process.env.MULLVAD_PATH || path.resolve(path.join(__dirname, '../../../../target/debug')) ); } else { - return process.resourcesPath!; + return process.resourcesPath; } } diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index 73de4302bf..9eabd147b5 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -27,6 +27,7 @@ import { loadTranslations, messages, relayLocations } from '../shared/gettext'; import { IGuiSettingsState, SYSTEM_PREFERRED_LOCALE_KEY } from '../shared/gui-settings-state'; import { IpcRendererEventChannel, IRelayListPair } from '../shared/ipc-event-channel'; import { getRendererLogFile, setupLogging } from '../shared/logging'; +import consumePromise from '../shared/promise'; import { AccountToken, @@ -121,7 +122,7 @@ export default class AppRenderer { }); IpcRendererEventChannel.daemonConnected.listen(() => { - this.onDaemonConnected(); + consumePromise(this.onDaemonConnected()); }); IpcRendererEventChannel.daemonDisconnected.listen((errorMessage?: string) => { @@ -206,7 +207,7 @@ export default class AppRenderer { this.setWireguardPublicKey(initialState.wireguardPublicKey); if (initialState.isConnected) { - this.onDaemonConnected(); + consumePromise(this.onDaemonConnected()); } // disable pinch to zoom @@ -290,7 +291,7 @@ export default class AppRenderer { return IpcRendererEventChannel.settings.updateBridgeSettings(bridgeSettings); } - public async removeAccountFromHistory(accountToken: AccountToken): Promise<void> { + public removeAccountFromHistory(accountToken: AccountToken): Promise<void> { return IpcRendererEventChannel.accountHistory.removeItem(accountToken); } @@ -301,7 +302,7 @@ export default class AppRenderer { } catch (e) { log.error(`Failed to get the WWW auth token: ${e.message}`); } - shell.openExternal(`${link}?token=${token}`); + consumePromise(shell.openExternal(`${link}?token=${token}`)); } public async setAllowLan(allowLan: boolean) { diff --git a/gui/src/renderer/components/Accordion.tsx b/gui/src/renderer/components/Accordion.tsx index 19c9ddee56..cf6603774e 100644 --- a/gui/src/renderer/components/Accordion.tsx +++ b/gui/src/renderer/components/Accordion.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { Animated, Component, Styles, Types, UserInterface, View } from 'reactxp'; +import consumePromise from '../../shared/promise'; interface IProps { expanded: boolean; @@ -56,11 +57,11 @@ export default class Accordion extends Component<IProps, IState> { if (this.props.expanded && !this.state.mountChildren) { this.setState({ mountChildren: true }); } else { - this.animate(this.props.expanded); + consumePromise(this.animate(this.props.expanded)); } } else if (this.state.mountChildren && !oldState.mountChildren) { // run animations once the children are mounted - this.animate(this.props.expanded); + consumePromise(this.animate(this.props.expanded)); } } diff --git a/gui/src/renderer/components/AppButton.tsx b/gui/src/renderer/components/AppButton.tsx index d31194e072..e1c37c014b 100644 --- a/gui/src/renderer/components/AppButton.tsx +++ b/gui/src/renderer/components/AppButton.tsx @@ -2,6 +2,7 @@ import log from 'electron-log'; import * as React from 'react'; import { Button, Component, Styles, Text, Types, UserInterface, View } from 'reactxp'; import { colors } from '../../config.json'; +import consumePromise from '../../shared/promise'; import styles from './AppButtonStyles'; import ImageView from './ImageView'; @@ -94,7 +95,7 @@ class BaseButton extends Component<IProps, IState> { private textViewRef = React.createRef<PrivateLabel>(); public componentDidMount() { - this.forceUpdateTextAdjustment(); + consumePromise(this.forceUpdateTextAdjustment()); } public render() { @@ -135,7 +136,7 @@ class BaseButton extends Component<IProps, IState> { this, ); - this.updateTextAdjustment(containerLayout); + await this.updateTextAdjustment(containerLayout); } } @@ -160,8 +161,8 @@ class BaseButton extends Component<IProps, IState> { } } - private onLayout = async (containerLayout: Types.ViewOnLayoutEvent) => { - this.updateTextAdjustment(containerLayout); + private onLayout = (containerLayout: Types.ViewOnLayoutEvent) => { + consumePromise(this.updateTextAdjustment(containerLayout)); }; } diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx index 9e2ff82433..f49054f076 100644 --- a/gui/src/renderer/components/Login.tsx +++ b/gui/src/renderer/components/Login.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { Animated, Component, Styles, Text, TextInput, Types, UserInterface, View } from 'reactxp'; import { colors, links } from '../../config.json'; +import consumePromise from '../../shared/promise'; import { messages } from '../../shared/gettext'; import Accordion from './Accordion'; import * as AppButton from './AppButton'; @@ -72,7 +73,7 @@ export default class Login extends Component<IProps, IState> { } public componentDidMount() { - this.setFooterVisibility(this.shouldShowFooter()); + consumePromise(this.setFooterVisibility(this.shouldShowFooter())); } public componentDidUpdate(prevProps: IProps, _prevState: IState) { @@ -91,7 +92,7 @@ export default class Login extends Component<IProps, IState> { } this.setLoginButtonActive(this.shouldActivateLoginButton()); - this.setFooterVisibility(this.shouldShowFooter()); + consumePromise(this.setFooterVisibility(this.shouldShowFooter())); } public render() { @@ -142,7 +143,7 @@ export default class Login extends Component<IProps, IState> { this.setState({ isActive: false }); }; - private async setLoginButtonActive(isActive: boolean) { + private setLoginButtonActive(isActive: boolean) { if (this.isLoginButtonActive === isActive) { return; } @@ -336,7 +337,7 @@ export default class Login extends Component<IProps, IState> { }; private onRemoveAccountFromHistory = (accountToken: string) => { - this.removeAccountFromHistory(accountToken); + consumePromise(this.removeAccountFromHistory(accountToken)); }; private async removeAccountFromHistory(accountToken: AccountToken) { diff --git a/gui/src/renderer/components/Marquee.tsx b/gui/src/renderer/components/Marquee.tsx index dc019d74ca..04b095711e 100644 --- a/gui/src/renderer/components/Marquee.tsx +++ b/gui/src/renderer/components/Marquee.tsx @@ -45,7 +45,7 @@ export default class Marquee extends Component<IMarqueeProps> { ); } - private async startAnimation() { + private startAnimation() { this.stopAnimation(); this.animationTimeout = setTimeout(async () => { diff --git a/gui/src/renderer/components/NotificationBanner.tsx b/gui/src/renderer/components/NotificationBanner.tsx index ba626c07f4..360c910403 100644 --- a/gui/src/renderer/components/NotificationBanner.tsx +++ b/gui/src/renderer/components/NotificationBanner.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import { Animated, Button, Component, Styles, Text, Types, UserInterface, View } from 'reactxp'; import { colors } from '../../config.json'; +import consumePromise from '../../shared/promise'; import { BlockingButton } from './AppButton'; import ImageView from './ImageView'; @@ -213,7 +214,7 @@ export class NotificationBanner extends Component< if (prevProps.visible !== this.props.visible) { // enable drawer-like animation when changing banner's visibility this.setState({ contentPinnedToBottom: true }, () => { - this.animateHeightChanges(); + consumePromise(this.animateHeightChanges()); }); } } @@ -249,7 +250,7 @@ export class NotificationBanner extends Component< // notification banner to slide down each time the component is mounted. if (this.didFinishFirstLayoutPass) { if (oldHeight !== height) { - this.animateHeightChanges(); + consumePromise(this.animateHeightChanges()); } } else { this.didFinishFirstLayoutPass = true; diff --git a/gui/src/renderer/containers/AccountPage.tsx b/gui/src/renderer/containers/AccountPage.tsx index 945512a2f7..012427b94d 100644 --- a/gui/src/renderer/containers/AccountPage.tsx +++ b/gui/src/renderer/containers/AccountPage.tsx @@ -2,6 +2,7 @@ import { goBack } from 'connected-react-router'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { links } from '../../config.json'; +import consumePromise from '../../shared/promise'; import Account from '../components/Account'; import withAppContext, { IAppContext } from '../context'; @@ -17,7 +18,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => { const history = bindActionCreators({ goBack }, dispatch); return { onLogout: () => { - props.app.logout(); + consumePromise(props.app.logout()); }, onClose: () => { history.goBack(); diff --git a/gui/src/renderer/containers/LoginPage.tsx b/gui/src/renderer/containers/LoginPage.tsx index 9b39520881..2f221ad875 100644 --- a/gui/src/renderer/containers/LoginPage.tsx +++ b/gui/src/renderer/containers/LoginPage.tsx @@ -2,6 +2,7 @@ import { push } from 'connected-react-router'; import { shell } from 'electron'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import consumePromise from '../../shared/promise'; import Login from '../components/Login'; import withAppContext, { IAppContext } from '../context'; import accountActions from '../redux/account/actions'; @@ -24,7 +25,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => { history.push('/settings'); }, login: (account: string) => { - props.app.login(account); + consumePromise(props.app.login(account)); }, resetLoginError: () => { resetLoginError(); diff --git a/gui/src/renderer/containers/PreferencesPage.tsx b/gui/src/renderer/containers/PreferencesPage.tsx index 068f6f8d1d..299d5799cb 100644 --- a/gui/src/renderer/containers/PreferencesPage.tsx +++ b/gui/src/renderer/containers/PreferencesPage.tsx @@ -2,6 +2,7 @@ import { goBack } from 'connected-react-router'; import log from 'electron-log'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import consumePromise from '../../shared/promise'; import Preferences from '../components/Preferences'; import withAppContext, { IAppContext } from '../context'; import { IReduxState, ReduxDispatch } from '../redux/store'; @@ -35,7 +36,7 @@ const mapDispatchToProps = (dispatch: ReduxDispatch, props: IAppContext) => { props.app.setAutoConnect(autoConnect); }, setAllowLan: (allowLan: boolean) => { - props.app.setAllowLan(allowLan); + consumePromise(props.app.setAllowLan(allowLan)); }, setStartMinimized: (startMinimized: boolean) => { props.app.setStartMinimized(startMinimized); diff --git a/gui/src/shared/promise.ts b/gui/src/shared/promise.ts new file mode 100644 index 0000000000..c0228e23e8 --- /dev/null +++ b/gui/src/shared/promise.ts @@ -0,0 +1,6 @@ +// eslint-disable-next-line @typescript-eslint/no-empty-function +const noop = () => {}; + +export default function consumePromise<T>(promise: Promise<T>): void { + promise.then(noop, noop); +} diff --git a/gui/types/d3-geo-projection/index.d.ts b/gui/types/d3-geo-projection/index.d.ts index 0c70c39e6b..0f6de59ba2 100644 --- a/gui/types/d3-geo-projection/index.d.ts +++ b/gui/types/d3-geo-projection/index.d.ts @@ -1,5 +1,4 @@ declare module 'd3-geo-projection' { - // eslint-disable-next-line import/no-extraneous-dependencies import { GeoProjection } from 'd3-geo'; export function geoTimes(): GeoProjection; |
