diff options
-rw-r--r-- | CHANGELOG.md | 1 | ||||
-rw-r--r-- | app/notification.html | 16 | ||||
-rw-r--r-- | app/scripts/background.js | 2 | ||||
-rw-r--r-- | app/scripts/lib/extension-instance.js | 6 | ||||
-rw-r--r-- | app/scripts/lib/is-popup-or-notification.js | 8 | ||||
-rw-r--r-- | app/scripts/lib/notifications.js | 152 | ||||
-rw-r--r-- | app/scripts/popup.js | 7 | ||||
-rw-r--r-- | ui/app/app.js | 5 | ||||
-rw-r--r-- | ui/app/conf-tx.js | 6 | ||||
-rw-r--r-- | ui/app/reducers/app.js | 9 |
10 files changed, 74 insertions, 138 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 95f9174eb..08cb59976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Current Master +- Changed transaction approval from notifications system to popup system. - Transaction history now has a hard limit. - Added info link on account screen that visits Etherscan. diff --git a/app/notification.html b/app/notification.html new file mode 100644 index 000000000..cc485da7f --- /dev/null +++ b/app/notification.html @@ -0,0 +1,16 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title>MetaMask Notification</title> + <style> + body { + overflow: hidden; + } + </style> + </head> + <body> + <div id="app-content"></div> + <script src="./scripts/popup.js" type="text/javascript" charset="utf-8"></script> + </body> +</html> diff --git a/app/scripts/background.js b/app/scripts/background.js index e04309e74..79f8f9fd9 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -69,7 +69,7 @@ function showUnconfirmedTx (txParams, txData, onTxDoneCb) { extension.runtime.onConnect.addListener(connectRemote) function connectRemote (remotePort) { - var isMetaMaskInternalProcess = (remotePort.name === 'popup') + var isMetaMaskInternalProcess = remotePort.name === 'popup' || remotePort.name === 'notification' var portStream = new PortStream(remotePort) if (isMetaMaskInternalProcess) { // communication with popup diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js index eb3b8a1e9..1098130e3 100644 --- a/app/scripts/lib/extension-instance.js +++ b/app/scripts/lib/extension-instance.js @@ -42,6 +42,12 @@ function Extension () { } catch (e) {} try { + if (browser[api]) { + _this[api] = browser[api] + } + } catch (e) {} + + try { _this.api = browser.extension[api] } catch (e) {} diff --git a/app/scripts/lib/is-popup-or-notification.js b/app/scripts/lib/is-popup-or-notification.js new file mode 100644 index 000000000..5c38ac823 --- /dev/null +++ b/app/scripts/lib/is-popup-or-notification.js @@ -0,0 +1,8 @@ +module.exports = function isPopupOrNotification() { + const url = window.location.href + if (url.match(/popup.html$/)) { + return 'popup' + } else { + return 'notification' + } +} diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index 6c1601df1..278c7674e 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -1,14 +1,4 @@ -const createId = require('hat') -const extend = require('xtend') -const unmountComponentAtNode = require('react-dom').unmountComponentAtNode -const findDOMNode = require('react-dom').findDOMNode -const render = require('react-dom').render -const h = require('react-hyperscript') -const PendingTxDetails = require('../../../ui/app/components/pending-tx-details') -const PendingMsgDetails = require('../../../ui/app/components/pending-msg-details') -const MetaMaskUiCss = require('../../../ui/css') const extension = require('./extension') -var notificationHandlers = {} const notifications = { createUnlockRequestNotification: createUnlockRequestNotification, @@ -18,142 +8,36 @@ const notifications = { module.exports = notifications window.METAMASK_NOTIFIER = notifications -setupListeners() - -function setupListeners () { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - - // notification button press - extension.notifications.onButtonClicked.addListener(function (notificationId, buttonIndex) { - var handlers = notificationHandlers[notificationId] - if (buttonIndex === 0) { - handlers.confirm() - } else { - handlers.cancel() - } - extension.notifications.clear(notificationId) - }) - - // notification teardown - extension.notifications.onClosed.addListener(function (notificationId) { - delete notificationHandlers[notificationId] - }) -} - -// creation helper function createUnlockRequestNotification (opts) { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - var message = 'An Ethereum app has requested a signature. Please unlock your account.' - - var id = createId() - extension.notifications.create(id, { - type: 'basic', - iconUrl: '/images/icon-128.png', - title: opts.title, - message: message, - }) + showNotification() } function createTxNotification (state) { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - - renderTxNotificationSVG(state, function (err, notificationSvgSource) { - if (err) throw err - - showNotification(extend(state, { - title: 'New Unsigned Transaction', - imageUrl: toSvgUri(notificationSvgSource), - })) - }) + showNotification() } function createMsgNotification (state) { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - - renderMsgNotificationSVG(state, function (err, notificationSvgSource) { - if (err) throw err - - showNotification(extend(state, { - title: 'New Unsigned Message', - imageUrl: toSvgUri(notificationSvgSource), - })) - }) + showNotification() } -function showNotification (state) { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') +function showNotification() { + extension.windows.getAll({}, (windows) => { - var id = createId() - extension.notifications.create(id, { - type: 'image', - requireInteraction: true, - iconUrl: '/images/icon-128.png', - imageUrl: state.imageUrl, - title: state.title, - message: '', - buttons: [{ - title: 'Approve', - }, { - title: 'Reject', - }], - }) - notificationHandlers[id] = { - confirm: state.onConfirm, - cancel: state.onCancel, - } -} - -function renderTxNotificationSVG (state, cb) { - var content = h(PendingTxDetails, state) - renderNotificationSVG(content, cb) -} + let popupWindow = windows.find((win) => { + return win.type === 'popup' + }) -function renderMsgNotificationSVG (state, cb) { - var content = h(PendingMsgDetails, state) - renderNotificationSVG(content, cb) -} - -function renderNotificationSVG (content, cb) { - var container = document.createElement('div') - var confirmView = h('div.app-primary', { - style: { - width: '360px', - height: '240px', - padding: '16px', - // background: '#F7F7F7', - background: 'white', - }, - }, [ - h('style', MetaMaskUiCss()), - content, - ]) + if (popupWindow) { + return extension.windows.update(popupWindow.id, { focused: true }) + } - render(confirmView, container, function ready() { - var rootElement = findDOMNode(this) - var viewSource = rootElement.outerHTML - unmountComponentAtNode(container) - var svgSource = svgWrapper(viewSource) - // insert content into svg wrapper - cb(null, svgSource) + extension.windows.create({ + url: 'notification.html', + type: 'detached_panel', + focused: true, + width: 360, + height: 500, + }) }) } -function svgWrapper (content) { - var wrapperSource = ` - <svg xmlns="http://www.w3.org/2000/svg" width="360" height="240"> - <foreignObject x="0" y="0" width="100%" height="100%"> - <body xmlns="http://www.w3.org/1999/xhtml" height="100%">{{content}}</body> - </foreignObject> - </svg> - ` - return wrapperSource.split('{{content}}').join(content) -} - -function toSvgUri (content) { - return 'data:image/svg+xml;utf8,' + encodeURIComponent(content) -} diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 20be15df7..4c729e227 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -9,6 +9,7 @@ const injectCss = require('inject-css') const PortStream = require('./lib/port-stream.js') const StreamProvider = require('web3-stream-provider') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex +const isPopupOrNotification = require('./lib/is-popup-or-notification') const extension = require('./lib/extension') // setup app @@ -22,7 +23,10 @@ async.parallel({ function connectToAccountManager (cb) { // setup communication with background - var pluginPort = extension.runtime.connect({name: 'popup'}) + + var name = isPopupOrNotification() + window.METAMASK_UI_TYPE = name + var pluginPort = extension.runtime.connect({ name }) var portStream = new PortStream(pluginPort) // setup multiplexing var mx = setupMultiplex(portStream) @@ -93,3 +97,4 @@ function setupApp (err, opts) { networkVersion: opts.networkVersion, }) } + diff --git a/ui/app/app.js b/ui/app/app.js index 84ff16ec8..53ab7dd00 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -96,6 +96,11 @@ App.prototype.render = function () { } App.prototype.renderAppBar = function () { + + if (window.METAMASK_UI_TYPE === 'notification') { + return null + } + const props = this.props const state = this.state || {} const isNetworkMenuOpen = state.isNetworkMenuOpen || false diff --git a/ui/app/conf-tx.js b/ui/app/conf-tx.js index db876dd9b..f832b8a4b 100644 --- a/ui/app/conf-tx.js +++ b/ui/app/conf-tx.js @@ -5,6 +5,7 @@ const h = require('react-hyperscript') const connect = require('react-redux').connect const actions = require('./actions') const txHelper = require('../lib/tx-helper') +const isPopupOrNotification = require('../../app/scripts/lib/is-popup-or-notification') const PendingTx = require('./components/pending-tx') const PendingMsg = require('./components/pending-msg') @@ -36,6 +37,7 @@ ConfirmTxScreen.prototype.render = function () { var unconfTxList = txHelper(unconfTxs, unconfMsgs) var index = state.index !== undefined ? state.index : 0 var txData = unconfTxList[index] || {} + var isNotification = isPopupOrNotification() === 'notification' return ( @@ -43,9 +45,9 @@ ConfirmTxScreen.prototype.render = function () { // subtitle and nav h('.section-title.flex-row.flex-center', [ - h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { + !isNotification ? h('i.fa.fa-arrow-left.fa-lg.cursor-pointer', { onClick: this.goHome.bind(this), - }), + }) : null, h('h2.page-subtitle', 'Confirm Transaction'), ]), diff --git a/ui/app/reducers/app.js b/ui/app/reducers/app.js index 8c2696877..94b7e8bf7 100644 --- a/ui/app/reducers/app.js +++ b/ui/app/reducers/app.js @@ -1,6 +1,7 @@ const extend = require('xtend') const actions = require('../actions') const txHelper = require('../../lib/tx-helper') +const extension = require('../../../app/scripts/lib/extension') module.exports = reduceApp @@ -250,6 +251,14 @@ function reduceApp (state, action) { warning: null, }) } else { + + const isNotification = window.METAMASK_UI_TYPE === 'notification' + if (isNotification) { + extension.windows.getCurrent({}, (win) => { + extension.windows.remove(win.id, console.error) + }) + } + return extend(appState, { transForward: false, warning: null, |