const extension = require('extensionizer') const NOTIFICATION_HEIGHT = 620 const NOTIFICATION_WIDTH = 360 class NotificationManager { /** * A collection of methods for controlling the showing and hiding of the notification popup. * * @typedef {Object} NotificationManager * */ /** * Either brings an existing MetaMask notification window into focus, or creates a new notification window. New * notification windows are given a 'popup' type. * */ showPopup () { this._getPopup((err, popup) => { if (err) { throw err } // Bring focus to chrome popup if (popup) { // bring focus to existing chrome popup extension.windows.update(popup.id, { focused: true }) } else { const { screenX, screenY, outerWidth, outerHeight } = window const notificationTop = Math.round(screenY + (outerHeight / 2) - (NOTIFICATION_HEIGHT / 2)) const notificationLeft = Math.round(screenX + (outerWidth / 2) - (NOTIFICATION_WIDTH / 2)) const cb = (currentPopup) => { this._popupId = currentPopup.id } // create new notification popup const creation = extension.windows.create({ url: 'notification.html', type: 'popup', width: NOTIFICATION_WIDTH, height: NOTIFICATION_HEIGHT, top: Math.max(notificationTop, 0), left: Math.max(notificationLeft, 0), }, cb) creation && creation.then && creation.then(cb) } }) } /** * Closes a MetaMask notification if it window exists. * */ closePopup () { // closes notification popup this._getPopup((err, popup) => { if (err) { throw err } if (!popup) { return } extension.windows.remove(popup.id, console.error) }) } /** * Checks all open MetaMask windows, and returns the first one it finds that is a notification window (i.e. has the * type 'popup') * * @private * @param {Function} cb A node style callback that to whcih the found notification window will be passed. * */ _getPopup (cb) { this._getWindows((err, windows) => { if (err) { throw err } cb(null, this._getPopupIn(windows)) }) } /** * Returns all open MetaMask windows. * * @private * @param {Function} cb A node style callback that to which the windows will be passed. * */ _getWindows (cb) { // Ignore in test environment if (!extension.windows) { return cb() } extension.windows.getAll({}, (windows) => { cb(null, windows) }) } /** * Given an array of windows, returns the 'popup' that has been opened by MetaMask, or null if no such window exists. * * @private * @param {array} windows An array of objects containing data about the open MetaMask extension windows. * */ _getPopupIn (windows) { return windows ? windows.find((win) => { // Returns notification popup return (win && win.type === 'popup' && win.id === this._popupId) }) : null } } module.exports = NotificationManager