-
Notifications
You must be signed in to change notification settings - Fork 3k
/
Copy pathindex.native.js
167 lines (147 loc) · 5.71 KB
/
index.native.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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import _ from 'underscore';
import {AppState} from 'react-native';
import {UrbanAirship, EventType} from 'urbanairship-react-native';
import lodashGet from 'lodash/get';
import Log from '../../Log';
import NotificationType from './NotificationType';
const notificationEventActionMap = {};
/**
* Handle a push notification event, and trigger and bound actions.
*
* @param {String} eventType
* @param {Object} notification
*/
function pushNotificationEventCallback(eventType, notification) {
const actionMap = notificationEventActionMap[eventType] || {};
let payload = lodashGet(notification, 'extras.payload');
// On Android, some notification payloads are sent as a JSON string rather than an object
if (_.isString(payload)) {
payload = JSON.parse(payload);
}
Log.info(`[PUSH_NOTIFICATION] Callback triggered for ${eventType}`);
if (!payload) {
Log.warn('[PUSH_NOTIFICATION] Notification has null or undefined payload, not executing any callback.');
return;
}
if (!payload.type) {
Log.warn('[PUSH_NOTIFICATION] No type value provided in payload, not executing any callback.');
return;
}
const action = actionMap[payload.type];
if (!action) {
Log.warn('[PUSH_NOTIFICATION] No callback set up: ', {
event: eventType,
notificationType: payload.type,
});
return;
}
action(payload);
}
/**
* Register push notification callbacks. This is separate from namedUser registration because it needs to be executed
* from a headless JS process, outside of any react lifecycle.
*
* WARNING: Moving or changing this code could break Push Notification processing in non-obvious ways.
* DO NOT ALTER UNLESS YOU KNOW WHAT YOU'RE DOING. See this PR for details: https://github.com/Expensify/App/pull/3877
*/
function init() {
// Setup event listeners
UrbanAirship.addListener(EventType.PushReceived, (notification) => {
// If a push notification is received while the app is in foreground,
// we'll assume pusher is connected so we'll ignore it and not fetch the same data twice.
if (AppState.currentState === 'active') {
Log.info('[PUSH_NOTIFICATION] Push received while app is in foreground, not executing any callback.');
return;
}
pushNotificationEventCallback(EventType.PushReceived, notification);
});
// Note: the NotificationResponse event has a nested PushReceived event,
// so event.notification refers to the same thing as notification above ^
UrbanAirship.addListener(EventType.NotificationResponse, (event) => {
pushNotificationEventCallback(EventType.NotificationResponse, event.notification);
});
}
/**
* Register this device for push notifications for the given accountID.
*
* @param {String|Number} accountID
*/
function register(accountID) {
if (UrbanAirship.getNamedUser() === accountID.toString()) {
// No need to register again for this accountID.
return;
}
// Get permissions to display push notifications (prompts user on iOS, but not Android)
UrbanAirship.enableUserPushNotifications()
.then((isEnabled) => {
if (isEnabled) {
return;
}
Log.info('[PUSH_NOTIFICATIONS] User has disabled visible push notifications for this app.');
});
// Register this device as a named user in AirshipAPI.
// Regardless of the user's opt-in status, we still want to receive silent push notifications.
Log.info(`[PUSH_NOTIFICATIONS] Subscribing to notifications for account ID ${accountID}`);
UrbanAirship.setNamedUser(accountID.toString());
}
/**
* Deregister this device from push notifications.
*/
function deregister() {
Log.info('[PUSH_NOTIFICATIONS] Unsubscribing from push notifications.');
UrbanAirship.setNamedUser(null);
UrbanAirship.removeAllListeners(EventType.PushReceived);
UrbanAirship.removeAllListeners(EventType.NotificationResponse);
}
/**
* Bind a callback to a push notification of a given type.
* See https://github.com/Expensify/Web-Expensify/blob/main/lib/MobilePushNotifications.php for the various
* types of push notifications sent, along with the data that they provide.
*
* Note: This implementation allows for only one callback to be bound to an Event/Type pair. For example,
* if we attempt to bind two callbacks to the PushReceived event for reportComment notifications,
* the second will overwrite the first.
*
* @param {String} notificationType
* @param {Function} callback
* @param {String} [triggerEvent] - The event that should trigger this callback. Should be one of UrbanAirship.EventType
*/
function bind(notificationType, callback, triggerEvent) {
if (!notificationEventActionMap[triggerEvent]) {
notificationEventActionMap[triggerEvent] = {};
}
notificationEventActionMap[triggerEvent][notificationType] = callback;
}
/**
* Bind a callback to be executed when a push notification of a given type is received.
*
* @param {String} notificationType
* @param {Function} callback
*/
function onReceived(notificationType, callback) {
bind(notificationType, callback, EventType.PushReceived);
}
/**
* Bind a callback to be executed when a push notification of a given type is tapped by the user.
*
* @param {String} notificationType
* @param {Function} callback
*/
function onSelected(notificationType, callback) {
bind(notificationType, callback, EventType.NotificationResponse);
}
/**
* Clear all push notifications
*/
function clearNotifications() {
UrbanAirship.clearNotifications();
}
export default {
init,
register,
deregister,
onReceived,
onSelected,
TYPE: NotificationType,
clearNotifications,
};