-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathBrowserNotifications.js
142 lines (126 loc) · 4.34 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
140
141
142
// Web and desktop implementation only. Do not import for direct use. Use LocalNotification.
import _ from 'underscore';
import focusApp from './focusApp';
import * as AppUpdate from '../../actions/AppUpdate';
import EXPENSIFY_ICON_URL from '../../../../assets/images/expensify-logo-round-clearspace.png';
import * as ReportUtils from '../../ReportUtils';
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] Path to icon
* @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}) {
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,
tag,
icon,
});
// 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 = () => {
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.report
* @param {Object} params.reportAction
* @param {Function} params.onClick
* @param {Boolean} usesIcon true if notification uses right circular icon
*/
pushReportCommentNotification({report, reportAction, onClick}, usesIcon = false) {
let title;
let body;
const isChatRoom = ReportUtils.isChatRoom(report);
const {person, message} = reportAction;
const plainTextPerson = _.map(person, (f) => f.text).join();
// Specifically target the comment part of the message
const plainTextMessage = (_.find(message, (f) => f.type === 'COMMENT') || {}).text;
if (isChatRoom) {
const roomName = _.get(report, 'displayName', '');
title = roomName;
body = `${plainTextPerson}: ${plainTextMessage}`;
} else {
title = plainTextPerson;
body = plainTextMessage;
}
push({
title,
body,
delay: 0,
onClick,
icon: usesIcon ? EXPENSIFY_ICON_URL : '',
});
},
/**
* Create a notification to indicate that an update is available.
*/
pushUpdateAvailableNotification() {
push({
title: 'Update available',
body: 'A new version of this app is available!',
delay: 0,
onClick: () => {
AppUpdate.triggerUpdateAvailable();
},
});
},
};