-
Notifications
You must be signed in to change notification settings - Fork 2.9k
/
BrowserNotifications.js
139 lines (124 loc) · 4.06 KB
/
BrowserNotifications.js
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
// Web and desktop implementation only. Do not import for direct use. Use LocalNotification.
import Str from 'expensify-common/lib/str';
import Onyx from 'react-native-onyx';
import focusApp from './focusApp';
import EXPENSIFY_ICON_URL from '../../../../assets/images/expensify-logo-round.png';
import ONYXKEYS from '../../../ONYXKEYS';
const DEFAULT_DELAY = 4000;
/**
* Checks if the user has granted permission to show browser notifications
*
* @return {Promise}
*/
function canUseBrowserNotifications() {
return new Promise((resolve) => {
// They have no browser notifications so we can't use this feature
if (!window.Notification) {
return resolve(false);
}
// Check if they previously granted or denied us access to send a notification
const permissionGranted = Notification.permission === 'granted';
if (permissionGranted || Notification.permission === 'denied') {
return resolve(permissionGranted);
}
// Check their global preferences for browser notifications and ask permission if they have none
Notification.requestPermission()
.then((status) => {
resolve(status === 'granted');
});
});
}
/**
* Light abstraction around browser push notifications.
* Checks for permission before determining whether to send.
*
* @param {Object} params
* @param {String} params.title
* @param {String} params.body
* @param {String} [params.icon] Default to Expensify logo
* @param {Number} [params.delay]
* @param {Function} [params.onClick]
* @param {String} [params.tag]
*
* @return {Promise} - resolves with Notification object or undefined
*/
function push({
title,
body,
delay = DEFAULT_DELAY,
onClick = () => {},
tag = '',
icon = EXPENSIFY_ICON_URL,
}) {
return new Promise((resolve) => {
if (!title || !body) {
throw new Error('BrowserNotification must include title and body parameter.');
}
canUseBrowserNotifications().then((canUseNotifications) => {
if (!canUseNotifications) {
resolve();
return;
}
const notification = new Notification(title, {
body,
icon,
tag,
});
// If we pass in a delay param greater than 0 the notification
// will auto-close after the specified time.
if (delay > 0) {
setTimeout(notification.close.bind(notification), delay);
}
notification.onclick = (event) => {
event.preventDefault();
onClick();
window.parent.focus();
window.focus();
focusApp();
notification.close();
};
resolve(notification);
});
});
}
/**
* BrowserNotification
* @namespace
*/
export default {
/**
* Create a report comment notification
*
* @param {Object} params
* @param {Object} params.reportAction
* @param {Function} params.onClick
*/
pushReportCommentNotification({reportAction, onClick}) {
const {person, message} = reportAction;
const plainTextPerson = Str.htmlDecode(person.map(f => f.text).join());
// Specifically target the comment part of the message
const plainTextMessage = Str.htmlDecode((message.find(f => f.type === 'COMMENT') || {}).text);
push({
title: `New message from ${plainTextPerson}`,
body: plainTextMessage,
delay: 0,
onClick,
});
},
/**
* Create a notification to indicate that an update is available.
*
* @param {Object} params
* @param {String} params.version
*/
pushUpdateAvailableNotification({version}) {
push({
title: 'Update available',
body: 'A new version of Expensify.cash is available!',
delay: 0,
onClick: () => {
Onyx.merge(ONYXKEYS.UPDATE_VERSION, version);
},
});
},
};