From 5479509618e601391586d0851acee4e408523c4f Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 Aug 2016 15:39:40 -0700 Subject: Set up MVP for popup-based notifications. --- app/scripts/lib/notifications.js | 136 +++------------------------------------ 1 file changed, 9 insertions(+), 127 deletions(-) (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index 6c1601df1..75fb60dd0 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -18,142 +18,24 @@ 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...') - - 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', - }], +function showNotification() { + chrome.windows.create({ + url:"notification.html", + type:"panel", + width:360, + height:500, }) - notificationHandlers[id] = { - confirm: state.onConfirm, - cancel: state.onCancel, - } -} - -function renderTxNotificationSVG (state, cb) { - var content = h(PendingTxDetails, state) - renderNotificationSVG(content, cb) } -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, - ]) - - 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) - }) -} - -function svgWrapper (content) { - var wrapperSource = ` - - - {{content}} - - - ` - return wrapperSource.split('{{content}}').join(content) -} - -function toSvgUri (content) { - return 'data:image/svg+xml;utf8,' + encodeURIComponent(content) -} -- cgit v1.2.3 From 030bdec27a95390207b9147c95b810893756db6d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 Aug 2016 16:46:44 -0700 Subject: Unify notification and popup ui files --- app/scripts/lib/extension-instance.js | 6 ++++++ app/scripts/lib/is-popup-or-notification.js | 8 ++++++++ app/scripts/lib/notifications.js | 2 +- 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 app/scripts/lib/is-popup-or-notification.js (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js index eb3b8a1e9..d284895bc 100644 --- a/app/scripts/lib/extension-instance.js +++ b/app/scripts/lib/extension-instance.js @@ -41,6 +41,12 @@ function Extension () { } } catch (e) {} + try { + if (browser[api]) { + _this[api] = browser[api] + } + } + 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 75fb60dd0..e6bdeff09 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -31,7 +31,7 @@ function createMsgNotification (state) { } function showNotification() { - chrome.windows.create({ + extension.windows.create({ url:"notification.html", type:"panel", width:360, -- cgit v1.2.3 From a167bbc5a0f29568ec8e53ecdd942724aa15604b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 Aug 2016 17:32:54 -0700 Subject: MVP Popup Notifications Working I'm unsure which will be more performant: A notification using a trimmed down version of the UI, or using them both, letting the browser cache them both. In any case, here I've modified the normal UI to recognize when it's a popup, and change the UX accordingly in a few ways: - Hide the menu bar - Hide the back button from the notifications view. - When confirming the last tx, close the window. --- app/scripts/lib/extension-instance.js | 2 +- app/scripts/lib/notifications.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js index d284895bc..1098130e3 100644 --- a/app/scripts/lib/extension-instance.js +++ b/app/scripts/lib/extension-instance.js @@ -45,7 +45,7 @@ function Extension () { if (browser[api]) { _this[api] = browser[api] } - } + } catch (e) {} try { _this.api = browser.extension[api] diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index e6bdeff09..de9cf26e3 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -33,7 +33,8 @@ function createMsgNotification (state) { function showNotification() { extension.windows.create({ url:"notification.html", - type:"panel", + type:"detached_panel", + focused:true, width:360, height:500, }) -- cgit v1.2.3 From dfaac78e39ef1bd06e224ab56e493b4fa3201bef Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 Aug 2016 17:50:51 -0700 Subject: Linted --- app/scripts/lib/notifications.js | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index de9cf26e3..d33db0ef9 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, @@ -32,11 +22,11 @@ function createMsgNotification (state) { function showNotification() { extension.windows.create({ - url:"notification.html", - type:"detached_panel", - focused:true, - width:360, - height:500, + url: 'notification.html', + type: 'detached_panel', + focused: true, + width: 360, + height: 500, }) } -- cgit v1.2.3 From 361e26fad779dc35e480cf5333b6237f437732a5 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 22 Aug 2016 17:18:14 -0700 Subject: Limit to one popup, re-focus on additional notifications. --- app/scripts/lib/notifications.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index d33db0ef9..278c7674e 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -21,12 +21,23 @@ function createMsgNotification (state) { } function showNotification() { - extension.windows.create({ - url: 'notification.html', - type: 'detached_panel', - focused: true, - width: 360, - height: 500, + extension.windows.getAll({}, (windows) => { + + let popupWindow = windows.find((win) => { + return win.type === 'popup' + }) + + if (popupWindow) { + return extension.windows.update(popupWindow.id, { focused: true }) + } + + extension.windows.create({ + url: 'notification.html', + type: 'detached_panel', + focused: true, + width: 360, + height: 500, + }) }) } -- cgit v1.2.3 From e5ca83d2bf7e97131e20da0ad352a38c7f8a2f86 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 Aug 2016 11:15:56 -0700 Subject: Emit updates to all listeners on pending tx updates Previously the metamask controller only supported a single UI event listener, which wasn't useful for having a separate notification UI open at the same time. Also reduced the notification's complexity down to a single method, which is heavily re-used. Still has an outstanding bug where if the plugin ui dismisses the last tx, it does not close the notification popup. --- app/scripts/lib/notifications.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index 278c7674e..4c2aa91de 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -1,25 +1,11 @@ const extension = require('./extension') const notifications = { - createUnlockRequestNotification: createUnlockRequestNotification, - createTxNotification: createTxNotification, - createMsgNotification: createMsgNotification, + show: showNotification, } module.exports = notifications window.METAMASK_NOTIFIER = notifications -function createUnlockRequestNotification (opts) { - showNotification() -} - -function createTxNotification (state) { - showNotification() -} - -function createMsgNotification (state) { - showNotification() -} - function showNotification() { extension.windows.getAll({}, (windows) => { -- cgit v1.2.3 From 4fb49dfb4b3f23a5510c5a958671e9454d214a11 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 Aug 2016 11:40:08 -0700 Subject: Close popup even if last tx is dismissed from main UI --- app/scripts/lib/notifications.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index 4c2aa91de..cf4e1c216 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -2,19 +2,15 @@ const extension = require('./extension') const notifications = { show: showNotification, + getPopup, } module.exports = notifications window.METAMASK_NOTIFIER = notifications function showNotification() { - extension.windows.getAll({}, (windows) => { - - let popupWindow = windows.find((win) => { - return win.type === 'popup' - }) - - if (popupWindow) { - return extension.windows.update(popupWindow.id, { focused: true }) + getPopup((popup) => { + if (popup) { + return extension.windows.update(popup.id, { focused: true }) } extension.windows.create({ @@ -27,3 +23,13 @@ function showNotification() { }) } +function getPopup(cb) { + extension.windows.getAll({}, (windows) => { + let popup = windows.find((win) => { + return win.type === 'popup' + }) + + cb(popup) + }) +} + -- cgit v1.2.3 From b3887ffd0a33096ef63fd4bbba9b5ff559775b3e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 Aug 2016 11:48:46 -0700 Subject: Skip popup dismissal in tests --- app/scripts/lib/notifications.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index cf4e1c216..c8ecad805 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -24,6 +24,12 @@ function showNotification() { } function getPopup(cb) { + + // Ignore in test environment + if (!extension.windows) { + return cb(null) + } + extension.windows.getAll({}, (windows) => { let popup = windows.find((win) => { return win.type === 'popup' -- cgit v1.2.3 From 671ca33abb93fafeb55a18543e81942c5963da8e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 Aug 2016 15:44:50 -0700 Subject: Close notification on opening main UI --- app/scripts/lib/notifications.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'app/scripts/lib') diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index c8ecad805..dcb946845 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -1,13 +1,14 @@ const extension = require('./extension') const notifications = { - show: showNotification, + show, getPopup, + closePopup, } module.exports = notifications window.METAMASK_NOTIFIER = notifications -function showNotification() { +function show () { getPopup((popup) => { if (popup) { return extension.windows.update(popup.id, { focused: true }) @@ -39,3 +40,9 @@ function getPopup(cb) { }) } +function closePopup() { + getPopup((popup) => { + if (!popup) return + extension.windows.remove(popup.id, console.error) + }) +} -- cgit v1.2.3