1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
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 = screenY + (outerHeight / 2) - (NOTIFICATION_HEIGHT / 2)
const notificationLeft = 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
|