From 62d9080bbc89a3aa02fdebbeeecf3692e693f8f8 Mon Sep 17 00:00:00 2001 From: reyraa Date: Thu, 28 Sep 2017 16:50:42 +0200 Subject: [PATCH 1/4] Create the utility to listen for openUrl events --- src/utils/externalLinks.js | 15 +++++++++++++++ src/utils/externalLinks.test.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/utils/externalLinks.js create mode 100644 src/utils/externalLinks.test.js diff --git a/src/utils/externalLinks.js b/src/utils/externalLinks.js new file mode 100644 index 000000000..82850416b --- /dev/null +++ b/src/utils/externalLinks.js @@ -0,0 +1,15 @@ +import history from '../history'; + +export default { + init: () => { + const { ipc } = window; + const protocolReg = /[lL][iI][sS][kK]:\/\//; + + if (ipc) { + ipc.on('openUrl', (action, url) => { + history.push(url.replace(protocolReg, '/')); + }); + } + }, +}; + diff --git a/src/utils/externalLinks.test.js b/src/utils/externalLinks.test.js new file mode 100644 index 000000000..126d98213 --- /dev/null +++ b/src/utils/externalLinks.test.js @@ -0,0 +1,30 @@ +import { expect } from 'chai'; +import { spy } from 'sinon'; +import externalLinks from './externalLinks'; + +describe.only('externalLinks', () => { + const ipc = { + on: spy(), + }; + + const history = { + push: spy(), + }; + + describe('init', () => { + it('should be a function', () => { + expect(typeof externalLinks.init).to.be.equal('function'); + }); + + it('calling init when ipc is not on window should do nothing', () => { + externalLinks.init(); + expect(ipc.on).to.not.have.been.calledWith(); + }); + + it('calling init when ipc is available on window should bind listeners', () => { + window.ipc = ipc; + externalLinks.init(); + expect(ipc.on).to.have.been.calledWith(); + }); + }); +}); From fd64c8772773416d7ef673f2645c7ce432200915 Mon Sep 17 00:00:00 2001 From: reyraa Date: Thu, 28 Sep 2017 16:51:05 +0200 Subject: [PATCH 2/4] Use extrenalLinks utility in main --- src/main.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main.js b/src/main.js index e31f4f7d5..460440bd7 100644 --- a/src/main.js +++ b/src/main.js @@ -8,10 +8,12 @@ import App from './components/app'; import store from './store'; import i18n from './i18n'; // initialized i18next instance import proxyLogin from './utils/proxyLogin'; +import externalLinks from './utils/externalLinks'; import env from './constants/env'; if (env.production) { proxyLogin.init(); + externalLinks.init(); } const rootElement = document.getElementById('app'); From 511a0a809db49d14fad96365f51b9913de63a5bf Mon Sep 17 00:00:00 2001 From: reyraa Date: Fri, 29 Sep 2017 11:54:34 +0200 Subject: [PATCH 3/4] Write unit tests for utility --- src/utils/externalLinks.test.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/utils/externalLinks.test.js b/src/utils/externalLinks.test.js index 126d98213..9eeac4872 100644 --- a/src/utils/externalLinks.test.js +++ b/src/utils/externalLinks.test.js @@ -2,15 +2,11 @@ import { expect } from 'chai'; import { spy } from 'sinon'; import externalLinks from './externalLinks'; -describe.only('externalLinks', () => { +describe('externalLinks', () => { const ipc = { on: spy(), }; - const history = { - push: spy(), - }; - describe('init', () => { it('should be a function', () => { expect(typeof externalLinks.init).to.be.equal('function'); From 9738de339fecadfcda893c51477d06fa1c41c0b7 Mon Sep 17 00:00:00 2001 From: reyraa Date: Fri, 29 Sep 2017 16:33:21 +0200 Subject: [PATCH 4/4] Check the openUrl event value, prevent navigation to wrong URLs, inform the user --- src/components/dialog/dialog.js | 29 ++++------------------------- src/utils/externalLinks.js | 12 ++++++++++-- src/utils/routes.js | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 27 deletions(-) create mode 100644 src/utils/routes.js diff --git a/src/components/dialog/dialog.js b/src/components/dialog/dialog.js index 65adec27b..6dd5042d2 100644 --- a/src/components/dialog/dialog.js +++ b/src/components/dialog/dialog.js @@ -5,37 +5,15 @@ import AppBar from 'react-toolbox/lib/app_bar'; import { IconButton } from 'react-toolbox/lib/button'; import styles from './dialog.css'; import dialogs from './dialogs'; +import routesReg from '../../utils/routes'; class DialogElement extends Component { constructor() { super(); this.state = {}; - this.routesReg = [ - { - regex: /\/main\/transactions(?:\/[^/]*)?$/, - path: '/main/transactions/', - params: 'dialog', - name: 'transactions', - }, { - regex: /\/main\/voting(?:\/[^/]*)?$/, - path: '/main/voting/', - params: 'dialog', - name: 'voting', - }, { - regex: /\/main\/forging(?:\/[^/]*)?$/, - path: '/main/forging/', - params: 'dialog', - name: 'forging', - }, { - regex: /\/(\w+)?$/, - path: '/', - params: 'dialog', - name: 'login', - }, - ]; this.current = { pathname: '/', - reg: this.routesReg[3], + reg: routesReg[3], list: [], dialog: '', }; @@ -50,8 +28,9 @@ class DialogElement extends Component { } checkForDialog() { + // if the dialog is wrong, show a toast if (this.current.pathname !== this.props.history.location.pathname) { - this.current.reg = this.routesReg.find(item => + this.current.reg = routesReg.find(item => item.regex.test(this.props.history.location.pathname)); this.current.pathname = this.props.history.location.pathname; const dialogName = this.props.history.location.pathname.replace(this.current.reg.path, ''); diff --git a/src/utils/externalLinks.js b/src/utils/externalLinks.js index 82850416b..57778eb32 100644 --- a/src/utils/externalLinks.js +++ b/src/utils/externalLinks.js @@ -1,13 +1,21 @@ import history from '../history'; +import routesReg from './routes'; +import { errorToastDisplayed } from '../actions/toaster'; +import store from '../store'; export default { init: () => { const { ipc } = window; - const protocolReg = /[lL][iI][sS][kK]:\/\//; if (ipc) { ipc.on('openUrl', (action, url) => { - history.push(url.replace(protocolReg, '/')); + const normalizedUrl = url.toLowerCase().replace('lisk://', '/'); + const route = routesReg.find(item => item.regex.test(normalizedUrl)); + if (route !== undefined) { + history.push(normalizedUrl); + } else { + store.dispatch(errorToastDisplayed({ label: 'The URL was invalid' })); + } }); } }, diff --git a/src/utils/routes.js b/src/utils/routes.js new file mode 100644 index 000000000..582e6bef1 --- /dev/null +++ b/src/utils/routes.js @@ -0,0 +1,28 @@ +export default [ + { + regex: /\/main\/transactions(?:\/[^/]*)?$/, + path: '/main/transactions/', + params: 'dialog', + name: 'transactions', + }, { + regex: /\/main\/voting(?:\/[^/]*)?$/, + path: '/main/voting/', + params: 'dialog', + name: 'voting', + }, { + regex: /\/main\/forging(?:\/[^/]*)?$/, + path: '/main/forging/', + params: 'dialog', + name: 'forging', + }, { + regex: /register(\/)?$/, + path: '/', + params: 'dialog', + name: 'login', + }, { + regex: /^\/$/, + path: '/', + params: 'dialog', + name: 'login', + }, +];